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