aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/gnunet-service-testbed_hc.c
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-01-30 10:06:33 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-01-30 10:06:33 +0000
commit105e00be9252a2e6db0dec566b2b0d9e633a31bf (patch)
tree36cbccc92d2da220cd0f1e5354b2f175a93ccbaa /src/testbed/gnunet-service-testbed_hc.c
parent8cc87399cf760b9fa3cbdb40bf71d1eb333c8434 (diff)
downloadgnunet-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.c170
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
41enum CacheGetType 38enum 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 */
66struct 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 */
317static void
318peer_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
266static void 343static void
267opstart_get_handle_transport (void *cls) 344opstart_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
292oprelease_get_handle_transport (void *cls) 369oprelease_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)
303static struct GSTCacheGetHandle * 386static struct GSTCacheGetHandle *
304cache_get_handle (unsigned int peer_id, 387cache_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)
423void 522void
424GST_cache_get_handle_done (struct GSTCacheGetHandle *cgh) 523GST_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 *
467GST_cache_get_handle_transport (unsigned int peer_id, 573GST_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