aboutsummaryrefslogtreecommitdiff
path: root/src/dht/gnunet-service-xdht_routing.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dht/gnunet-service-xdht_routing.c')
-rw-r--r--src/dht/gnunet-service-xdht_routing.c268
1 files changed, 188 insertions, 80 deletions
diff --git a/src/dht/gnunet-service-xdht_routing.c b/src/dht/gnunet-service-xdht_routing.c
index 3601a4186..7bf96e9d0 100644
--- a/src/dht/gnunet-service-xdht_routing.c
+++ b/src/dht/gnunet-service-xdht_routing.c
@@ -34,11 +34,6 @@
34 3. do we need next_hop to uniquely identify a trail in remove_trail. */ 34 3. do we need next_hop to uniquely identify a trail in remove_trail. */
35 35
36/** 36/**
37 * Number of requests we track at most (for routing replies).
38 */
39#define DHT_MAX_RECENT (1024 * 16)
40
41/**
42 * Maximum number of entries in routing table. 37 * Maximum number of entries in routing table.
43 */ 38 */
44#define ROUTING_TABLE_THRESHOLD 64 39#define ROUTING_TABLE_THRESHOLD 64
@@ -76,59 +71,76 @@ struct RoutingTrail
76 */ 71 */
77static struct GNUNET_CONTAINER_MultiPeerMap *routing_table; 72static struct GNUNET_CONTAINER_MultiPeerMap *routing_table;
78 73
74
79/** 75/**
80 * Iterate over routing table and remove entries for which peer is a part. 76 * Get next hop from the trail with source peer, destination peer and next hop
81 * @param cls closure 77 * same as the argument to this function.
82 * @param key current public key 78 * @param source_peer Source peer of the trail.
83 * @param value value in the hash map 79 * @param destination_peer Destination peer of the trail.
84 * @return #GNUNET_YES if we should continue to 80 * @param prev_hop Previous hop of the trail.
85 * iterate, 81 * @return #GNUNET_YES if we found the matching trail.
86 * #GNUNET_NO if not. 82 * #GNUNET_NO if we found no matching trail.
87 */ 83 */
88static int 84static int
89remove_routing_entry (void *cls, 85get_next_hop (struct RoutingTrail *trail,
90 const struct GNUNET_PeerIdentity *key, 86 struct GNUNET_PeerIdentity *source_peer,
91 void *value) 87 struct GNUNET_PeerIdentity *destination_peer,
88 const struct GNUNET_PeerIdentity *prev_hop)
92{ 89{
93 struct RoutingTrail *remove_entry = value; 90 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(trail->source),source_peer))
94 const struct GNUNET_PeerIdentity *disconnected_peer = cls;
95
96 if ((0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_entry->source), disconnected_peer)) ||
97 (0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_entry->destination), disconnected_peer)) ||
98 (0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_entry->next_hop), disconnected_peer)) ||
99 (0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_entry->prev_hop), disconnected_peer)))
100 { 91 {
101 GNUNET_assert (GNUNET_YES == 92 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(trail->prev_hop),prev_hop))
102 GNUNET_CONTAINER_multipeermap_remove (routing_table, 93 {
103 key, 94 return GNUNET_YES;
104 remove_entry)); 95 }
96 else
97 return GNUNET_NO;
105 } 98 }
106 return GNUNET_YES; 99 return GNUNET_NO;
107} 100}
108 101
109 102
110/** 103/**
111 * Iterate over multiple entries for same destination value and get 104 * FIXME: How to ensure that with only 3 fields also we have a unique trail.
112 * the correct next hop. 105 * in case of redundant routes we can have different next hop.
113 * @param cls struct RoutingTrail 106 * in that case we have to call this function on each entry of routing table
114 * @param key Destination identity 107 * and from multiple next hop we return one. Here also we are going to return one.
115 * @param value struct RoutingTrail 108 * URGENT.
116 * @return #GNUNET_YES to continue looking, #GNUNET_NO if we found the next hop 109 * Assumption - there can be only on one trail with all these fields. But if
110 * we consider only 3 fields then it is possible that next hop is differet.
111 * Update prev_hop field to source_peer. Trail from source peer to destination
112 * peer is compressed such that I am the first friend in the trail.
113 * @param source_peer Source of the trail.
114 * @param destination_peer Destination of the trail.
115 * @param prev_hop Peer before me in the trail.
116 * @return #GNUNET_YES trail is updated.
117 * #GNUNET_NO, trail not found.
117 */ 118 */
118int 119int
119get_next_hop (void *cls, const struct GNUNET_PeerIdentity *key, void *value) 120GDS_ROUTING_trail_update (struct GNUNET_PeerIdentity *source_peer,
121 struct GNUNET_PeerIdentity *destination_peer,
122 struct GNUNET_PeerIdentity *prev_hop)
120{ 123{
121 /* Here you should match if source, prev hop matches if yes then send 124 /* 1. find the trail corresponding to these values.
122 GNUNET_NO as you don't need to check more entries. */ 125 2. update the prev hop to source peer. */
123 struct RoutingTrail *request = cls; 126 struct RoutingTrail *trail;
124 struct RoutingTrail *existing_entry = (struct RoutingTrail *)value; 127 struct GNUNET_CONTAINER_MultiPeerMapIterator *iterator;
128 int i;
125 129
126 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(request->source), &(existing_entry->source))) 130 iterator = GNUNET_CONTAINER_multipeermap_iterator_create (routing_table);
131 for (i = 0; i< GNUNET_CONTAINER_multipeermap_size(routing_table); i++)
127 { 132 {
128 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(request->prev_hop), &(existing_entry->prev_hop))) 133 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iterator, NULL,
134 (const void **)&trail))
129 { 135 {
130 memcpy (&(request->next_hop), &(existing_entry->next_hop), sizeof (struct GNUNET_PeerIdentity)); 136 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(trail->destination), destination_peer))
131 return GNUNET_YES; 137 {
138 if (GNUNET_YES == get_next_hop (trail, source_peer, destination_peer, prev_hop))
139 {
140 memcpy (&(trail->prev_hop), source_peer, sizeof (struct GNUNET_PeerIdentity));
141 return GNUNET_YES;
142 }
143 }
132 } 144 }
133 } 145 }
134 return GNUNET_NO; 146 return GNUNET_NO;
@@ -136,6 +148,42 @@ get_next_hop (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
136 148
137 149
138/** 150/**
151 * Find the next hop to send packet to.
152 * @param source_peer Source of the trail.
153 * @param destination_peer Destination of the trail.
154 * @param prev_hop Previous hop in the trail.
155 * @return Next hop in the trail from source to destination.
156 */
157struct GNUNET_PeerIdentity *
158GDS_ROUTING_search (struct GNUNET_PeerIdentity *source_peer,
159 struct GNUNET_PeerIdentity *destination_peer,
160 const struct GNUNET_PeerIdentity *prev_hop)
161{
162 struct RoutingTrail *trail;
163 struct GNUNET_CONTAINER_MultiPeerMapIterator *iterator;
164 int i;
165
166 iterator = GNUNET_CONTAINER_multipeermap_iterator_create (routing_table);
167 for (i = 0; i< GNUNET_CONTAINER_multipeermap_size(routing_table); i++)
168 {
169 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iterator, NULL,
170 (const void **)&trail))
171 {
172 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(trail->destination), destination_peer))
173 {
174 if (GNUNET_YES == get_next_hop (trail, source_peer, destination_peer, prev_hop))
175 {
176 return &(trail->next_hop);
177 }
178 }
179 }
180 }
181 GNUNET_CONTAINER_multipeermap_iterator_destroy (iterator);
182 return NULL;
183}
184
185
186/**
139 * Add a new entry to our routing table. 187 * Add a new entry to our routing table.
140 * @param source peer Source of the trail. 188 * @param source peer Source of the trail.
141 * @param destintation Destination of the trail. 189 * @param destintation Destination of the trail.
@@ -171,71 +219,100 @@ GDS_ROUTING_add (const struct GNUNET_PeerIdentity *source,
171 219
172/** 220/**
173 * Iterate over routing table and remove entries for which peer is a part. 221 * Iterate over routing table and remove entries for which peer is a part.
174 * @param peer 222 * @param cls closure
175 * @return 223 * @param key current public key
224 * @param value value in the hash map
225 * @return #GNUNET_YES if we should continue to
226 * iterate,
227 * #GNUNET_NO if not.
228 */
229static int
230remove_routing_entry (void *cls,
231 const struct GNUNET_PeerIdentity *key,
232 void *value)
233{
234 struct RoutingTrail *remove_entry = value;
235 const struct GNUNET_PeerIdentity *disconnected_peer = cls;
236
237 if ((0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_entry->source), disconnected_peer)) ||
238 (0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_entry->destination), disconnected_peer)) ||
239 (0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_entry->next_hop), disconnected_peer)) ||
240 (0 == GNUNET_CRYPTO_cmp_peer_identity (&(remove_entry->prev_hop), disconnected_peer)))
241 {
242 GNUNET_assert (GNUNET_YES ==
243 GNUNET_CONTAINER_multipeermap_remove (routing_table,
244 key,
245 remove_entry));
246 }
247 return GNUNET_YES;
248}
249
250
251/**
252 * FIXME: add a return value.
253 * Iterate over routing table and remove all entries for which peer is a part.
254 * @param peer Peer to be searched for in the trail to remove that trail.
176 */ 255 */
177void 256void
178GDS_ROUTING_remove_entry (const struct GNUNET_PeerIdentity *peer) 257GDS_ROUTING_remove_entry (const struct GNUNET_PeerIdentity *peer)
179{ 258{
180 GNUNET_CONTAINER_multipeermap_iterate (routing_table, &remove_routing_entry, 259 GNUNET_CONTAINER_multipeermap_iterate (routing_table, &remove_routing_entry,
181 (void *)peer); 260 (void *)peer);
182} 261}
183 262
184 263
185/** FIXME:TODO URGNET Need to understand if we need next hop to uniquely identify an entry 264/**
186 * in routing table or not. 265 * In response to trail teardown message, remove the trail with source peer,
187 * Remove the trail as result of trail tear down message. 266 * destination peer and next hop same as the argument to this function.
267 * Assumption - there can be only one possible trail with these 4 values.
188 * @param source_peer Source of the trail. 268 * @param source_peer Source of the trail.
189 * @param destination_peer Destination of the trail. 269 * @param destination_peer Destination of the trail.
190 * @param next_hop Next hop 270 * @param next_hop Next hop
191 * @param prev_hop Previous hop. 271 * @param prev_hop Previous hop.
272 * @return #GNUNET_YES Matching trail deleted from routing table.
273 * #GNUNET_NO No matching trail found.
274 *
192 */ 275 */
193int 276int
194GDS_ROUTING_remove_trail (struct GNUNET_PeerIdentity *source_peer, 277GDS_ROUTING_remove_trail (struct GNUNET_PeerIdentity *source_peer,
195 struct GNUNET_PeerIdentity *destination_peer, 278 struct GNUNET_PeerIdentity *destination_peer,
196 const struct GNUNET_PeerIdentity *prev_hop) 279 const struct GNUNET_PeerIdentity *prev_hop)
197{ 280{
281 struct RoutingTrail *trail;
282 struct GNUNET_CONTAINER_MultiPeerMapIterator *iterator;
283 int i;
284
285 iterator = GNUNET_CONTAINER_multipeermap_iterator_create (routing_table);
286 for (i = 0; i< GNUNET_CONTAINER_multipeermap_size(routing_table); i++)
287 {
288 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iterator, NULL,
289 (const void **)&trail))
290 {
291 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&(trail->destination), destination_peer))
292 {
293 GNUNET_assert (GNUNET_YES ==
294 GNUNET_CONTAINER_multipeermap_remove (routing_table,
295 &(trail->destination),
296 trail));
297 return GNUNET_YES;
298 }
299 }
300 }
301 GNUNET_CONTAINER_multipeermap_iterator_destroy (iterator);
198 return GNUNET_NO; 302 return GNUNET_NO;
199} 303}
200 304
201/**
202 * Find the next hop to send packet to.
203 * @param source_peer Source of the trail.
204 * @param destination_peer Destination of the trail.
205 * @param prev_hop Previous hop in the trail.
206 * @return Next hop in the trail from source to destination.
207 */
208struct GNUNET_PeerIdentity *
209GDS_ROUTING_search(struct GNUNET_PeerIdentity *source_peer,
210 struct GNUNET_PeerIdentity *destination_peer,
211 const struct GNUNET_PeerIdentity *prev_hop)
212{
213 struct RoutingTrail *trail;
214 trail = GNUNET_malloc (sizeof (struct RoutingTrail));
215 memcpy (&(trail->destination), destination_peer, sizeof (struct GNUNET_PeerIdentity));
216 memcpy (&(trail->source), source_peer, sizeof (struct GNUNET_PeerIdentity));
217 memcpy (&(trail->prev_hop), prev_hop, sizeof (struct GNUNET_PeerIdentity));
218
219 GNUNET_CONTAINER_multipeermap_get_multiple (routing_table, destination_peer,
220 get_next_hop, trail);
221 if(trail != NULL)
222 return &(trail->next_hop);
223 else
224 return NULL;
225}
226 305
227 306
228/** 307/**
229 * FIXME:URGENT:Better name.
230 * Check if the size of routing table has crossed threshold. 308 * Check if the size of routing table has crossed threshold.
231 * @return #GNUNET_YES, if threshold crossed else #GNUNET_NO. 309 * @return #GNUNET_YES, if threshold crossed else #GNUNET_NO.
232 */ 310 */
233int 311int
234GDS_ROUTING_check_threshold () 312GDS_ROUTING_check_threshold ()
235{ 313{
236 int ret; 314 return (GNUNET_CONTAINER_multipeermap_size(routing_table) > ROUTING_TABLE_THRESHOLD) ?
237 ret = (GNUNET_CONTAINER_multipeermap_size(routing_table) > ROUTING_TABLE_THRESHOLD) ? GNUNET_YES:GNUNET_NO; 315 GNUNET_YES:GNUNET_NO;
238 return ret;
239} 316}
240 317
241 318
@@ -245,11 +322,42 @@ GDS_ROUTING_check_threshold ()
245void 322void
246GDS_ROUTING_init (void) 323GDS_ROUTING_init (void)
247{ 324{
248 routing_table = GNUNET_CONTAINER_multipeermap_create (DHT_MAX_RECENT * 4 / 3, GNUNET_NO); 325 routing_table = GNUNET_CONTAINER_multipeermap_create (ROUTING_TABLE_THRESHOLD * 4 / 3,
326 GNUNET_NO);
249} 327}
250 328
251
252/** 329/**
330 * ONLY FOR TESTING.
331 */
332void
333GDS_ROUTING_print (void)
334{
335 struct RoutingTrail *trail;
336 struct GNUNET_CONTAINER_MultiPeerMapIterator *iterator;
337 int i;
338
339 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing table entries \n");
340 iterator = GNUNET_CONTAINER_multipeermap_iterator_create (routing_table);
341 for (i = 0; i< GNUNET_CONTAINER_multipeermap_size(routing_table); i++)
342 {
343 if(GNUNET_YES == GNUNET_CONTAINER_multipeermap_iterator_next (iterator, NULL,
344 (const void **)&trail))
345 {
346 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing trail source \n", GNUNET_i2s (&(trail->source)));
347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing trail source \n", GNUNET_i2s (&(trail->destination)));
348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing trail source \n", GNUNET_i2s (&(trail->next_hop)));
349 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Routing trail source \n", GNUNET_i2s (&(trail->prev_hop)));
350 }
351 }
352
353}
354/**
355 * FIXME: here you can have routing table with size 0, only when you delete
356 * the entries correctly. Possible scenarios where we delete the entries are
357 * 1. when one of my friend gets disconnected then I remove any trail (does not
358 * matter if that friend is source, destination, next hop or previous hop).
359 * 2. if I get a trail teardown message then I remove the entry.
360 * Is there any other case that I may have missed?
253 * Shutdown routing subsystem. 361 * Shutdown routing subsystem.
254 */ 362 */
255void 363void