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