gnunet-service-xdht_routing.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2011 - 2014 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 dht/gnunet-service-xdht_routing.c
  19. * @brief GNUnet DHT tracking of requests for routing replies
  20. * @author Supriti Singh
  21. */
  22. #include "platform.h"
  23. #include "gnunet-service-xdht_neighbours.h"
  24. #include "gnunet-service-xdht_routing.h"
  25. #include "gnunet-service-xdht.h"
  26. /**
  27. * FIXME: Check if its better to store pointer to friend rather than storing
  28. * peer identity next_hop or prev_hop.
  29. * keep entries in destnation and source peer also. so when we send the trail
  30. * teardown message then we don't know the source but if source gets the message
  31. * then it shold remove that trail id from its finger table. But how does
  32. * source know what is the desination finger ? It will whenevr contact a trail
  33. * will do a lookup in routing table and if no trail id present the remove
  34. * that trail of the finger and if only one trail then remove the finger.
  35. * because of this use case of trail teardown I think trail compression
  36. * and trail teardown should not be merged.
  37. * 2. store a pointer to friendInfo in place o peer identity.
  38. */
  39. /**
  40. * Maximum number of entries in routing table.
  41. */
  42. #define ROUTING_TABLE_THRESHOLD 80000
  43. /**
  44. * FIXME: Store friend pointer instead of peer identifier.
  45. * Routing table entry .
  46. */
  47. struct RoutingTrail
  48. {
  49. /**
  50. * Global Unique identifier of the trail.
  51. */
  52. struct GNUNET_HashCode trail_id;
  53. /**
  54. * The peer to which this request should be passed to.
  55. */
  56. struct GNUNET_PeerIdentity next_hop;
  57. /**
  58. * Peer just before next hop in the trail.
  59. */
  60. struct GNUNET_PeerIdentity prev_hop;
  61. };
  62. /**
  63. * Routing table of the peer
  64. */
  65. static struct GNUNET_CONTAINER_MultiHashMap *routing_table;
  66. /**
  67. * Update the prev. hop of the trail. Call made by trail compression where
  68. * if you are the first friend now in the trail then you need to update
  69. * your prev. hop.
  70. * @param trail_id
  71. * @return #GNUNET_OK success
  72. * #GNUNET_SYSERR in case no matching entry found in routing table.
  73. */
  74. int
  75. GDS_ROUTING_update_trail_prev_hop (const struct GNUNET_HashCode trail_id,
  76. struct GNUNET_PeerIdentity prev_hop)
  77. {
  78. struct RoutingTrail *trail;
  79. trail = GNUNET_CONTAINER_multihashmap_get (routing_table, &trail_id);
  80. if (NULL == trail)
  81. return GNUNET_SYSERR;
  82. trail->prev_hop = prev_hop;
  83. return GNUNET_OK;
  84. }
  85. /**
  86. * Update the next hop of the trail. Call made by trail compression where
  87. * if you are source of the trail and now you have a new first friend, then
  88. * you should update the trail.
  89. * @param trail_id
  90. * @return #GNUNET_OK success
  91. * #GNUNET_SYSERR in case no matching entry found in routing table.
  92. */
  93. int
  94. GDS_ROUTING_update_trail_next_hop (const struct GNUNET_HashCode trail_id,
  95. struct GNUNET_PeerIdentity next_hop)
  96. {
  97. struct RoutingTrail *trail;
  98. trail = GNUNET_CONTAINER_multihashmap_get (routing_table, &trail_id);
  99. if (NULL == trail)
  100. return GNUNET_SYSERR;
  101. trail->next_hop = next_hop;
  102. return GNUNET_OK;
  103. }
  104. /**
  105. * Get the next hop for trail corresponding to trail_id
  106. * @param trail_id Trail id to be searched.
  107. * @return Next_hop if found
  108. * NULL If next hop not found.
  109. */
  110. struct GNUNET_PeerIdentity *
  111. GDS_ROUTING_get_next_hop (const struct GNUNET_HashCode trail_id,
  112. enum GDS_ROUTING_trail_direction trail_direction)
  113. {
  114. struct RoutingTrail *trail;
  115. trail = GNUNET_CONTAINER_multihashmap_get (routing_table, &trail_id);
  116. if (NULL == trail)
  117. {
  118. /* If a friend got disconnected and we removed all the entry from the
  119. routing table, then trail will be deleted and my identity will not know
  120. and when it tries to reach to that finger it fails. thats why
  121. assertion always fails in*/
  122. return NULL;
  123. }
  124. switch (trail_direction)
  125. {
  126. case GDS_ROUTING_SRC_TO_DEST:
  127. return &(trail->next_hop);
  128. case GDS_ROUTING_DEST_TO_SRC:
  129. return &(trail->prev_hop);
  130. }
  131. return NULL;
  132. }
  133. /**
  134. * Remove trail with trail_id
  135. * @param trail_id Trail id to be removed
  136. * @return #GNUNET_YES success
  137. * #GNUNET_NO if entry not found.
  138. */
  139. int
  140. GDS_ROUTING_remove_trail (const struct GNUNET_HashCode remove_trail_id)
  141. {
  142. struct RoutingTrail *remove_entry;
  143. remove_entry = GNUNET_CONTAINER_multihashmap_get (routing_table, &remove_trail_id);
  144. if (NULL == remove_entry)
  145. return GNUNET_NO;
  146. if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (routing_table,
  147. &remove_trail_id,
  148. remove_entry))
  149. {
  150. GNUNET_free (remove_entry);
  151. return GNUNET_YES;
  152. }
  153. return GNUNET_NO;
  154. }
  155. /**
  156. * Iterate over routing table and remove entries with value as part of any trail.
  157. *
  158. * @param cls closure
  159. * @param key current public key
  160. * @param value value in the hash map
  161. * @return #GNUNET_YES if we should continue to iterate,
  162. * #GNUNET_NO if not.
  163. */
  164. static int remove_matching_trails (void *cls,
  165. const struct GNUNET_HashCode *key,
  166. void *value)
  167. {
  168. struct RoutingTrail *remove_trail = value;
  169. struct GNUNET_PeerIdentity *disconnected_peer = cls;
  170. struct GNUNET_HashCode trail_id = *key;
  171. struct GNUNET_PeerIdentity my_identity;
  172. /* If disconnected_peer is next_hop, then send a trail teardown message through
  173. * prev_hop in direction from destination to source. */
  174. if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_trail->next_hop,
  175. disconnected_peer))
  176. {
  177. my_identity = GDS_NEIGHBOURS_get_my_id ();
  178. if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
  179. &remove_trail->prev_hop))
  180. {
  181. GDS_NEIGHBOURS_send_trail_teardown (&trail_id,
  182. GDS_ROUTING_DEST_TO_SRC,
  183. &remove_trail->prev_hop);
  184. }
  185. }
  186. /* If disconnected_peer is prev_hop, then send a trail teardown through
  187. * next_hop in direction from Source to Destination. */
  188. if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_trail->prev_hop,
  189. disconnected_peer))
  190. {
  191. my_identity = GDS_NEIGHBOURS_get_my_id ();
  192. if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
  193. &remove_trail->next_hop))
  194. {
  195. GDS_NEIGHBOURS_send_trail_teardown (&trail_id,
  196. GDS_ROUTING_SRC_TO_DEST,
  197. &remove_trail->next_hop);
  198. }
  199. }
  200. GNUNET_assert (GNUNET_YES ==
  201. GNUNET_CONTAINER_multihashmap_remove (routing_table,
  202. &trail_id,
  203. remove_trail));
  204. GNUNET_free (remove_trail);
  205. return GNUNET_YES;
  206. }
  207. #if 0
  208. /**
  209. * TEST FUNCTION
  210. * Remove after using.
  211. */
  212. void
  213. GDS_ROUTING_test_print (void)
  214. {
  215. struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
  216. struct RoutingTrail *trail;
  217. struct GNUNET_PeerIdentity print_peer;
  218. struct GNUNET_HashCode key_ret;
  219. int i;
  220. struct GNUNET_PeerIdentity my_identity = GDS_NEIGHBOURS_get_my_id();
  221. print_peer = my_identity;
  222. FPRINTF (stderr,_("\nSUPU ***PRINTING ROUTING TABLE ***** of =%s"),GNUNET_i2s(&print_peer));
  223. iter =GNUNET_CONTAINER_multihashmap_iterator_create (routing_table);
  224. for (i = 0; i < GNUNET_CONTAINER_multihashmap_size(routing_table); i++)
  225. {
  226. if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter,
  227. &key_ret,
  228. (const void **)&trail))
  229. {
  230. FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->trail_id = %s"),
  231. __FILE__, __func__,__LINE__, GNUNET_h2s(&trail->trail_id));
  232. memcpy (&print_peer, &trail->next_hop, sizeof (struct GNUNET_PeerIdentity));
  233. FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->next_hop = %s"),
  234. __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer));
  235. memcpy (&print_peer, &trail->prev_hop, sizeof (struct GNUNET_PeerIdentity));
  236. FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->prev_hop = %s"),
  237. __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer));
  238. }
  239. }
  240. }
  241. #endif
  242. /**
  243. * Remove every trail where peer is either next_hop or prev_hop. Also send a
  244. * trail teardown message in direction of hop which is not disconnected.
  245. * @param peer Peer identity. Trail containing this peer should be removed.
  246. */
  247. int
  248. GDS_ROUTING_remove_trail_by_peer (const struct GNUNET_PeerIdentity *peer)
  249. {
  250. int ret;
  251. /* No entries in my routing table. */
  252. if (0 == GNUNET_CONTAINER_multihashmap_size(routing_table))
  253. return GNUNET_YES;
  254. ret = GNUNET_CONTAINER_multihashmap_iterate (routing_table,
  255. &remove_matching_trails,
  256. (void *)peer);
  257. return ret;
  258. }
  259. /**
  260. * Add a new entry in routing table
  261. * @param new_trail_id
  262. * @param prev_hop
  263. * @param next_hop
  264. * @return #GNUNET_OK success
  265. * #GNUNET_SYSERR in case new_trail_id already exists in the network
  266. * but with different prev_hop/next_hop
  267. */
  268. int
  269. GDS_ROUTING_add (struct GNUNET_HashCode new_trail_id,
  270. struct GNUNET_PeerIdentity prev_hop,
  271. struct GNUNET_PeerIdentity next_hop)
  272. {
  273. struct RoutingTrail *new_entry;
  274. new_entry = GNUNET_new (struct RoutingTrail);
  275. new_entry->trail_id = new_trail_id;
  276. new_entry->next_hop = next_hop;
  277. new_entry->prev_hop = prev_hop;
  278. return GNUNET_CONTAINER_multihashmap_put (routing_table,
  279. &new_trail_id, new_entry,
  280. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
  281. }
  282. /**
  283. * Check if the size of routing table has crossed ROUTING_TABLE_THRESHOLD.
  284. * It means that I don't have any more space in my routing table and I can not
  285. * be part of any more trails till there is free space in my routing table.
  286. * @return #GNUNET_YES, if threshold crossed else #GNUNET_NO.
  287. */
  288. int
  289. GDS_ROUTING_threshold_reached (void)
  290. {
  291. return (GNUNET_CONTAINER_multihashmap_size(routing_table) >
  292. ROUTING_TABLE_THRESHOLD) ? GNUNET_YES:GNUNET_NO;
  293. }
  294. /**
  295. * Initialize routing subsystem.
  296. */
  297. void
  298. GDS_ROUTING_init (void)
  299. {
  300. routing_table = GNUNET_CONTAINER_multihashmap_create (ROUTING_TABLE_THRESHOLD * 4 / 3,
  301. GNUNET_NO);
  302. }
  303. /**
  304. * Shutdown routing subsystem.
  305. */
  306. void
  307. GDS_ROUTING_done (void)
  308. {
  309. GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (routing_table));
  310. GNUNET_CONTAINER_multihashmap_destroy (routing_table);
  311. }
  312. /* end of gnunet-service-xdht_routing.c */