diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-01-30 10:06:33 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-01-30 10:06:33 +0000 |
commit | 105e00be9252a2e6db0dec566b2b0d9e633a31bf (patch) | |
tree | 36cbccc92d2da220cd0f1e5354b2f175a93ccbaa /src/testbed/gnunet-service-testbed_hc.c | |
parent | 8cc87399cf760b9fa3cbdb40bf71d1eb333c8434 (diff) | |
download | gnunet-105e00be9252a2e6db0dec566b2b0d9e633a31bf.tar.gz gnunet-105e00be9252a2e6db0dec566b2b0d9e633a31bf.zip |
cache transport handles with peer connect notifications
Diffstat (limited to 'src/testbed/gnunet-service-testbed_hc.c')
-rw-r--r-- | src/testbed/gnunet-service-testbed_hc.c | 170 |
1 files changed, 140 insertions, 30 deletions
diff --git a/src/testbed/gnunet-service-testbed_hc.c b/src/testbed/gnunet-service-testbed_hc.c index 7a7689cce..2f3586c45 100644 --- a/src/testbed/gnunet-service-testbed_hc.c +++ b/src/testbed/gnunet-service-testbed_hc.c | |||
@@ -34,9 +34,6 @@ | |||
34 | #define LOG(kind,...) \ | 34 | #define LOG(kind,...) \ |
35 | GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__) | 35 | GNUNET_log_from (kind, "testbed-cache", __VA_ARGS__) |
36 | 36 | ||
37 | /* #define LOG_DEBUG(...) \ */ | ||
38 | /* LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) */ | ||
39 | |||
40 | 37 | ||
41 | enum CacheGetType | 38 | enum CacheGetType |
42 | { | 39 | { |
@@ -61,6 +58,40 @@ struct GSTCacheGetHandle | |||
61 | int notify_called; | 58 | int notify_called; |
62 | }; | 59 | }; |
63 | 60 | ||
61 | |||
62 | /** | ||
63 | * This context structure is used to maintain a queue of notifications to check | ||
64 | * which of them are to be notified when a peer is connected. | ||
65 | */ | ||
66 | struct ConnectNotifyContext | ||
67 | { | ||
68 | /** | ||
69 | * The next ptr for the DLL | ||
70 | */ | ||
71 | struct ConnectNotifyContext *next; | ||
72 | |||
73 | /** | ||
74 | * The prev ptr for the DLL | ||
75 | */ | ||
76 | struct ConnectNotifyContext *prev; | ||
77 | |||
78 | /** | ||
79 | * The peer identity of the target peer. When this target peer is connected, | ||
80 | * call the notify callback | ||
81 | */ | ||
82 | const struct GNUNET_PeerIdentity *target; | ||
83 | |||
84 | /** | ||
85 | * The notify callback to be called when the target peer is connected | ||
86 | */ | ||
87 | GST_cache_peer_connect_notify cb; | ||
88 | |||
89 | /** | ||
90 | * The closure for the notify callback | ||
91 | */ | ||
92 | void *cb_cls; | ||
93 | }; | ||
94 | |||
64 | /** | 95 | /** |
65 | * Cache entry | 96 | * Cache entry |
66 | */ | 97 | */ |
@@ -105,12 +136,24 @@ struct CacheEntry | |||
105 | /** | 136 | /** |
106 | * the head of the CacheGetHandle queue | 137 | * the head of the CacheGetHandle queue |
107 | */ | 138 | */ |
108 | struct GSTCacheGetHandle *cghq_head; | 139 | struct GSTCacheGetHandle *cgh_qhead; |
109 | 140 | ||
110 | /** | 141 | /** |
111 | * the tail of the CacheGetHandle queue | 142 | * the tail of the CacheGetHandle queue |
112 | */ | 143 | */ |
113 | struct GSTCacheGetHandle *cghq_tail; | 144 | struct GSTCacheGetHandle *cgh_qtail; |
145 | |||
146 | /** | ||
147 | * DLL head for the queue of notifications contexts to check which of them are to | ||
148 | * be notified when a peer is connected. | ||
149 | */ | ||
150 | struct ConnectNotifyContext *nctxt_qhead; | ||
151 | |||
152 | /** | ||
153 | * DLL tail for the queue of notifications contexts to check which of them are to | ||
154 | * be notified when a peer is connected. | ||
155 | */ | ||
156 | struct ConnectNotifyContext *nctxt_qtail; | ||
114 | 157 | ||
115 | /** | 158 | /** |
116 | * The task that calls the cache callback | 159 | * The task that calls the cache callback |
@@ -247,12 +290,12 @@ call_cgh_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
247 | 290 | ||
248 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != entry->notify_task); | 291 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != entry->notify_task); |
249 | entry->notify_task = GNUNET_SCHEDULER_NO_TASK; | 292 | entry->notify_task = GNUNET_SCHEDULER_NO_TASK; |
250 | cgh = entry->cghq_head; | 293 | cgh = entry->cgh_qhead; |
251 | GNUNET_assert (GNUNET_NO == cgh->notify_called); | 294 | GNUNET_assert (GNUNET_NO == cgh->notify_called); |
252 | GNUNET_CONTAINER_DLL_remove (entry->cghq_head, entry->cghq_tail, cgh); | 295 | GNUNET_CONTAINER_DLL_remove (entry->cgh_qhead, entry->cgh_qtail, cgh); |
253 | cgh->notify_called = GNUNET_YES; | 296 | cgh->notify_called = GNUNET_YES; |
254 | GNUNET_CONTAINER_DLL_insert_tail (entry->cghq_head, entry->cghq_tail, cgh); | 297 | GNUNET_CONTAINER_DLL_insert_tail (entry->cgh_qhead, entry->cgh_qtail, cgh); |
255 | if (GNUNET_NO == entry->cghq_head->notify_called) | 298 | if (GNUNET_NO == entry->cgh_qhead->notify_called) |
256 | entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry); | 299 | entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry); |
257 | switch (cgh->type) | 300 | switch (cgh->type) |
258 | { | 301 | { |
@@ -262,6 +305,40 @@ call_cgh_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
262 | } | 305 | } |
263 | } | 306 | } |
264 | 307 | ||
308 | /** | ||
309 | * Function called to notify transport users that another | ||
310 | * peer connected to us. | ||
311 | * | ||
312 | * @param cls closure | ||
313 | * @param peer the peer that connected | ||
314 | * @param ats performance data | ||
315 | * @param ats_count number of entries in ats (excluding 0-termination) | ||
316 | */ | ||
317 | static void | ||
318 | peer_connect_notify_cb (void *cls, | ||
319 | const struct GNUNET_PeerIdentity *peer, | ||
320 | const struct GNUNET_ATS_Information *ats, | ||
321 | uint32_t ats_count) | ||
322 | { | ||
323 | struct CacheEntry *entry = cls; | ||
324 | struct ConnectNotifyContext *ctxt; | ||
325 | GST_cache_peer_connect_notify cb; | ||
326 | void *cb_cls; | ||
327 | |||
328 | while (NULL != (ctxt = entry->nctxt_qhead)) | ||
329 | { | ||
330 | if (0 == memcmp (ctxt->target, peer, sizeof (struct GNUNET_PeerIdentity))) | ||
331 | break; | ||
332 | } | ||
333 | if (NULL == ctxt) | ||
334 | return; | ||
335 | cb = ctxt->cb; | ||
336 | cb_cls = ctxt->cb_cls; | ||
337 | GNUNET_CONTAINER_DLL_remove (entry->nctxt_qhead, entry->nctxt_qtail, ctxt); | ||
338 | GNUNET_free (ctxt); | ||
339 | cb (cb_cls, peer); | ||
340 | } | ||
341 | |||
265 | 342 | ||
266 | static void | 343 | static void |
267 | opstart_get_handle_transport (void *cls) | 344 | opstart_get_handle_transport (void *cls) |
@@ -271,9 +348,9 @@ opstart_get_handle_transport (void *cls) | |||
271 | GNUNET_assert (NULL != entry); | 348 | GNUNET_assert (NULL != entry); |
272 | LOG_DEBUG ("Opening a transport connection to peer %u\n", entry->peer_id); | 349 | LOG_DEBUG ("Opening a transport connection to peer %u\n", entry->peer_id); |
273 | entry->transport_handle = GNUNET_TRANSPORT_connect (entry->cfg, | 350 | entry->transport_handle = GNUNET_TRANSPORT_connect (entry->cfg, |
274 | NULL, NULL, | 351 | NULL, entry, |
275 | NULL, | ||
276 | NULL, | 352 | NULL, |
353 | &peer_connect_notify_cb, | ||
277 | NULL); | 354 | NULL); |
278 | if (NULL == entry->transport_handle) | 355 | if (NULL == entry->transport_handle) |
279 | { | 356 | { |
@@ -283,7 +360,7 @@ opstart_get_handle_transport (void *cls) | |||
283 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == entry->notify_task); | 360 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == entry->notify_task); |
284 | if (0 == entry->demand) | 361 | if (0 == entry->demand) |
285 | return; | 362 | return; |
286 | if (GNUNET_NO == entry->cghq_head->notify_called) | 363 | if (GNUNET_NO == entry->cgh_qhead->notify_called) |
287 | entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry); | 364 | entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry); |
288 | } | 365 | } |
289 | 366 | ||
@@ -292,7 +369,13 @@ static void | |||
292 | oprelease_get_handle_transport (void *cls) | 369 | oprelease_get_handle_transport (void *cls) |
293 | { | 370 | { |
294 | struct CacheEntry *entry = cls; | 371 | struct CacheEntry *entry = cls; |
295 | 372 | struct ConnectNotifyContext *ctxt; | |
373 | |||
374 | while (NULL != (ctxt = entry->nctxt_qhead)) | ||
375 | { | ||
376 | GNUNET_CONTAINER_DLL_remove (entry->nctxt_qhead, entry->nctxt_qtail, ctxt); | ||
377 | GNUNET_free (ctxt); | ||
378 | } | ||
296 | if (NULL == entry->transport_handle) | 379 | if (NULL == entry->transport_handle) |
297 | return; | 380 | return; |
298 | GNUNET_TRANSPORT_disconnect (entry->transport_handle); | 381 | GNUNET_TRANSPORT_disconnect (entry->transport_handle); |
@@ -303,11 +386,15 @@ oprelease_get_handle_transport (void *cls) | |||
303 | static struct GSTCacheGetHandle * | 386 | static struct GSTCacheGetHandle * |
304 | cache_get_handle (unsigned int peer_id, | 387 | cache_get_handle (unsigned int peer_id, |
305 | struct GSTCacheGetHandle *cgh, | 388 | struct GSTCacheGetHandle *cgh, |
306 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 389 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
390 | const struct GNUNET_PeerIdentity *target, | ||
391 | GST_cache_peer_connect_notify connect_notify_cb, | ||
392 | void *connect_notify_cb_cls) | ||
307 | { | 393 | { |
308 | struct GNUNET_HashCode key; | 394 | struct GNUNET_HashCode key; |
309 | void *handle; | 395 | void *handle; |
310 | struct CacheEntry *entry; | 396 | struct CacheEntry *entry; |
397 | struct ConnectNotifyContext *ctxt; | ||
311 | 398 | ||
312 | GNUNET_assert (0 != cgh->type); | 399 | GNUNET_assert (0 != cgh->type); |
313 | GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key); | 400 | GNUNET_CRYPTO_hash (&peer_id, sizeof (peer_id), &key); |
@@ -332,7 +419,15 @@ cache_get_handle (unsigned int peer_id, | |||
332 | entry->cfg = GNUNET_CONFIGURATION_dup (cfg); | 419 | entry->cfg = GNUNET_CONFIGURATION_dup (cfg); |
333 | entry->demand++; | 420 | entry->demand++; |
334 | cgh->entry = entry; | 421 | cgh->entry = entry; |
335 | GNUNET_CONTAINER_DLL_insert (entry->cghq_head, entry->cghq_tail, cgh); | 422 | GNUNET_CONTAINER_DLL_insert (entry->cgh_qhead, entry->cgh_qtail, cgh); |
423 | if ((NULL != target) && (NULL != connect_notify_cb)) | ||
424 | { | ||
425 | ctxt = GNUNET_malloc (sizeof (struct ConnectNotifyContext)); | ||
426 | ctxt->target = target; | ||
427 | ctxt->cb = connect_notify_cb; | ||
428 | ctxt->cb_cls = connect_notify_cb_cls; | ||
429 | GNUNET_CONTAINER_DLL_insert_tail (entry->nctxt_qhead, entry->nctxt_qtail, ctxt); | ||
430 | } | ||
336 | if ((NULL != entry->transport_handle) || (NULL != entry->transport_op)) | 431 | if ((NULL != entry->transport_handle) || (NULL != entry->transport_op)) |
337 | { | 432 | { |
338 | if (GNUNET_SCHEDULER_NO_TASK == entry->notify_task) | 433 | if (GNUNET_SCHEDULER_NO_TASK == entry->notify_task) |
@@ -380,6 +475,10 @@ cache_clear_iterator (void *cls, | |||
380 | GNUNET_free_non_null (entry->hello); | 475 | GNUNET_free_non_null (entry->hello); |
381 | GNUNET_break (NULL == entry->transport_handle); | 476 | GNUNET_break (NULL == entry->transport_handle); |
382 | GNUNET_break (NULL == entry->cfg); | 477 | GNUNET_break (NULL == entry->cfg); |
478 | GNUNET_assert (NULL == entry->cgh_qhead); | ||
479 | GNUNET_assert (NULL == entry->cgh_qtail); | ||
480 | GNUNET_assert (NULL == entry->nctxt_qhead); | ||
481 | GNUNET_assert (NULL == entry->nctxt_qtail); | ||
383 | GNUNET_free (entry); | 482 | GNUNET_free (entry); |
384 | return GNUNET_YES; | 483 | return GNUNET_YES; |
385 | } | 484 | } |
@@ -423,27 +522,28 @@ GST_cache_init (unsigned int size) | |||
423 | void | 522 | void |
424 | GST_cache_get_handle_done (struct GSTCacheGetHandle *cgh) | 523 | GST_cache_get_handle_done (struct GSTCacheGetHandle *cgh) |
425 | { | 524 | { |
426 | GNUNET_assert (NULL != cgh->entry); | 525 | struct CacheEntry *entry; |
427 | GNUNET_assert (0 < cgh->entry->demand); | 526 | |
428 | cgh->entry->demand--; | 527 | entry = cgh->entry; |
429 | if (GNUNET_SCHEDULER_NO_TASK != cgh->entry->notify_task) | 528 | GNUNET_assert (NULL != entry); |
529 | GNUNET_assert (0 < entry->demand); | ||
530 | entry->demand--; | ||
531 | if (GNUNET_SCHEDULER_NO_TASK != entry->notify_task) | ||
430 | { | 532 | { |
431 | GNUNET_SCHEDULER_cancel (cgh->entry->notify_task); | 533 | GNUNET_SCHEDULER_cancel (entry->notify_task); |
432 | cgh->entry->notify_task = GNUNET_SCHEDULER_NO_TASK; | 534 | entry->notify_task = GNUNET_SCHEDULER_NO_TASK; |
433 | } | 535 | } |
434 | GNUNET_CONTAINER_DLL_remove (cgh->entry->cghq_head, | 536 | GNUNET_CONTAINER_DLL_remove (entry->cgh_qhead, entry->cgh_qtail, cgh); |
435 | cgh->entry->cghq_tail, | 537 | if (0 == entry->demand) |
436 | cgh); | ||
437 | if (0 == cgh->entry->demand) | ||
438 | { | 538 | { |
439 | GNUNET_CONTAINER_DLL_insert_tail (lru_cache_head, lru_cache_tail, cgh->entry); | 539 | GNUNET_CONTAINER_DLL_insert_tail (lru_cache_head, lru_cache_tail, entry); |
440 | if (lru_cache_size > lru_cache_threshold_size) | 540 | if (lru_cache_size > lru_cache_threshold_size) |
441 | cache_remove (lru_cache_head); | 541 | cache_remove (lru_cache_head); |
442 | } | 542 | } |
443 | else | 543 | else |
444 | { | 544 | { |
445 | if (GNUNET_NO == cgh->entry->cghq_head->notify_called) | 545 | if (GNUNET_NO == entry->cgh_qhead->notify_called) |
446 | cgh->entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, cgh->entry); | 546 | entry->notify_task = GNUNET_SCHEDULER_add_now (&call_cgh_cb, entry); |
447 | } | 547 | } |
448 | GNUNET_free (cgh); | 548 | GNUNET_free (cgh); |
449 | } | 549 | } |
@@ -460,6 +560,12 @@ GST_cache_get_handle_done (struct GSTCacheGetHandle *cgh) | |||
460 | * created if it was not present in the cache | 560 | * created if it was not present in the cache |
461 | * @param cb the callback to notify when the transport handle is available | 561 | * @param cb the callback to notify when the transport handle is available |
462 | * @param cb_cls the closure for the above callback | 562 | * @param cb_cls the closure for the above callback |
563 | * @param target the peer identify of the peer whose connection to our TRANSPORT | ||
564 | * subsystem will be notified through the connect_notify_cb. Can be NULL | ||
565 | * @param connect_notify_cb the callback to call when the given target peer is | ||
566 | * connected. This callback will only be called once or never again (in | ||
567 | * case the target peer cannot be connected). Can be NULL | ||
568 | * @param connect_notify_cb_cls the closure for the above callback | ||
463 | * @return the handle which can be used cancel or mark that the handle is no | 569 | * @return the handle which can be used cancel or mark that the handle is no |
464 | * longer being used | 570 | * longer being used |
465 | */ | 571 | */ |
@@ -467,7 +573,10 @@ struct GSTCacheGetHandle * | |||
467 | GST_cache_get_handle_transport (unsigned int peer_id, | 573 | GST_cache_get_handle_transport (unsigned int peer_id, |
468 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 574 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
469 | GST_cache_callback cb, | 575 | GST_cache_callback cb, |
470 | void *cb_cls) | 576 | void *cb_cls, |
577 | const struct GNUNET_PeerIdentity *target, | ||
578 | GST_cache_peer_connect_notify connect_notify_cb, | ||
579 | void *connect_notify_cb_cls) | ||
471 | { | 580 | { |
472 | struct GSTCacheGetHandle *cgh; | 581 | struct GSTCacheGetHandle *cgh; |
473 | 582 | ||
@@ -475,7 +584,8 @@ GST_cache_get_handle_transport (unsigned int peer_id, | |||
475 | cgh->cb = cb; | 584 | cgh->cb = cb; |
476 | cgh->cb_cls = cb_cls; | 585 | cgh->cb_cls = cb_cls; |
477 | cgh->type = CGT_TRANSPORT_HANDLE; | 586 | cgh->type = CGT_TRANSPORT_HANDLE; |
478 | return cache_get_handle (peer_id, cgh, cfg); | 587 | return cache_get_handle (peer_id, cgh, cfg, |
588 | target, connect_notify_cb, connect_notify_cb_cls); | ||
479 | } | 589 | } |
480 | 590 | ||
481 | 591 | ||