migrate transport_core API to MQ
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed_oc.c
1 /*
2   This file is part of GNUnet.
3   Copyright (C) 2008--2015 GNUnet e.V.
4
5   GNUnet is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published
7   by the Free Software Foundation; either version 3, or (at your
8   option) any later version.
9
10   GNUnet is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with GNUnet; see the file COPYING.  If not, write to the
17   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18   Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file testbed/gnunet-service-testbed_oc.c
23  * @brief code for handling overlay connect operations
24  * @author Sree Harsha Totakura
25  */
26
27 #include "gnunet-service-testbed.h"
28 #include "gnunet-service-testbed_connectionpool.h"
29
30 /**
31  * Redefine LOG with a changed log component string
32  */
33 #ifdef LOG
34 #undef LOG
35 #endif
36 #define LOG(kind,...)                                   \
37   GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
38
39
40 /**
41  * Context information for requesting ATS to connect to a peer
42  */
43 struct ConnectivitySuggestContext
44 {
45
46   /**
47    * The transport handle obtained from cache. Do NOT close/disconnect.
48    */
49   struct GNUNET_TRANSPORT_Handle *th_;
50
51   /**
52    * Configuration of the peer from cache. Do not free!
53    */
54   const struct GNUNET_CONFIGURATION_Handle *cfg;
55
56   /**
57    * The GetCacheHandle for the peer2's transport handle
58    * (used to offer the HELLO to the peer).
59    */
60   struct GST_ConnectionPool_GetHandle *cgh_p2_th;
61
62   /**
63    * The GetCacheHandle for the peer2's ATS handle.
64    */
65   struct GST_ConnectionPool_GetHandle *cgh_p2_ats;
66
67   /**
68    * The ATS handle for the connectivity suggestion.
69    */
70   struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
71
72 };
73
74
75 /**
76  * Types for context information we create for overlay connect requests
77  */
78 enum OverlayConnectContextType
79 {
80   /**
81    * This type is used if the overlay connection is local i.e. the connection
82    * has to be made between local peers
83    */
84   OCC_TYPE_LOCAL,
85
86   /**
87    * Type to be used when the first peer is local and the other peer is on a slave
88    * controller started by us
89    */
90   OCC_TYPE_REMOTE_SLAVE,
91
92   /**
93    * Type to be used when the first peer is local and the other peer is on a
94    * controller which is not started by us.
95    */
96   OCC_TYPE_REMOTE_LATERAL
97 };
98
99
100 /**
101  * Context data for operations on second peer in local overlay connection
102  * contexts
103  */
104 struct LocalPeer2Context
105 {
106   /**
107    * The handle for offering the HELLO of the first peer to the second
108    * peer.
109    */
110   struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
111
112   /**
113    * The transport ConnectivitySuggestContext
114    */
115   struct ConnectivitySuggestContext tcc;
116 };
117
118
119 /**
120  * Context data for operations on second peer in remote overlay connection
121  * contexts
122  */
123 struct RemotePeer2Context
124 {
125   /**
126    * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay
127    * connection then this can be NULL until the connection to the controller is
128    * established
129    */
130   struct GNUNET_TESTBED_Controller *p2c;
131
132   /**
133    * Operation context for the suboperation we start to get the identity of the
134    * second peer
135    */
136   struct OperationContext *opc;
137
138   /**
139    * Notification handle acquire to connect to a remote controller.  Only used
140    * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL.
141    */
142   struct NeighbourConnectNotification *ncn;
143
144   /**
145    * The neighbour handle.  Only used if the type of overlay connection is
146    * #OCC_TYPE_REMOTE_LATERAL.
147    */
148   struct Neighbour *p2n;
149 };
150
151 /**
152  * Context information for connecting 2 peers in overlay.
153  */
154 struct OverlayConnectContext
155 {
156   /**
157    * The next pointer for maintaining a DLL of all OverlayConnectContexts
158    */
159   struct OverlayConnectContext *next;
160
161   /**
162    * The prev pointer for maintaining a DLL of all OverlayConnectContexts
163    */
164   struct OverlayConnectContext *prev;
165
166   /**
167    * The client which has requested for overlay connection. This is used to send
168    * either a success of failure message
169    */
170   struct GNUNET_SERVER_Client *client;
171
172   /**
173    * the first peer which is to expect an overlay connection from the second peer.
174    */
175   struct Peer *peer;
176
177   /**
178    * Transport handle of the first peer obtained from cache to get its HELLO. Do
179    * NOT close/disconnect.
180    */
181   struct GNUNET_TRANSPORT_Handle *p1th_;
182
183   /**
184    * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
185    */
186   struct GST_ConnectionPool_GetHandle *cgh_p1th;
187
188   /**
189    * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
190    * level peer connects and to get our identity.
191    */
192   struct GST_ConnectionPool_GetHandle *cgh_ch;
193
194   /**
195    * HELLO of the first peer.  This should be sent to the second peer.
196    */
197   struct GNUNET_MessageHeader *hello;
198
199   /**
200    * Get GetHelloHandle to acquire a HELLO of the first peer
201    */
202   struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
203
204   /**
205    * The error message we send if this overlay connect operation has timed out
206    */
207   char *emsg;
208
209   /**
210    * Context information for operations on the second peer
211    */
212   union {
213
214     /**
215      * Context information to be used if the second peer is local
216      */
217     struct LocalPeer2Context local;
218
219     /**
220      * Context information to be used if the second peer is remote
221      */
222     struct RemotePeer2Context remote;
223
224   } p2ctx;
225
226   /**
227    * The peer identity of the first peer
228    */
229   struct GNUNET_PeerIdentity peer_identity;
230
231   /**
232    * The peer identity of the other peer
233    */
234   struct GNUNET_PeerIdentity other_peer_identity;
235
236   /**
237    * The id of the operation responsible for creating this context
238    */
239   uint64_t op_id;
240
241   /**
242    * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
243    * connect to peer 2
244    */
245   struct GNUNET_SCHEDULER_Task *send_hello_task;
246
247   /**
248    * The id of the overlay connect timeout task
249    */
250   struct GNUNET_SCHEDULER_Task *timeout_task;
251
252   /**
253    * The id of the cleanup task
254    */
255   struct GNUNET_SCHEDULER_Task *cleanup_task;
256
257   /**
258    * The type of this context information
259    */
260   enum OverlayConnectContextType type;
261
262   /**
263    * The id of the second peer which is has to connect to the first peer
264    */
265   uint32_t other_peer_id;
266 };
267
268
269 /**
270  * Context information for remote overlay connect operations.  Remote overlay
271  * connections are used when peers A and B reside on different hosts.  In these
272  * operations the host controller for peer B is asked by the host controller of
273  * peer A to make peer B connect to peer A by sending the controller of peer B
274  * the HELLO of peer A.
275  */
276 struct RemoteOverlayConnectCtx
277 {
278   /**
279    * the next pointer for DLL
280    */
281   struct RemoteOverlayConnectCtx *next;
282
283   /**
284    * the prev pointer for DLL
285    */
286   struct RemoteOverlayConnectCtx *prev;
287
288   /**
289    * The peer handle of peer B
290    */
291   struct Peer *peer;
292
293   /**
294    * Peer A's HELLO
295    */
296   struct GNUNET_MessageHeader *hello;
297
298   /**
299    * The handle for offering HELLO
300    */
301   struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
302
303   /**
304    * The transport try connect context
305    */
306   struct ConnectivitySuggestContext tcc;
307
308   /**
309    * The peer identity of peer A
310    */
311   struct GNUNET_PeerIdentity a_id;
312
313   /**
314    * Task for offering HELLO of A to B and doing try_connect
315    */
316   struct GNUNET_SCHEDULER_Task *attempt_connect_task_id;
317
318   /**
319    * Task to timeout RequestOverlayConnect
320    */
321   struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id;
322
323   /**
324    * The id of the operation responsible for creating this context
325    */
326   uint64_t op_id;
327 };
328
329
330 /**
331  * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
332  */
333 static struct OverlayConnectContext *occq_head;
334
335 /**
336  * DLL tail for OverlayConnectContext DLL
337  */
338 static struct OverlayConnectContext *occq_tail;
339
340 /**
341  * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
342  * shutdown
343  */
344 static struct RemoteOverlayConnectCtx *roccq_head;
345
346 /**
347  * DLL tail for RequectOverlayConnectContext DLL
348  */
349 static struct RemoteOverlayConnectCtx *roccq_tail;
350
351
352 /**
353  * Cleans up ForwardedOverlayConnectContext
354  *
355  * @param focc the ForwardedOverlayConnectContext to cleanup
356  */
357 void
358 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
359 {
360   GNUNET_SERVER_client_drop (focc->client);
361   GNUNET_free_non_null (focc->orig_msg);
362   GNUNET_free (focc);
363 }
364
365
366 /**
367  * Timeout task for cancelling a forwarded overlay connect connect
368  *
369  * @param cls the ForwardedOverlayConnectContext
370  */
371 static void
372 forwarded_overlay_connect_timeout (void *cls)
373 {
374   struct ForwardedOperationContext *fopc = cls;
375   struct RegisteredHostContext *rhc;
376   struct ForwardedOverlayConnectContext *focc;
377
378   rhc = fopc->cls;
379   focc = rhc->focc_dll_head;
380   GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
381   LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
382              focc->peer2);
383   GST_cleanup_focc (focc);
384   GST_forwarded_operation_timeout (fopc);
385   if (NULL != rhc->focc_dll_head)
386     GST_process_next_focc (rhc);
387 }
388
389
390 /**
391  * Callback to be called when forwarded overlay connection operation has a reply
392  * from the sub-controller successfull. We have to relay the reply msg back to
393  * the client
394  *
395  * @param cls ForwardedOperationContext
396  * @param msg the peer create success message
397  */
398 static void
399 forwarded_overlay_connect_listener (void *cls,
400                                     const struct GNUNET_MessageHeader *msg)
401 {
402   struct ForwardedOperationContext *fopc = cls;
403   struct RegisteredHostContext *rhc;
404   struct ForwardedOverlayConnectContext *focc;
405
406   rhc = fopc->cls;
407   GST_forwarded_operation_reply_relay (cls, msg);
408   focc = rhc->focc_dll_head;
409   GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
410   GST_cleanup_focc (focc);
411   if (NULL != rhc->focc_dll_head)
412     GST_process_next_focc (rhc);
413 }
414
415
416 /**
417  * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
418  *
419  * @param rhc the RegisteredHostContext
420  */
421 void
422 GST_process_next_focc (struct RegisteredHostContext *rhc)
423 {
424   struct ForwardedOperationContext *fopc;
425   struct ForwardedOverlayConnectContext *focc;
426   struct Peer *peer;
427   struct Slave *slave;
428
429   focc = rhc->focc_dll_head;
430   GNUNET_assert (NULL != focc);
431   GNUNET_assert (RHC_DONE == rhc->state);
432   GNUNET_assert (VALID_PEER_ID (focc->peer1));
433   peer = GST_peer_list[focc->peer1];
434   GNUNET_assert (GNUNET_YES == peer->is_remote);
435   GNUNET_assert (NULL != (slave = peer->details.remote.slave));
436   fopc = GNUNET_new (struct ForwardedOperationContext);
437   GNUNET_SERVER_client_keep (focc->client);
438   fopc->client = focc->client;
439   fopc->operation_id = focc->operation_id;
440   fopc->cls = rhc;
441   fopc->type = OP_OVERLAY_CONNECT;
442   fopc->opc =
443       GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
444                                              focc->operation_id, focc->orig_msg,
445                                              &forwarded_overlay_connect_listener,
446                                              fopc);
447   GNUNET_free (focc->orig_msg);
448   focc->orig_msg = NULL;
449   fopc->timeout_task =
450       GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout,
451                                     fopc);
452   GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
453 }
454
455
456 /**
457  * Cleans up any used handles in local peer2 context
458  *
459  * @param lp2c the local peer2 context information
460  */
461 static void
462 cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
463 {
464   if (NULL != lp2c->ohh)
465   {
466     GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
467     lp2c->ohh = NULL;
468   }
469   if (NULL != lp2c->tcc.cgh_p2_th)
470   {
471     GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th);
472     lp2c->tcc.cgh_p2_th = NULL;
473   }
474   if (NULL != lp2c->tcc.cgh_p2_ats)
475   {
476     GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats);
477     lp2c->tcc.cgh_p2_ats = NULL;
478   }
479   if (NULL != lp2c->tcc.csh)
480   {
481     GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh);
482     lp2c->tcc.csh = NULL;
483   }
484 }
485
486
487 /**
488  * Cleans up any used handles in remote peer2 context.  Relinquishes the
489  * remote controller connection if it has been established on-demand.
490  *
491  * @param rp2c the remote peer2 context information
492  */
493 static void
494 cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
495 {
496   if (NULL != rp2c->opc)
497   {
498     GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
499     rp2c->opc = NULL;
500   }
501   if (NULL != rp2c->ncn)
502   {
503     GST_neighbour_get_connection_cancel (rp2c->ncn);
504     rp2c->ncn = NULL;
505   }
506   if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
507   {
508     GST_neighbour_release_connection (rp2c->p2n);
509     rp2c->p2n = NULL;
510   }
511 }
512
513 /**
514  * Condition for checking if given peer is ready to be destroyed
515  *
516  * @param peer the peer to check
517  */
518 #define PEER_EXPIRED(peer)                      \
519   ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
520
521 /**
522  * Cleanup overlay connect context structure
523  *
524  * @param occ the overlay connect context
525  */
526 static void
527 cleanup_occ (struct OverlayConnectContext *occ)
528 {
529   struct Peer *peer2;
530
531   LOG_DEBUG ("0x%llx: Cleaning up occ\n",
532              occ->op_id);
533   GNUNET_free_non_null (occ->emsg);
534   GNUNET_free_non_null (occ->hello);
535   GNUNET_SERVER_client_drop (occ->client);
536   if (NULL != occ->send_hello_task)
537     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
538   if (NULL != occ->cleanup_task)
539     GNUNET_SCHEDULER_cancel (occ->cleanup_task);
540   if (NULL != occ->timeout_task)
541     GNUNET_SCHEDULER_cancel (occ->timeout_task);
542   if (NULL != occ->cgh_ch)
543     GST_connection_pool_get_handle_done (occ->cgh_ch);
544   if (NULL != occ->ghh)
545     GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
546   GST_connection_pool_get_handle_done (occ->cgh_p1th);
547   GNUNET_assert (NULL != GST_peer_list);
548   GNUNET_assert (occ->peer->reference_cnt > 0);
549   occ->peer->reference_cnt--;
550   if (PEER_EXPIRED (occ->peer))
551     GST_destroy_peer (occ->peer);
552   switch (occ->type)
553   {
554   case OCC_TYPE_LOCAL:
555     peer2 = GST_peer_list[occ->other_peer_id];
556     GNUNET_assert (peer2->reference_cnt > 0);
557     peer2->reference_cnt--;
558     if (PEER_EXPIRED (peer2))
559       GST_destroy_peer (peer2);
560     cleanup_occ_lp2c (&occ->p2ctx.local);
561     break;
562   case OCC_TYPE_REMOTE_SLAVE:
563   case OCC_TYPE_REMOTE_LATERAL:
564     cleanup_occ_rp2c (&occ->p2ctx.remote);
565     break;
566   }
567   GNUNET_CONTAINER_DLL_remove (occq_head,
568                                occq_tail,
569                                occ);
570   GNUNET_free (occ);
571 }
572
573
574 /**
575  * Task for cleaing up overlay connect context structure
576  *
577  * @param cls the overlay connect context
578  */
579 static void
580 do_cleanup_occ (void *cls)
581 {
582   struct OverlayConnectContext *occ = cls;
583
584   occ->cleanup_task = NULL;
585   cleanup_occ (occ);
586 }
587
588
589 /**
590  * Task which will be run when overlay connect request has been timed out
591  *
592  * @param cls the OverlayConnectContext
593  */
594 static void
595 timeout_overlay_connect (void *cls)
596 {
597   struct OverlayConnectContext *occ = cls;
598
599   GNUNET_assert (NULL != occ->timeout_task);
600   occ->timeout_task = NULL;
601   /* LOG (GNUNET_ERROR_TYPE_WARNING, */
602   /*      "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
603   /*      occ->peer->id, occ->other_peer_id, occ->emsg); */
604   GST_send_operation_fail_msg (occ->client,
605                                occ->op_id,
606                                occ->emsg);
607   cleanup_occ (occ);
608 }
609
610
611 /**
612  * FIXME.
613  */
614 static void
615 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
616 {
617   struct GNUNET_TESTBED_ConnectionEventMessage *msg;
618
619   LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
620              occ->op_id);
621   msg = GNUNET_new (struct GNUNET_TESTBED_ConnectionEventMessage);
622   msg->header.size =
623       htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
624   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
625   msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
626   msg->peer1 = htonl (occ->peer->id);
627   msg->peer2 = htonl (occ->other_peer_id);
628   msg->operation_id = GNUNET_htonll (occ->op_id);
629   GST_queue_message (occ->client, &msg->header);
630 }
631
632
633 /**
634  * Function called to notify transport users that another
635  * peer connected to us.
636  *
637  * @param cls closure
638  * @param new_peer the peer that connected
639  */
640 static void
641 overlay_connect_notify (void *cls,
642                         const struct GNUNET_PeerIdentity *new_peer)
643 {
644   struct OverlayConnectContext *occ = cls;
645   char *new_peer_str;
646   char *other_peer_str;
647
648   LOG_DEBUG ("Overlay connect notify\n");
649   if (0 ==
650       memcmp (new_peer, &occ->peer_identity,
651               sizeof (struct GNUNET_PeerIdentity)))
652     return;
653   new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
654   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
655   if (0 !=
656       memcmp (new_peer,
657               &occ->other_peer_identity,
658               sizeof (struct GNUNET_PeerIdentity)))
659   {
660     LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
661                new_peer_str,
662                other_peer_str);
663     GNUNET_free (new_peer_str);
664     GNUNET_free (other_peer_str);
665     return;
666   }
667   GNUNET_free (new_peer_str);
668   LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
669              occ->op_id,
670              other_peer_str,
671              GNUNET_i2s (&occ->peer_identity));
672   GNUNET_free (other_peer_str);
673   if (NULL != occ->send_hello_task)
674   {
675     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
676     occ->send_hello_task = NULL;
677   }
678   GNUNET_assert (NULL != occ->timeout_task);
679   GNUNET_SCHEDULER_cancel (occ->timeout_task);
680   occ->timeout_task = NULL;
681   switch (occ->type)
682   {
683   case OCC_TYPE_LOCAL:
684     cleanup_occ_lp2c (&occ->p2ctx.local);
685     break;
686   case OCC_TYPE_REMOTE_SLAVE:
687   case OCC_TYPE_REMOTE_LATERAL:
688     cleanup_occ_rp2c (&occ->p2ctx.remote);
689     break;
690   }
691   GNUNET_free_non_null (occ->emsg);
692   occ->emsg = NULL;
693   send_overlay_connect_success_msg (occ);
694   occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
695                                                 occ);
696 }
697
698
699 /**
700  * Callback from cache with needed ATS handle set
701  *
702  * @param cls a `struct OverlayConnectCtx *`
703  * @param ch the handle to CORE. Can be NULL if it is not requested
704  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
705  * @param ac the handle to ATS. Can be NULL if it is not requested
706  * @param my_identity the identity of our peer
707  * @param cfg configuration of the peer
708  */
709 static void
710 occ_cache_get_handle_ats_occ_cb (void *cls,
711                                  struct GNUNET_CORE_Handle *ch,
712                                  struct GNUNET_TRANSPORT_Handle *th,
713                                  struct GNUNET_ATS_ConnectivityHandle *ac,
714                                  const struct GNUNET_PeerIdentity *my_identity,
715                                  const struct GNUNET_CONFIGURATION_Handle *cfg)
716 {
717   struct OverlayConnectContext *occ = cls;
718   struct LocalPeer2Context *lp2c;
719
720   GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
721   GNUNET_assert (NULL != occ->timeout_task);
722   GNUNET_free_non_null (occ->emsg);
723   if (NULL == ac)
724   {
725     GNUNET_asprintf (&occ->emsg,
726                      "0x%llx: Failed to connect to ATS of peer with id: %u",
727                      occ->op_id,
728                      occ->peer->id);
729     GNUNET_SCHEDULER_cancel (occ->timeout_task);
730     occ->timeout_task =
731         GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
732                                   occ);
733     return;
734   }
735   occ->emsg = NULL;
736
737   GNUNET_asprintf (&occ->emsg,
738                    "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
739                    occ->op_id,
740                    GNUNET_i2s (&occ->other_peer_identity));
741
742   lp2c = &occ->p2ctx.local;
743   lp2c->tcc.csh =
744     GNUNET_ATS_connectivity_suggest (ac,
745                                      &occ->peer_identity,
746                                      1);
747 }
748
749
750 /**
751  * Callback from cache with needed ATS handle set
752  *
753  * @param cls a `struct RemoteOverlayConnectCtx *`
754  * @param ch the handle to CORE. Can be NULL if it is not requested
755  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
756  * @param ac the handle to ATS. Can be NULL if it is not requested
757  * @param my_identity the identity of our peer
758  */
759 static void
760 occ_cache_get_handle_ats_rocc_cb (void *cls,
761                                   struct GNUNET_CORE_Handle *ch,
762                                   struct GNUNET_TRANSPORT_Handle *th,
763                                   struct GNUNET_ATS_ConnectivityHandle *ac,
764                                   const struct GNUNET_PeerIdentity *my_identity,
765                                   const struct GNUNET_CONFIGURATION_Handle *cfg)
766 {
767   struct RemoteOverlayConnectCtx *rocc = cls;
768
769   rocc->tcc.csh =
770     GNUNET_ATS_connectivity_suggest (ac,
771                                      &rocc->a_id,
772                                      1);
773 }
774
775
776 /**
777  * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
778  * peer 1.
779  *
780  * @param cls the OverlayConnectContext
781  */
782 static void
783 send_hello (void *cls);
784
785
786 /**
787  * Task that is run when hello has been sent If tc->reason =
788  * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
789  * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
790  *
791  * @param cls the overlay connect context
792  */
793 static void
794 occ_hello_sent_cb (void *cls)
795 {
796   struct OverlayConnectContext *occ = cls;
797   struct LocalPeer2Context *lp2c;
798   struct Peer *peer2;
799   const struct GNUNET_SCHEDULER_TaskContext *tc;
800
801   tc = GNUNET_SCHEDULER_get_task_context ();
802   GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
803   GNUNET_assert (NULL != occ->timeout_task);
804   lp2c = &occ->p2ctx.local;
805   lp2c->ohh = NULL;
806
807   GNUNET_assert (NULL == occ->send_hello_task);
808   if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
809   {
810     GNUNET_free_non_null (occ->emsg);
811     GNUNET_asprintf (&occ->emsg,
812                      "0x%llx: Timeout while offering HELLO to other peer",
813                      occ->op_id);
814     occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello,
815                                                      occ);
816     return;
817   }
818   if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
819     return;
820   GNUNET_free_non_null (occ->emsg);
821
822   GNUNET_asprintf (&occ->emsg,
823                    "0x%llx: Timeout while acquiring ATS of %s from cache",
824                    occ->op_id,
825                    GNUNET_i2s (&occ->other_peer_identity));
826   GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
827   lp2c->tcc.cgh_p2_ats =
828     GST_connection_pool_get_handle (occ->other_peer_id,
829                                     peer2->details.local.cfg,
830                                     GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
831                                     &occ_cache_get_handle_ats_occ_cb,
832                                     occ, NULL, NULL, NULL);
833 }
834
835
836 /**
837  * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
838  * request.
839  *
840  * @param occ the overlay connect context.  Its type must be either
841  *          #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
842  */
843 static void
844 send_hello_thru_rocc (struct OverlayConnectContext *occ)
845 {
846   struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
847   char *other_peer_str;
848   uint16_t msize;
849   uint16_t hello_size;
850
851   GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
852   GNUNET_assert (NULL != occ->hello);
853   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
854   LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
855              occ->op_id,
856              GNUNET_i2s (&occ->peer_identity),
857              ntohs (occ->hello->size),
858              other_peer_str);
859   GNUNET_free (other_peer_str);
860   hello_size = ntohs (occ->hello->size);
861   msize = sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
862   msg = GNUNET_malloc (msize);
863   msg->header.type =
864       htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
865   msg->header.size = htons (msize);
866   msg->peer = htonl (occ->other_peer_id);
867   msg->operation_id = GNUNET_htonll (occ->op_id);
868   msg->peer_identity = occ->peer_identity;
869   memcpy (msg->hello,
870           occ->hello,
871           hello_size);
872   GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
873                                  &msg->header);
874 }
875
876
877 /**
878  * Task to offer HELLO of peer 1 to peer 2.  If peer2 is local it is offered
879  * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
880  * send_hello_thru_rocc()
881  *
882  * @param cls the OverlayConnectContext
883  */
884 static void
885 send_hello (void *cls)
886 {
887   struct OverlayConnectContext *occ = cls;
888   struct LocalPeer2Context *lp2c;
889   char *other_peer_str;
890
891   occ->send_hello_task = NULL;
892   GNUNET_assert (NULL != occ->timeout_task);
893   GNUNET_assert (NULL != occ->hello);
894   if (OCC_TYPE_LOCAL != occ->type)
895   {
896     send_hello_thru_rocc (occ);
897     return;
898   }
899   lp2c = &occ->p2ctx.local;
900   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
901   LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
902              occ->op_id,
903              GNUNET_i2s (&occ->peer_identity),
904              other_peer_str);
905   GNUNET_free (other_peer_str);
906   lp2c->ohh =
907       GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
908                                     occ->hello,
909                                     occ_hello_sent_cb,
910                                     occ);
911   if (NULL == lp2c->ohh)
912   {
913     GNUNET_break (0);
914     occ->send_hello_task =
915         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
916                                       (GNUNET_TIME_UNIT_MILLISECONDS,
917                                        100 +
918                                        GNUNET_CRYPTO_random_u32
919                                        (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
920                                       &send_hello, occ);
921   }
922 }
923
924
925 /**
926  * Callback from cache with needed handles set
927  *
928  * @param cls the closure passed to GST_cache_get_handle_transport()
929  * @param ch the handle to CORE. Can be NULL if it is not requested
930  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
931  * @param ac the handle to ATS. Can be NULL if it is not requested
932  * @param ignore_ peer identity which is ignored in this callback
933  * @param cfg configuration of the peer
934 */
935 static void
936 p2_transport_connect_cache_callback (void *cls,
937                                      struct GNUNET_CORE_Handle *ch,
938                                      struct GNUNET_TRANSPORT_Handle *th,
939                                      struct GNUNET_ATS_ConnectivityHandle *ac,
940                                      const struct GNUNET_PeerIdentity *ignore_,
941                                      const struct GNUNET_CONFIGURATION_Handle *cfg)
942 {
943   struct OverlayConnectContext *occ = cls;
944
945   GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
946   if (NULL == th)
947   {
948     GNUNET_asprintf (&occ->emsg,
949                      "0x%llx: Cannot connect to TRANSPORT of %s",
950                      occ->op_id,
951                      GNUNET_i2s (&occ->other_peer_identity));
952     GNUNET_SCHEDULER_cancel (occ->timeout_task);
953     occ->timeout_task =
954         GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
955     return;
956   }
957   occ->p2ctx.local.tcc.th_ = th;
958   occ->p2ctx.local.tcc.cfg = cfg;
959   GNUNET_asprintf (&occ->emsg,
960                    "0x%llx: Timeout while offering HELLO to %s",
961                    occ->op_id,
962                    GNUNET_i2s (&occ->other_peer_identity));
963   occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
964 }
965
966
967 /**
968  * Connects to the transport of the other peer if it is a local peer and
969  * schedules the send hello task
970  *
971  * @param occ the overlay connect context
972  */
973 static void
974 p2_transport_connect (struct OverlayConnectContext *occ)
975 {
976   struct Peer *peer2;
977
978   GNUNET_assert (NULL == occ->emsg);
979   GNUNET_assert (NULL != occ->hello);
980   GNUNET_assert (NULL == occ->ghh);
981   GNUNET_assert (NULL == occ->p1th_);
982   GNUNET_assert (NULL == occ->cgh_p1th);
983   if (OCC_TYPE_LOCAL == occ->type)
984   {
985     GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
986     occ->p2ctx.local.tcc.cgh_p2_th =
987         GST_connection_pool_get_handle (occ->other_peer_id,
988                                         peer2->details.local.cfg,
989                                         GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
990                                         &p2_transport_connect_cache_callback,
991                                         occ, NULL, NULL, NULL);
992     return;
993   }
994   GNUNET_asprintf (&occ->emsg,
995                    "0x%llx: Timeout while offering HELLO to %s",
996                    occ->op_id,
997                    GNUNET_i2s (&occ->other_peer_identity));
998   occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
999 }
1000
1001
1002 /**
1003  * Test for checking whether HELLO message is empty
1004  *
1005  * @param cls empty flag to set
1006  * @param address the HELLO
1007  * @param expiration expiration of the HELLO
1008  * @return #GNUNET_OK
1009  */
1010 static int
1011 test_address (void *cls,
1012               const struct GNUNET_HELLO_Address *address,
1013               struct GNUNET_TIME_Absolute expiration)
1014 {
1015   int *empty = cls;
1016
1017   *empty = GNUNET_NO;
1018   return GNUNET_OK;
1019 }
1020
1021
1022 /**
1023  * Function called whenever there is an update to the HELLO of peers in the
1024  * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
1025  * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
1026  *
1027  * @param cls closure
1028  * @param hello our updated HELLO
1029  */
1030 static void
1031 hello_update_cb (void *cls,
1032                  const struct GNUNET_MessageHeader *hello)
1033 {
1034   struct OverlayConnectContext *occ = cls;
1035   int empty;
1036   uint16_t msize;
1037
1038   msize = ntohs (hello->size);
1039   empty = GNUNET_YES;
1040   (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
1041                                          hello, GNUNET_NO,
1042                                          &test_address,
1043                                          &empty);
1044   if (GNUNET_YES == empty)
1045   {
1046     LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
1047                occ->op_id,
1048                GNUNET_i2s (&occ->peer_identity));
1049     return;
1050   }
1051   LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
1052              occ->op_id,
1053              GNUNET_i2s (&occ->peer_identity));
1054   occ->hello = GNUNET_malloc (msize);
1055   GST_cache_add_hello (occ->peer->id, hello);
1056   memcpy (occ->hello, hello, msize);
1057   GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
1058   occ->ghh = NULL;
1059   GST_connection_pool_get_handle_done (occ->cgh_p1th);
1060   occ->cgh_p1th = NULL;
1061   occ->p1th_ = NULL;
1062   GNUNET_free_non_null (occ->emsg);
1063   occ->emsg = NULL;
1064   p2_transport_connect (occ);
1065 }
1066
1067
1068 /**
1069  * Callback from cache with needed handles set
1070  *
1071  * @param cls the closure passed to GST_cache_get_handle_transport()
1072  * @param ch the handle to CORE. Can be NULL if it is not requested
1073  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1074  * @param ac the handle to ATS. Can be NULL if it is not requested
1075  * @param ignore_ peer identity which is ignored in this callback
1076  */
1077 static void
1078 p1_transport_connect_cache_callback (void *cls,
1079                                      struct GNUNET_CORE_Handle *ch,
1080                                      struct GNUNET_TRANSPORT_Handle *th,
1081                                      struct GNUNET_ATS_ConnectivityHandle *ac,
1082                                      const struct GNUNET_PeerIdentity *ignore_,
1083                                      const struct GNUNET_CONFIGURATION_Handle *cfg)
1084 {
1085   struct OverlayConnectContext *occ = cls;
1086
1087   GNUNET_free_non_null (occ->emsg);
1088   occ->emsg = NULL;
1089   if (NULL == th)
1090   {
1091     GNUNET_asprintf (&occ->emsg,
1092                      "0x%llx: Cannot connect to TRANSPORT of %s",
1093                      occ->op_id,
1094                      GNUNET_i2s (&occ->peer_identity));
1095     GNUNET_SCHEDULER_cancel (occ->timeout_task);
1096     occ->timeout_task =
1097         GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1098     return;
1099   }
1100   GNUNET_assert (NULL == occ->p1th_);
1101   GNUNET_assert (NULL != occ->cgh_p1th);
1102   occ->p1th_ = th;
1103   GNUNET_asprintf (&occ->emsg,
1104                    "0x%llx: Timeout while acquiring HELLO of peer %s",
1105                    occ->op_id,
1106                    GNUNET_i2s (&occ->peer_identity));
1107   occ->ghh = GNUNET_TRANSPORT_get_hello (cfg,
1108                                          &hello_update_cb,
1109                                          occ);
1110 }
1111
1112
1113 /**
1114  * Callback from cache with needed CORE handle set
1115  *
1116  * @param cls the closure passed to GST_cache_get_handle_transport()
1117  * @param ch the handle to CORE. Can be NULL if it is not requested
1118  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1119  * @param ac the handle to ATS. Can be NULL if it is not requested
1120  * @param my_identity the identity of our peer
1121  */
1122 static void
1123 occ_cache_get_handle_core_cb (void *cls,
1124                               struct GNUNET_CORE_Handle *ch,
1125                               struct GNUNET_TRANSPORT_Handle *th,
1126                               struct GNUNET_ATS_ConnectivityHandle *ac,
1127                               const struct GNUNET_PeerIdentity *my_identity,
1128                               const struct GNUNET_CONFIGURATION_Handle *cfg)
1129 {
1130   struct OverlayConnectContext *occ = cls;
1131   const struct GNUNET_MessageHeader *hello;
1132
1133   GNUNET_assert (NULL != occ->timeout_task);
1134   GNUNET_free_non_null (occ->emsg);
1135   if ((NULL == ch) || (NULL == my_identity))
1136   {
1137     GNUNET_asprintf (&occ->emsg,
1138                      "0x%llx: Failed to connect to CORE of peer with "
1139                      "id: %u",
1140                      occ->op_id,
1141                      occ->peer->id);
1142     GNUNET_SCHEDULER_cancel (occ->timeout_task);
1143     occ->timeout_task =
1144         GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1145     return;
1146   }
1147   occ->emsg = NULL;
1148   if (GNUNET_YES ==
1149       GNUNET_CORE_is_peer_connected_sync (ch,
1150                                           &occ->other_peer_identity))
1151   {
1152     LOG_DEBUG ("0x%llx: Target peer already connected\n",
1153                occ->op_id);
1154     GNUNET_SCHEDULER_cancel (occ->timeout_task);
1155     occ->timeout_task = NULL;
1156     send_overlay_connect_success_msg (occ);
1157     occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1158     return;
1159   }
1160   occ->peer_identity = *my_identity;
1161   LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
1162              occ->op_id,
1163              GNUNET_i2s (&occ->peer_identity));
1164   /* Lookup for HELLO in hello cache */
1165   if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1166   {
1167     LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
1168                occ->op_id,
1169                GNUNET_i2s (&occ->peer_identity));
1170     occ->hello = GNUNET_copy_message (hello);
1171     p2_transport_connect (occ);
1172     return;
1173   }
1174   GNUNET_asprintf (&occ->emsg,
1175                    "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1176                    occ->op_id,
1177                    GNUNET_i2s (&occ->peer_identity));
1178   occ->cgh_p1th =
1179       GST_connection_pool_get_handle (occ->peer->id,
1180                                       occ->peer->details.local.cfg,
1181                                       GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1182                                       p1_transport_connect_cache_callback,
1183                                       occ,
1184                                       NULL, NULL, NULL);
1185 }
1186
1187
1188 /**
1189  * Callback to be called when forwarded get peer config operation as part of
1190  * overlay connect is successfull. Connection to Peer 1's core is made and is
1191  * checked for new connection from peer 2
1192  *
1193  * @param cls ForwardedOperationContext
1194  * @param msg the peer create success message
1195  */
1196 static void
1197 overlay_connect_get_config (void *cls,
1198                             const struct GNUNET_MessageHeader *msg)
1199 {
1200   struct OverlayConnectContext *occ = cls;
1201   struct RemotePeer2Context *rp2c;
1202   const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1203
1204   GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1205   rp2c = &occ->p2ctx.remote;
1206   rp2c->opc = NULL;
1207   GNUNET_assert (NULL != occ->timeout_task);
1208   if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1209   {
1210     GNUNET_SCHEDULER_cancel (occ->timeout_task);
1211     occ->timeout_task =
1212         GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1213   }
1214   cmsg =
1215       (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1216   occ->other_peer_identity = cmsg->peer_identity;
1217   GNUNET_free_non_null (occ->emsg);
1218   GNUNET_asprintf (&occ->emsg,
1219                    "0x%llx: Timeout while connecting to CORE of peer with "
1220                    "id: %u",
1221                    occ->op_id,
1222                    occ->peer->id);
1223   occ->cgh_ch =
1224       GST_connection_pool_get_handle (occ->peer->id,
1225                                       occ->peer->details.local.cfg,
1226                                       GST_CONNECTIONPOOL_SERVICE_CORE,
1227                                       occ_cache_get_handle_core_cb,
1228                                       occ,
1229                                       &occ->other_peer_identity,
1230                                       &overlay_connect_notify,
1231                                       occ);
1232   return;
1233 }
1234
1235
1236 /**
1237  * Callback which will be called after a host registration succeeded or failed
1238  *
1239  * @param cls the RegisteredHostContext
1240  * @param emsg the error message; NULL if host registration is successful
1241  */
1242 static void
1243 host_registration_comp (void *cls, const char *emsg)
1244 {
1245   struct RegisteredHostContext *rhc = cls;
1246
1247   rhc->state = RHC_DONE;
1248   GST_process_next_focc (rhc);
1249 }
1250
1251
1252 /**
1253  * Iterator to match a registered host context
1254  *
1255  * @param cls pointer 2 pointer of RegisteredHostContext
1256  * @param key current key code
1257  * @param value value in the hash map
1258  * @return #GNUNET_YES if we should continue to
1259  *         iterate,
1260  *         #GNUNET_NO if not.
1261  */
1262 static int
1263 reghost_match_iterator (void *cls,
1264                         const struct GNUNET_HashCode *key,
1265                         void *value)
1266 {
1267   struct RegisteredHostContext **rh = cls;
1268   struct RegisteredHostContext *rh_val = value;
1269
1270   if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1271   {
1272     GNUNET_free (*rh);
1273     *rh = rh_val;
1274     return GNUNET_NO;
1275   }
1276   return GNUNET_YES;
1277 }
1278
1279
1280 /**
1281  * Function to generate the hashcode corresponding to a RegisteredHostContext
1282  *
1283  * @param reg_host the host which is being registered in RegisteredHostContext
1284  * @param host the host of the controller which has to connect to the above rhost
1285  * @return the hashcode
1286  */
1287 static struct GNUNET_HashCode
1288 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1289             struct GNUNET_TESTBED_Host *host)
1290 {
1291   struct GNUNET_HashCode hash;
1292   uint32_t host_ids[2];
1293
1294   host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1295   host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1296   GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1297   return hash;
1298 }
1299
1300
1301 /**
1302  * Checks if the given host is registered at the given slave.
1303  *
1304  * @param slave the slave where registration has to be checked.  The check is
1305  *          actually done through a locally maintained hashmap.  No
1306  *          communication with the slave is involved.
1307  * @param host the host to register
1308  * @return If the given host is not registered already or the registration is
1309  *           pending, it returns the registration context.  Any overlay connects
1310  *           to be forwarded should be queued in the context so that they can be
1311  *           executed when the registration is completed.  If the given host is
1312  *           already registered, NULL is returned.
1313  */
1314 static struct RegisteredHostContext *
1315 register_host (struct Slave *slave,
1316                struct GNUNET_TESTBED_Host *host)
1317 {
1318   struct GNUNET_HashCode hash;
1319   struct RegisteredHostContext *rhc;
1320
1321   rhc = GNUNET_new (struct RegisteredHostContext);
1322   rhc->reg_host = host;
1323   rhc->host = GST_host_list[slave->host_id];
1324   GNUNET_assert (NULL != rhc->reg_host);
1325   GNUNET_assert (NULL != rhc->host);
1326   rhc->state = RHC_INIT;
1327   hash = hash_hosts (rhc->reg_host, rhc->host);
1328   if ((GNUNET_NO ==
1329        GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, &hash)) ||
1330       (GNUNET_SYSERR !=
1331        GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1332                                                    &hash,
1333                                                    reghost_match_iterator,
1334                                                    &rhc)))
1335   {
1336     /* create and add a new registerd host context */
1337     /* add the focc to its queue */
1338     GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, &hash, rhc,
1339                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1340     GST_queue_host_registration (slave, host_registration_comp,
1341                                  rhc, rhc->reg_host);
1342   }
1343   else
1344   {
1345     /* rhc is now set to the existing one from the hash map by
1346      * reghost_match_iterator() */
1347     /* if queue is empty then ignore creating focc and proceed with normal
1348      * forwarding */
1349     if (RHC_DONE == rhc->state)
1350       return NULL;
1351   }
1352   return rhc;
1353 }
1354
1355
1356 /**
1357  * Forwards the overlay connect request to a slave controller.  Before
1358  * forwarding, any hosts which are needed to be known by the slave controller to
1359  * execute the overlay connect request are registered at slave.
1360  *
1361  * @param msg the overlay connect request message to be forwarded
1362  * @param client the client to which the status of the forwarded request has to
1363  *          be notified
1364  */
1365 static void
1366 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1367                          struct GNUNET_SERVER_Client *client)
1368 {
1369   struct ForwardedOperationContext *fopc;
1370   struct Route *route_to_peer2_host;
1371   struct Route *route_to_peer1_host;
1372   struct Peer *peer;
1373   struct RegisteredHostContext *rhc;
1374   struct ForwardedOverlayConnectContext *focc;
1375   uint64_t op_id;
1376   uint32_t peer2_host_id;
1377   uint32_t p1;
1378   uint32_t p2;
1379
1380   p1 = ntohl (msg->peer1);
1381   p2 = ntohl (msg->peer2);
1382   op_id = GNUNET_ntohll (msg->operation_id);
1383   peer2_host_id = ntohl (msg->peer2_host_id);
1384   GNUNET_assert (VALID_PEER_ID (p1));
1385   GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1386   peer = GST_peer_list[p1];
1387   GNUNET_assert (GNUNET_YES == peer->is_remote);
1388   LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1389   route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1390   route_to_peer1_host = GST_find_dest_route
1391       (peer->details.remote.remote_host_id);
1392   GNUNET_assert (NULL != route_to_peer1_host);
1393   if ((NULL != route_to_peer2_host) &&
1394       (route_to_peer1_host->dest == route_to_peer2_host->dest))
1395     goto forward;
1396   /* Peer2 is either with us OR peer1 and peer2 can be reached through
1397      different subtrees OR peer2 is on a subtree unknown to us */
1398   if (NULL != (rhc = register_host (peer->details.remote.slave,
1399                                     GST_host_list[peer2_host_id])))
1400   {
1401     LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2);
1402     focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1403     focc->peer1 = p1;
1404     focc->peer2 = p2;
1405     focc->peer2_host_id = peer2_host_id;
1406     focc->orig_msg = GNUNET_copy_message (&msg->header);
1407     focc->operation_id = op_id;
1408     focc->client = client;
1409     GNUNET_SERVER_client_keep (client);
1410     GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, rhc->focc_dll_tail,
1411                                       focc);
1412     return;
1413   }
1414
1415  forward:
1416   LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2);
1417   fopc = GNUNET_new (struct ForwardedOperationContext);
1418   GNUNET_SERVER_client_keep (client);
1419   fopc->client = client;
1420   fopc->operation_id = op_id;
1421   fopc->type = OP_OVERLAY_CONNECT;
1422   fopc->opc =
1423       GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1424                                              slave->controller, op_id,
1425                                              &msg->header,
1426                                              &GST_forwarded_operation_reply_relay,
1427                                              fopc);
1428   fopc->timeout_task =
1429       GNUNET_SCHEDULER_add_delayed (GST_timeout,
1430                                     &GST_forwarded_operation_timeout,
1431                                     fopc);
1432   GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
1433                                     fopcq_tail,
1434                                     fopc);
1435 }
1436
1437
1438 /**
1439  * Callback called when a connection to the controller of peer2 has been
1440  * established
1441  *
1442  * @param cls the overlay connect contexts
1443  * @param c handle to the controller connection
1444  */
1445 static void
1446 p2_controller_connect_cb (void *cls,
1447                           struct GNUNET_TESTBED_Controller *c)
1448 {
1449   struct OverlayConnectContext *occ = cls;
1450   struct RemotePeer2Context *rp2c;
1451   struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1452
1453   GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1454   rp2c = &occ->p2ctx.remote;
1455   rp2c->ncn = NULL;
1456   rp2c->p2c = c;
1457   cmsg.header.size =
1458       htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1459   cmsg.header.type =
1460       htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1461   cmsg.peer_id = htonl (occ->other_peer_id);
1462   cmsg.operation_id = GNUNET_htonll (occ->op_id);
1463   rp2c->opc =
1464       GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1465                                              occ->op_id, &cmsg.header,
1466                                              &overlay_connect_get_config,
1467                                              occ);
1468   GNUNET_free_non_null (occ->emsg);
1469   GNUNET_asprintf (&occ->emsg,
1470                    "0x%llx: Timeout while getting peer identity of peer "
1471                    "with id: %u",
1472                    occ->op_id,
1473                    occ->other_peer_id);
1474 }
1475
1476
1477 /**
1478  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1479  *
1480  * @param cls NULL
1481  * @param client identification of the client
1482  * @param message the actual message
1483  */
1484 void
1485 GST_handle_overlay_connect (void *cls,
1486                             struct GNUNET_SERVER_Client *client,
1487                             const struct GNUNET_MessageHeader *message)
1488 {
1489   const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1490   struct Peer *peer;
1491   struct Peer *peer2;
1492   struct OverlayConnectContext *occ;
1493   struct Neighbour *p2n;
1494   uint64_t operation_id;
1495   uint32_t p1;
1496   uint32_t p2;
1497   uint32_t peer2_host_id;
1498
1499   if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1500       ntohs (message->size))
1501   {
1502     GNUNET_break (0);
1503     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1504     return;
1505   }
1506   msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1507   p1 = ntohl (msg->peer1);
1508   p2 = ntohl (msg->peer2);
1509   if (!VALID_PEER_ID (p1))
1510   {
1511     GNUNET_break (0);
1512     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1513     return;
1514   }
1515   peer = GST_peer_list[p1];
1516   operation_id = GNUNET_ntohll (msg->operation_id);
1517   LOG_DEBUG
1518       ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
1519        p1,
1520        p2,
1521        operation_id);
1522   peer2_host_id = ntohl (msg->peer2_host_id);
1523   if (GNUNET_YES == peer->is_remote)
1524   {
1525     if (! VALID_HOST_ID (peer2_host_id))
1526     {
1527       GNUNET_break (0);
1528       GNUNET_SERVER_receive_done (client,
1529                                   GNUNET_SYSERR);
1530       return;
1531     }
1532     forward_overlay_connect (msg, client);
1533     GNUNET_SERVER_receive_done (client,
1534                                 GNUNET_OK);
1535     return;
1536   }
1537   p2n = NULL;
1538   occ = GNUNET_new (struct OverlayConnectContext);
1539   occ->type = OCC_TYPE_LOCAL;
1540   if (!VALID_PEER_ID (p2))       /* May be peer2 is on a another controller */
1541   {
1542     if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1543     {
1544       if (!VALID_HOST_ID (peer2_host_id))
1545       {
1546         GNUNET_break (0);
1547         LOG (GNUNET_ERROR_TYPE_WARNING,
1548              "0x%llx: Peer %u's host not in our neighbours list\n",
1549              operation_id, p2);
1550         GNUNET_SERVER_receive_done (client,
1551                                     GNUNET_SYSERR);
1552         GNUNET_free (occ);
1553         return;
1554       }
1555       p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1556     }
1557     occ->type = OCC_TYPE_REMOTE_LATERAL;
1558     occ->p2ctx.remote.p2n = p2n;
1559   }
1560   else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1561   {
1562     occ->type = OCC_TYPE_REMOTE_SLAVE;
1563     occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1564   }
1565   GNUNET_CONTAINER_DLL_insert_tail (occq_head,
1566                                     occq_tail,
1567                                     occ);
1568   GNUNET_SERVER_client_keep (client);
1569   occ->client = client;
1570   occ->other_peer_id = p2;
1571   GST_peer_list[p1]->reference_cnt++;
1572   occ->peer = GST_peer_list[p1];
1573   occ->op_id = operation_id;
1574   GNUNET_assert (NULL == occ->timeout_task);
1575   occ->timeout_task =
1576       GNUNET_SCHEDULER_add_delayed (GST_timeout,
1577                                     &timeout_overlay_connect,
1578                                     occ);
1579   switch (occ->type)
1580   {
1581   case OCC_TYPE_REMOTE_LATERAL:
1582     GNUNET_asprintf (&occ->emsg,
1583                      "0x%llx: Timeout while acquiring connection to peer %u's "
1584                      "host: %u\n",
1585                      occ->op_id,
1586                      occ->other_peer_id,
1587                      peer2_host_id);
1588     occ->p2ctx.remote.ncn =
1589         GST_neighbour_get_connection (p2n, &p2_controller_connect_cb, occ);
1590     break;
1591   case OCC_TYPE_REMOTE_SLAVE:
1592     p2_controller_connect_cb (occ, occ->p2ctx.remote.p2c);
1593     break;
1594   case OCC_TYPE_LOCAL:
1595     peer2 = GST_peer_list[occ->other_peer_id];
1596     peer2->reference_cnt++;
1597     GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1598                                       &occ->other_peer_identity);
1599     GNUNET_asprintf (&occ->emsg,
1600                      "0x%llx: Timeout while connecting to CORE of peer with "
1601                      "id: %u",
1602                      occ->op_id,
1603                      occ->peer->id);
1604     occ->cgh_ch =
1605         GST_connection_pool_get_handle (occ->peer->id,
1606                                         occ->peer->details.local.cfg,
1607                                         GST_CONNECTIONPOOL_SERVICE_CORE,
1608                                         occ_cache_get_handle_core_cb, occ,
1609                                         &occ->other_peer_identity,
1610                                         &overlay_connect_notify, occ);
1611     break;
1612   }
1613   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1614 }
1615
1616
1617 /**
1618  * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1619  * with it
1620  *
1621  * @param rocc the RemoteOverlayConnectCtx
1622  */
1623 static void
1624 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1625 {
1626   LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
1627              rocc->op_id);
1628   if (NULL != rocc->attempt_connect_task_id)
1629     GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1630   if (NULL != rocc->timeout_rocc_task_id)
1631     GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1632   if (NULL != rocc->ohh)
1633     GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1634   if (NULL != rocc->tcc.csh)
1635     GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
1636   GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
1637   GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
1638   GNUNET_assert (rocc->peer->reference_cnt > 0);
1639   rocc->peer->reference_cnt--;
1640   if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1641       (0 == rocc->peer->reference_cnt))
1642     GST_destroy_peer (rocc->peer);
1643   GNUNET_free_non_null (rocc->hello);
1644   GNUNET_CONTAINER_DLL_remove (roccq_head,
1645                                roccq_tail,
1646                                rocc);
1647   GNUNET_free (rocc);
1648 }
1649
1650
1651 /**
1652  * Task to timeout rocc and cleanit up
1653  *
1654  * @param cls the RemoteOverlayConnectCtx
1655  */
1656 static void
1657 timeout_rocc_task (void *cls)
1658 {
1659   struct RemoteOverlayConnectCtx *rocc = cls;
1660
1661   GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1662   rocc->timeout_rocc_task_id = NULL;
1663   LOG_DEBUG ("0x%llx: rocc timed out\n",
1664              rocc->op_id);
1665   cleanup_rocc (rocc);
1666 }
1667
1668
1669 /**
1670  * Function called to notify transport users that another
1671  * peer connected to us.
1672  *
1673  * @param cls the RemoteOverlayConnectContext
1674  * @param new_peer the peer that connected
1675  */
1676 static void
1677 cache_transport_peer_connect_notify (void *cls,
1678                                      const struct GNUNET_PeerIdentity *new_peer)
1679 {
1680   struct RemoteOverlayConnectCtx *rocc = cls;
1681
1682   LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
1683              rocc->op_id);
1684   GNUNET_assert (0 ==
1685                  memcmp (new_peer, &rocc->a_id,
1686                          sizeof (struct GNUNET_PeerIdentity)));
1687   LOG_DEBUG ("0x%llx: Peer %s connected\n",
1688              rocc->op_id,
1689              GNUNET_i2s (&rocc->a_id));
1690   cleanup_rocc (rocc);
1691 }
1692
1693
1694 /**
1695  * Task to offer the HELLO message to the peer and ask it to connect to the peer
1696  * whose identity is in RemoteOverlayConnectCtx
1697  *
1698  * @param cls the RemoteOverlayConnectCtx
1699  */
1700 static void
1701 attempt_connect_task (void *cls);
1702
1703
1704 /**
1705  * Task that is run when hello has been sent If tc->reason =
1706  * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1707  * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1708  *
1709  * @param cls the overlay connect context
1710  */
1711 static void
1712 rocc_hello_sent_cb (void *cls)
1713 {
1714   struct RemoteOverlayConnectCtx *rocc = cls;
1715   const struct GNUNET_SCHEDULER_TaskContext *tc;
1716
1717   rocc->ohh = NULL;
1718   GNUNET_assert (NULL == rocc->attempt_connect_task_id);
1719   LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
1720              rocc->op_id,
1721              GNUNET_i2s (&rocc->a_id),
1722              rocc->peer->id);
1723   tc = GNUNET_SCHEDULER_get_task_context ();
1724   if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
1725   {
1726     GNUNET_break (0);
1727     rocc->attempt_connect_task_id =
1728         GNUNET_SCHEDULER_add_now (&attempt_connect_task,
1729                                   rocc);
1730     return;
1731   }
1732   rocc->tcc.cgh_p2_ats =
1733     GST_connection_pool_get_handle (rocc->peer->id,
1734                                     rocc->peer->details.local.cfg,
1735                                     GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
1736                                     &occ_cache_get_handle_ats_rocc_cb,
1737                                     rocc, NULL, NULL, NULL);
1738 }
1739
1740
1741 /**
1742  * Task to offer the HELLO message to the peer and ask it to connect to the peer
1743  * whose identity is in RemoteOverlayConnectCtx
1744  *
1745  * @param cls the RemoteOverlayConnectCtx
1746  */
1747 static void
1748 attempt_connect_task (void *cls)
1749 {
1750   struct RemoteOverlayConnectCtx *rocc = cls;
1751
1752   GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1753   rocc->attempt_connect_task_id = NULL;
1754   LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
1755              rocc->op_id,
1756              GNUNET_i2s (&rocc->a_id),
1757              rocc->peer->id);
1758   rocc->ohh =
1759       GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
1760                                     rocc->hello,
1761                                     &rocc_hello_sent_cb,
1762                                     rocc);
1763   if (NULL == rocc->ohh)
1764     rocc->attempt_connect_task_id =
1765         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1766                                       (GNUNET_TIME_UNIT_MILLISECONDS,
1767                                        100 +
1768                                        GNUNET_CRYPTO_random_u32
1769                                        (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1770                                       &attempt_connect_task, rocc);
1771 }
1772
1773
1774 /**
1775  * Callback from cache with needed handles set
1776  *
1777  * @param cls the closure passed to GST_cache_get_handle_transport()
1778  * @param ch the handle to CORE. Can be NULL if it is not requested
1779  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1780  * @param ac the handle to ATS. Can be NULL if it is not requested
1781  * @param ignore_ peer identity which is ignored in this callback
1782  */
1783 static void
1784 rocc_cache_get_handle_transport_cb (void *cls,
1785                                     struct GNUNET_CORE_Handle *ch,
1786                                     struct GNUNET_TRANSPORT_Handle *th,
1787                                     struct GNUNET_ATS_ConnectivityHandle *ac,
1788                                     const struct GNUNET_PeerIdentity *ignore_,
1789                                     const struct GNUNET_CONFIGURATION_Handle *cfg)
1790 {
1791   struct RemoteOverlayConnectCtx *rocc = cls;
1792
1793   if (NULL == th)
1794   {
1795     rocc->timeout_rocc_task_id =
1796         GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1797     return;
1798   }
1799   rocc->tcc.th_ = th;
1800   rocc->tcc.cfg = cfg;
1801   if (GNUNET_YES ==
1802       GNUNET_TRANSPORT_check_peer_connected (rocc->tcc.th_,
1803                                              &rocc->a_id))
1804   {
1805     LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
1806                rocc->op_id,
1807                GNUNET_i2s (&rocc->a_id),
1808                rocc->peer->id);
1809     cleanup_rocc (rocc);
1810     return;
1811   }
1812   rocc->attempt_connect_task_id =
1813       GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1814 }
1815
1816
1817 /**
1818  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REQUEST_CONNECT messages
1819  *
1820  * @param cls NULL
1821  * @param client identification of the client
1822  * @param message the actual message
1823  */
1824 void
1825 GST_handle_remote_overlay_connect (void *cls,
1826                                    struct GNUNET_SERVER_Client *client,
1827                                    const struct GNUNET_MessageHeader *message)
1828 {
1829   const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
1830   struct RemoteOverlayConnectCtx *rocc;
1831   struct Peer *peer;
1832   struct GNUNET_PeerIdentity pid;
1833   static char pid_str[16];
1834   uint32_t peer_id;
1835   uint16_t msize;
1836   uint16_t hsize;
1837
1838   msize = ntohs (message->size);
1839   if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1840   {
1841     GNUNET_break (0);
1842     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1843     return;
1844   }
1845   msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1846   if ((NULL == msg->hello) ||
1847       ((GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))))
1848   {
1849     GNUNET_break (0);
1850     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1851     return;
1852   }
1853   hsize = ntohs (msg->hello->size);
1854   if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1855       msize)
1856   {
1857     GNUNET_break (0);
1858     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1859     return;
1860   }
1861   peer_id = ntohl (msg->peer);
1862   if ((peer_id >= GST_peer_list_size) ||
1863       (NULL == (peer = GST_peer_list[peer_id])))
1864   {
1865     GNUNET_break_op (0);
1866     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1867     return;
1868   }
1869   if (GNUNET_YES == peer->is_remote)
1870   {
1871     struct GNUNET_MessageHeader *msg2;
1872
1873     msg2 = GNUNET_copy_message (message);
1874     GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1875                                    msg2);
1876     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1877     return;
1878   }
1879   rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1880   rocc->op_id = GNUNET_ntohll (msg->operation_id);
1881   GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
1882                                     roccq_tail,
1883                                     rocc);
1884   rocc->a_id = msg->peer_identity;
1885   GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1886                                     &pid);
1887   (void) strncpy (pid_str,
1888                   GNUNET_i2s (&pid),
1889                   15);
1890   LOG_DEBUG ("0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
1891              rocc->op_id,
1892              pid_str,
1893              GNUNET_i2s (&rocc->a_id),
1894              hsize);
1895   rocc->peer = peer;
1896   rocc->peer->reference_cnt++;
1897   rocc->hello = GNUNET_malloc (hsize);
1898   memcpy (rocc->hello, msg->hello, hsize);
1899   rocc->tcc.cgh_p2_th =
1900       GST_connection_pool_get_handle (peer_id,
1901                                       rocc->peer->details.local.cfg,
1902                                       GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1903                                       &rocc_cache_get_handle_transport_cb,
1904                                       rocc,
1905                                       &rocc->a_id,
1906                                       &cache_transport_peer_connect_notify,
1907                                       rocc);
1908   rocc->timeout_rocc_task_id =
1909       GNUNET_SCHEDULER_add_delayed (GST_timeout,
1910                                     &timeout_rocc_task,
1911                                     rocc);
1912   GNUNET_SERVER_receive_done (client,
1913                               GNUNET_OK);
1914 }
1915
1916
1917 /**
1918  * Clears all pending overlay connect contexts in queue
1919  */
1920 void
1921 GST_free_occq ()
1922 {
1923   struct OverlayConnectContext *occ;
1924
1925   while (NULL != (occ = occq_head))
1926     cleanup_occ (occ);
1927 }
1928
1929
1930 /**
1931  * Clears all pending remote overlay connect contexts in queue
1932  */
1933 void
1934 GST_free_roccq ()
1935 {
1936   struct RemoteOverlayConnectCtx *rocc;
1937
1938   while (NULL != (rocc = roccq_head))
1939     cleanup_rocc (rocc);
1940 }