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