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