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