gnunet-service-transport_manipulation.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010-2013 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file transport/gnunet-service-transport_manipulation.c
  18. * @brief transport component manipulation traffic for simulation
  19. * @author Christian Grothoff
  20. * @author Matthias Wachs
  21. */
  22. #include "platform.h"
  23. #include "gnunet-service-transport_hello.h"
  24. #include "gnunet-service-transport_neighbours.h"
  25. #include "gnunet-service-transport_plugins.h"
  26. #include "gnunet-service-transport_validation.h"
  27. #include "gnunet-service-transport.h"
  28. #include "transport.h"
  29. /**
  30. * Struct containing information about manipulations to a specific peer
  31. */
  32. struct TM_Peer
  33. {
  34. /**
  35. * Peer ID
  36. */
  37. struct GNUNET_PeerIdentity peer;
  38. /**
  39. * How long to delay incoming messages for this peer.
  40. */
  41. struct GNUNET_TIME_Relative delay_in;
  42. /**
  43. * How long to delay outgoing messages for this peer.
  44. */
  45. struct GNUNET_TIME_Relative delay_out;
  46. /**
  47. * Manipulated properties to use for this peer.
  48. */
  49. struct GNUNET_ATS_Properties properties;
  50. /**
  51. * Task to schedule delayed sendding
  52. */
  53. struct GNUNET_SCHEDULER_Task *send_delay_task;
  54. /**
  55. * Send queue DLL head
  56. */
  57. struct DelayQueueEntry *send_head;
  58. /**
  59. * Send queue DLL tail
  60. */
  61. struct DelayQueueEntry *send_tail;
  62. };
  63. /**
  64. * Entry in the delay queue for an outbound delayed message
  65. */
  66. struct DelayQueueEntry
  67. {
  68. /**
  69. * Next in DLL
  70. */
  71. struct DelayQueueEntry *prev;
  72. /**
  73. * Previous in DLL
  74. */
  75. struct DelayQueueEntry *next;
  76. /**
  77. * Peer this entry is belonging to if (NULL == tmp): enqueued in
  78. * generic DLL and scheduled by generic_send_delay_task else:
  79. * enqueued in tmp->send_head and tmp->send_tail and scheduled by
  80. * tmp->send_delay_task
  81. */
  82. struct TM_Peer *tmp;
  83. /**
  84. * Peer ID
  85. */
  86. struct GNUNET_PeerIdentity id;
  87. /**
  88. * Absolute time when to send
  89. */
  90. struct GNUNET_TIME_Absolute sent_at;
  91. /**
  92. * The message
  93. */
  94. void *msg;
  95. /**
  96. * The message size
  97. */
  98. size_t msg_size;
  99. /**
  100. * Message timeout
  101. */
  102. struct GNUNET_TIME_Relative timeout;
  103. /**
  104. * Transports send continuation
  105. */
  106. GST_NeighbourSendContinuation cont;
  107. /**
  108. * Transports send continuation cls
  109. */
  110. void *cont_cls;
  111. };
  112. /**
  113. * Hashmap contain all peers currently manipulated
  114. */
  115. static struct GNUNET_CONTAINER_MultiPeerMap *peers;
  116. /**
  117. * Inbound delay to apply to all peers.
  118. */
  119. static struct GNUNET_TIME_Relative delay_in;
  120. /**
  121. * Outbound delay to apply to all peers.
  122. */
  123. static struct GNUNET_TIME_Relative delay_out;
  124. /**
  125. * DLL head for delayed messages based on general delay
  126. */
  127. static struct DelayQueueEntry *generic_dqe_head;
  128. /**
  129. * DLL tail for delayed messages based on general delay
  130. */
  131. static struct DelayQueueEntry *generic_dqe_tail;
  132. /**
  133. * Task to schedule delayed sending based on general delay
  134. */
  135. static struct GNUNET_SCHEDULER_Task *generic_send_delay_task;
  136. /**
  137. * Set traffic metric to manipulate
  138. *
  139. * @param message containing information
  140. */
  141. void
  142. GST_manipulation_set_metric (const struct TrafficMetricMessage *tm)
  143. {
  144. static struct GNUNET_PeerIdentity zero;
  145. struct TM_Peer *tmp;
  146. if (0 == memcmp (&tm->peer,
  147. &zero,
  148. sizeof(struct GNUNET_PeerIdentity)))
  149. {
  150. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  151. "Received traffic metrics for all peers\n");
  152. delay_in = GNUNET_TIME_relative_ntoh (tm->delay_in);
  153. delay_out = GNUNET_TIME_relative_ntoh (tm->delay_out);
  154. return;
  155. }
  156. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  157. "Received traffic metrics for peer `%s'\n",
  158. GNUNET_i2s (&tm->peer));
  159. if (NULL ==
  160. (tmp = GNUNET_CONTAINER_multipeermap_get (peers,
  161. &tm->peer)))
  162. {
  163. tmp = GNUNET_new (struct TM_Peer);
  164. tmp->peer = tm->peer;
  165. GNUNET_CONTAINER_multipeermap_put (peers,
  166. &tm->peer,
  167. tmp,
  168. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
  169. }
  170. GNUNET_ATS_properties_ntoh (&tmp->properties,
  171. &tm->properties);
  172. tmp->delay_in = GNUNET_TIME_relative_ntoh (tm->delay_in);
  173. tmp->delay_out = GNUNET_TIME_relative_ntoh (tm->delay_out);
  174. }
  175. /**
  176. * We have delayed transmission, now it is time to send the
  177. * message.
  178. *
  179. * @param cls the `struct DelayQueueEntry` to transmit
  180. */
  181. static void
  182. send_delayed (void *cls)
  183. {
  184. struct DelayQueueEntry *dqe = cls;
  185. struct DelayQueueEntry *next;
  186. struct TM_Peer *tmp = dqe->tmp;
  187. GNUNET_break (GNUNET_YES ==
  188. GST_neighbours_test_connected (&dqe->id));
  189. if (NULL != tmp)
  190. {
  191. tmp->send_delay_task = NULL;
  192. GNUNET_CONTAINER_DLL_remove (tmp->send_head,
  193. tmp->send_tail,
  194. dqe);
  195. next = tmp->send_head;
  196. if (NULL != next)
  197. {
  198. /* More delayed messages */
  199. tmp->send_delay_task = GNUNET_SCHEDULER_add_at (next->sent_at,
  200. &send_delayed,
  201. next);
  202. }
  203. }
  204. else
  205. {
  206. /* Remove from generic queue */
  207. generic_send_delay_task = NULL;
  208. GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
  209. generic_dqe_tail,
  210. dqe);
  211. next = generic_dqe_head;
  212. if (NULL != next)
  213. {
  214. /* More delayed messages */
  215. generic_send_delay_task = GNUNET_SCHEDULER_add_at (next->sent_at,
  216. &send_delayed,
  217. next);
  218. }
  219. }
  220. GST_neighbours_send (&dqe->id,
  221. dqe->msg,
  222. dqe->msg_size,
  223. dqe->timeout,
  224. dqe->cont,
  225. dqe->cont_cls);
  226. GNUNET_free(dqe);
  227. }
  228. /**
  229. * Adapter function between transport's send function and transport plugins.
  230. * Delays message transmission if an artificial delay is configured.
  231. *
  232. * @param target the peer the message to send to
  233. * @param msg the message received
  234. * @param msg_size message size
  235. * @param timeout timeout
  236. * @param cont the continuation to call after sending
  237. * @param cont_cls cls for @a cont
  238. */
  239. void
  240. GST_manipulation_send (const struct GNUNET_PeerIdentity *target,
  241. const void *msg,
  242. size_t msg_size,
  243. struct GNUNET_TIME_Relative timeout,
  244. GST_NeighbourSendContinuation cont,
  245. void *cont_cls)
  246. {
  247. struct TM_Peer *tmp;
  248. struct DelayQueueEntry *dqe;
  249. struct GNUNET_TIME_Relative delay;
  250. if (NULL != (tmp =
  251. GNUNET_CONTAINER_multipeermap_get (peers,
  252. target)))
  253. delay = tmp->delay_out;
  254. else
  255. delay = delay_out;
  256. if (0 == delay.rel_value_us)
  257. {
  258. /* Normal sending */
  259. GST_neighbours_send (target,
  260. msg,
  261. msg_size,
  262. timeout,
  263. cont, cont_cls);
  264. return;
  265. }
  266. dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size);
  267. dqe->id = *target;
  268. dqe->tmp = tmp;
  269. dqe->sent_at = GNUNET_TIME_relative_to_absolute (delay);
  270. dqe->cont = cont;
  271. dqe->cont_cls = cont_cls;
  272. dqe->msg = &dqe[1];
  273. dqe->msg_size = msg_size;
  274. dqe->timeout = timeout;
  275. GNUNET_memcpy (dqe->msg,
  276. msg,
  277. msg_size);
  278. if (NULL == tmp)
  279. {
  280. GNUNET_CONTAINER_DLL_insert_tail (generic_dqe_head,
  281. generic_dqe_tail,
  282. dqe);
  283. if (NULL == generic_send_delay_task)
  284. generic_send_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
  285. &send_delayed,
  286. dqe);
  287. }
  288. else
  289. {
  290. GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head,
  291. tmp->send_tail,
  292. dqe);
  293. if (NULL == tmp->send_delay_task)
  294. tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed (delay,
  295. &send_delayed,
  296. dqe);
  297. }
  298. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  299. "Delaying %u byte message to peer `%s' with peer specific delay for %s\n",
  300. (unsigned int) msg_size,
  301. GNUNET_i2s (target),
  302. GNUNET_STRINGS_relative_time_to_string (delay,
  303. GNUNET_YES));
  304. }
  305. /**
  306. * Function that will be called to manipulate ATS information according to
  307. * current manipulation settings
  308. *
  309. * @param address binary address
  310. * @param session the session
  311. * @param prop[IN|OUT] metrics to modify
  312. */
  313. void
  314. GST_manipulation_manipulate_metrics (const struct GNUNET_HELLO_Address *address,
  315. struct GNUNET_ATS_Session *session,
  316. struct GNUNET_ATS_Properties *prop)
  317. {
  318. const struct GNUNET_PeerIdentity *peer = &address->peer;
  319. struct TM_Peer *tmp;
  320. tmp = GNUNET_CONTAINER_multipeermap_get (peers,
  321. peer);
  322. if (NULL != tmp)
  323. *prop = tmp->properties;
  324. }
  325. /**
  326. * Adapter function between transport plugins and transport receive function
  327. * manipulation delays for next send.
  328. *
  329. * @param cls the closure for transport
  330. * @param address the address and the peer the message was received from
  331. * @param message the message received
  332. * @param session the session the message was received on
  333. * @return manipulated delay for next receive
  334. */
  335. struct GNUNET_TIME_Relative
  336. GST_manipulation_recv (void *cls,
  337. const struct GNUNET_HELLO_Address *address,
  338. struct GNUNET_ATS_Session *session,
  339. const struct GNUNET_MessageHeader *message)
  340. {
  341. struct TM_Peer *tmp;
  342. struct GNUNET_TIME_Relative quota_delay;
  343. struct GNUNET_TIME_Relative m_delay;
  344. if (NULL !=
  345. (tmp = GNUNET_CONTAINER_multipeermap_get (peers,
  346. &address->peer)))
  347. m_delay = tmp->delay_in;
  348. else
  349. m_delay = delay_in;
  350. quota_delay = GST_receive_callback (cls,
  351. address,
  352. session,
  353. message);
  354. m_delay = GNUNET_TIME_relative_max (m_delay,
  355. quota_delay);
  356. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  357. "Delaying next receive for peer `%s' for %s\n",
  358. GNUNET_i2s (&address->peer),
  359. GNUNET_STRINGS_relative_time_to_string (m_delay,
  360. GNUNET_YES));
  361. return m_delay;
  362. }
  363. /**
  364. * Initialize traffic manipulation
  365. */
  366. void
  367. GST_manipulation_init ()
  368. {
  369. struct GNUNET_TIME_Relative delay;
  370. if ( (GNUNET_OK ==
  371. GNUNET_CONFIGURATION_get_value_time (GST_cfg,
  372. "transport",
  373. "MANIPULATE_DELAY_IN",
  374. &delay)) &&
  375. (delay.rel_value_us > 0) )
  376. {
  377. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  378. "Delaying inbound traffic for %s\n",
  379. GNUNET_STRINGS_relative_time_to_string (delay,
  380. GNUNET_YES));
  381. delay_in = delay;
  382. }
  383. if ( (GNUNET_OK ==
  384. GNUNET_CONFIGURATION_get_value_time (GST_cfg,
  385. "transport",
  386. "MANIPULATE_DELAY_OUT",
  387. &delay)) &&
  388. (delay.rel_value_us > 0) )
  389. {
  390. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  391. "Delaying outbound traffic for %s\n",
  392. GNUNET_STRINGS_relative_time_to_string (delay,
  393. GNUNET_YES));
  394. delay_out = delay;
  395. }
  396. peers = GNUNET_CONTAINER_multipeermap_create (4,
  397. GNUNET_NO);
  398. }
  399. /**
  400. * Notify manipulation about disconnect so it can discard queued messages
  401. *
  402. * @param peer the disconnecting peer
  403. */
  404. void
  405. GST_manipulation_peer_disconnect (const struct GNUNET_PeerIdentity *peer)
  406. {
  407. struct TM_Peer *tmp;
  408. struct DelayQueueEntry *dqe;
  409. struct DelayQueueEntry *next;
  410. tmp = GNUNET_CONTAINER_multipeermap_get (peers,
  411. peer);
  412. if (NULL != tmp)
  413. {
  414. while (NULL != (dqe = tmp->send_head))
  415. {
  416. GNUNET_CONTAINER_DLL_remove (tmp->send_head,
  417. tmp->send_tail,
  418. dqe);
  419. if (NULL != dqe->cont)
  420. dqe->cont (dqe->cont_cls,
  421. GNUNET_SYSERR,
  422. dqe->msg_size,
  423. 0);
  424. GNUNET_free(dqe);
  425. }
  426. }
  427. next = generic_dqe_head;
  428. while (NULL != (dqe = next))
  429. {
  430. next = dqe->next;
  431. if (0 == memcmp (peer,
  432. &dqe->id,
  433. sizeof (dqe->id)))
  434. {
  435. GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
  436. generic_dqe_tail,
  437. dqe);
  438. if (NULL != dqe->cont)
  439. dqe->cont (dqe->cont_cls,
  440. GNUNET_SYSERR,
  441. dqe->msg_size,
  442. 0);
  443. GNUNET_free(dqe);
  444. }
  445. }
  446. if (NULL != generic_send_delay_task)
  447. {
  448. GNUNET_SCHEDULER_cancel (generic_send_delay_task);
  449. generic_send_delay_task = NULL;
  450. if (NULL != generic_dqe_head)
  451. generic_send_delay_task
  452. = GNUNET_SCHEDULER_add_at (generic_dqe_head->sent_at,
  453. &send_delayed,
  454. generic_dqe_head);
  455. }
  456. }
  457. /**
  458. * Free manipulation information about a peer.
  459. *
  460. * @param cls NULL
  461. * @param key peer the info is about
  462. * @param value a `struct TM_Peer` to free
  463. * @return #GNUNET_OK (continue to iterate)
  464. */
  465. static int
  466. free_tmps (void *cls,
  467. const struct GNUNET_PeerIdentity *key,
  468. void *value)
  469. {
  470. struct TM_Peer *tmp = value;
  471. struct DelayQueueEntry *dqe;
  472. GNUNET_break (GNUNET_YES ==
  473. GNUNET_CONTAINER_multipeermap_remove (peers,
  474. key,
  475. value));
  476. while (NULL != (dqe = tmp->send_head))
  477. {
  478. GNUNET_CONTAINER_DLL_remove (tmp->send_head,
  479. tmp->send_tail,
  480. dqe);
  481. if (NULL != dqe->cont)
  482. dqe->cont (dqe->cont_cls,
  483. GNUNET_SYSERR,
  484. dqe->msg_size,
  485. 0);
  486. GNUNET_free (dqe);
  487. }
  488. if (NULL != tmp->send_delay_task)
  489. {
  490. GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
  491. tmp->send_delay_task = NULL;
  492. }
  493. GNUNET_free (tmp);
  494. return GNUNET_OK;
  495. }
  496. /**
  497. * Stop traffic manipulation
  498. */
  499. void
  500. GST_manipulation_stop ()
  501. {
  502. struct DelayQueueEntry *cur;
  503. GNUNET_CONTAINER_multipeermap_iterate (peers,
  504. &free_tmps,
  505. NULL);
  506. GNUNET_CONTAINER_multipeermap_destroy (peers);
  507. peers = NULL;
  508. while (NULL != (cur = generic_dqe_head))
  509. {
  510. GNUNET_CONTAINER_DLL_remove (generic_dqe_head,
  511. generic_dqe_tail,
  512. cur);
  513. if (NULL != cur->cont)
  514. cur->cont (cur->cont_cls,
  515. GNUNET_SYSERR,
  516. cur->msg_size,
  517. 0);
  518. GNUNET_free (cur);
  519. }
  520. if (NULL != generic_send_delay_task)
  521. {
  522. GNUNET_SCHEDULER_cancel (generic_send_delay_task);
  523. generic_send_delay_task = NULL;
  524. }
  525. }
  526. /* end of file gnunet-service-transport_manipulation.c */