gnunet-service-transport_manipulation.c 17 KB

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