yapf format.
[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  * 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
567   case OCC_TYPE_REMOTE_SLAVE:
568   case OCC_TYPE_REMOTE_LATERAL:
569     cleanup_occ_rp2c (&occ->p2ctx.remote);
570     break;
571   }
572   GNUNET_CONTAINER_DLL_remove (occq_head,
573                                occq_tail,
574                                occ);
575   GNUNET_free (occ);
576 }
577
578
579 /**
580  * Task for cleaing up overlay connect context structure
581  *
582  * @param cls the overlay connect context
583  */
584 static void
585 do_cleanup_occ (void *cls)
586 {
587   struct OverlayConnectContext *occ = cls;
588
589   occ->cleanup_task = NULL;
590   cleanup_occ (occ);
591 }
592
593
594 /**
595  * Task which will be run when overlay connect request has been timed out
596  *
597  * @param cls the OverlayConnectContext
598  */
599 static void
600 timeout_overlay_connect (void *cls)
601 {
602   struct OverlayConnectContext *occ = cls;
603
604   GNUNET_assert (NULL != occ->timeout_task);
605   occ->timeout_task = NULL;
606   /* LOG (GNUNET_ERROR_TYPE_WARNING, */
607   /*      "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
608   /*      occ->peer->id, occ->other_peer_id, occ->emsg); */
609   GST_send_operation_fail_msg (occ->client,
610                                occ->op_id,
611                                occ->emsg);
612   cleanup_occ (occ);
613 }
614
615
616 /**
617  * Notify OC subsystem that @a client disconnected.
618  *
619  * @param client the client that disconnected
620  */
621 void
622 GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client)
623 {
624   struct ForwardedOperationContext *fopc;
625   struct ForwardedOperationContext *fopcn;
626   struct OverlayConnectContext *occ;
627   struct OverlayConnectContext *occn;
628
629   for (fopc = fopcq_head; NULL != fopc; fopc = fopcn)
630   {
631     fopcn = fopc->next;
632     if (fopc->client == client)
633     {
634       GNUNET_SCHEDULER_cancel (fopc->timeout_task);
635       GST_forwarded_operation_timeout (fopc);
636     }
637   }
638   for (occ = occq_head; NULL != occ; occ = occn)
639   {
640     occn = occ->next;
641     if (occ->client == client)
642       cleanup_occ (occ);
643   }
644   // FIXME: implement clean up for client_keep replacements!
645 }
646
647
648
649
650 /**
651  * FIXME.
652  */
653 static void
654 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
655 {
656   struct GNUNET_MQ_Envelope *env;
657   struct GNUNET_TESTBED_ConnectionEventMessage *msg;
658
659   LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
660              occ->op_id);
661   env = GNUNET_MQ_msg (msg,
662                        GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
663   msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
664   msg->peer1 = htonl (occ->peer->id);
665   msg->peer2 = htonl (occ->other_peer_id);
666   msg->operation_id = GNUNET_htonll (occ->op_id);
667   GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client),
668                   env);
669 }
670
671
672 /**
673  * Function called to notify transport users that another
674  * peer connected to us.
675  *
676  * @param cls closure
677  * @param new_peer the peer that connected
678  */
679 static void
680 overlay_connect_notify (void *cls,
681                         const struct GNUNET_PeerIdentity *new_peer)
682 {
683   struct OverlayConnectContext *occ = cls;
684   char *new_peer_str;
685   char *other_peer_str;
686
687   LOG_DEBUG ("Overlay connect notify\n");
688   if (0 ==
689       memcmp (new_peer, &occ->peer_identity,
690               sizeof(struct GNUNET_PeerIdentity)))
691     return;
692   new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
693   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
694   if (0 !=
695       memcmp (new_peer,
696               &occ->other_peer_identity,
697               sizeof(struct GNUNET_PeerIdentity)))
698   {
699     LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
700                new_peer_str,
701                other_peer_str);
702     GNUNET_free (new_peer_str);
703     GNUNET_free (other_peer_str);
704     return;
705   }
706   GNUNET_free (new_peer_str);
707   LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
708              occ->op_id,
709              other_peer_str,
710              GNUNET_i2s (&occ->peer_identity));
711   GNUNET_free (other_peer_str);
712   if (NULL != occ->send_hello_task)
713   {
714     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
715     occ->send_hello_task = NULL;
716   }
717   GNUNET_assert (NULL != occ->timeout_task);
718   GNUNET_SCHEDULER_cancel (occ->timeout_task);
719   occ->timeout_task = NULL;
720   switch (occ->type)
721   {
722   case OCC_TYPE_LOCAL:
723     cleanup_occ_lp2c (&occ->p2ctx.local);
724     break;
725
726   case OCC_TYPE_REMOTE_SLAVE:
727   case OCC_TYPE_REMOTE_LATERAL:
728     cleanup_occ_rp2c (&occ->p2ctx.remote);
729     break;
730   }
731   GNUNET_free_non_null (occ->emsg);
732   occ->emsg = NULL;
733   send_overlay_connect_success_msg (occ);
734   occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
735                                                 occ);
736 }
737
738
739 /**
740  * Callback from cache with needed ATS handle set
741  *
742  * @param cls a `struct OverlayConnectCtx *`
743  * @param ch the handle to CORE. Can be NULL if it is not requested
744  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
745  * @param ac the handle to ATS. Can be NULL if it is not requested
746  * @param my_identity the identity of our peer
747  * @param cfg configuration of the peer
748  */
749 static void
750 occ_cache_get_handle_ats_occ_cb (void *cls,
751                                  struct GNUNET_CORE_Handle *ch,
752                                  struct GNUNET_TRANSPORT_CoreHandle *th,
753                                  struct GNUNET_ATS_ConnectivityHandle *ac,
754                                  const struct GNUNET_PeerIdentity *my_identity,
755                                  const struct GNUNET_CONFIGURATION_Handle *cfg)
756 {
757   struct OverlayConnectContext *occ = cls;
758   struct LocalPeer2Context *lp2c;
759
760   GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
761   GNUNET_assert (NULL != occ->timeout_task);
762   GNUNET_free_non_null (occ->emsg);
763   if (NULL == ac)
764   {
765     GNUNET_asprintf (&occ->emsg,
766                      "0x%llx: Failed to connect to ATS of peer with id: %u",
767                      occ->op_id,
768                      occ->peer->id);
769     GNUNET_SCHEDULER_cancel (occ->timeout_task);
770     occ->timeout_task =
771       GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
772                                 occ);
773     return;
774   }
775   occ->emsg = NULL;
776
777   GNUNET_asprintf (&occ->emsg,
778                    "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
779                    occ->op_id,
780                    GNUNET_i2s (&occ->other_peer_identity));
781
782   lp2c = &occ->p2ctx.local;
783   lp2c->tcc.csh =
784     GNUNET_ATS_connectivity_suggest (ac,
785                                      &occ->peer_identity,
786                                      1);
787 }
788
789
790 /**
791  * Callback from cache with needed ATS handle set
792  *
793  * @param cls a `struct RemoteOverlayConnectCtx *`
794  * @param ch the handle to CORE. Can be NULL if it is not requested
795  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
796  * @param ac the handle to ATS. Can be NULL if it is not requested
797  * @param my_identity the identity of our peer
798  */
799 static void
800 occ_cache_get_handle_ats_rocc_cb (void *cls,
801                                   struct GNUNET_CORE_Handle *ch,
802                                   struct GNUNET_TRANSPORT_CoreHandle *th,
803                                   struct GNUNET_ATS_ConnectivityHandle *ac,
804                                   const struct GNUNET_PeerIdentity *my_identity,
805                                   const struct GNUNET_CONFIGURATION_Handle *cfg)
806 {
807   struct RemoteOverlayConnectCtx *rocc = cls;
808
809   rocc->tcc.csh =
810     GNUNET_ATS_connectivity_suggest (ac,
811                                      &rocc->a_id,
812                                      1);
813 }
814
815
816 /**
817  * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
818  * peer 1.
819  *
820  * @param cls the OverlayConnectContext
821  */
822 static void
823 send_hello (void *cls);
824
825
826 /**
827  * Task that is run when hello has been sent If tc->reason =
828  * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
829  * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
830  *
831  * @param cls the overlay connect context
832  */
833 static void
834 occ_hello_sent_cb (void *cls)
835 {
836   struct OverlayConnectContext *occ = cls;
837   struct LocalPeer2Context *lp2c;
838   struct Peer *peer2;
839
840   GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
841   GNUNET_assert (NULL != occ->timeout_task);
842   lp2c = &occ->p2ctx.local;
843   lp2c->ohh = NULL;
844
845   GNUNET_assert (NULL == occ->send_hello_task);
846   GNUNET_free_non_null (occ->emsg);
847
848   GNUNET_asprintf (&occ->emsg,
849                    "0x%llx: Timeout while acquiring ATS of %s from cache",
850                    occ->op_id,
851                    GNUNET_i2s (&occ->other_peer_identity));
852   GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
853   lp2c->tcc.cgh_p2_ats =
854     GST_connection_pool_get_handle (occ->other_peer_id,
855                                     peer2->details.local.cfg,
856                                     GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
857                                     &occ_cache_get_handle_ats_occ_cb,
858                                     occ, NULL, NULL, NULL);
859 }
860
861
862 /**
863  * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
864  * request.
865  *
866  * @param occ the overlay connect context.  Its type must be either
867  *          #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
868  */
869 static void
870 send_hello_thru_rocc (struct OverlayConnectContext *occ)
871 {
872   struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
873   char *other_peer_str;
874   uint16_t msize;
875   uint16_t hello_size;
876
877   GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
878   GNUNET_assert (NULL != occ->hello);
879   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
880   LOG_DEBUG (
881     "0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
882     occ->op_id,
883     GNUNET_i2s (&occ->peer_identity),
884     ntohs (occ->hello->size),
885     other_peer_str);
886   GNUNET_free (other_peer_str);
887   hello_size = ntohs (occ->hello->size);
888   msize = sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage)
889           + hello_size;
890   msg = GNUNET_malloc (msize);
891   msg->header.type =
892     htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
893   msg->header.size = htons (msize);
894   msg->peer = htonl (occ->other_peer_id);
895   msg->operation_id = GNUNET_htonll (occ->op_id);
896   msg->peer_identity = occ->peer_identity;
897   GNUNET_memcpy (msg->hello,
898                  occ->hello,
899                  hello_size);
900   GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
901                                  &msg->header);
902 }
903
904
905 /**
906  * Task to offer HELLO of peer 1 to peer 2.  If peer2 is local it is offered
907  * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
908  * send_hello_thru_rocc()
909  *
910  * @param cls the OverlayConnectContext
911  */
912 static void
913 send_hello (void *cls)
914 {
915   struct OverlayConnectContext *occ = cls;
916   struct LocalPeer2Context *lp2c;
917   char *other_peer_str;
918
919   occ->send_hello_task = NULL;
920   GNUNET_assert (NULL != occ->timeout_task);
921   GNUNET_assert (NULL != occ->hello);
922   if (OCC_TYPE_LOCAL != occ->type)
923   {
924     send_hello_thru_rocc (occ);
925     return;
926   }
927   lp2c = &occ->p2ctx.local;
928   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
929   LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
930              occ->op_id,
931              GNUNET_i2s (&occ->peer_identity),
932              other_peer_str);
933   GNUNET_free (other_peer_str);
934   lp2c->ohh =
935     GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
936                                   occ->hello,
937                                   &occ_hello_sent_cb,
938                                   occ);
939   if (NULL == lp2c->ohh)
940   {
941     GNUNET_break (0);
942     occ->send_hello_task =
943       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
944                                       (GNUNET_TIME_UNIT_MILLISECONDS,
945                                       100
946                                       + GNUNET_CRYPTO_random_u32
947                                         (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
948                                     &send_hello, occ);
949   }
950 }
951
952
953 /**
954  * Callback from cache with needed handles set
955  *
956  * @param cls the closure passed to GST_cache_get_handle_transport()
957  * @param ch the handle to CORE. Can be NULL if it is not requested
958  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
959  * @param ac the handle to ATS. Can be NULL if it is not requested
960  * @param ignore_ peer identity which is ignored in this callback
961  * @param cfg configuration of the peer
962  */
963 static void
964 p2_transport_connect_cache_callback (void *cls,
965                                      struct GNUNET_CORE_Handle *ch,
966                                      struct GNUNET_TRANSPORT_CoreHandle *th,
967                                      struct GNUNET_ATS_ConnectivityHandle *ac,
968                                      const struct GNUNET_PeerIdentity *ignore_,
969                                      const struct
970                                      GNUNET_CONFIGURATION_Handle *cfg)
971 {
972   struct OverlayConnectContext *occ = cls;
973
974   GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
975   if (NULL == th)
976   {
977     GNUNET_asprintf (&occ->emsg,
978                      "0x%llx: Cannot connect to TRANSPORT of %s",
979                      occ->op_id,
980                      GNUNET_i2s (&occ->other_peer_identity));
981     GNUNET_SCHEDULER_cancel (occ->timeout_task);
982     occ->timeout_task =
983       GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
984     return;
985   }
986   occ->p2ctx.local.tcc.th_ = th;
987   occ->p2ctx.local.tcc.cfg = cfg;
988   GNUNET_asprintf (&occ->emsg,
989                    "0x%llx: Timeout while offering HELLO to %s",
990                    occ->op_id,
991                    GNUNET_i2s (&occ->other_peer_identity));
992   occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
993 }
994
995
996 /**
997  * Connects to the transport of the other peer if it is a local peer and
998  * schedules the send hello task
999  *
1000  * @param occ the overlay connect context
1001  */
1002 static void
1003 p2_transport_connect (struct OverlayConnectContext *occ)
1004 {
1005   struct Peer *peer2;
1006
1007   /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the
1008      HELLO! */
1009   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1010               "Connecting to transport of peer %s to obtain HELLO\n",
1011               GNUNET_i2s (&occ->other_peer_identity));
1012   GNUNET_assert (NULL == occ->emsg);
1013   GNUNET_assert (NULL != occ->hello);
1014   GNUNET_assert (NULL == occ->ghh);
1015   GNUNET_assert (NULL == occ->p1th_);
1016   GNUNET_assert (NULL == occ->cgh_p1th);
1017   if (OCC_TYPE_LOCAL == occ->type)
1018   {
1019     GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
1020     occ->p2ctx.local.tcc.cgh_p2_th =
1021       GST_connection_pool_get_handle (occ->other_peer_id,
1022                                       peer2->details.local.cfg,
1023                                       GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1024                                       &p2_transport_connect_cache_callback,
1025                                       occ, NULL, NULL, NULL);
1026     return;
1027   }
1028   GNUNET_asprintf (&occ->emsg,
1029                    "0x%llx: Timeout while offering HELLO to %s",
1030                    occ->op_id,
1031                    GNUNET_i2s (&occ->other_peer_identity));
1032   occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
1033 }
1034
1035
1036 /**
1037  * Test for checking whether HELLO message is empty
1038  *
1039  * @param cls empty flag to set
1040  * @param address the HELLO
1041  * @param expiration expiration of the HELLO
1042  * @return #GNUNET_OK
1043  */
1044 static int
1045 test_address (void *cls,
1046               const struct GNUNET_HELLO_Address *address,
1047               struct GNUNET_TIME_Absolute expiration)
1048 {
1049   int *empty = cls;
1050
1051   *empty = GNUNET_NO;
1052   return GNUNET_OK;
1053 }
1054
1055
1056 /**
1057  * Function called whenever there is an update to the HELLO of peers in the
1058  * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
1059  * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
1060  *
1061  * @param cls closure
1062  * @param hello our updated HELLO
1063  */
1064 static void
1065 hello_update_cb (void *cls,
1066                  const struct GNUNET_MessageHeader *hello)
1067 {
1068   struct OverlayConnectContext *occ = cls;
1069   int empty;
1070   uint16_t msize;
1071
1072   msize = ntohs (hello->size);
1073   empty = GNUNET_YES;
1074   (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
1075                                          hello, GNUNET_NO,
1076                                          &test_address,
1077                                          &empty);
1078   if (GNUNET_YES == empty)
1079   {
1080     LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
1081                occ->op_id,
1082                GNUNET_i2s (&occ->peer_identity));
1083     return;
1084   }
1085   LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
1086              occ->op_id,
1087              GNUNET_i2s (&occ->peer_identity));
1088   occ->hello = GNUNET_malloc (msize);
1089   GST_cache_add_hello (occ->peer->id, hello);
1090   GNUNET_memcpy (occ->hello, hello, msize);
1091   GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
1092   occ->ghh = NULL;
1093   GST_connection_pool_get_handle_done (occ->cgh_p1th);
1094   occ->cgh_p1th = NULL;
1095   occ->p1th_ = NULL;
1096   GNUNET_free_non_null (occ->emsg);
1097   occ->emsg = NULL;
1098   p2_transport_connect (occ);
1099 }
1100
1101
1102 /**
1103  * Callback from cache with needed handles set
1104  *
1105  * @param cls the closure passed to GST_cache_get_handle_transport()
1106  * @param ch the handle to CORE. Can be NULL if it is not requested
1107  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1108  * @param ac the handle to ATS. Can be NULL if it is not requested
1109  * @param ignore_ peer identity which is ignored in this callback
1110  */
1111 static void
1112 p1_transport_connect_cache_callback (void *cls,
1113                                      struct GNUNET_CORE_Handle *ch,
1114                                      struct GNUNET_TRANSPORT_CoreHandle *th,
1115                                      struct GNUNET_ATS_ConnectivityHandle *ac,
1116                                      const struct GNUNET_PeerIdentity *ignore_,
1117                                      const struct
1118                                      GNUNET_CONFIGURATION_Handle *cfg)
1119 {
1120   struct OverlayConnectContext *occ = cls;
1121
1122   GNUNET_free_non_null (occ->emsg);
1123   occ->emsg = NULL;
1124   if (NULL == th)
1125   {
1126     GNUNET_asprintf (&occ->emsg,
1127                      "0x%llx: Cannot connect to TRANSPORT of %s",
1128                      occ->op_id,
1129                      GNUNET_i2s (&occ->peer_identity));
1130     GNUNET_SCHEDULER_cancel (occ->timeout_task);
1131     occ->timeout_task =
1132       GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1133     return;
1134   }
1135   GNUNET_assert (NULL == occ->p1th_);
1136   GNUNET_assert (NULL != occ->cgh_p1th);
1137   occ->p1th_ = th;
1138   GNUNET_asprintf (&occ->emsg,
1139                    "0x%llx: Timeout while acquiring HELLO of peer %s",
1140                    occ->op_id,
1141                    GNUNET_i2s (&occ->peer_identity));
1142   occ->ghh = GNUNET_TRANSPORT_hello_get (cfg,
1143                                          GNUNET_TRANSPORT_AC_ANY,
1144                                          &hello_update_cb,
1145                                          occ);
1146 }
1147
1148
1149 /**
1150  * Callback from cache with needed CORE handle set
1151  *
1152  * @param cls the closure passed to GST_cache_get_handle_transport()
1153  * @param ch the handle to CORE. Can be NULL if it is not requested
1154  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1155  * @param ac the handle to ATS. Can be NULL if it is not requested
1156  * @param my_identity the identity of our peer
1157  */
1158 static void
1159 occ_cache_get_handle_core_cb (void *cls,
1160                               struct GNUNET_CORE_Handle *ch,
1161                               struct GNUNET_TRANSPORT_CoreHandle *th,
1162                               struct GNUNET_ATS_ConnectivityHandle *ac,
1163                               const struct GNUNET_PeerIdentity *my_identity,
1164                               const struct GNUNET_CONFIGURATION_Handle *cfg)
1165 {
1166   struct OverlayConnectContext *occ = cls;
1167   const struct GNUNET_MessageHeader *hello;
1168
1169   GNUNET_assert (NULL != occ->timeout_task);
1170   GNUNET_free_non_null (occ->emsg);
1171   if ((NULL == ch) || (NULL == my_identity))
1172   {
1173     GNUNET_asprintf (&occ->emsg,
1174                      "0x%llx: Failed to connect to CORE of peer with "
1175                      "id: %u",
1176                      occ->op_id,
1177                      occ->peer->id);
1178     GNUNET_SCHEDULER_cancel (occ->timeout_task);
1179     occ->timeout_task =
1180       GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1181     return;
1182   }
1183   occ->emsg = NULL;
1184   if (NULL !=
1185       GNUNET_CORE_get_mq (ch,
1186                           &occ->other_peer_identity))
1187   {
1188     LOG_DEBUG ("0x%llx: Target peer already connected\n",
1189                occ->op_id);
1190     GNUNET_SCHEDULER_cancel (occ->timeout_task);
1191     occ->timeout_task = NULL;
1192     send_overlay_connect_success_msg (occ);
1193     occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1194     return;
1195   }
1196   occ->peer_identity = *my_identity;
1197   LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
1198              occ->op_id,
1199              GNUNET_i2s (&occ->peer_identity));
1200   /* Lookup for HELLO in hello cache */
1201   if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1202   {
1203     LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
1204                occ->op_id,
1205                GNUNET_i2s (&occ->peer_identity));
1206     occ->hello = GNUNET_copy_message (hello);
1207     p2_transport_connect (occ);
1208     return;
1209   }
1210   GNUNET_asprintf (&occ->emsg,
1211                    "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1212                    occ->op_id,
1213                    GNUNET_i2s (&occ->peer_identity));
1214   occ->cgh_p1th =
1215     GST_connection_pool_get_handle (occ->peer->id,
1216                                     occ->peer->details.local.cfg,
1217                                     GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1218                                     p1_transport_connect_cache_callback,
1219                                     occ,
1220                                     NULL, NULL, NULL);
1221 }
1222
1223
1224 /**
1225  * Callback to be called when forwarded get peer config operation as part of
1226  * overlay connect is successfull. Connection to Peer 1's core is made and is
1227  * checked for new connection from peer 2
1228  *
1229  * @param cls ForwardedOperationContext
1230  * @param msg the peer create success message
1231  */
1232 static void
1233 overlay_connect_get_config (void *cls,
1234                             const struct GNUNET_MessageHeader *msg)
1235 {
1236   struct OverlayConnectContext *occ = cls;
1237   struct RemotePeer2Context *rp2c;
1238   const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1239
1240   GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1241   rp2c = &occ->p2ctx.remote;
1242   rp2c->opc = NULL;
1243   GNUNET_assert (NULL != occ->timeout_task);
1244   if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1245   {
1246     GNUNET_SCHEDULER_cancel (occ->timeout_task);
1247     occ->timeout_task =
1248       GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1249   }
1250   cmsg =
1251     (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1252   occ->other_peer_identity = cmsg->peer_identity;
1253   GNUNET_free_non_null (occ->emsg);
1254   GNUNET_asprintf (&occ->emsg,
1255                    "0x%llx: Timeout while connecting to CORE of peer with "
1256                    "id: %u",
1257                    occ->op_id,
1258                    occ->peer->id);
1259   occ->cgh_ch =
1260     GST_connection_pool_get_handle (occ->peer->id,
1261                                     occ->peer->details.local.cfg,
1262                                     GST_CONNECTIONPOOL_SERVICE_CORE,
1263                                     occ_cache_get_handle_core_cb,
1264                                     occ,
1265                                     &occ->other_peer_identity,
1266                                     &overlay_connect_notify,
1267                                     occ);
1268   return;
1269 }
1270
1271
1272 /**
1273  * Callback which will be called after a host registration succeeded or failed
1274  *
1275  * @param cls the RegisteredHostContext
1276  * @param emsg the error message; NULL if host registration is successful
1277  */
1278 static void
1279 host_registration_comp (void *cls, const char *emsg)
1280 {
1281   struct RegisteredHostContext *rhc = cls;
1282
1283   rhc->state = RHC_DONE;
1284   GST_process_next_focc (rhc);
1285 }
1286
1287
1288 /**
1289  * Iterator to match a registered host context
1290  *
1291  * @param cls pointer 2 pointer of RegisteredHostContext
1292  * @param key current key code
1293  * @param value value in the hash map
1294  * @return #GNUNET_YES if we should continue to
1295  *         iterate,
1296  *         #GNUNET_NO if not.
1297  */
1298 static int
1299 reghost_match_iterator (void *cls,
1300                         const struct GNUNET_HashCode *key,
1301                         void *value)
1302 {
1303   struct RegisteredHostContext **rh = cls;
1304   struct RegisteredHostContext *rh_val = value;
1305
1306   if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1307   {
1308     GNUNET_free (*rh);
1309     *rh = rh_val;
1310     return GNUNET_NO;
1311   }
1312   return GNUNET_YES;
1313 }
1314
1315
1316 /**
1317  * Function to generate the hashcode corresponding to a RegisteredHostContext
1318  *
1319  * @param reg_host the host which is being registered in RegisteredHostContext
1320  * @param host the host of the controller which has to connect to the above rhost
1321  * @return the hashcode
1322  */
1323 static struct GNUNET_HashCode
1324 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1325             struct GNUNET_TESTBED_Host *host)
1326 {
1327   struct GNUNET_HashCode hash;
1328   uint32_t host_ids[2];
1329
1330   host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1331   host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1332   GNUNET_CRYPTO_hash (host_ids, sizeof(host_ids), &hash);
1333   return hash;
1334 }
1335
1336
1337 /**
1338  * Checks if the given host is registered at the given slave.
1339  *
1340  * @param slave the slave where registration has to be checked.  The check is
1341  *          actually done through a locally maintained hashmap.  No
1342  *          communication with the slave is involved.
1343  * @param host the host to register
1344  * @return If the given host is not registered already or the registration is
1345  *           pending, it returns the registration context.  Any overlay connects
1346  *           to be forwarded should be queued in the context so that they can be
1347  *           executed when the registration is completed.  If the given host is
1348  *           already registered, NULL is returned.
1349  */
1350 static struct RegisteredHostContext *
1351 register_host (struct Slave *slave,
1352                struct GNUNET_TESTBED_Host *host)
1353 {
1354   struct GNUNET_HashCode hash;
1355   struct RegisteredHostContext *rhc;
1356
1357   rhc = GNUNET_new (struct RegisteredHostContext);
1358   rhc->reg_host = host;
1359   rhc->host = GST_host_list[slave->host_id];
1360   GNUNET_assert (NULL != rhc->reg_host);
1361   GNUNET_assert (NULL != rhc->host);
1362   rhc->state = RHC_INIT;
1363   hash = hash_hosts (rhc->reg_host, rhc->host);
1364   if ((GNUNET_NO ==
1365        GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map,
1366                                                &hash)) ||
1367       (GNUNET_SYSERR !=
1368        GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1369                                                    &hash,
1370                                                    reghost_match_iterator,
1371                                                    &rhc)))
1372   {
1373     /* create and add a new registerd host context */
1374     /* add the focc to its queue */
1375     GNUNET_CONTAINER_multihashmap_put (slave->reghost_map,
1376                                        &hash,
1377                                        rhc,
1378                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1379     GST_queue_host_registration (slave,
1380                                  host_registration_comp,
1381                                  rhc,
1382                                  rhc->reg_host);
1383   }
1384   else
1385   {
1386     /* rhc is now set to the existing one from the hash map by
1387      * reghost_match_iterator() */
1388     /* if queue is empty then ignore creating focc and proceed with normal
1389      * forwarding */
1390     if (RHC_DONE == rhc->state)
1391       return NULL;
1392   }
1393   return rhc;
1394 }
1395
1396
1397 /**
1398  * Forwards the overlay connect request to a slave controller.  Before
1399  * forwarding, any hosts which are needed to be known by the slave controller to
1400  * execute the overlay connect request are registered at slave.
1401  *
1402  * @param msg the overlay connect request message to be forwarded
1403  * @param client the client to which the status of the forwarded request has to
1404  *          be notified
1405  */
1406 static void
1407 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1408                          struct GNUNET_SERVICE_Client *client)
1409 {
1410   struct ForwardedOperationContext *fopc;
1411   struct Route *route_to_peer2_host;
1412   struct Route *route_to_peer1_host;
1413   struct Peer *peer;
1414   struct RegisteredHostContext *rhc;
1415   struct ForwardedOverlayConnectContext *focc;
1416   uint64_t op_id;
1417   uint32_t peer2_host_id;
1418   uint32_t p1;
1419   uint32_t p2;
1420
1421   p1 = ntohl (msg->peer1);
1422   p2 = ntohl (msg->peer2);
1423   op_id = GNUNET_ntohll (msg->operation_id);
1424   peer2_host_id = ntohl (msg->peer2_host_id);
1425   GNUNET_assert (VALID_PEER_ID (p1));
1426   GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1427   peer = GST_peer_list[p1];
1428   GNUNET_assert (GNUNET_YES == peer->is_remote);
1429   LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1430   route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1431   route_to_peer1_host = GST_find_dest_route
1432                           (peer->details.remote.remote_host_id);
1433   GNUNET_assert (NULL != route_to_peer1_host);
1434   if ((NULL != route_to_peer2_host) &&
1435       (route_to_peer1_host->dest == route_to_peer2_host->dest))
1436     goto forward;
1437   /* Peer2 is either with us OR peer1 and peer2 can be reached through
1438      different subtrees OR peer2 is on a subtree unknown to us */
1439   if (NULL != (rhc = register_host (peer->details.remote.slave,
1440                                     GST_host_list[peer2_host_id])))
1441   {
1442     LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1,
1443                p2);
1444     focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1445     focc->rhc = rhc;
1446     focc->peer1 = p1;
1447     focc->peer2 = p2;
1448     focc->peer2_host_id = peer2_host_id;
1449     focc->orig_msg = GNUNET_copy_message (&msg->header);
1450     focc->operation_id = op_id;
1451     focc->client = client;
1452     GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1453                                       rhc->focc_dll_tail,
1454                                       focc);
1455     return;
1456   }
1457
1458 forward:
1459   LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1,
1460              p2);
1461   fopc = GNUNET_new (struct ForwardedOperationContext);
1462   fopc->client = client;
1463   fopc->operation_id = op_id;
1464   fopc->type = OP_OVERLAY_CONNECT;
1465   fopc->opc =
1466     GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1467                                            slave->controller, op_id,
1468                                            &msg->header,
1469                                            &GST_forwarded_operation_reply_relay,
1470                                            fopc);
1471   fopc->timeout_task =
1472     GNUNET_SCHEDULER_add_delayed (GST_timeout,
1473                                   &GST_forwarded_operation_timeout,
1474                                   fopc);
1475   GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
1476                                     fopcq_tail,
1477                                     fopc);
1478 }
1479
1480
1481 /**
1482  * Callback called when a connection to the controller of peer2 has been
1483  * established
1484  *
1485  * @param cls the overlay connect contexts
1486  * @param c handle to the controller connection
1487  */
1488 static void
1489 p2_controller_connect_cb (void *cls,
1490                           struct GNUNET_TESTBED_Controller *c)
1491 {
1492   struct OverlayConnectContext *occ = cls;
1493   struct RemotePeer2Context *rp2c;
1494   struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1495
1496   GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1497   rp2c = &occ->p2ctx.remote;
1498   rp2c->ncn = NULL;
1499   rp2c->p2c = c;
1500   cmsg.header.size =
1501     htons (sizeof(struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1502   cmsg.header.type =
1503     htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1504   cmsg.peer_id = htonl (occ->other_peer_id);
1505   cmsg.operation_id = GNUNET_htonll (occ->op_id);
1506   rp2c->opc =
1507     GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1508                                            occ->op_id,
1509                                            &cmsg.header,
1510                                            &overlay_connect_get_config,
1511                                            occ);
1512   GNUNET_free_non_null (occ->emsg);
1513   GNUNET_asprintf (&occ->emsg,
1514                    "0x%llx: Timeout while getting peer identity of peer "
1515                    "with id: %u",
1516                    occ->op_id,
1517                    occ->other_peer_id);
1518 }
1519
1520
1521 /**
1522  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages
1523  *
1524  * @param cls identification of the client
1525  * @param msg the actual message
1526  */
1527 void
1528 handle_overlay_connect (void *cls,
1529                         const struct GNUNET_TESTBED_OverlayConnectMessage *msg)
1530 {
1531   struct GNUNET_SERVICE_Client *client = cls;
1532   struct Peer *peer;
1533   struct Peer *peer2;
1534   struct OverlayConnectContext *occ;
1535   struct Neighbour *p2n;
1536   uint64_t operation_id;
1537   uint32_t p1;
1538   uint32_t p2;
1539   uint32_t peer2_host_id;
1540
1541   p1 = ntohl (msg->peer1);
1542   p2 = ntohl (msg->peer2);
1543   if (! VALID_PEER_ID (p1))
1544   {
1545     GNUNET_break (0);
1546     GNUNET_SERVICE_client_drop (client);
1547     return;
1548   }
1549   peer = GST_peer_list[p1];
1550   operation_id = GNUNET_ntohll (msg->operation_id);
1551   LOG_DEBUG
1552     ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
1553     p1,
1554     p2,
1555     operation_id);
1556   peer2_host_id = ntohl (msg->peer2_host_id);
1557   if (GNUNET_YES == peer->is_remote)
1558   {
1559     if (! VALID_HOST_ID (peer2_host_id))
1560     {
1561       GNUNET_break (0);
1562       GNUNET_SERVICE_client_drop (client);
1563       return;
1564     }
1565     forward_overlay_connect (msg, client);
1566     GNUNET_SERVICE_client_continue (client);
1567     return;
1568   }
1569   p2n = NULL;
1570   occ = GNUNET_new (struct OverlayConnectContext);
1571   occ->type = OCC_TYPE_LOCAL;
1572   if (! VALID_PEER_ID (p2))         /* May be peer2 is on a another controller */
1573   {
1574     if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1575     {
1576       if (! VALID_HOST_ID (peer2_host_id))
1577       {
1578         GNUNET_break (0);
1579         LOG (GNUNET_ERROR_TYPE_WARNING,
1580              "0x%llx: Peer %u's host not in our neighbours list\n",
1581              operation_id, p2);
1582         GNUNET_SERVICE_client_drop (client);
1583         GNUNET_free (occ);
1584         return;
1585       }
1586       p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1587     }
1588     occ->type = OCC_TYPE_REMOTE_LATERAL;
1589     occ->p2ctx.remote.p2n = p2n;
1590   }
1591   else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1592   {
1593     occ->type = OCC_TYPE_REMOTE_SLAVE;
1594     occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1595   }
1596   GNUNET_CONTAINER_DLL_insert_tail (occq_head,
1597                                     occq_tail,
1598                                     occ);
1599   occ->client = client;
1600   occ->other_peer_id = p2;
1601   GST_peer_list[p1]->reference_cnt++;
1602   occ->peer = GST_peer_list[p1];
1603   occ->op_id = operation_id;
1604   GNUNET_assert (NULL == occ->timeout_task);
1605   occ->timeout_task =
1606     GNUNET_SCHEDULER_add_delayed (GST_timeout,
1607                                   &timeout_overlay_connect,
1608                                   occ);
1609   switch (occ->type)
1610   {
1611   case OCC_TYPE_REMOTE_LATERAL:
1612     GNUNET_asprintf (&occ->emsg,
1613                      "0x%llx: Timeout while acquiring connection to peer %u's "
1614                      "host: %u\n",
1615                      occ->op_id,
1616                      occ->other_peer_id,
1617                      peer2_host_id);
1618     occ->p2ctx.remote.ncn
1619       = GST_neighbour_get_connection (p2n,
1620                                       &p2_controller_connect_cb,
1621                                       occ);
1622     break;
1623
1624   case OCC_TYPE_REMOTE_SLAVE:
1625     p2_controller_connect_cb (occ,
1626                               occ->p2ctx.remote.p2c);
1627     break;
1628
1629   case OCC_TYPE_LOCAL:
1630     peer2 = GST_peer_list[occ->other_peer_id];
1631     peer2->reference_cnt++;
1632     GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1633                                       &occ->other_peer_identity);
1634     GNUNET_asprintf (&occ->emsg,
1635                      "0x%llx: Timeout while connecting to CORE of peer with "
1636                      "id: %u",
1637                      occ->op_id,
1638                      occ->peer->id);
1639     occ->cgh_ch =
1640       GST_connection_pool_get_handle (occ->peer->id,
1641                                       occ->peer->details.local.cfg,
1642                                       GST_CONNECTIONPOOL_SERVICE_CORE,
1643                                       occ_cache_get_handle_core_cb, occ,
1644                                       &occ->other_peer_identity,
1645                                       &overlay_connect_notify, occ);
1646     break;
1647   }
1648   GNUNET_SERVICE_client_continue (client);
1649 }
1650
1651
1652 /**
1653  * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1654  * with it
1655  *
1656  * @param rocc the RemoteOverlayConnectCtx
1657  */
1658 static void
1659 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1660 {
1661   LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
1662              rocc->op_id);
1663   if (NULL != rocc->attempt_connect_task_id)
1664     GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1665   if (NULL != rocc->timeout_rocc_task_id)
1666     GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1667   if (NULL != rocc->ohh)
1668     GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1669   if (NULL != rocc->tcc.csh)
1670     GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
1671   GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
1672   GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
1673   GNUNET_assert (rocc->peer->reference_cnt > 0);
1674   rocc->peer->reference_cnt--;
1675   if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1676       (0 == rocc->peer->reference_cnt))
1677     GST_destroy_peer (rocc->peer);
1678   GNUNET_free_non_null (rocc->hello);
1679   GNUNET_CONTAINER_DLL_remove (roccq_head,
1680                                roccq_tail,
1681                                rocc);
1682   GNUNET_free (rocc);
1683 }
1684
1685
1686 /**
1687  * Task to timeout rocc and cleanit up
1688  *
1689  * @param cls the RemoteOverlayConnectCtx
1690  */
1691 static void
1692 timeout_rocc_task (void *cls)
1693 {
1694   struct RemoteOverlayConnectCtx *rocc = cls;
1695
1696   GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1697   rocc->timeout_rocc_task_id = NULL;
1698   LOG_DEBUG ("0x%llx: rocc timed out\n",
1699              rocc->op_id);
1700   cleanup_rocc (rocc);
1701 }
1702
1703
1704 /**
1705  * Function called to notify transport users that another
1706  * peer connected to us.
1707  *
1708  * @param cls the RemoteOverlayConnectContext
1709  * @param new_peer the peer that connected
1710  */
1711 static void
1712 cache_transport_peer_connect_notify (void *cls,
1713                                      const struct GNUNET_PeerIdentity *new_peer)
1714 {
1715   struct RemoteOverlayConnectCtx *rocc = cls;
1716
1717   LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
1718              rocc->op_id);
1719   GNUNET_assert (0 ==
1720                  memcmp (new_peer, &rocc->a_id,
1721                          sizeof(struct GNUNET_PeerIdentity)));
1722   LOG_DEBUG ("0x%llx: Peer %s connected\n",
1723              rocc->op_id,
1724              GNUNET_i2s (&rocc->a_id));
1725   cleanup_rocc (rocc);
1726 }
1727
1728
1729 /**
1730  * Task to offer the HELLO message to the peer and ask it to connect to the peer
1731  * whose identity is in RemoteOverlayConnectCtx
1732  *
1733  * @param cls the RemoteOverlayConnectCtx
1734  */
1735 static void
1736 attempt_connect_task (void *cls);
1737
1738
1739 /**
1740  * Task that is run when hello has been sent If tc->reason =
1741  * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1742  * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1743  *
1744  * @param cls the overlay connect context
1745  */
1746 static void
1747 rocc_hello_sent_cb (void *cls)
1748 {
1749   struct RemoteOverlayConnectCtx *rocc = cls;
1750
1751   rocc->ohh = NULL;
1752   GNUNET_assert (NULL == rocc->attempt_connect_task_id);
1753   LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
1754              rocc->op_id,
1755              GNUNET_i2s (&rocc->a_id),
1756              rocc->peer->id);
1757   rocc->tcc.cgh_p2_ats =
1758     GST_connection_pool_get_handle (rocc->peer->id,
1759                                     rocc->peer->details.local.cfg,
1760                                     GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
1761                                     &occ_cache_get_handle_ats_rocc_cb,
1762                                     rocc, NULL, NULL, NULL);
1763 }
1764
1765
1766 /**
1767  * Task to offer the HELLO message to the peer and ask it to connect to the peer
1768  * whose identity is in RemoteOverlayConnectCtx
1769  *
1770  * @param cls the RemoteOverlayConnectCtx
1771  */
1772 static void
1773 attempt_connect_task (void *cls)
1774 {
1775   struct RemoteOverlayConnectCtx *rocc = cls;
1776
1777   GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1778   rocc->attempt_connect_task_id = NULL;
1779   LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
1780              rocc->op_id,
1781              GNUNET_i2s (&rocc->a_id),
1782              rocc->peer->id);
1783   rocc->ohh =
1784     GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
1785                                   rocc->hello,
1786                                   &rocc_hello_sent_cb,
1787                                   rocc);
1788   if (NULL == rocc->ohh)
1789     rocc->attempt_connect_task_id =
1790       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1791                                       (GNUNET_TIME_UNIT_MILLISECONDS,
1792                                       100
1793                                       + GNUNET_CRYPTO_random_u32
1794                                         (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1795                                     &attempt_connect_task, rocc);
1796 }
1797
1798
1799 /**
1800  * Callback from cache with needed handles set
1801  *
1802  * @param cls the closure passed to GST_cache_get_handle_transport()
1803  * @param ch the handle to CORE. Can be NULL if it is not requested
1804  * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1805  * @param ac the handle to ATS. Can be NULL if it is not requested
1806  * @param ignore_ peer identity which is ignored in this callback
1807  */
1808 static void
1809 rocc_cache_get_handle_transport_cb (void *cls,
1810                                     struct GNUNET_CORE_Handle *ch,
1811                                     struct GNUNET_TRANSPORT_CoreHandle *th,
1812                                     struct GNUNET_ATS_ConnectivityHandle *ac,
1813                                     const struct GNUNET_PeerIdentity *ignore_,
1814                                     const struct
1815                                     GNUNET_CONFIGURATION_Handle *cfg)
1816 {
1817   struct RemoteOverlayConnectCtx *rocc = cls;
1818
1819   if (NULL == th)
1820   {
1821     rocc->timeout_rocc_task_id =
1822       GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1823     return;
1824   }
1825   rocc->tcc.th_ = th;
1826   rocc->tcc.cfg = cfg;
1827   if (NULL !=
1828       GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_,
1829                                     &rocc->a_id))
1830   {
1831     LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
1832                rocc->op_id,
1833                GNUNET_i2s (&rocc->a_id),
1834                rocc->peer->id);
1835     cleanup_rocc (rocc);
1836     return;
1837   }
1838   rocc->attempt_connect_task_id =
1839     GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1840 }
1841
1842
1843 /**
1844  * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1845  *
1846  * @param cls identification of the client
1847  * @param msg the actual message
1848  * @return #GNUNET_OK if @a msg is well-formed
1849  */
1850 int
1851 check_remote_overlay_connect (void *cls,
1852                               const struct
1853                               GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1854 {
1855   uint32_t peer_id;
1856   uint16_t msize;
1857   uint16_t hsize;
1858
1859   msize = ntohs (msg->header.size);
1860   if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))
1861   {
1862     GNUNET_break (0);
1863     return GNUNET_SYSERR;
1864   }
1865   hsize = ntohs (msg->hello->size);
1866   if ((sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1867       msize)
1868   {
1869     GNUNET_break (0);
1870     return GNUNET_SYSERR;
1871   }
1872   peer_id = ntohl (msg->peer);
1873   if ((peer_id >= GST_peer_list_size) ||
1874       (NULL == GST_peer_list[peer_id]))
1875   {
1876     GNUNET_break_op (0);
1877     return GNUNET_SYSERR;
1878   }
1879   return GNUNET_OK;
1880 }
1881
1882
1883 /**
1884  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1885  *
1886  * @param cls identification of the client
1887  * @param msg the actual message
1888  */
1889 void
1890 handle_remote_overlay_connect (void *cls,
1891                                const struct
1892                                GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1893 {
1894   struct GNUNET_SERVICE_Client *client = cls;
1895   struct RemoteOverlayConnectCtx *rocc;
1896   struct Peer *peer;
1897   struct GNUNET_PeerIdentity pid;
1898   static char pid_str[16];
1899   uint32_t peer_id;
1900   uint16_t hsize;
1901
1902   hsize = ntohs (msg->hello->size);
1903   peer_id = ntohl (msg->peer);
1904   peer = GST_peer_list[peer_id];
1905   if (GNUNET_YES == peer->is_remote)
1906   {
1907     struct GNUNET_MessageHeader *msg2;
1908
1909     msg2 = GNUNET_copy_message (&msg->header);
1910     GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1911                                    msg2);
1912     GNUNET_SERVICE_client_continue (client);
1913     return;
1914   }
1915   rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1916   rocc->op_id = GNUNET_ntohll (msg->operation_id);
1917   GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
1918                                     roccq_tail,
1919                                     rocc);
1920   rocc->a_id = msg->peer_identity;
1921   GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1922                                     &pid);
1923   (void) GNUNET_strlcpy (pid_str,
1924                          GNUNET_i2s (&pid),
1925                          sizeof(pid_str));
1926   LOG_DEBUG (
1927     "0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
1928     rocc->op_id,
1929     pid_str,
1930     GNUNET_i2s (&rocc->a_id),
1931     hsize);
1932   rocc->peer = peer;
1933   rocc->peer->reference_cnt++;
1934   rocc->hello = GNUNET_malloc (hsize);
1935   GNUNET_memcpy (rocc->hello,
1936                  msg->hello,
1937                  hsize);
1938   rocc->tcc.cgh_p2_th =
1939     GST_connection_pool_get_handle (peer_id,
1940                                     rocc->peer->details.local.cfg,
1941                                     GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1942                                     &rocc_cache_get_handle_transport_cb,
1943                                     rocc,
1944                                     &rocc->a_id,
1945                                     &cache_transport_peer_connect_notify,
1946                                     rocc);
1947   rocc->timeout_rocc_task_id =
1948     GNUNET_SCHEDULER_add_delayed (GST_timeout,
1949                                   &timeout_rocc_task,
1950                                   rocc);
1951   GNUNET_SERVICE_client_continue (client);
1952 }
1953
1954
1955 /**
1956  * Clears all pending overlay connect contexts in queue
1957  */
1958 void
1959 GST_free_occq ()
1960 {
1961   struct OverlayConnectContext *occ;
1962
1963   while (NULL != (occ = occq_head))
1964     cleanup_occ (occ);
1965 }
1966
1967
1968 /**
1969  * Clears all pending remote overlay connect contexts in queue
1970  */
1971 void
1972 GST_free_roccq ()
1973 {
1974   struct RemoteOverlayConnectCtx *rocc;
1975
1976   while (NULL != (rocc = roccq_head))
1977     cleanup_rocc (rocc);
1978 }