diff options
Diffstat (limited to 'src/dht/gnunet-service-xdht_routing.c')
-rw-r--r-- | src/dht/gnunet-service-xdht_routing.c | 268 |
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 | */ |
77 | static struct GNUNET_CONTAINER_MultiPeerMap *routing_table; | 72 | static 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 | */ |
88 | static int | 84 | static int |
89 | remove_routing_entry (void *cls, | 85 | get_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 | */ |
118 | int | 119 | int |
119 | get_next_hop (void *cls, const struct GNUNET_PeerIdentity *key, void *value) | 120 | GDS_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 | */ | ||
157 | struct GNUNET_PeerIdentity * | ||
158 | GDS_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 | */ | ||
229 | static int | ||
230 | remove_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 | */ |
177 | void | 256 | void |
178 | GDS_ROUTING_remove_entry (const struct GNUNET_PeerIdentity *peer) | 257 | GDS_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 | */ |
193 | int | 276 | int |
194 | GDS_ROUTING_remove_trail (struct GNUNET_PeerIdentity *source_peer, | 277 | GDS_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 | */ | ||
208 | struct GNUNET_PeerIdentity * | ||
209 | GDS_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 | */ |
233 | int | 311 | int |
234 | GDS_ROUTING_check_threshold () | 312 | GDS_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 () | |||
245 | void | 322 | void |
246 | GDS_ROUTING_init (void) | 323 | GDS_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 | */ | ||
332 | void | ||
333 | GDS_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 | */ |
255 | void | 363 | void |