aboutsummaryrefslogtreecommitdiff
path: root/src/dht/gnunet-service-dht_routing.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dht/gnunet-service-dht_routing.c')
-rw-r--r--src/dht/gnunet-service-dht_routing.c389
1 files changed, 198 insertions, 191 deletions
diff --git a/src/dht/gnunet-service-dht_routing.c b/src/dht/gnunet-service-dht_routing.c
index 99c6b5e4f..3454c1acb 100644
--- a/src/dht/gnunet-service-dht_routing.c
+++ b/src/dht/gnunet-service-dht_routing.c
@@ -39,7 +39,8 @@
39 * Information we keep about all recent GET requests 39 * Information we keep about all recent GET requests
40 * so that we can route replies. 40 * so that we can route replies.
41 */ 41 */
42struct RecentRequest { 42struct RecentRequest
43{
43 /** 44 /**
44 * The peer this request was received from. 45 * The peer this request was received from.
45 */ 46 */
@@ -97,7 +98,8 @@ static struct GNUNET_CONTAINER_MultiHashMap *recent_map;
97/** 98/**
98 * Closure for the 'process' function. 99 * Closure for the 'process' function.
99 */ 100 */
100struct ProcessContext { 101struct ProcessContext
102{
101 /** 103 /**
102 * Path of the original PUT 104 * Path of the original PUT
103 */ 105 */
@@ -150,9 +152,9 @@ struct ProcessContext {
150 * #GNUNET_SYSERR if the result is malformed or type unsupported 152 * #GNUNET_SYSERR if the result is malformed or type unsupported
151 */ 153 */
152static int 154static int
153process(void *cls, 155process (void *cls,
154 const struct GNUNET_HashCode *key, 156 const struct GNUNET_HashCode *key,
155 void *value) 157 void *value)
156{ 158{
157 struct ProcessContext *pc = cls; 159 struct ProcessContext *pc = cls;
158 struct RecentRequest *rr = value; 160 struct RecentRequest *rr = value;
@@ -167,106 +169,110 @@ process(void *cls,
167 return GNUNET_OK; /* type missmatch */ 169 return GNUNET_OK; /* type missmatch */
168 170
169 if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE)) 171 if (0 != (rr->options & GNUNET_DHT_RO_RECORD_ROUTE))
170 { 172 {
171 gpl = pc->get_path_length; 173 gpl = pc->get_path_length;
172 ppl = pc->put_path_length; 174 ppl = pc->put_path_length;
173 } 175 }
174 else 176 else
175 { 177 {
176 gpl = 0; 178 gpl = 0;
177 ppl = 0; 179 ppl = 0;
178 } 180 }
179 if ((0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) && 181 if ((0 != (rr->options & GNUNET_DHT_RO_FIND_PEER)) &&
180 (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO)) 182 (pc->type == GNUNET_BLOCK_TYPE_DHT_HELLO))
181 { 183 {
182 /* key may not match HELLO, which is OK since 184 /* key may not match HELLO, which is OK since
183 * the search is approximate. Still, the evaluation 185 * the search is approximate. Still, the evaluation
184 * would fail since the match is not exact. So 186 * would fail since the match is not exact. So
185 * we fake it by changing the key to the actual PID ... */ 187 * we fake it by changing the key to the actual PID ... */
186 GNUNET_BLOCK_get_key(GDS_block_context, 188 GNUNET_BLOCK_get_key (GDS_block_context,
187 GNUNET_BLOCK_TYPE_DHT_HELLO, 189 GNUNET_BLOCK_TYPE_DHT_HELLO,
188 pc->data, 190 pc->data,
189 pc->data_size, 191 pc->data_size,
190 &hc); 192 &hc);
191 eval_key = &hc; 193 eval_key = &hc;
192 } 194 }
193 else 195 else
194 { 196 {
195 eval_key = key; 197 eval_key = key;
196 } 198 }
197 eval 199 eval
198 = GNUNET_BLOCK_evaluate(GDS_block_context, 200 = GNUNET_BLOCK_evaluate (GDS_block_context,
199 pc->type, 201 pc->type,
200 rr->bg, 202 rr->bg,
201 GNUNET_BLOCK_EO_NONE, 203 GNUNET_BLOCK_EO_NONE,
202 eval_key, 204 eval_key,
203 rr->xquery, 205 rr->xquery,
204 rr->xquery_size, 206 rr->xquery_size,
205 pc->data, 207 pc->data,
206 pc->data_size); 208 pc->data_size);
207 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, 209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
208 "Result for %s of type %d was evaluated as %d\n", 210 "Result for %s of type %d was evaluated as %d\n",
209 GNUNET_h2s(key), 211 GNUNET_h2s (key),
210 pc->type, 212 pc->type,
211 eval); 213 eval);
212 switch (eval) 214 switch (eval)
213 { 215 {
214 case GNUNET_BLOCK_EVALUATION_OK_MORE: 216 case GNUNET_BLOCK_EVALUATION_OK_MORE:
215 case GNUNET_BLOCK_EVALUATION_OK_LAST: 217 case GNUNET_BLOCK_EVALUATION_OK_LAST:
216 GNUNET_STATISTICS_update(GDS_stats, 218 GNUNET_STATISTICS_update (GDS_stats,
217 gettext_noop 219 gettext_noop
218 ("# Good REPLIES matched against routing table"), 220 ("# Good REPLIES matched against routing table"),
219 1, GNUNET_NO); 221 1, GNUNET_NO);
220 GDS_NEIGHBOURS_handle_reply(&rr->peer, 222 GDS_NEIGHBOURS_handle_reply (&rr->peer,
221 pc->type, 223 pc->type,
222 pc->expiration_time, 224 pc->expiration_time,
223 key, 225 key,
224 ppl, pc->put_path, 226 ppl, pc->put_path,
225 gpl, pc->get_path, 227 gpl, pc->get_path,
226 pc->data, 228 pc->data,
227 pc->data_size); 229 pc->data_size);
228 break; 230 break;
229 231
230 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE: 232 case GNUNET_BLOCK_EVALUATION_OK_DUPLICATE:
231 GNUNET_STATISTICS_update(GDS_stats, 233 GNUNET_STATISTICS_update (GDS_stats,
232 gettext_noop 234 gettext_noop
233 ("# Duplicate REPLIES matched against routing table"), 235 (
234 1, GNUNET_NO); 236 "# Duplicate REPLIES matched against routing table"),
235 return GNUNET_OK; 237 1, GNUNET_NO);
236 238 return GNUNET_OK;
237 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID: 239
238 GNUNET_STATISTICS_update(GDS_stats, 240 case GNUNET_BLOCK_EVALUATION_RESULT_INVALID:
239 gettext_noop 241 GNUNET_STATISTICS_update (GDS_stats,
240 ("# Invalid REPLIES matched against routing table"), 242 gettext_noop
241 1, GNUNET_NO); 243 (
242 return GNUNET_SYSERR; 244 "# Invalid REPLIES matched against routing table"),
243 245 1, GNUNET_NO);
244 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT: 246 return GNUNET_SYSERR;
245 GNUNET_STATISTICS_update(GDS_stats, 247
246 gettext_noop 248 case GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT:
247 ("# Irrelevant REPLIES matched against routing table"), 249 GNUNET_STATISTICS_update (GDS_stats,
248 1, GNUNET_NO); 250 gettext_noop
249 return GNUNET_OK; 251 (
250 252 "# Irrelevant REPLIES matched against routing table"),
251 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID: 253 1, GNUNET_NO);
252 GNUNET_break(0); 254 return GNUNET_OK;
253 return GNUNET_OK; 255
254 256 case GNUNET_BLOCK_EVALUATION_REQUEST_VALID:
255 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID: 257 GNUNET_break (0);
256 GNUNET_break(0); 258 return GNUNET_OK;
257 return GNUNET_OK; 259
258 260 case GNUNET_BLOCK_EVALUATION_REQUEST_INVALID:
259 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED: 261 GNUNET_break (0);
260 GNUNET_STATISTICS_update(GDS_stats, 262 return GNUNET_OK;
261 gettext_noop 263
262 ("# Unsupported REPLIES matched against routing table"), 264 case GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED:
263 1, GNUNET_NO); 265 GNUNET_STATISTICS_update (GDS_stats,
264 return GNUNET_SYSERR; 266 gettext_noop
265 267 (
266 default: 268 "# Unsupported REPLIES matched against routing table"),
267 GNUNET_break(0); 269 1, GNUNET_NO);
268 return GNUNET_SYSERR; 270 return GNUNET_SYSERR;
269 } 271
272 default:
273 GNUNET_break (0);
274 return GNUNET_SYSERR;
275 }
270 return GNUNET_OK; 276 return GNUNET_OK;
271} 277}
272 278
@@ -289,15 +295,15 @@ process(void *cls,
289 * @param data_size number of bytes in data 295 * @param data_size number of bytes in data
290 */ 296 */
291void 297void
292GDS_ROUTING_process(enum GNUNET_BLOCK_Type type, 298GDS_ROUTING_process (enum GNUNET_BLOCK_Type type,
293 struct GNUNET_TIME_Absolute expiration_time, 299 struct GNUNET_TIME_Absolute expiration_time,
294 const struct GNUNET_HashCode *key, 300 const struct GNUNET_HashCode *key,
295 unsigned int put_path_length, 301 unsigned int put_path_length,
296 const struct GNUNET_PeerIdentity *put_path, 302 const struct GNUNET_PeerIdentity *put_path,
297 unsigned int get_path_length, 303 unsigned int get_path_length,
298 const struct GNUNET_PeerIdentity *get_path, 304 const struct GNUNET_PeerIdentity *get_path,
299 const void *data, 305 const void *data,
300 size_t data_size) 306 size_t data_size)
301{ 307{
302 struct ProcessContext pc; 308 struct ProcessContext pc;
303 309
@@ -310,19 +316,19 @@ GDS_ROUTING_process(enum GNUNET_BLOCK_Type type,
310 pc.data = data; 316 pc.data = data;
311 pc.data_size = data_size; 317 pc.data_size = data_size;
312 if (NULL == data) 318 if (NULL == data)
313 { 319 {
314 /* Some apps might have an 'empty' reply as a valid reply; however, 320 /* Some apps might have an 'empty' reply as a valid reply; however,
315 'process' will call GNUNET_BLOCK_evaluate' which treats a 'NULL' 321 'process' will call GNUNET_BLOCK_evaluate' which treats a 'NULL'
316 reply as request-validation (but we need response-validation). 322 reply as request-validation (but we need response-validation).
317 So we set 'data' to a 0-byte non-NULL value just to be sure */ 323 So we set 'data' to a 0-byte non-NULL value just to be sure */
318 GNUNET_break(0 == data_size); 324 GNUNET_break (0 == data_size);
319 pc.data_size = 0; 325 pc.data_size = 0;
320 pc.data = ""; /* something not null */ 326 pc.data = ""; /* something not null */
321 } 327 }
322 GNUNET_CONTAINER_multihashmap_get_multiple(recent_map, 328 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map,
323 key, 329 key,
324 &process, 330 &process,
325 &pc); 331 &pc);
326} 332}
327 333
328 334
@@ -332,23 +338,23 @@ GDS_ROUTING_process(enum GNUNET_BLOCK_Type type,
332 * in the heap and hashmap. 338 * in the heap and hashmap.
333 */ 339 */
334static void 340static void
335expire_oldest_entry() 341expire_oldest_entry ()
336{ 342{
337 struct RecentRequest *recent_req; 343 struct RecentRequest *recent_req;
338 344
339 GNUNET_STATISTICS_update(GDS_stats, 345 GNUNET_STATISTICS_update (GDS_stats,
340 gettext_noop 346 gettext_noop
341 ("# Entries removed from routing table"), 1, 347 ("# Entries removed from routing table"), 1,
342 GNUNET_NO); 348 GNUNET_NO);
343 recent_req = GNUNET_CONTAINER_heap_peek(recent_heap); 349 recent_req = GNUNET_CONTAINER_heap_peek (recent_heap);
344 GNUNET_assert(recent_req != NULL); 350 GNUNET_assert (recent_req != NULL);
345 GNUNET_CONTAINER_heap_remove_node(recent_req->heap_node); 351 GNUNET_CONTAINER_heap_remove_node (recent_req->heap_node);
346 GNUNET_BLOCK_group_destroy(recent_req->bg); 352 GNUNET_BLOCK_group_destroy (recent_req->bg);
347 GNUNET_assert(GNUNET_YES == 353 GNUNET_assert (GNUNET_YES ==
348 GNUNET_CONTAINER_multihashmap_remove(recent_map, 354 GNUNET_CONTAINER_multihashmap_remove (recent_map,
349 &recent_req->key, 355 &recent_req->key,
350 recent_req)); 356 recent_req));
351 GNUNET_free(recent_req); 357 GNUNET_free (recent_req);
352} 358}
353 359
354 360
@@ -363,26 +369,26 @@ expire_oldest_entry()
363 * #GNUNET_SYSERR if the request was successfully combined 369 * #GNUNET_SYSERR if the request was successfully combined
364 */ 370 */
365static int 371static int
366try_combine_recent(void *cls, 372try_combine_recent (void *cls,
367 const struct GNUNET_HashCode *key, 373 const struct GNUNET_HashCode *key,
368 void *value) 374 void *value)
369{ 375{
370 struct RecentRequest *in = cls; 376 struct RecentRequest *in = cls;
371 struct RecentRequest *rr = value; 377 struct RecentRequest *rr = value;
372 378
373 if ((0 != GNUNET_memcmp(&in->peer, 379 if ((0 != GNUNET_memcmp (&in->peer,
374 &rr->peer)) || 380 &rr->peer)) ||
375 (in->type != rr->type) || 381 (in->type != rr->type) ||
376 (in->xquery_size != rr->xquery_size) || 382 (in->xquery_size != rr->xquery_size) ||
377 (0 != memcmp(in->xquery, 383 (0 != memcmp (in->xquery,
378 rr->xquery, 384 rr->xquery,
379 in->xquery_size))) 385 in->xquery_size)))
380 return GNUNET_OK; 386 return GNUNET_OK;
381 GNUNET_break(GNUNET_SYSERR != 387 GNUNET_break (GNUNET_SYSERR !=
382 GNUNET_BLOCK_group_merge(in->bg, 388 GNUNET_BLOCK_group_merge (in->bg,
383 rr->bg)); 389 rr->bg));
384 rr->bg = in->bg; 390 rr->bg = in->bg;
385 GNUNET_free(in); 391 GNUNET_free (in);
386 return GNUNET_SYSERR; 392 return GNUNET_SYSERR;
387} 393}
388 394
@@ -400,53 +406,53 @@ try_combine_recent(void *cls,
400 * @param reply_bf_mutator mutator for @a reply_bf 406 * @param reply_bf_mutator mutator for @a reply_bf
401 */ 407 */
402void 408void
403GDS_ROUTING_add(const struct GNUNET_PeerIdentity *sender, 409GDS_ROUTING_add (const struct GNUNET_PeerIdentity *sender,
404 enum GNUNET_BLOCK_Type type, 410 enum GNUNET_BLOCK_Type type,
405 struct GNUNET_BLOCK_Group *bg, 411 struct GNUNET_BLOCK_Group *bg,
406 enum GNUNET_DHT_RouteOption options, 412 enum GNUNET_DHT_RouteOption options,
407 const struct GNUNET_HashCode *key, 413 const struct GNUNET_HashCode *key,
408 const void *xquery, 414 const void *xquery,
409 size_t xquery_size) 415 size_t xquery_size)
410{ 416{
411 struct RecentRequest *recent_req; 417 struct RecentRequest *recent_req;
412 418
413 while (GNUNET_CONTAINER_heap_get_size(recent_heap) >= DHT_MAX_RECENT) 419 while (GNUNET_CONTAINER_heap_get_size (recent_heap) >= DHT_MAX_RECENT)
414 expire_oldest_entry(); 420 expire_oldest_entry ();
415 GNUNET_STATISTICS_update(GDS_stats, 421 GNUNET_STATISTICS_update (GDS_stats,
416 gettext_noop("# Entries added to routing table"), 422 gettext_noop ("# Entries added to routing table"),
417 1, 423 1,
418 GNUNET_NO); 424 GNUNET_NO);
419 recent_req = GNUNET_malloc(sizeof(struct RecentRequest) + xquery_size); 425 recent_req = GNUNET_malloc (sizeof(struct RecentRequest) + xquery_size);
420 recent_req->peer = *sender; 426 recent_req->peer = *sender;
421 recent_req->key = *key; 427 recent_req->key = *key;
422 recent_req->bg = bg; 428 recent_req->bg = bg;
423 recent_req->type = type; 429 recent_req->type = type;
424 recent_req->options = options; 430 recent_req->options = options;
425 recent_req->xquery = &recent_req[1]; 431 recent_req->xquery = &recent_req[1];
426 GNUNET_memcpy(&recent_req[1], 432 GNUNET_memcpy (&recent_req[1],
427 xquery, 433 xquery,
428 xquery_size); 434 xquery_size);
429 recent_req->xquery_size = xquery_size; 435 recent_req->xquery_size = xquery_size;
430 if (GNUNET_SYSERR == 436 if (GNUNET_SYSERR ==
431 GNUNET_CONTAINER_multihashmap_get_multiple(recent_map, 437 GNUNET_CONTAINER_multihashmap_get_multiple (recent_map,
432 key, 438 key,
433 &try_combine_recent, 439 &try_combine_recent,
434 recent_req)) 440 recent_req))
435 { 441 {
436 GNUNET_STATISTICS_update(GDS_stats, 442 GNUNET_STATISTICS_update (GDS_stats,
437 gettext_noop 443 gettext_noop
438 ("# DHT requests combined"), 444 ("# DHT requests combined"),
439 1, GNUNET_NO); 445 1, GNUNET_NO);
440 return; 446 return;
441 } 447 }
442 recent_req->heap_node 448 recent_req->heap_node
443 = GNUNET_CONTAINER_heap_insert(recent_heap, 449 = GNUNET_CONTAINER_heap_insert (recent_heap,
444 recent_req,
445 GNUNET_TIME_absolute_get().abs_value_us);
446 GNUNET_CONTAINER_multihashmap_put(recent_map,
447 key,
448 recent_req, 450 recent_req,
449 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); 451 GNUNET_TIME_absolute_get ().abs_value_us);
452 GNUNET_CONTAINER_multihashmap_put (recent_map,
453 key,
454 recent_req,
455 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
450} 456}
451 457
452 458
@@ -454,10 +460,11 @@ GDS_ROUTING_add(const struct GNUNET_PeerIdentity *sender,
454 * Initialize routing subsystem. 460 * Initialize routing subsystem.
455 */ 461 */
456void 462void
457GDS_ROUTING_init() 463GDS_ROUTING_init ()
458{ 464{
459 recent_heap = GNUNET_CONTAINER_heap_create(GNUNET_CONTAINER_HEAP_ORDER_MIN); 465 recent_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
460 recent_map = GNUNET_CONTAINER_multihashmap_create(DHT_MAX_RECENT * 4 / 3, GNUNET_NO); 466 recent_map = GNUNET_CONTAINER_multihashmap_create (DHT_MAX_RECENT * 4 / 3,
467 GNUNET_NO);
461} 468}
462 469
463 470
@@ -465,15 +472,15 @@ GDS_ROUTING_init()
465 * Shutdown routing subsystem. 472 * Shutdown routing subsystem.
466 */ 473 */
467void 474void
468GDS_ROUTING_done() 475GDS_ROUTING_done ()
469{ 476{
470 while (GNUNET_CONTAINER_heap_get_size(recent_heap) > 0) 477 while (GNUNET_CONTAINER_heap_get_size (recent_heap) > 0)
471 expire_oldest_entry(); 478 expire_oldest_entry ();
472 GNUNET_assert(0 == GNUNET_CONTAINER_heap_get_size(recent_heap)); 479 GNUNET_assert (0 == GNUNET_CONTAINER_heap_get_size (recent_heap));
473 GNUNET_CONTAINER_heap_destroy(recent_heap); 480 GNUNET_CONTAINER_heap_destroy (recent_heap);
474 recent_heap = NULL; 481 recent_heap = NULL;
475 GNUNET_assert(0 == GNUNET_CONTAINER_multihashmap_size(recent_map)); 482 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap_size (recent_map));
476 GNUNET_CONTAINER_multihashmap_destroy(recent_map); 483 GNUNET_CONTAINER_multihashmap_destroy (recent_map);
477 recent_map = NULL; 484 recent_map = NULL;
478} 485}
479 486