aboutsummaryrefslogtreecommitdiff
path: root/src/dht/gnunet-service-wdht_routing.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dht/gnunet-service-wdht_routing.c')
-rw-r--r--src/dht/gnunet-service-wdht_routing.c363
1 files changed, 363 insertions, 0 deletions
diff --git a/src/dht/gnunet-service-wdht_routing.c b/src/dht/gnunet-service-wdht_routing.c
new file mode 100644
index 000000000..986eb11ac
--- /dev/null
+++ b/src/dht/gnunet-service-wdht_routing.c
@@ -0,0 +1,363 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 - 2014 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file dht/gnunet-service-xdht_routing.c
23 * @brief GNUnet DHT tracking of requests for routing replies
24 * @author Supriti Singh
25 */
26#include "platform.h"
27#include "gnunet-service-wdht_neighbours.h"
28#include "gnunet-service-wdht_routing.h"
29#include "gnunet-service-wdht.h"
30
31
32/**
33 * FIXME: Check if its better to store pointer to friend rather than storing
34 * peer identity next_hop or prev_hop.
35 * keep entries in destnation and source peer also. so when we send the trail
36 * teardown message then we don't know the source but if source gets the message
37 * then it shold remove that trail id from its finger table. But how does
38 * source know what is the desination finger ? It will whenevr contact a trail
39 * will do a lookup in routing table and if no trail id present the remove
40 * that trail of the finger and if only one trail then remove the finger.
41 * because of this use case of trail teardown I think trail compression
42 * and trail teardown should not be merged.
43 * 2. store a pointer to friendInfo in place o peer identity.
44 */
45/**
46 * Maximum number of entries in routing table.
47 */
48#define ROUTING_TABLE_THRESHOLD 80000
49
50/**
51 * FIXME: Store friend pointer instead of peer identifier.
52 * Routing table entry .
53 */
54struct RoutingTrail
55{
56 /**
57 * Global Unique identifier of the trail.
58 */
59 struct GNUNET_HashCode trail_id;
60
61 /**
62 * The peer to which this request should be passed to.
63 */
64 struct GNUNET_PeerIdentity next_hop;
65
66 /**
67 * Peer just before next hop in the trail.
68 */
69 struct GNUNET_PeerIdentity prev_hop;
70};
71
72/**
73 * Routing table of the peer
74 */
75static struct GNUNET_CONTAINER_MultiHashMap *routing_table;
76
77/**
78 * Update the prev. hop of the trail. Call made by trail compression where
79 * if you are the first friend now in the trail then you need to update
80 * your prev. hop.
81 * @param trail_id
82 * @return #GNUNET_OK success
83 * #GNUNET_SYSERR in case no matching entry found in routing table.
84 */
85int
86GDS_ROUTING_update_trail_prev_hop (const struct GNUNET_HashCode trail_id,
87 struct GNUNET_PeerIdentity prev_hop)
88{
89 struct RoutingTrail *trail;
90
91 trail = GNUNET_CONTAINER_multihashmap_get (routing_table, &trail_id);
92
93 if (NULL == trail)
94 return GNUNET_SYSERR;
95
96 trail->prev_hop = prev_hop;
97 return GNUNET_OK;
98}
99
100/**
101 * Update the next hop of the trail. Call made by trail compression where
102 * if you are source of the trail and now you have a new first friend, then
103 * you should update the trail.
104 * @param trail_id
105 * @return #GNUNET_OK success
106 * #GNUNET_SYSERR in case no matching entry found in routing table.
107 */
108int
109GDS_ROUTING_update_trail_next_hop (const struct GNUNET_HashCode trail_id,
110 struct GNUNET_PeerIdentity next_hop)
111{
112 struct RoutingTrail *trail;
113
114 trail = GNUNET_CONTAINER_multihashmap_get (routing_table, &trail_id);
115
116 if (NULL == trail)
117
118 return GNUNET_SYSERR;
119
120 trail->next_hop = next_hop;
121 return GNUNET_OK;
122}
123
124/**
125 * Get the next hop for trail corresponding to trail_id
126 * @param trail_id Trail id to be searched.
127 * @return Next_hop if found
128 * NULL If next hop not found.
129 */
130struct GNUNET_PeerIdentity *
131GDS_ROUTING_get_next_hop (const struct GNUNET_HashCode trail_id,
132 enum GDS_ROUTING_trail_direction trail_direction)
133{
134 struct RoutingTrail *trail;
135
136 trail = GNUNET_CONTAINER_multihashmap_get (routing_table, &trail_id);
137 if (NULL == trail)
138 {
139 /* If a friend got disconnected and we removed all the entry from the
140 routing table, then trail will be deleted and my identity will not know
141 and when it tries to reach to that finger it fails. thats why
142 assertion always fails in*/
143 return NULL;
144 }
145 switch (trail_direction)
146 {
147 case GDS_ROUTING_SRC_TO_DEST:
148 return &(trail->next_hop);
149 case GDS_ROUTING_DEST_TO_SRC:
150 return &(trail->prev_hop);
151 }
152 return NULL;
153}
154
155
156/**
157 * Remove trail with trail_id
158 * @param trail_id Trail id to be removed
159 * @return #GNUNET_YES success
160 * #GNUNET_NO if entry not found.
161 */
162int
163GDS_ROUTING_remove_trail (const struct GNUNET_HashCode remove_trail_id)
164{
165 struct RoutingTrail *remove_entry;
166
167 remove_entry = GNUNET_CONTAINER_multihashmap_get (routing_table, &remove_trail_id);
168 if (NULL == remove_entry)
169 return GNUNET_NO;
170
171 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (routing_table,
172 &remove_trail_id,
173 remove_entry))
174 {
175 GNUNET_free (remove_entry);
176 return GNUNET_YES;
177 }
178
179 return GNUNET_NO;
180}
181
182
183/**
184 * Iterate over routing table and remove entries with value as part of any trail.
185 *
186 * @param cls closure
187 * @param key current public key
188 * @param value value in the hash map
189 * @return #GNUNET_YES if we should continue to iterate,
190 * #GNUNET_NO if not.
191 */
192static int remove_matching_trails (void *cls,
193 const struct GNUNET_HashCode *key,
194 void *value)
195{
196 struct RoutingTrail *remove_trail = value;
197 struct GNUNET_PeerIdentity *disconnected_peer = cls;
198 struct GNUNET_HashCode trail_id = *key;
199 struct GNUNET_PeerIdentity my_identity;
200
201 /* If disconnected_peer is next_hop, then send a trail teardown message through
202 * prev_hop in direction from destination to source. */
203 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_trail->next_hop,
204 disconnected_peer))
205 {
206 my_identity = GDS_NEIGHBOURS_get_my_id ();
207 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
208 &remove_trail->prev_hop))
209 {
210 GDS_NEIGHBOURS_send_trail_teardown (&trail_id,
211 GDS_ROUTING_DEST_TO_SRC,
212 &remove_trail->prev_hop);
213 }
214 }
215
216 /* If disconnected_peer is prev_hop, then send a trail teardown through
217 * next_hop in direction from Source to Destination. */
218 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&remove_trail->prev_hop,
219 disconnected_peer))
220 {
221 my_identity = GDS_NEIGHBOURS_get_my_id ();
222
223 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&my_identity,
224 &remove_trail->next_hop))
225 {
226 GDS_NEIGHBOURS_send_trail_teardown (&trail_id,
227 GDS_ROUTING_SRC_TO_DEST,
228 &remove_trail->next_hop);
229 }
230 }
231
232 GNUNET_assert (GNUNET_YES ==
233 GNUNET_CONTAINER_multihashmap_remove (routing_table,
234 &trail_id,
235 remove_trail));
236 GNUNET_free (remove_trail);
237 return GNUNET_YES;
238}
239
240#if 0
241/**
242 * TEST FUNCTION
243 * Remove after using.
244 */
245void
246GDS_ROUTING_test_print (void)
247{
248 struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
249 struct RoutingTrail *trail;
250 struct GNUNET_PeerIdentity print_peer;
251 struct GNUNET_HashCode key_ret;
252 int i;
253
254 struct GNUNET_PeerIdentity my_identity = GDS_NEIGHBOURS_get_my_id();
255 print_peer = my_identity;
256 FPRINTF (stderr,_("\nSUPU ***PRINTING ROUTING TABLE ***** of =%s"),GNUNET_i2s(&print_peer));
257 iter =GNUNET_CONTAINER_multihashmap_iterator_create (routing_table);
258 for (i = 0; i < GNUNET_CONTAINER_multihashmap_size(routing_table); i++)
259 {
260 if(GNUNET_YES == GNUNET_CONTAINER_multihashmap_iterator_next (iter,
261 &key_ret,
262 (const void **)&trail))
263 {
264 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->trail_id = %s"),
265 __FILE__, __func__,__LINE__, GNUNET_h2s(&trail->trail_id));
266 memcpy (&print_peer, &trail->next_hop, sizeof (struct GNUNET_PeerIdentity));
267 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->next_hop = %s"),
268 __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer));
269 memcpy (&print_peer, &trail->prev_hop, sizeof (struct GNUNET_PeerIdentity));
270 FPRINTF (stderr,_("\nSUPU %s, %s, %d, trail->prev_hop = %s"),
271 __FILE__, __func__,__LINE__, GNUNET_i2s(&print_peer));
272 }
273 }
274}
275#endif
276
277/**
278 * Remove every trail where peer is either next_hop or prev_hop. Also send a
279 * trail teardown message in direction of hop which is not disconnected.
280 * @param peer Peer identity. Trail containing this peer should be removed.
281 */
282int
283GDS_ROUTING_remove_trail_by_peer (const struct GNUNET_PeerIdentity *peer)
284{
285 int ret;
286
287
288 /* No entries in my routing table. */
289 if (0 == GNUNET_CONTAINER_multihashmap_size(routing_table))
290 return GNUNET_YES;
291
292 ret = GNUNET_CONTAINER_multihashmap_iterate (routing_table,
293 &remove_matching_trails,
294 (void *)peer);
295 return ret;
296}
297
298
299/**
300 * Add a new entry in routing table
301 * @param new_trail_id
302 * @param prev_hop
303 * @param next_hop
304 * @return #GNUNET_OK success
305 * #GNUNET_SYSERR in case new_trail_id already exists in the network
306 * but with different prev_hop/next_hop
307 */
308int
309GDS_ROUTING_add (struct GNUNET_HashCode new_trail_id,
310 struct GNUNET_PeerIdentity prev_hop,
311 struct GNUNET_PeerIdentity next_hop)
312{
313 struct RoutingTrail *new_entry;
314
315 new_entry = GNUNET_new (struct RoutingTrail);
316 new_entry->trail_id = new_trail_id;
317 new_entry->next_hop = next_hop;
318 new_entry->prev_hop = prev_hop;
319
320
321 return GNUNET_CONTAINER_multihashmap_put (routing_table,
322 &new_trail_id, new_entry,
323 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
324
325}
326
327
328/**
329 * Check if the size of routing table has crossed ROUTING_TABLE_THRESHOLD.
330 * It means that I don't have any more space in my routing table and I can not
331 * be part of any more trails till there is free space in my routing table.
332 * @return #GNUNET_YES, if threshold crossed else #GNUNET_NO.
333 */
334int
335GDS_ROUTING_threshold_reached (void)
336{
337 return (GNUNET_CONTAINER_multihashmap_size(routing_table) >
338 ROUTING_TABLE_THRESHOLD) ? GNUNET_YES:GNUNET_NO;
339}
340
341
342/**
343 * Initialize routing subsystem.
344 */
345void
346GDS_ROUTING_init (void)
347{
348 routing_table = GNUNET_CONTAINER_multihashmap_create (ROUTING_TABLE_THRESHOLD * 4 / 3,
349 GNUNET_NO);
350}
351
352
353/**
354 * Shutdown routing subsystem.
355 */
356void
357GDS_ROUTING_done (void)
358{
359 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (routing_table));
360 GNUNET_CONTAINER_multihashmap_destroy (routing_table);
361}
362
363/* end of gnunet-service-xdht_routing.c */