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