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