dead code
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed.c
1 /*
2   This file is part of GNUnet.
3   (C) 2012 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.c
23  * @brief implementation of the TESTBED service
24  * @author Sree Harsha Totakura
25  */
26
27 #include "platform.h"
28 #include "gnunet_service_lib.h"
29 #include "gnunet_server_lib.h"
30 #include "gnunet_transport_service.h"
31 #include "gnunet_core_service.h"
32 #include "gnunet_hello_lib.h"
33 #include <zlib.h>
34
35 #include "gnunet_testbed_service.h"
36 #include "testbed.h"
37 #include "testbed_api.h"
38 #include "testbed_api_hosts.h"
39 #include "gnunet_testing_lib-new.h"
40
41 /**
42  * Generic logging
43  */
44 #define LOG(kind,...)                           \
45   GNUNET_log (kind, __VA_ARGS__)
46
47 /**
48  * Debug logging
49  */
50 #define LOG_DEBUG(...)                          \
51   LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
52
53 /**
54  * By how much should the arrays lists grow
55  */
56 #define LIST_GROW_STEP 10
57
58 /**
59  * Default timeout for operations which may take some time
60  */
61 #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
62
63 /**
64  * The main context information associated with the client which started us
65  */
66 struct Context
67 {
68   /**
69    * The client handle associated with this context
70    */
71   struct GNUNET_SERVER_Client *client;
72
73   /**
74    * The network address of the master controller
75    */
76   char *master_ip;
77
78   /**
79    * The TESTING system handle for starting peers locally
80    */
81   struct GNUNET_TESTING_System *system;
82   
83   /**
84    * Our host id according to this context
85    */
86   uint32_t host_id;
87 };
88
89
90 /**
91  * The message queue for sending messages to clients
92  */
93 struct MessageQueue
94 {
95   /**
96    * The message to be sent
97    */
98   struct GNUNET_MessageHeader *msg;
99
100   /**
101    * The client to send the message to
102    */
103   struct GNUNET_SERVER_Client *client;
104
105   /**
106    * next pointer for DLL
107    */
108   struct MessageQueue *next;
109
110   /**
111    * prev pointer for DLL
112    */
113   struct MessageQueue *prev;
114 };
115
116
117 /**
118  * The structure for identifying a shared service
119  */
120 struct SharedService
121 {
122   /**
123    * The name of the shared service
124    */
125   char *name;
126
127   /**
128    * Number of shared peers per instance of the shared service
129    */
130   uint32_t num_shared;
131
132   /**
133    * Number of peers currently sharing the service
134    */
135   uint32_t num_sharing;
136 };
137
138
139 /**
140  * A routing entry
141  */
142 struct Route
143 {
144   /**
145    * destination host
146    */
147   uint32_t dest;
148
149   /**
150    * The destination host is reachable thru
151    */
152   uint32_t thru;
153 };
154
155
156 /**
157  * Context information used while linking controllers
158  */
159 struct LinkControllersContext;
160
161
162 /**
163  * A DLL of host registrations to be made
164  */
165 struct HostRegistration
166 {
167   /**
168    * next registration in the DLL
169    */
170   struct HostRegistration *next;
171
172   /**
173    * previous registration in the DLL
174    */
175   struct HostRegistration *prev;
176
177   /**
178    * The callback to call after this registration's status is available
179    */
180   GNUNET_TESTBED_HostRegistrationCompletion cb;
181
182   /**
183    * The closure for the above callback
184    */
185   void *cb_cls;
186
187   /**
188    * The host that has to be registered
189    */
190   struct GNUNET_TESTBED_Host *host;
191 };
192
193
194 /**
195  * This context information will be created for each host that is registered at
196  * slave controllers during overlay connects.
197  */
198 struct RegisteredHostContext
199 {
200   /**
201    * The host which is being registered
202    */
203   struct GNUNET_TESTBED_Host *reg_host;
204
205   /**
206    * The host of the controller which has to connect to the above rhost
207    */
208   struct GNUNET_TESTBED_Host *host;
209
210   /**
211    * The gateway to which this operation is forwarded to
212    */
213   struct Slave *gateway;
214
215   /**
216    * The gateway through which peer2's controller can be reached
217    */
218   struct Slave *gateway2;
219
220   /**
221    * Handle for sub-operations
222    */
223   struct GNUNET_TESTBED_Operation *sub_op;
224
225   /**
226    * The client which initiated the link controller operation
227    */
228   struct GNUNET_SERVER_Client *client;
229
230   /**
231    * Head of the ForwardedOverlayConnectContext DLL
232    */
233   struct ForwardedOverlayConnectContext *focc_dll_head;
234
235   /**
236    * Tail of the ForwardedOverlayConnectContext DLL
237    */
238   struct ForwardedOverlayConnectContext *focc_dll_tail;
239   
240   /**
241    * Enumeration of states for this context
242    */
243   enum RHCState {
244
245     /**
246      * The initial state
247      */
248     RHC_INIT = 0,
249
250     /**
251      * State where we attempt to get peer2's controller configuration
252      */
253     RHC_GET_CFG,
254
255     /**
256      * State where we attempt to link the controller of peer 1 to the controller
257      * of peer2
258      */
259     RHC_LINK,
260
261     /**
262      * State where we attempt to do the overlay connection again
263      */
264     RHC_OL_CONNECT
265     
266   } state;
267
268 };
269
270
271 /**
272  * Structure representing a connected(directly-linked) controller
273  */
274 struct Slave
275 {
276   /**
277    * The controller process handle if we had started the controller
278    */
279   struct GNUNET_TESTBED_ControllerProc *controller_proc;
280
281   /**
282    * The controller handle
283    */
284   struct GNUNET_TESTBED_Controller *controller;
285
286   /**
287    * The configuration of the slave. Cannot be NULL
288    */
289   struct GNUNET_CONFIGURATION_Handle *cfg;
290
291   /**
292    * handle to lcc which is associated with this slave startup. Should be set to
293    * NULL when the slave has successfully started up
294    */
295   struct LinkControllersContext *lcc;
296
297   /**
298    * Head of the host registration DLL
299    */
300   struct HostRegistration *hr_dll_head;
301
302   /**
303    * Tail of the host registration DLL
304    */
305   struct HostRegistration *hr_dll_tail;
306
307   /**
308    * The current host registration handle
309    */
310   struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
311
312   /**
313    * Hashmap to hold Registered host contexts
314    */
315   struct GNUNET_CONTAINER_MultiHashMap *reghost_map;
316
317   /**
318    * The id of the host this controller is running on
319    */
320   uint32_t host_id;
321
322 };
323
324
325 /**
326  * States of LCFContext
327  */
328 enum LCFContextState
329 {
330   /**
331    * The Context has been initialized; Nothing has been done on it
332    */
333   INIT,
334
335   /**
336    * Delegated host has been registered at the forwarding controller
337    */
338   DELEGATED_HOST_REGISTERED,
339   
340   /**
341    * The slave host has been registred at the forwarding controller
342    */
343   SLAVE_HOST_REGISTERED,
344   
345   /**
346    * The context has been finished (may have error)
347    */
348   FINISHED
349 };
350
351
352 /**
353  * Link controllers request forwarding context
354  */
355 struct LCFContext
356 {
357   /**
358    * The gateway which will pass the link message to delegated host
359    */
360   struct Slave *gateway;
361
362   /**
363    * The controller link message that has to be forwarded to
364    */
365   struct GNUNET_TESTBED_ControllerLinkMessage *msg;
366
367   /**
368    * The client which has asked to perform this operation
369    */
370   struct GNUNET_SERVER_Client *client;
371
372   /**
373    * Handle for operations which are forwarded while linking controllers
374    */
375   struct ForwardedOperationContext *fopc;
376
377   /**
378    * The id of the operation which created this context
379    */
380   uint64_t operation_id;
381
382   /**
383    * The state of this context
384    */
385   enum LCFContextState state;
386
387   /**
388    * The delegated host
389    */
390   uint32_t delegated_host_id;
391
392   /**
393    * The slave host
394    */
395   uint32_t slave_host_id;
396
397 };
398
399
400 /**
401  * Structure of a queue entry in LCFContext request queue
402  */
403 struct LCFContextQueue
404 {
405   /**
406    * The LCFContext
407    */
408   struct LCFContext *lcf;
409
410   /**
411    * Head prt for DLL
412    */
413   struct LCFContextQueue *next;
414
415   /**
416    * Tail ptr for DLL
417    */
418   struct LCFContextQueue *prev;
419 };
420
421
422 /**
423  * A peer
424  */
425 struct Peer
426 {
427   
428   union
429   {
430     struct
431     {
432       /**
433        * The peer handle from testing API
434        */
435       struct GNUNET_TESTING_Peer *peer;
436
437       /**
438        * The modified (by GNUNET_TESTING_peer_configure) configuration this
439        * peer is configured with
440        */
441       struct GNUNET_CONFIGURATION_Handle *cfg;
442       
443       /**
444        * Is the peer running
445        */
446       int is_running;
447
448     } local;
449
450     struct
451     {
452       /**
453        * The slave this peer is started through
454        */
455       struct Slave *slave;
456
457       /**
458        * The id of the remote host this peer is running on
459        */
460       uint32_t remote_host_id;
461
462     } remote;
463
464   } details;
465
466   /**
467    * Is this peer locally created?
468    */
469   int is_remote;
470
471   /**
472    * Our local reference id for this peer
473    */
474   uint32_t id;
475
476   /**
477    * References to peers are using in forwarded overlay contexts and remote
478    * overlay connect contexts. A peer can only be destroyed after all such
479    * contexts are destroyed. For this, we maintain a reference counter. When we
480    * use a peer in any such context, we increment this counter. We decrement it
481    * when we are destroying these contexts
482    */
483   uint32_t reference_cnt;
484
485   /**
486    * While destroying a peer, due to the fact that there could be references to
487    * this peer, we delay the peer destroy to a further time. We do this by using
488    * this flag to destroy the peer while destroying a context in which this peer
489    * has been used. When the flag is set to 1 and reference_cnt = 0 we destroy
490    * the peer
491    */
492   uint32_t destroy_flag;
493
494 };
495
496
497 /**
498  * Context information for connecting 2 peers in overlay
499  */
500 struct OverlayConnectContext
501 {
502   /**
503    * The next pointer for maintaining a DLL
504    */
505   struct OverlayConnectContext *next;
506
507   /**
508    * The prev pointer for maintaining a DLL
509    */
510   struct OverlayConnectContext *prev;
511   
512   /**
513    * The client which has requested for overlay connection
514    */
515   struct GNUNET_SERVER_Client *client;
516
517   /**
518    * the peer which has to connect to the other peer
519    */
520   struct Peer *peer;
521
522   /**
523    * Transport handle of the first peer to get its HELLO
524    */
525   struct GNUNET_TRANSPORT_Handle *p1th;
526
527   /**
528    * Transport handle of other peer to offer first peer's HELLO
529    */
530   struct GNUNET_TRANSPORT_Handle *p2th;
531
532   /**
533    * Core handles of the first peer; used to notify when second peer connects to it
534    */
535   struct GNUNET_CORE_Handle *ch;
536
537   /**
538    * HELLO of the other peer
539    */
540   struct GNUNET_MessageHeader *hello;
541
542   /**
543    * Get hello handle to acquire HELLO of first peer
544    */
545   struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
546
547   /**
548    * The error message we send if this overlay connect operation has timed out
549    */
550   char *emsg;
551
552   /**
553    * Operation context for suboperations
554    */
555   struct OperationContext *opc;
556
557   /**
558    * Controller of peer 2; NULL if the peer is local
559    */
560   struct GNUNET_TESTBED_Controller *peer2_controller;
561
562   /**
563    * The peer identity of the first peer
564    */
565   struct GNUNET_PeerIdentity peer_identity;
566
567   /**
568    * The peer identity of the other peer
569    */
570   struct GNUNET_PeerIdentity other_peer_identity;
571
572   /**
573    * The id of the operation responsible for creating this context
574    */
575   uint64_t op_id;
576
577   /**
578    * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
579    * connect to peer 2
580    */
581   GNUNET_SCHEDULER_TaskIdentifier send_hello_task;
582
583   /**
584    * The id of the overlay connect timeout task
585    */
586   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
587
588   /**
589    * The id of the cleanup task
590    */
591   GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
592
593   /**
594    * The id of peer A
595    */
596   uint32_t peer_id;
597
598   /**
599    * The id of peer B
600    */
601   uint32_t other_peer_id;
602
603 };
604
605
606 /**
607  * Context information for RequestOverlayConnect
608  * operations. RequestOverlayConnect is used when peers A, B reside on different
609  * hosts and the host controller for peer B is asked by the host controller of
610  * peer A to make peer B connect to peer A
611  */
612 struct RequestOverlayConnectContext
613 {
614   /**
615    * the next pointer for DLL
616    */
617   struct RequestOverlayConnectContext *next;
618
619   /**
620    * the prev pointer for DLL
621    */
622   struct RequestOverlayConnectContext *prev;
623
624   /**
625    * The transport handle of peer B
626    */
627   struct GNUNET_TRANSPORT_Handle *th;
628   
629   /**
630    * Peer A's HELLO
631    */
632   struct GNUNET_MessageHeader *hello;
633
634   /**
635    * The peer identity of peer A
636    */
637   struct GNUNET_PeerIdentity a_id;
638
639   /**
640    * Task for offering HELLO of A to B and doing try_connect
641    */
642   GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task_id;
643   
644   /**
645    * Task to timeout RequestOverlayConnect
646    */
647   GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id;
648   
649 };
650
651
652 /**
653  * Context information for operations forwarded to subcontrollers
654  */
655 struct ForwardedOperationContext
656 {
657   /**
658    * The next pointer for DLL
659    */
660   struct ForwardedOperationContext *next;
661
662   /**
663    * The prev pointer for DLL
664    */
665   struct ForwardedOperationContext *prev;
666   
667   /**
668    * The generated operation context
669    */
670   struct OperationContext *opc;
671
672   /**
673    * The client to which we have to reply
674    */
675   struct GNUNET_SERVER_Client *client;
676
677   /**
678    * Closure pointer
679    */
680   void *cls;
681
682   /**
683    * Task ID for the timeout task
684    */
685   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
686
687   /**
688    * The id of the operation that has been forwarded
689    */
690   uint64_t operation_id;
691
692   /**
693    * The type of the operation which is forwarded
694    */
695   enum OperationType type;
696
697 };
698
699
700 /**
701  * Context information used while linking controllers
702  */
703 struct LinkControllersContext
704 {
705   /**
706    * The client which initiated the link controller operation
707    */
708   struct GNUNET_SERVER_Client *client;
709
710   /**
711    * The ID of the operation
712    */
713   uint64_t operation_id;
714
715 };
716
717
718 /**
719  * Context information to used during operations which forward the overlay
720  * connect message
721  */
722 struct ForwardedOverlayConnectContext
723 {
724   /**
725    * next ForwardedOverlayConnectContext in the DLL
726    */
727   struct ForwardedOverlayConnectContext *next;
728
729   /**
730    * previous ForwardedOverlayConnectContext in the DLL
731    */
732   struct ForwardedOverlayConnectContext *prev;
733
734   /**
735    * A copy of the original overlay connect message
736    */
737   struct GNUNET_MessageHeader *orig_msg;
738
739   /**
740    * The id of the operation which created this context information
741    */
742   uint64_t operation_id;
743
744   /**
745    * the id of peer 1
746    */
747   uint32_t peer1;
748   
749   /**
750    * The id of peer 2
751    */
752   uint32_t peer2;
753   
754   /**
755    * Id of the host where peer2 is running
756    */
757   uint32_t peer2_host_id;
758 };
759
760
761
762 /**
763  * The master context; generated with the first INIT message
764  */
765 static struct Context *master_context;
766
767 /**
768  * Our hostname; we give this to all the peers we start
769  */
770 static char *hostname;
771
772
773 /***********/
774 /* Handles */
775 /***********/
776
777 /**
778  * Our configuration
779  */
780 static struct GNUNET_CONFIGURATION_Handle *our_config;
781
782 /**
783  * Current Transmit Handle; NULL if no notify transmit exists currently
784  */
785 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
786
787 /****************/
788 /* Lists & Maps */
789 /****************/
790
791 /**
792  * The head for the LCF queue
793  */
794 static struct LCFContextQueue *lcfq_head;
795
796 /**
797  * The tail for the LCF queue
798  */
799 static struct LCFContextQueue *lcfq_tail;
800
801 /**
802  * The message queue head
803  */
804 static struct MessageQueue *mq_head;
805
806 /**
807  * The message queue tail
808  */
809 static struct MessageQueue *mq_tail;
810
811 /**
812  * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
813  */
814 static struct OverlayConnectContext *occq_head;
815
816 /**
817  * DLL tail for OverlayConnectContext DLL
818  */
819 static struct OverlayConnectContext *occq_tail;
820
821 /**
822  * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
823  * shutdown
824  */
825 static struct RequestOverlayConnectContext *roccq_head;
826
827 /**
828  * DLL tail for RequectOverlayConnectContext DLL
829  */
830 static struct RequestOverlayConnectContext *roccq_tail;
831
832 /**
833  * DLL head for forwarded operation contexts
834  */
835 static struct ForwardedOperationContext *fopcq_head;
836
837 /**
838  * DLL tail for forwarded operation contexts
839  */
840 static struct ForwardedOperationContext *fopcq_tail;
841
842 /**
843  * Array of hosts
844  */
845 static struct GNUNET_TESTBED_Host **host_list;
846
847 /**
848  * A list of routes
849  */
850 static struct Route **route_list;
851
852 /**
853  * A list of directly linked neighbours
854  */
855 static struct Slave **slave_list;
856
857 /**
858  * A list of peers we know about
859  */
860 static struct Peer **peer_list;
861
862 /**
863  * The hashmap of shared services
864  */
865 static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
866
867 /**
868  * The event mask for the events we listen from sub-controllers
869  */
870 static uint64_t event_mask;
871
872 /**
873  * The size of the host list
874  */
875 static uint32_t host_list_size;
876
877 /**
878  * The size of the route list
879  */
880 static uint32_t route_list_size;
881
882 /**
883  * The size of directly linked neighbours list
884  */
885 static uint32_t slave_list_size;
886
887 /**
888  * The size of the peer list
889  */
890 static uint32_t peer_list_size;
891
892 /*********/
893 /* Tasks */
894 /*********/
895
896 /**
897  * The lcf_task handle
898  */
899 static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
900
901 /**
902  * The shutdown task handle
903  */
904 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
905
906
907 /**
908  * Function called to notify a client about the connection begin ready to queue
909  * more data.  "buf" will be NULL and "size" zero if the connection was closed
910  * for writing in the meantime.
911  *
912  * @param cls NULL
913  * @param size number of bytes available in buf
914  * @param buf where the callee should write the message
915  * @return number of bytes written to buf
916  */
917 static size_t
918 transmit_ready_notify (void *cls, size_t size, void *buf)
919 {
920   struct MessageQueue *mq_entry;
921
922   transmit_handle = NULL;
923   mq_entry = mq_head;
924   GNUNET_assert (NULL != mq_entry);
925   if (0 == size)
926     return 0;
927   GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
928   size = ntohs (mq_entry->msg->size);
929   memcpy (buf, mq_entry->msg, size);
930   GNUNET_free (mq_entry->msg);
931   GNUNET_SERVER_client_drop (mq_entry->client);
932   GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
933   GNUNET_free (mq_entry);
934   mq_entry = mq_head;
935   if (NULL != mq_entry)
936     transmit_handle =
937         GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
938                                              ntohs (mq_entry->msg->size),
939                                              GNUNET_TIME_UNIT_FOREVER_REL,
940                                              &transmit_ready_notify, NULL);
941   return size;
942 }
943
944
945 /**
946  * Queues a message in send queue for sending to the service
947  *
948  * @param client the client to whom the queued message has to be sent
949  * @param msg the message to queue
950  */
951 static void
952 queue_message (struct GNUNET_SERVER_Client *client,
953                struct GNUNET_MessageHeader *msg)
954 {
955   struct MessageQueue *mq_entry;
956   uint16_t type;
957   uint16_t size;
958
959   type = ntohs (msg->type);
960   size = ntohs (msg->size);
961   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
962                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
963   mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
964   mq_entry->msg = msg;
965   mq_entry->client = client;
966   GNUNET_SERVER_client_keep (client);
967   LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", type,
968              ntohs (msg->size));
969   GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
970   if (NULL == transmit_handle)
971     transmit_handle =
972         GNUNET_SERVER_notify_transmit_ready (client, size,
973                                              GNUNET_TIME_UNIT_FOREVER_REL,
974                                              &transmit_ready_notify, NULL);
975 }
976
977
978 /**
979  * Similar to GNUNET_realloc; however clears tail part of newly allocated memory
980  *
981  * @param ptr the memory block to realloc
982  * @param size the size of ptr
983  * @param new_size the size to which ptr has to be realloc'ed
984  * @return the newly reallocated memory block
985  */
986 static void *
987 TESTBED_realloc (void *ptr, size_t size, size_t new_size)
988 {
989   ptr = GNUNET_realloc (ptr, new_size);
990   if (new_size > size)
991     (void) memset (ptr + size, 0, new_size - size);
992   return ptr;
993 }
994
995
996 /**
997  * Function to add a host to the current list of known hosts
998  *
999  * @param host the host to add
1000  * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
1001  *           already in use
1002  */
1003 static int
1004 host_list_add (struct GNUNET_TESTBED_Host *host)
1005 {
1006   uint32_t host_id;
1007   uint32_t orig_size;
1008
1009   host_id = GNUNET_TESTBED_host_get_id_ (host);
1010   orig_size = host_list_size;  
1011   if (host_list_size <= host_id)
1012   {
1013     while (host_list_size <= host_id)
1014       host_list_size += LIST_GROW_STEP;
1015     host_list =
1016         TESTBED_realloc (host_list,
1017                          sizeof (struct GNUNET_TESTBED_Host *) * orig_size,
1018                          sizeof (struct GNUNET_TESTBED_Host *)
1019                          * host_list_size);
1020   }
1021   if (NULL != host_list[host_id])
1022   {
1023     LOG_DEBUG ("A host with id: %u already exists\n", host_id);
1024     return GNUNET_SYSERR;
1025   }
1026   host_list[host_id] = host;
1027   return GNUNET_OK;
1028 }
1029
1030
1031 /**
1032  * Adds a route to the route list
1033  *
1034  * @param route the route to add
1035  */
1036 static void
1037 route_list_add (struct Route *route)
1038 {
1039   uint32_t orig_size;
1040
1041   orig_size = route_list_size;  
1042   if (route->dest >= route_list_size)
1043   {
1044     while (route->dest >= route_list_size)
1045       route_list_size += LIST_GROW_STEP;
1046     route_list =
1047         TESTBED_realloc (route_list,
1048                          sizeof (struct Route *) * orig_size,
1049                          sizeof (struct Route *) * route_list_size);
1050   }
1051   GNUNET_assert (NULL == route_list[route->dest]);
1052   route_list[route->dest] = route;
1053 }
1054
1055
1056 /**
1057  * Adds a slave to the slave array
1058  *
1059  * @param slave the slave controller to add
1060  */
1061 static void
1062 slave_list_add (struct Slave *slave)
1063 {
1064   uint32_t orig_size;
1065
1066   orig_size = slave_list_size;  
1067   if (slave->host_id >= slave_list_size)
1068   {
1069     while (slave->host_id >= slave_list_size)
1070       slave_list_size += LIST_GROW_STEP;
1071     slave_list =
1072         TESTBED_realloc (slave_list, sizeof (struct Slave *) * orig_size,
1073                          sizeof (struct Slave *) * slave_list_size);
1074   }
1075   GNUNET_assert (NULL == slave_list[slave->host_id]);
1076   slave_list[slave->host_id] = slave;
1077 }
1078
1079
1080 /**
1081  * Adds a peer to the peer array
1082  *
1083  * @param peer the peer to add
1084  */
1085 static void
1086 peer_list_add (struct Peer *peer)
1087 {
1088   uint32_t orig_size;
1089
1090   orig_size = peer_list_size;
1091   if (peer->id >= peer_list_size)
1092   {
1093     while (peer->id >= peer_list_size)
1094       peer_list_size += LIST_GROW_STEP;
1095     peer_list =
1096         TESTBED_realloc (peer_list, sizeof (struct Peer *) * orig_size,
1097                          sizeof (struct Peer *) * peer_list_size);
1098   }  
1099   GNUNET_assert (NULL == peer_list[peer->id]);
1100   peer_list[peer->id] = peer;
1101 }
1102
1103
1104 /**
1105  * Removes a the give peer from the peer array
1106  *
1107  * @param peer the peer to be removed
1108  */
1109 static void
1110 peer_list_remove (struct Peer *peer)
1111 {
1112   uint32_t id;
1113   uint32_t orig_size;
1114
1115   peer_list[peer->id] = NULL;
1116   orig_size = peer_list_size;
1117   while (peer_list_size >= LIST_GROW_STEP)
1118   {
1119     for (id = peer_list_size - 1;
1120          (id >= peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); id--)
1121       if (NULL != peer_list[id])
1122         break;
1123     if (id != ((peer_list_size - LIST_GROW_STEP) - 1))
1124       break;
1125     peer_list_size -= LIST_GROW_STEP;
1126   }
1127   if (orig_size == peer_list_size)
1128     return;
1129   peer_list =
1130       GNUNET_realloc (peer_list, sizeof (struct Peer *) * peer_list_size);
1131 }
1132
1133
1134 /**
1135  * Finds the route with directly connected host as destination through which
1136  * the destination host can be reached
1137  *
1138  * @param host_id the id of the destination host
1139  * @return the route with directly connected destination host; NULL if no route
1140  *           is found
1141  */
1142 static struct Route *
1143 find_dest_route (uint32_t host_id)
1144 {
1145   struct Route *route;
1146
1147   if (route_list_size <= host_id)
1148     return NULL;
1149   while (NULL != (route = route_list[host_id]))
1150   {
1151     if (route->thru == master_context->host_id)
1152       break;
1153     host_id = route->thru;
1154   }
1155   return route;
1156 }
1157
1158
1159 /**
1160  * Routes message to a host given its host_id
1161  *
1162  * @param host_id the id of the destination host
1163  * @param msg the message to be routed
1164  */
1165 static void
1166 route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
1167 {
1168   GNUNET_break (0);
1169 }
1170
1171
1172 /**
1173  * Send operation failure message to client
1174  *
1175  * @param client the client to which the failure message has to be sent to
1176  * @param operation_id the id of the failed operation
1177  * @param emsg the error message; can be NULL
1178  */
1179 static void
1180 send_operation_fail_msg (struct GNUNET_SERVER_Client *client,
1181                          uint64_t operation_id, const char *emsg)
1182 {
1183   struct GNUNET_TESTBED_OperationFailureEventMessage *msg;
1184   uint16_t msize;
1185   uint16_t emsg_len;
1186
1187   msize = sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
1188   emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1;
1189   msize += emsg_len;
1190   msg = GNUNET_malloc (msize);
1191   msg->header.size = htons (msize);
1192   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT);
1193   msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1194   msg->operation_id = GNUNET_htonll (operation_id);
1195   if (0 != emsg_len)
1196     memcpy (&msg[1], emsg, emsg_len);
1197   queue_message (client, &msg->header);
1198 }
1199
1200
1201 /**
1202  * Function to send generic operation success message to given client
1203  *
1204  * @param client the client to send the message to
1205  * @param operation_id the id of the operation which was successful
1206  */
1207 static void
1208 send_operation_success_msg (struct GNUNET_SERVER_Client *client,
1209                             uint64_t operation_id)
1210 {
1211   struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg;
1212   uint16_t msize;
1213
1214   msize = sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage);
1215   msg = GNUNET_malloc (msize);
1216   msg->header.size = htons (msize);
1217   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS);
1218   msg->operation_id = GNUNET_htonll (operation_id);
1219   msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1220   queue_message (client, &msg->header);
1221 }
1222
1223
1224 /**
1225  * Callback which will be called to after a host registration succeeded or failed
1226  *
1227  * @param cls the handle to the slave at which the registration is completed
1228  * @param emsg the error message; NULL if host registration is successful
1229  */
1230 static void 
1231 hr_completion (void *cls, const char *emsg);
1232
1233
1234 /**
1235  * Attempts to register the next host in the host registration queue
1236  *
1237  * @param slave the slave controller whose host registration queue is checked
1238  *          for host registrations
1239  */
1240 static void
1241 register_next_host (struct Slave *slave)
1242 {
1243   struct HostRegistration *hr;
1244   
1245   hr = slave->hr_dll_head;
1246   GNUNET_assert (NULL != hr);
1247   GNUNET_assert (NULL == slave->rhandle);
1248   LOG (GNUNET_ERROR_TYPE_DEBUG,
1249        "Registering host %u at %u\n",
1250        GNUNET_TESTBED_host_get_id_ (hr->host),
1251        GNUNET_TESTBED_host_get_id_ (host_list[slave->host_id]));
1252   slave->rhandle = GNUNET_TESTBED_register_host (slave->controller,
1253                                                  hr->host,
1254                                                  hr_completion,
1255                                                  slave);
1256 }
1257
1258
1259 /**
1260  * Callback which will be called to after a host registration succeeded or failed
1261  *
1262  * @param cls the handle to the slave at which the registration is completed
1263  * @param emsg the error message; NULL if host registration is successful
1264  */
1265 static void 
1266 hr_completion (void *cls, const char *emsg)
1267 {
1268   struct Slave *slave = cls;
1269   struct HostRegistration *hr;
1270
1271   slave->rhandle = NULL;
1272   hr = slave->hr_dll_head;
1273   GNUNET_assert (NULL != hr);
1274   LOG (GNUNET_ERROR_TYPE_DEBUG,
1275        "Registering host %u at %u successful\n",
1276        GNUNET_TESTBED_host_get_id_ (hr->host),
1277        GNUNET_TESTBED_host_get_id_ (host_list[slave->host_id]));
1278   GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head,
1279                                slave->hr_dll_tail,
1280                                hr);
1281   if (NULL != hr->cb)
1282     hr->cb (hr->cb_cls, emsg);
1283   GNUNET_free (hr);
1284   if (NULL != slave->hr_dll_head)
1285     register_next_host (slave);
1286 }
1287
1288
1289 /**
1290  * Adds a host registration's request to a slave's registration queue
1291  *
1292  * @param slave the slave controller at which the given host has to be
1293  *          registered 
1294  * @param cb the host registration completion callback
1295  * @param cb_cls the closure for the host registration completion callback
1296  * @param host the host which has to be registered
1297  */
1298 static void
1299 queue_host_registration (struct Slave *slave,
1300                          GNUNET_TESTBED_HostRegistrationCompletion cb,
1301                          void *cb_cls,
1302                          struct GNUNET_TESTBED_Host *host)
1303 {
1304   struct HostRegistration *hr;
1305   int call_register;
1306
1307   LOG (GNUNET_ERROR_TYPE_DEBUG,
1308        "Queueing host registration for host %u at %u\n",
1309        GNUNET_TESTBED_host_get_id_ (host),
1310        GNUNET_TESTBED_host_get_id_ (host_list[slave->host_id]));
1311   hr = GNUNET_malloc (sizeof (struct HostRegistration));
1312   hr->cb = cb;
1313   hr->cb_cls = cb_cls;
1314   hr->host = host;
1315   call_register = (NULL == slave->hr_dll_head) ? GNUNET_YES : GNUNET_NO;
1316   GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head,
1317                                     slave->hr_dll_tail,
1318                                     hr);
1319   if (GNUNET_YES == call_register)
1320     register_next_host (slave);
1321 }
1322
1323
1324 /**
1325  * The  Link Controller forwarding task
1326  *
1327  * @param cls the LCFContext
1328  * @param tc the Task context from scheduler
1329  */
1330 static void
1331 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1332
1333
1334 /**
1335  * Completion callback for host registrations while forwarding Link Controller messages
1336  *
1337  * @param cls the LCFContext
1338  * @param emsg the error message; NULL if host registration is successful
1339  */
1340 static void
1341 lcf_proc_cc (void *cls, const char *emsg)
1342 {
1343   struct LCFContext *lcf = cls;
1344
1345   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1346   switch (lcf->state)
1347   {
1348   case INIT:
1349     if (NULL != emsg)
1350       goto registration_error;
1351     lcf->state = DELEGATED_HOST_REGISTERED;
1352     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1353     break;
1354   case DELEGATED_HOST_REGISTERED:
1355     if (NULL != emsg)
1356       goto registration_error;
1357     lcf->state = SLAVE_HOST_REGISTERED;
1358     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1359     break;
1360   default:
1361     GNUNET_assert (0);          /* Shouldn't reach here */
1362   }
1363   return;
1364
1365  registration_error:
1366   LOG (GNUNET_ERROR_TYPE_WARNING, "Host registration failed with message: %s\n",
1367        emsg);
1368   lcf->state = FINISHED;
1369   lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1370 }
1371
1372
1373 /**
1374  * Callback to relay the reply msg of a forwarded operation back to the client
1375  *
1376  * @param cls ForwardedOperationContext
1377  * @param msg the message to relay
1378  */
1379 static void
1380 forwarded_operation_reply_relay (void *cls,
1381                                  const struct GNUNET_MessageHeader *msg)
1382 {
1383   struct ForwardedOperationContext *fopc = cls;
1384   struct GNUNET_MessageHeader *dup_msg;
1385   uint16_t msize;
1386
1387   msize = ntohs (msg->size);
1388   LOG_DEBUG ("Relaying message with type: %u, size: %u\n", ntohs (msg->type),
1389              msize);
1390   dup_msg = GNUNET_copy_message (msg);
1391   queue_message (fopc->client, dup_msg);
1392   GNUNET_SERVER_client_drop (fopc->client);
1393   GNUNET_SCHEDULER_cancel (fopc->timeout_task);
1394   GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc);
1395   GNUNET_free (fopc);
1396 }
1397
1398
1399 /**
1400  * Task to free resources when forwarded operation has been timedout
1401  *
1402  * @param cls the ForwardedOperationContext
1403  * @param tc the task context from scheduler
1404  */
1405 static void
1406 forwarded_operation_timeout (void *cls,
1407                              const struct GNUNET_SCHEDULER_TaskContext *tc)
1408 {
1409   struct ForwardedOperationContext *fopc = cls;
1410
1411   GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc);
1412   LOG (GNUNET_ERROR_TYPE_WARNING, "A forwarded operation has timed out\n");
1413   send_operation_fail_msg (fopc->client, fopc->operation_id, "Timeout");
1414   GNUNET_SERVER_client_drop (fopc->client);
1415   GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc);
1416   GNUNET_free (fopc);
1417 }
1418
1419
1420 /**
1421  * The  Link Controller forwarding task
1422  *
1423  * @param cls the LCFContext
1424  * @param tc the Task context from scheduler
1425  */
1426 static void
1427 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1428
1429
1430 /**
1431  * Callback to be called when forwarded link controllers operation is
1432  * successfull. We have to relay the reply msg back to the client
1433  *
1434  * @param cls the LCFContext
1435  * @param msg the message to relay
1436  */
1437 static void
1438 lcf_forwarded_operation_reply_relay (void *cls,
1439                                      const struct GNUNET_MessageHeader *msg)
1440 {
1441   struct LCFContext *lcf = cls;
1442
1443   GNUNET_assert (NULL != lcf->fopc);
1444   forwarded_operation_reply_relay (lcf->fopc, msg);
1445   lcf->fopc = NULL;
1446   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1447   lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1448 }
1449
1450
1451 /**
1452  * Task to free resources when forwarded link controllers has been timedout
1453  *
1454  * @param cls the LCFContext
1455  * @param tc the task context from scheduler
1456  */
1457 static void
1458 lcf_forwarded_operation_timeout (void *cls,
1459                                  const struct GNUNET_SCHEDULER_TaskContext *tc)
1460 {
1461   struct LCFContext *lcf = cls;
1462
1463   GNUNET_assert (NULL != lcf->fopc);
1464   lcf->fopc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1465   forwarded_operation_timeout (lcf->fopc, tc);
1466   lcf->fopc = NULL;
1467   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1468   lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1469 }
1470
1471
1472 /**
1473  * The  Link Controller forwarding task
1474  *
1475  * @param cls the LCFContext
1476  * @param tc the Task context from scheduler
1477  */
1478 static void
1479 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1480 {
1481   struct LCFContext *lcf = cls;
1482   struct LCFContextQueue *lcfq;
1483
1484   lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1485   switch (lcf->state)
1486   {
1487   case INIT:
1488     if (GNUNET_NO ==
1489         GNUNET_TESTBED_is_host_registered_ (host_list[lcf->delegated_host_id],
1490                                             lcf->gateway->controller))
1491     {
1492       queue_host_registration (lcf->gateway,
1493                                lcf_proc_cc, lcf,
1494                                host_list[lcf->delegated_host_id]);
1495     }
1496     else
1497     {
1498       lcf->state = DELEGATED_HOST_REGISTERED;
1499       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1500     }
1501     break;
1502   case DELEGATED_HOST_REGISTERED:
1503     if (GNUNET_NO ==
1504         GNUNET_TESTBED_is_host_registered_ (host_list[lcf->slave_host_id],
1505                                             lcf->gateway->controller))
1506     {
1507       queue_host_registration (lcf->gateway,
1508                                lcf_proc_cc, lcf,
1509                                host_list[lcf->slave_host_id]);
1510     }
1511     else
1512     {
1513       lcf->state = SLAVE_HOST_REGISTERED;
1514       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1515     }
1516     break;
1517   case SLAVE_HOST_REGISTERED:
1518     lcf->fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1519     lcf->fopc->client = lcf->client;
1520     lcf->fopc->operation_id = lcf->operation_id;
1521     lcf->fopc->type = OP_LINK_CONTROLLERS;
1522     lcf->fopc->opc =
1523         GNUNET_TESTBED_forward_operation_msg_ (lcf->gateway->controller,
1524                                                lcf->operation_id,
1525                                                &lcf->msg->header,
1526                                                &lcf_forwarded_operation_reply_relay,
1527                                                lcf);
1528     lcf->fopc->timeout_task =
1529         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &lcf_forwarded_operation_timeout,
1530                                       lcf);
1531     GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, lcf->fopc);
1532     lcf->state = FINISHED;
1533     break;
1534   case FINISHED:
1535     lcfq = lcfq_head;
1536     GNUNET_assert (lcfq->lcf == lcf);
1537     GNUNET_free (lcf->msg);
1538     GNUNET_free (lcf);
1539     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
1540     GNUNET_free (lcfq);
1541     if (NULL != lcfq_head)
1542       lcf_proc_task_id =
1543           GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
1544   }
1545 }
1546
1547
1548 /**
1549  * Cleans up ForwardedOverlayConnectContext
1550  *
1551  * @param focc the ForwardedOverlayConnectContext to cleanup
1552  */
1553 static void
1554 cleanup_focc (struct ForwardedOverlayConnectContext *focc)
1555 {
1556   GNUNET_free_non_null (focc->orig_msg);
1557   GNUNET_free (focc);
1558 }
1559
1560
1561 /**
1562  * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
1563  *
1564  * @param rhc the RegisteredHostContext
1565  */
1566 static void
1567 process_next_focc (struct RegisteredHostContext *rhc);
1568
1569
1570 /**
1571  * Timeout task for cancelling a forwarded overlay connect connect
1572  *
1573  * @param cls the ForwardedOverlayConnectContext
1574  * @param tc the task context from the scheduler
1575  */
1576 static void
1577 forwarded_overlay_connect_timeout (void *cls,
1578                                    const struct GNUNET_SCHEDULER_TaskContext
1579                                    *tc)
1580 {
1581   struct ForwardedOperationContext *fopc = cls;
1582   struct RegisteredHostContext *rhc;
1583   struct ForwardedOverlayConnectContext *focc;
1584   
1585   rhc = fopc->cls;
1586   focc = rhc->focc_dll_head;
1587   GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
1588   cleanup_focc (focc);
1589   LOG_DEBUG ("Overlay linking between peers %u and %u failed\n",
1590              focc->peer1, focc->peer2);
1591   forwarded_operation_timeout (cls, tc);
1592   if (NULL != rhc->focc_dll_head)
1593     process_next_focc (rhc);
1594 }
1595
1596
1597 /**
1598  * Callback to be called when forwarded overlay connection operation has a reply
1599  * from the sub-controller successfull. We have to relay the reply msg back to
1600  * the client
1601  *
1602  * @param cls ForwardedOperationContext
1603  * @param msg the peer create success message
1604  */
1605 static void
1606 forwarded_overlay_connect_listener (void *cls,
1607                                     const struct GNUNET_MessageHeader *msg)
1608 {
1609   struct ForwardedOperationContext *fopc = cls;
1610   struct RegisteredHostContext *rhc;
1611   struct ForwardedOverlayConnectContext *focc;
1612   
1613   rhc = fopc->cls;
1614   forwarded_operation_reply_relay (cls, msg);
1615   focc = rhc->focc_dll_head;
1616   GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
1617   cleanup_focc (focc);
1618   if (NULL != rhc->focc_dll_head)
1619     process_next_focc (rhc);
1620 }
1621
1622
1623 /**
1624  * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
1625  *
1626  * @param rhc the RegisteredHostContext
1627  */
1628 static void
1629 process_next_focc (struct RegisteredHostContext *rhc)
1630 {
1631   struct ForwardedOperationContext *fopc;
1632   struct ForwardedOverlayConnectContext *focc;
1633
1634   focc = rhc->focc_dll_head;
1635   GNUNET_assert (NULL != focc);
1636   GNUNET_assert (RHC_OL_CONNECT == rhc->state);
1637   fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1638   GNUNET_SERVER_client_keep (rhc->client);
1639   fopc->client = rhc->client;  
1640   fopc->operation_id = focc->operation_id;
1641   fopc->cls = rhc;
1642   fopc->type = OP_OVERLAY_CONNECT;
1643   fopc->opc =
1644         GNUNET_TESTBED_forward_operation_msg_ (rhc->gateway->controller,
1645                                                focc->operation_id, focc->orig_msg,
1646                                                &forwarded_overlay_connect_listener,
1647                                                fopc);
1648   GNUNET_free (focc->orig_msg);
1649   focc->orig_msg = NULL;
1650   fopc->timeout_task =
1651       GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_overlay_connect_timeout,
1652                                     fopc);
1653   GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
1654 }
1655
1656
1657 /**
1658  * Callback for event from slave controllers
1659  *
1660  * @param cls struct Slave *
1661  * @param event information about the event
1662  */
1663 static void
1664 slave_event_callback (void *cls,
1665                       const struct GNUNET_TESTBED_EventInformation *event)
1666 {
1667   struct RegisteredHostContext *rhc;
1668   struct GNUNET_CONFIGURATION_Handle *cfg;
1669   struct GNUNET_TESTBED_Operation *old_op;
1670   
1671   /* We currently only get here when working on RegisteredHostContexts */
1672   GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
1673   rhc = event->details.operation_finished.op_cls;
1674   GNUNET_assert (rhc->sub_op == event->details.operation_finished.operation);
1675   switch (rhc->state)
1676   {
1677   case RHC_GET_CFG:
1678     cfg = event->details.operation_finished.generic;
1679     old_op = rhc->sub_op;
1680     rhc->state = RHC_LINK;
1681     rhc->sub_op =
1682         GNUNET_TESTBED_controller_link (rhc,
1683                                         rhc->gateway->controller,
1684                                         rhc->reg_host,
1685                                         rhc->host,
1686                                         cfg,
1687                                         GNUNET_NO);
1688     GNUNET_TESTBED_operation_done (old_op);
1689     break;
1690   case RHC_LINK:
1691     LOG_DEBUG ("OL: Linking controllers successfull\n");
1692     GNUNET_TESTBED_operation_done (rhc->sub_op);
1693     rhc->sub_op = NULL;
1694     rhc->state = RHC_OL_CONNECT;
1695     process_next_focc (rhc);
1696     break;
1697   default:
1698     GNUNET_assert (0);
1699   }
1700 }
1701
1702
1703 /**
1704  * Callback to signal successfull startup of the controller process
1705  *
1706  * @param cls the handle to the slave whose status is to be found here
1707  * @param cfg the configuration with which the controller has been started;
1708  *          NULL if status is not GNUNET_OK
1709  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
1710  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
1711  */
1712 static void
1713 slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
1714                        int status)
1715 {
1716   struct Slave *slave = cls;
1717   struct LinkControllersContext *lcc;
1718
1719   lcc = slave->lcc;
1720   if (GNUNET_SYSERR == status)
1721   {
1722     slave->controller_proc = NULL;
1723     slave_list[slave->host_id] = NULL;
1724     if (NULL != slave->cfg)
1725       GNUNET_CONFIGURATION_destroy (slave->cfg);
1726     GNUNET_free (slave);
1727     slave = NULL;
1728     LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n");
1729     GNUNET_SCHEDULER_shutdown ();       /* We too shutdown */
1730     goto clean_lcc;
1731   }
1732   slave->controller =
1733       GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1734                                          event_mask,
1735                                          &slave_event_callback, slave);
1736   if (NULL != slave->controller)
1737   {
1738     send_operation_success_msg (lcc->client, lcc->operation_id);
1739     slave->cfg = GNUNET_CONFIGURATION_dup (cfg);
1740   }
1741   else
1742   {
1743     send_operation_fail_msg (lcc->client, lcc->operation_id,
1744                              "Could not connect to delegated controller");
1745     GNUNET_TESTBED_controller_stop (slave->controller_proc);
1746     slave_list[slave->host_id] = NULL;
1747     GNUNET_free (slave);
1748     slave = NULL;
1749   }
1750
1751  clean_lcc:
1752   if (NULL != lcc)
1753   {
1754     if (NULL != lcc->client)
1755     {
1756       GNUNET_SERVER_receive_done (lcc->client, GNUNET_OK);
1757       GNUNET_SERVER_client_drop (lcc->client);
1758       lcc->client = NULL;
1759     }
1760     GNUNET_free (lcc);
1761   }
1762   if (NULL != slave)
1763     slave->lcc = NULL;
1764 }
1765
1766
1767 /**
1768  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
1769  *
1770  * @param cls NULL
1771  * @param client identification of the client
1772  * @param message the actual message
1773  */
1774 static void
1775 handle_init (void *cls, struct GNUNET_SERVER_Client *client,
1776              const struct GNUNET_MessageHeader *message)
1777 {
1778   const struct GNUNET_TESTBED_InitMessage *msg;
1779   struct GNUNET_TESTBED_Host *host;
1780   const char *controller_hostname;
1781   uint16_t msize;
1782
1783   if (NULL != master_context)
1784   {
1785     LOG_DEBUG ("We are being connected to laterally\n");
1786     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1787     return;
1788   }
1789   msg = (const struct GNUNET_TESTBED_InitMessage *) message;
1790   msize = ntohs (message->size);
1791   if (msize <= sizeof (struct GNUNET_TESTBED_InitMessage))
1792   {
1793     GNUNET_break (0);
1794     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1795     return;
1796   }
1797   msize -= sizeof (struct GNUNET_TESTBED_InitMessage);
1798   controller_hostname = (const char *) &msg[1];
1799   if ('\0' != controller_hostname[msize - 1])
1800   {
1801     GNUNET_break (0);
1802     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1803     return;
1804   }
1805   master_context = GNUNET_malloc (sizeof (struct Context));
1806   master_context->client = client;
1807   master_context->host_id = ntohl (msg->host_id);
1808   master_context->master_ip = GNUNET_strdup (controller_hostname);
1809   LOG_DEBUG ("Master Controller IP: %s\n", master_context->master_ip);
1810   master_context->system =
1811       GNUNET_TESTING_system_create ("testbed", master_context->master_ip, hostname);
1812   host =
1813       GNUNET_TESTBED_host_create_with_id (master_context->host_id,
1814                                           master_context->master_ip,
1815                                           NULL,
1816                                           0);
1817   host_list_add (host);
1818   GNUNET_SERVER_client_keep (client);
1819   LOG_DEBUG ("Created master context with host ID: %u\n",
1820              master_context->host_id);
1821   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1822 }
1823
1824
1825 /**
1826  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1827  *
1828  * @param cls NULL
1829  * @param client identification of the client
1830  * @param message the actual message
1831  */
1832 static void
1833 handle_add_host (void *cls, struct GNUNET_SERVER_Client *client,
1834                  const struct GNUNET_MessageHeader *message)
1835 {
1836   struct GNUNET_TESTBED_Host *host;
1837   const struct GNUNET_TESTBED_AddHostMessage *msg;
1838   struct GNUNET_TESTBED_HostConfirmedMessage *reply;
1839   char *username;
1840   char *hostname;
1841   char *emsg;
1842   uint32_t host_id;
1843   uint16_t username_length;
1844   uint16_t hostname_length;
1845   uint16_t reply_size;
1846   uint16_t msize;
1847
1848   msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
1849   msize = ntohs (msg->header.size);
1850   username = (char *) &msg[1];
1851   username_length = ntohs (msg->user_name_length);
1852   if (0 != username_length)
1853     username_length++;
1854   /* msg must contain hostname */
1855   GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1856                           username_length + 1));
1857   if (0 != username_length)
1858     GNUNET_assert ('\0' == username[username_length - 1]);
1859   hostname = username + username_length;
1860   hostname_length =
1861       msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length);
1862   GNUNET_assert ('\0' == hostname[hostname_length - 1]);
1863   GNUNET_assert (strlen (hostname) == hostname_length - 1);
1864   host_id = ntohl (msg->host_id);
1865   LOG_DEBUG ("Received ADDHOST %u message\n", host_id);
1866   LOG_DEBUG ("-------host id: %u\n", host_id);
1867   LOG_DEBUG ("-------hostname: %s\n", hostname);
1868   if (0 != username_length)
1869     LOG_DEBUG ("-------username: %s\n", username);
1870   else
1871   {
1872     LOG_DEBUG ("-------username: NULL\n");
1873     username = NULL;
1874   }
1875   LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
1876   host =
1877       GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
1878                                           ntohs (msg->ssh_port));
1879   GNUNET_assert (NULL != host);
1880   reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
1881   if (GNUNET_OK != host_list_add (host))
1882   {
1883     /* We are unable to add a host */
1884     emsg = "A host exists with given host-id";
1885     LOG_DEBUG ("%s: %u", emsg, host_id);
1886     GNUNET_TESTBED_host_destroy (host);
1887     reply_size += strlen (emsg) + 1;
1888     reply = GNUNET_malloc (reply_size);
1889     memcpy (&reply[1], emsg, strlen (emsg) + 1);
1890   }
1891   else
1892   {
1893     LOG_DEBUG ("Added host %u at %u\n",
1894                host_id, master_context->host_id);
1895     reply = GNUNET_malloc (reply_size);
1896   }
1897   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
1898   reply->header.size = htons (reply_size);
1899   reply->host_id = htonl (host_id);
1900   queue_message (client, &reply->header);
1901   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1902 }
1903
1904
1905 /**
1906  * Iterator over hash map entries.
1907  *
1908  * @param cls closure
1909  * @param key current key code
1910  * @param value value in the hash map
1911  * @return GNUNET_YES if we should continue to
1912  *         iterate,
1913  *         GNUNET_NO if not.
1914  */
1915 int
1916 ss_exists_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
1917 {
1918   struct SharedService *queried_ss = cls;
1919   struct SharedService *ss = value;
1920
1921   if (0 == strcmp (ss->name, queried_ss->name))
1922     return GNUNET_NO;
1923   else
1924     return GNUNET_YES;
1925 }
1926
1927
1928 /**
1929  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1930  *
1931  * @param cls NULL
1932  * @param client identification of the client
1933  * @param message the actual message
1934  */
1935 static void
1936 handle_configure_shared_service (void *cls, struct GNUNET_SERVER_Client *client,
1937                                  const struct GNUNET_MessageHeader *message)
1938 {
1939   const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1940   struct SharedService *ss;
1941   char *service_name;
1942   struct GNUNET_HashCode hash;
1943   uint16_t msg_size;
1944   uint16_t service_name_size;
1945
1946   msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
1947   msg_size = ntohs (message->size);
1948   if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
1949   {
1950     GNUNET_break (0);
1951     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1952     return;
1953   }
1954   service_name_size =
1955       msg_size - sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
1956   service_name = (char *) &msg[1];
1957   if ('\0' != service_name[service_name_size - 1])
1958   {
1959     GNUNET_break (0);
1960     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1961     return;
1962   }
1963   LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
1964              service_name, ntohl (msg->num_peers));
1965   if (ntohl (msg->host_id) != master_context->host_id)
1966   {
1967     route_message (ntohl (msg->host_id), message);
1968     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1969     return;
1970   }
1971   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1972   ss = GNUNET_malloc (sizeof (struct SharedService));
1973   ss->name = strdup (service_name);
1974   ss->num_shared = ntohl (msg->num_peers);
1975   GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
1976   if (GNUNET_SYSERR ==
1977       GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
1978                                                   &ss_exists_iterator, ss))
1979   {
1980     LOG (GNUNET_ERROR_TYPE_WARNING,
1981          "Service %s already configured as a shared service. "
1982          "Ignoring service sharing request \n", ss->name);
1983     GNUNET_free (ss->name);
1984     GNUNET_free (ss);
1985     return;
1986   }
1987   GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1988                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1989 }
1990
1991
1992 /**
1993  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1994  *
1995  * @param cls NULL
1996  * @param client identification of the client
1997  * @param message the actual message
1998  */
1999 static void
2000 handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
2001                          const struct GNUNET_MessageHeader *message)
2002 {
2003   const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
2004   struct GNUNET_CONFIGURATION_Handle *cfg;
2005   struct LCFContextQueue *lcfq;
2006   struct Route *route;
2007   struct Route *new_route;
2008   char *config;
2009   uLongf dest_size;
2010   size_t config_size;
2011   uint32_t delegated_host_id;
2012   uint32_t slave_host_id;
2013   uint16_t msize;
2014
2015   if (NULL == master_context)
2016   {
2017     GNUNET_break (0);
2018     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2019     return;
2020   }
2021   msize = ntohs (message->size);
2022   if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
2023   {
2024     GNUNET_break (0);
2025     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2026     return;
2027   }
2028   msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
2029   delegated_host_id = ntohl (msg->delegated_host_id);
2030   if (delegated_host_id == master_context->host_id)
2031   {
2032     GNUNET_break (0);
2033     LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
2034     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2035     return;
2036   }
2037   if ((delegated_host_id >= host_list_size) ||
2038       (NULL == host_list[delegated_host_id]))
2039   {
2040     LOG (GNUNET_ERROR_TYPE_WARNING,
2041          "Delegated host %u not registered with us\n", delegated_host_id);
2042     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2043     return;
2044   }
2045   slave_host_id = ntohl (msg->slave_host_id);
2046   if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
2047   {
2048     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n",
2049          slave_host_id);
2050     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2051     return;
2052   }
2053   if (slave_host_id == delegated_host_id)
2054   {
2055     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
2056     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2057     return;
2058   }
2059
2060   if (slave_host_id == master_context->host_id) /* Link from us */
2061   {
2062     struct Slave *slave;
2063     struct LinkControllersContext *lcc;
2064
2065     msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
2066     config_size = ntohs (msg->config_size);
2067     if ((delegated_host_id < slave_list_size) && (NULL != slave_list[delegated_host_id]))       /* We have already added */
2068     {
2069       LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
2070            delegated_host_id);
2071       GNUNET_SERVER_receive_done (client, GNUNET_OK);
2072       return;
2073     }
2074     config = GNUNET_malloc (config_size);
2075     dest_size = (uLongf) config_size;
2076     if (Z_OK !=
2077         uncompress ((Bytef *) config, &dest_size, (const Bytef *) &msg[1],
2078                     (uLong) msize))
2079     {
2080       GNUNET_break (0);         /* Compression error */
2081       GNUNET_free (config);
2082       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2083       return;
2084     }
2085     if (config_size != dest_size)
2086     {
2087       LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
2088       GNUNET_free (config);
2089       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2090       return;
2091     }
2092     cfg = GNUNET_CONFIGURATION_create ();       /* Free here or in lcfcontext */
2093     if (GNUNET_OK !=
2094         GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
2095     {
2096       GNUNET_break (0);         /* Configuration parsing error */
2097       GNUNET_free (config);
2098       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2099       return;
2100     }
2101     GNUNET_free (config);
2102     if ((delegated_host_id < slave_list_size) &&
2103         (NULL != slave_list[delegated_host_id]))
2104     {
2105       GNUNET_break (0);         /* Configuration parsing error */
2106       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2107       return;
2108     }
2109     slave = GNUNET_malloc (sizeof (struct Slave));
2110     slave->host_id = delegated_host_id;
2111     slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO);
2112     slave_list_add (slave);
2113     if (1 != msg->is_subordinate)
2114     {
2115       slave->controller =
2116           GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
2117                                              event_mask,
2118                                              &slave_event_callback, slave);
2119       slave->cfg = cfg;
2120       if (NULL != slave->controller)
2121         send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
2122       else
2123         send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2124                                  "Could not connect to delegated controller");
2125       GNUNET_SERVER_receive_done (client, GNUNET_OK);
2126       return;
2127     }
2128     lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
2129     lcc->operation_id = GNUNET_ntohll (msg->operation_id);
2130     GNUNET_SERVER_client_keep (client);
2131     lcc->client = client;
2132     slave->lcc = lcc;
2133     slave->controller_proc =
2134         GNUNET_TESTBED_controller_start (master_context->master_ip,
2135                                          host_list[slave->host_id], cfg,
2136                                          &slave_status_callback, slave);
2137     GNUNET_CONFIGURATION_destroy (cfg);
2138     new_route = GNUNET_malloc (sizeof (struct Route));
2139     new_route->dest = delegated_host_id;
2140     new_route->thru = master_context->host_id;
2141     route_list_add (new_route);
2142     return;
2143   }
2144
2145   /* Route the request */
2146   if (slave_host_id >= route_list_size)
2147   {
2148     LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
2149     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2150     return;
2151   }
2152   lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
2153   lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
2154   lcfq->lcf->delegated_host_id = delegated_host_id;
2155   lcfq->lcf->slave_host_id = slave_host_id;
2156   route = find_dest_route (slave_host_id);
2157   GNUNET_assert (NULL != route);        /* because we add routes carefully */
2158   GNUNET_assert (route->dest < slave_list_size);
2159   GNUNET_assert (NULL != slave_list[route->dest]);
2160   lcfq->lcf->state = INIT;
2161   lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id);
2162   lcfq->lcf->gateway = slave_list[route->dest];
2163   lcfq->lcf->msg = GNUNET_malloc (msize);
2164   (void) memcpy (lcfq->lcf->msg, msg, msize);
2165   GNUNET_SERVER_client_keep (client);
2166   lcfq->lcf->client = client;
2167   if (NULL == lcfq_head)
2168   {
2169     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
2170     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
2171     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf);
2172   }
2173   else
2174     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
2175   /* FIXME: Adding a new route should happen after the controllers are linked
2176    * successfully */
2177   if (1 != msg->is_subordinate)
2178   {
2179     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2180     return;
2181   }
2182   if ((delegated_host_id < route_list_size)
2183       && (NULL != route_list[delegated_host_id]))
2184   {
2185     GNUNET_break_op (0);        /* Are you trying to link delegated host twice
2186                                    with is subordinate flag set to GNUNET_YES? */
2187     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2188     return;
2189   }
2190   new_route = GNUNET_malloc (sizeof (struct Route));
2191   new_route->dest = delegated_host_id;
2192   new_route->thru = route->dest;
2193   route_list_add (new_route);
2194   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2195 }
2196
2197
2198 /**
2199  * The task to be executed if the forwarded peer create operation has been
2200  * timed out
2201  *
2202  * @param cls the FowardedOperationContext
2203  * @param tc the TaskContext from the scheduler
2204  */
2205 static void
2206 peer_create_forward_timeout (void *cls,
2207                              const struct GNUNET_SCHEDULER_TaskContext *tc)
2208 {
2209   struct ForwardedOperationContext *fopc = cls;
2210
2211   GNUNET_free (fopc->cls);
2212   forwarded_operation_timeout (fopc, tc);
2213 }
2214
2215
2216 /**
2217  * Callback to be called when forwarded peer create operation is successfull. We
2218  * have to relay the reply msg back to the client
2219  *
2220  * @param cls ForwardedOperationContext
2221  * @param msg the peer create success message
2222  */
2223 static void
2224 peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
2225 {
2226   struct ForwardedOperationContext *fopc = cls;
2227   struct Peer *remote_peer;
2228
2229   if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS)
2230   {
2231     GNUNET_assert (NULL != fopc->cls);
2232     remote_peer = fopc->cls;
2233     peer_list_add (remote_peer);
2234   }
2235   forwarded_operation_reply_relay (fopc, msg);
2236 }
2237
2238
2239 /**
2240  * Function to destroy a peer
2241  *
2242  * @param the peer structure to destroy
2243  */
2244 static void
2245 destroy_peer (struct Peer *peer)
2246 {
2247   GNUNET_break (0 == peer->reference_cnt);
2248   if (GNUNET_YES == peer->is_remote)
2249   {
2250     peer_list_remove (peer);
2251     GNUNET_free (peer);
2252     return;
2253   }
2254   if (GNUNET_YES == peer->details.local.is_running)
2255   {
2256     GNUNET_TESTING_peer_stop (peer->details.local.peer);
2257     peer->details.local.is_running = GNUNET_NO;
2258   }
2259   GNUNET_TESTING_peer_destroy (peer->details.local.peer);
2260   GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
2261   peer_list_remove (peer);
2262   GNUNET_free (peer);
2263 }
2264
2265
2266 /**
2267  * Callback to be called when forwarded peer destroy operation is successfull. We
2268  * have to relay the reply msg back to the client
2269  *
2270  * @param cls ForwardedOperationContext
2271  * @param msg the peer create success message
2272  */
2273 static void
2274 peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
2275 {
2276   struct ForwardedOperationContext *fopc = cls;
2277   struct Peer *remote_peer;
2278
2279   if (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS == ntohs (msg->type))
2280   {
2281     remote_peer = fopc->cls;
2282     GNUNET_assert (NULL != remote_peer);
2283     remote_peer->destroy_flag = GNUNET_YES;
2284     if (0 == remote_peer->reference_cnt)
2285       destroy_peer (remote_peer);
2286   }
2287   forwarded_operation_reply_relay (fopc, msg);
2288 }
2289
2290
2291
2292 /**
2293  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
2294  *
2295  * @param cls NULL
2296  * @param client identification of the client
2297  * @param message the actual message
2298  */
2299 static void
2300 handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
2301                     const struct GNUNET_MessageHeader *message)
2302 {
2303   const struct GNUNET_TESTBED_PeerCreateMessage *msg;
2304   struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
2305   struct GNUNET_CONFIGURATION_Handle *cfg;
2306   struct ForwardedOperationContext *fo_ctxt;
2307   struct Route *route;
2308   struct Peer *peer;
2309   char *config;
2310   size_t dest_size;
2311   int ret;
2312   uint32_t config_size;
2313   uint32_t host_id;
2314   uint32_t peer_id;
2315   uint16_t msize;
2316
2317
2318   msize = ntohs (message->size);
2319   if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
2320   {
2321     GNUNET_break (0);           /* We need configuration */
2322     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2323     return;
2324   }
2325   msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
2326   host_id = ntohl (msg->host_id);
2327   peer_id = ntohl (msg->peer_id);
2328   if (UINT32_MAX == peer_id)
2329   {
2330     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2331                              "Cannot create peer with given ID");
2332     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2333     return;
2334   }
2335   if (host_id == master_context->host_id)
2336   {
2337     char *emsg;
2338
2339     /* We are responsible for this peer */
2340     msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
2341     config_size = ntohl (msg->config_size);
2342     config = GNUNET_malloc (config_size);
2343     dest_size = config_size;
2344     if (Z_OK !=
2345         (ret =
2346          uncompress ((Bytef *) config, (uLongf *) & dest_size,
2347                      (const Bytef *) &msg[1], (uLong) msize)))
2348     {
2349       GNUNET_break (0);         /* uncompression error */
2350       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2351       return;
2352     }
2353     if (config_size != dest_size)
2354     {
2355       GNUNET_break (0);         /* Uncompressed config size mismatch */
2356       GNUNET_free (config);
2357       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2358       return;
2359     }
2360     cfg = GNUNET_CONFIGURATION_create ();
2361     if (GNUNET_OK !=
2362         GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
2363     {
2364       GNUNET_break (0);         /* Configuration parsing error */
2365       GNUNET_free (config);
2366       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2367       return;
2368     }
2369     GNUNET_free (config);
2370     peer = GNUNET_malloc (sizeof (struct Peer));
2371     peer->is_remote = GNUNET_NO;
2372     peer->details.local.cfg = cfg;
2373     peer->id = peer_id;
2374     LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
2375     peer->details.local.peer =
2376         GNUNET_TESTING_peer_configure (master_context->system,
2377                                        peer->details.local.cfg, peer->id,
2378                                        NULL /* Peer id */ ,
2379                                        &emsg);
2380     if (NULL == peer->details.local.peer)
2381     {
2382       LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
2383       GNUNET_free (emsg);
2384       GNUNET_free (peer);
2385       GNUNET_break (0);
2386       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2387       return;
2388     }
2389     peer->details.local.is_running = GNUNET_NO;
2390     peer_list_add (peer);
2391     reply =
2392         GNUNET_malloc (sizeof
2393                        (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
2394     reply->header.size =
2395         htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
2396     reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
2397     reply->peer_id = msg->peer_id;
2398     reply->operation_id = msg->operation_id;
2399     queue_message (client, &reply->header);
2400     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2401     return;
2402   }
2403
2404   /* Forward peer create request */
2405   route = find_dest_route (host_id);
2406   if (NULL == route)
2407   {
2408     GNUNET_break (0);
2409     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2410     return;
2411   }
2412
2413   peer = GNUNET_malloc (sizeof (struct Peer));
2414   peer->is_remote = GNUNET_YES;
2415   peer->id = peer_id;
2416   peer->details.remote.slave = slave_list[route->dest];
2417   peer->details.remote.remote_host_id = host_id;
2418   fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2419   GNUNET_SERVER_client_keep (client);
2420   fo_ctxt->client = client;
2421   fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
2422   fo_ctxt->cls = peer; //slave_list[route->dest]->controller;
2423   fo_ctxt->type = OP_PEER_CREATE;
2424   fo_ctxt->opc =
2425       GNUNET_TESTBED_forward_operation_msg_ (slave_list [route->dest]->controller,
2426                                              fo_ctxt->operation_id,
2427                                              &msg->header,
2428                                              peer_create_success_cb, fo_ctxt);
2429   fo_ctxt->timeout_task =
2430       GNUNET_SCHEDULER_add_delayed (TIMEOUT, &peer_create_forward_timeout,
2431                                     fo_ctxt);
2432   GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt);
2433   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2434 }
2435
2436
2437 /**
2438  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2439  *
2440  * @param cls NULL
2441  * @param client identification of the client
2442  * @param message the actual message
2443  */
2444 static void
2445 handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
2446                      const struct GNUNET_MessageHeader *message)
2447 {
2448   const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
2449   struct ForwardedOperationContext *fopc;
2450   struct Peer *peer;
2451   uint32_t peer_id;
2452
2453   msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
2454   peer_id = ntohl (msg->peer_id);
2455   LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
2456              peer_id, GNUNET_ntohll (msg->operation_id));
2457   if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
2458   {
2459     LOG (GNUNET_ERROR_TYPE_ERROR,
2460          "Asked to destroy a non existent peer with id: %u\n", peer_id);
2461     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2462                              "Peer doesn't exist");
2463     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2464     return;
2465   }
2466   peer = peer_list[peer_id];
2467   if (GNUNET_YES == peer->is_remote)
2468   {
2469     /* Forward the destory message to sub controller */
2470     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2471     GNUNET_SERVER_client_keep (client);
2472     fopc->client = client;
2473     fopc->cls = peer;
2474     fopc->type = OP_PEER_DESTROY;
2475     fopc->operation_id = GNUNET_ntohll (msg->operation_id);    
2476     fopc->opc = 
2477         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2478                                                fopc->operation_id, &msg->header,
2479                                                &peer_destroy_success_cb,
2480                                                fopc);
2481     fopc->timeout_task =
2482         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2483                                       fopc);
2484     GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
2485     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2486     return;
2487   }
2488   peer->destroy_flag = GNUNET_YES;
2489   if (0 == peer->reference_cnt)
2490     destroy_peer (peer);
2491   else
2492     LOG (GNUNET_ERROR_TYPE_WARNING,
2493          "Delaying peer destroy as peer is currently in use\n");
2494   send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
2495   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2496 }
2497
2498
2499 /**
2500  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2501  *
2502  * @param cls NULL
2503  * @param client identification of the client
2504  * @param message the actual message
2505  */
2506 static void
2507 handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
2508                    const struct GNUNET_MessageHeader *message)
2509 {
2510   const struct GNUNET_TESTBED_PeerStartMessage *msg;
2511   struct GNUNET_TESTBED_PeerEventMessage *reply;
2512   struct ForwardedOperationContext *fopc;
2513   struct Peer *peer;
2514   uint32_t peer_id;
2515
2516   msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
2517   peer_id = ntohl (msg->peer_id);
2518   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2519   {
2520     GNUNET_break (0);
2521     LOG (GNUNET_ERROR_TYPE_ERROR,
2522          "Asked to start a non existent peer with id: %u\n", peer_id);
2523     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2524     return;
2525   }
2526   peer = peer_list[peer_id];
2527   if (GNUNET_YES == peer->is_remote)
2528   {
2529     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2530     GNUNET_SERVER_client_keep (client);
2531     fopc->client = client;
2532     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2533     fopc->type = OP_PEER_START;
2534     fopc->opc =
2535         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2536                                                fopc->operation_id, &msg->header,
2537                                                &forwarded_operation_reply_relay,
2538                                                fopc);
2539     fopc->timeout_task =
2540         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2541                                       fopc);
2542     GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
2543     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2544     return;
2545   }
2546   if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer))
2547   {
2548     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2549                              "Failed to start");
2550     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2551     return;
2552   }
2553   peer->details.local.is_running = GNUNET_YES;
2554   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2555   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
2556   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2557   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
2558   reply->host_id = htonl (master_context->host_id);
2559   reply->peer_id = msg->peer_id;
2560   reply->operation_id = msg->operation_id;
2561   queue_message (client, &reply->header);
2562   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2563 }
2564
2565
2566 /**
2567  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2568  *
2569  * @param cls NULL
2570  * @param client identification of the client
2571  * @param message the actual message
2572  */
2573 static void
2574 handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
2575                   const struct GNUNET_MessageHeader *message)
2576 {
2577   const struct GNUNET_TESTBED_PeerStopMessage *msg;
2578   struct GNUNET_TESTBED_PeerEventMessage *reply;
2579   struct ForwardedOperationContext *fopc;
2580   struct Peer *peer;
2581   uint32_t peer_id;
2582
2583   msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
2584   peer_id = ntohl (msg->peer_id);
2585   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2586   {
2587     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2588                              "Peer not found");
2589     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2590     return;
2591   }
2592   peer = peer_list[peer_id];
2593   if (GNUNET_YES == peer->is_remote)
2594   {
2595     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2596     GNUNET_SERVER_client_keep (client);
2597     fopc->client = client;
2598     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2599     fopc->type = OP_PEER_STOP;
2600     fopc->opc =
2601         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2602                                                fopc->operation_id, &msg->header,
2603                                                &forwarded_operation_reply_relay,
2604                                                fopc);
2605     fopc->timeout_task =
2606         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2607                                       fopc);
2608     GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
2609     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2610     return;
2611   }
2612   if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer->details.local.peer))
2613   {
2614     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2615                              "Peer not running");
2616     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2617     return;
2618   }
2619   peer->details.local.is_running = GNUNET_NO;
2620   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2621   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
2622   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2623   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
2624   reply->host_id = htonl (master_context->host_id);
2625   reply->peer_id = msg->peer_id;
2626   reply->operation_id = msg->operation_id;
2627   queue_message (client, &reply->header);
2628   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2629 }
2630
2631
2632 /**
2633  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
2634  *
2635  * @param cls NULL
2636  * @param client identification of the client
2637  * @param message the actual message
2638  */
2639 static void
2640 handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
2641                         const struct GNUNET_MessageHeader *message)
2642 {
2643   const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
2644   struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
2645   struct Peer *peer;
2646   char *config;
2647   char *xconfig;
2648   size_t c_size;
2649   size_t xc_size;
2650   uint32_t peer_id;
2651   uint16_t msize;
2652
2653   msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
2654   peer_id = ntohl (msg->peer_id);
2655   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2656   {
2657     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2658                              "Peer not found");
2659     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2660     return;
2661   }
2662   peer = peer_list[peer_id];
2663   if (GNUNET_YES == peer->is_remote)
2664   {
2665     struct ForwardedOperationContext *fopc;
2666     
2667     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2668     GNUNET_SERVER_client_keep (client);
2669     fopc->client = client;
2670     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2671     fopc->type = OP_PEER_INFO;
2672     fopc->opc =
2673         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2674                                                fopc->operation_id, &msg->header,
2675                                                &forwarded_operation_reply_relay,
2676                                                fopc);
2677     fopc->timeout_task =
2678         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2679                                       fopc);
2680     GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); 
2681     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2682     return;
2683   }
2684   config =
2685       GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->details.local.cfg,
2686                                       &c_size);
2687   xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
2688   GNUNET_free (config);
2689   msize =
2690       xc_size +
2691       sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2692   reply = GNUNET_realloc (xconfig, msize);
2693   (void) memmove (&reply[1], reply, xc_size);
2694   reply->header.size = htons (msize);
2695   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
2696   reply->peer_id = msg->peer_id;
2697   reply->operation_id = msg->operation_id;
2698   GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->details.local.peer,
2699                                     &reply->peer_identity);
2700   reply->config_size = htons ((uint16_t) c_size);
2701   queue_message (client, &reply->header);
2702   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2703 }
2704
2705
2706 /**
2707  * Cleanup overlay connect context structure
2708  *
2709  * @param occ the overlay connect context
2710  */
2711 static void
2712 cleanup_occ (struct OverlayConnectContext *occ)
2713 {
2714   LOG_DEBUG ("Cleaning up occ\n");
2715   GNUNET_free_non_null (occ->emsg);
2716   GNUNET_free_non_null (occ->hello);
2717   GNUNET_SERVER_client_drop (occ->client);
2718   if (NULL != occ->opc)
2719     GNUNET_TESTBED_forward_operation_msg_cancel_ (occ->opc);
2720   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
2721     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
2722   if (GNUNET_SCHEDULER_NO_TASK != occ->cleanup_task)
2723     GNUNET_SCHEDULER_cancel (occ->cleanup_task);
2724   if (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task)
2725     GNUNET_SCHEDULER_cancel (occ->timeout_task);
2726   if (NULL != occ->ch)
2727   {
2728     GNUNET_CORE_disconnect (occ->ch);
2729     occ->peer->reference_cnt--;
2730   }
2731   if (NULL != occ->ghh)
2732     GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
2733   if (NULL != occ->p1th)
2734   {
2735     GNUNET_TRANSPORT_disconnect (occ->p1th);
2736     occ->peer->reference_cnt--;
2737   }
2738   if (NULL != occ->p2th)
2739   {
2740     GNUNET_TRANSPORT_disconnect (occ->p2th);
2741     peer_list[occ->other_peer_id]->reference_cnt--;
2742   }
2743   if ((GNUNET_YES == occ->peer->destroy_flag)
2744       && (0 == occ->peer->reference_cnt))
2745     destroy_peer (occ->peer);
2746   if ((NULL == occ->peer2_controller)
2747       && (GNUNET_YES == peer_list[occ->other_peer_id]->destroy_flag)
2748         && (0 == peer_list[occ->other_peer_id]->reference_cnt))
2749       destroy_peer (peer_list[occ->other_peer_id]);  
2750   GNUNET_CONTAINER_DLL_remove (occq_head, occq_tail, occ);
2751   GNUNET_free (occ);
2752 }
2753
2754
2755 /**
2756  * Task for cleaing up overlay connect context structure
2757  *
2758  * @param cls the overlay connect context
2759  * @param tc the task context
2760  */
2761 static void
2762 do_cleanup_occ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2763 {
2764   struct OverlayConnectContext *occ = cls;
2765   
2766   occ->cleanup_task = GNUNET_SCHEDULER_NO_TASK;
2767   cleanup_occ (occ);
2768 }
2769
2770
2771 /**
2772  * Task which will be run when overlay connect request has been timed out
2773  *
2774  * @param cls the OverlayConnectContext
2775  * @param tc the TaskContext
2776  */
2777 static void
2778 timeout_overlay_connect (void *cls,
2779                          const struct GNUNET_SCHEDULER_TaskContext *tc)
2780 {
2781   struct OverlayConnectContext *occ = cls;
2782
2783   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2784   LOG (GNUNET_ERROR_TYPE_WARNING,
2785        "Timeout while connecting peers %u and %u\n",
2786        occ->peer_id, occ->other_peer_id);
2787   send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
2788   cleanup_occ (occ);
2789 }
2790
2791
2792
2793 /**
2794  * Function called to notify transport users that another
2795  * peer connected to us.
2796  *
2797  * @param cls closure
2798  * @param new_peer the peer that connected
2799  * @param ats performance data
2800  * @param ats_count number of entries in ats (excluding 0-termination)
2801  */
2802 static void
2803 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
2804                         const struct GNUNET_ATS_Information *ats,
2805                         unsigned int ats_count)
2806 {
2807   struct OverlayConnectContext *occ = cls;
2808   struct GNUNET_TESTBED_ConnectionEventMessage *msg;
2809   char *new_peer_str;
2810   char *other_peer_str;
2811
2812   LOG_DEBUG ("Overlay connect notify\n");
2813   if (0 ==
2814       memcmp (new_peer, &occ->peer_identity,
2815               sizeof (struct GNUNET_PeerIdentity)))
2816     return;
2817   new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
2818   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2819   if (0 !=
2820       memcmp (new_peer, &occ->other_peer_identity,
2821               sizeof (struct GNUNET_PeerIdentity)))
2822   {
2823     LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n",
2824                new_peer_str, other_peer_str);
2825     GNUNET_free (new_peer_str);
2826     GNUNET_free (other_peer_str);
2827     return;
2828   }
2829   GNUNET_free (new_peer_str);
2830   LOG_DEBUG ("Peer %4s connected to peer %4s\n", other_peer_str, 
2831              GNUNET_i2s (&occ->peer_identity));
2832   GNUNET_free (other_peer_str);
2833   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
2834   {
2835     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
2836     occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2837   }
2838   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
2839   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2840   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2841   GNUNET_free_non_null (occ->emsg);
2842   occ->emsg = NULL;
2843   if (NULL != occ->p2th)
2844   {
2845     GNUNET_TRANSPORT_disconnect (occ->p2th);
2846     peer_list[occ->other_peer_id]->reference_cnt--;
2847   }
2848   occ->p2th = NULL;
2849   LOG_DEBUG ("Peers connected - Sending overlay connect success\n");
2850   msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2851   msg->header.size =
2852       htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2853   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT);
2854   msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
2855   msg->peer1 = htonl (occ->peer_id);
2856   msg->peer2 = htonl (occ->other_peer_id);
2857   msg->operation_id = GNUNET_htonll (occ->op_id);
2858   queue_message (occ->client, &msg->header);
2859   occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
2860   //cleanup_occ (occ);
2861 }
2862
2863
2864 /**
2865  * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
2866  * peer 1.
2867  *
2868  * @param cls the OverlayConnectContext
2869  * @param tc the TaskContext from scheduler
2870  */
2871 static void
2872 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2873 {
2874   struct OverlayConnectContext *occ = cls;
2875   char *other_peer_str;
2876
2877   occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2878   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2879     return;
2880   GNUNET_assert (NULL != occ->hello);
2881   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2882   if (NULL != occ->peer2_controller)
2883   {
2884     struct GNUNET_TESTBED_RequestConnectMessage *msg;
2885     uint16_t msize;
2886     uint16_t hello_size;
2887
2888     LOG_DEBUG ("Offering HELLO of %s to %s via Remote Overlay Request\n", 
2889                GNUNET_i2s (&occ->peer_identity), other_peer_str);
2890     hello_size = ntohs (occ->hello->size);
2891     msize = sizeof (struct GNUNET_TESTBED_RequestConnectMessage) + hello_size;
2892     msg = GNUNET_malloc (msize);
2893     msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT);
2894     msg->header.size = htons (msize);
2895     msg->peer = htonl (occ->other_peer_id);
2896     msg->operation_id = GNUNET_htonll (occ->op_id);
2897     (void) memcpy (&msg->peer_identity, &occ->peer_identity,
2898                    sizeof (struct GNUNET_PeerIdentity));
2899     memcpy (msg->hello, occ->hello, hello_size);
2900     GNUNET_TESTBED_queue_message_ (occ->peer2_controller, &msg->header);
2901   }
2902   else
2903   {
2904     LOG_DEBUG ("Offering HELLO of %s to %s\n", 
2905                GNUNET_i2s (&occ->peer_identity), other_peer_str);
2906     GNUNET_TRANSPORT_offer_hello (occ->p2th, occ->hello, NULL, NULL);
2907     GNUNET_TRANSPORT_try_connect (occ->p2th, &occ->peer_identity);
2908     occ->send_hello_task =
2909         GNUNET_SCHEDULER_add_delayed
2910         (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
2911                                         100 + GNUNET_CRYPTO_random_u32
2912                                         (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
2913          &send_hello, occ);
2914   }
2915   GNUNET_free (other_peer_str);  
2916 }
2917
2918 /**
2919  * Test for checking whether HELLO message is empty
2920  *
2921  * @param cls empty flag to set
2922  * @param address the HELLO
2923  * @param expiration expiration of the HELLO
2924  * @return
2925  */
2926 static int
2927 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
2928               struct GNUNET_TIME_Absolute expiration)
2929 {
2930   int *empty = cls;
2931
2932   *empty = GNUNET_NO;
2933   return GNUNET_OK;
2934 }
2935
2936
2937 /**
2938  * Function called whenever there is an update to the HELLO of peers in the
2939  * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
2940  * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
2941  *
2942  * @param cls closure
2943  * @param hello our updated HELLO
2944  */
2945 static void
2946 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
2947 {
2948   struct OverlayConnectContext *occ = cls;
2949   int empty;
2950   uint16_t msize;
2951
2952   msize = ntohs (hello->size);
2953   empty = GNUNET_YES;
2954   (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
2955                                          hello, GNUNET_NO, &test_address,
2956                                          &empty);
2957   if (GNUNET_YES == empty)
2958   {
2959     LOG_DEBUG ("HELLO of %s is empty\n", GNUNET_i2s (&occ->peer_identity));
2960     return;
2961   }
2962   LOG_DEBUG ("Received HELLO of %s\n", GNUNET_i2s (&occ->peer_identity));
2963   occ->hello = GNUNET_malloc (msize);
2964   memcpy (occ->hello, hello, msize);
2965   GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
2966   occ->ghh = NULL;
2967   GNUNET_TRANSPORT_disconnect (occ->p1th);
2968   occ->p1th = NULL;
2969   occ->peer->reference_cnt--;
2970   GNUNET_free_non_null (occ->emsg);
2971   if (NULL == occ->peer2_controller)
2972   {
2973     peer_list[occ->other_peer_id]->reference_cnt++;
2974     occ->p2th =
2975         GNUNET_TRANSPORT_connect (peer_list[occ->other_peer_id]->details.local.cfg,
2976                                   &occ->other_peer_identity, NULL, NULL, NULL,
2977                                   NULL);
2978     if (NULL == occ->p2th)
2979     {
2980       GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of %s\n",
2981                        GNUNET_i2s (&occ->other_peer_identity));
2982       GNUNET_SCHEDULER_cancel (occ->timeout_task);
2983       occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2984       return;
2985     }
2986   }
2987   occ->emsg = GNUNET_strdup ("Timeout while offering HELLO to other peer");
2988   occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
2989 }
2990
2991
2992 /**
2993  * Function called after GNUNET_CORE_connect has succeeded (or failed
2994  * for good).  Note that the private key of the peer is intentionally
2995  * not exposed here; if you need it, your process should try to read
2996  * the private key file directly (which should work if you are
2997  * authorized...).
2998  *
2999  * @param cls closure
3000  * @param server handle to the server, NULL if we failed
3001  * @param my_identity ID of this peer, NULL if we failed
3002  */
3003 static void
3004 core_startup_cb (void *cls, struct GNUNET_CORE_Handle *server,
3005                  const struct GNUNET_PeerIdentity *my_identity)
3006 {
3007   struct OverlayConnectContext *occ = cls;
3008
3009   GNUNET_free_non_null (occ->emsg);
3010   occ->emsg = GNUNET_strdup ("Failed to connect to CORE\n");
3011   if ((NULL == server) || (NULL == my_identity))
3012     goto error_return;
3013   GNUNET_free (occ->emsg);
3014   occ->ch = server;
3015   occ->emsg = NULL;
3016   memcpy (&occ->peer_identity, my_identity,
3017           sizeof (struct GNUNET_PeerIdentity));
3018   occ->peer->reference_cnt++;
3019   occ->p1th =
3020       GNUNET_TRANSPORT_connect (occ->peer->details.local.cfg,
3021                                 &occ->peer_identity, NULL, NULL, NULL, NULL);
3022   if (NULL == occ->p1th)
3023   {
3024     GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of peers %4s",
3025                     GNUNET_i2s (&occ->peer_identity));
3026     goto error_return;
3027   }
3028   LOG_DEBUG ("Acquiring HELLO of peer %s\n", GNUNET_i2s (&occ->peer_identity));
3029   occ->emsg = GNUNET_strdup ("Timeout while acquiring HELLO message");
3030   occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th, &hello_update_cb, occ);
3031   return;
3032   
3033  error_return:
3034   GNUNET_SCHEDULER_cancel (occ->timeout_task);
3035   occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
3036   return;
3037 }
3038
3039
3040 /**
3041  * Callback to be called when forwarded get peer config operation as part of
3042  * overlay connect is successfull. Connection to Peer 1's core is made and is
3043  * checked for new connection from peer 2
3044  *
3045  * @param cls ForwardedOperationContext
3046  * @param msg the peer create success message
3047  */
3048 static void
3049 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
3050 {
3051   struct OverlayConnectContext *occ = cls;
3052   const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
3053   const struct GNUNET_CORE_MessageHandler no_handlers[] = {
3054     {NULL, 0, 0}
3055   };
3056
3057   occ->opc = NULL;
3058   if (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG != ntohs (msg->type))
3059     goto error_return;
3060   cmsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *)
3061       msg;
3062   memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
3063           sizeof (struct GNUNET_PeerIdentity));
3064   GNUNET_free_non_null (occ->emsg);
3065   occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
3066   occ->peer->reference_cnt++;
3067   occ->ch =
3068       GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
3069                            &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
3070                            GNUNET_NO, no_handlers);
3071   if (NULL == occ->ch)
3072     goto error_return;
3073   return;
3074
3075  error_return:
3076   GNUNET_SCHEDULER_cancel (occ->timeout_task);
3077   occ->timeout_task = 
3078       GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
3079 }
3080
3081
3082 /**
3083  * Callback which will be called to after a host registration succeeded or failed
3084  *
3085  * @param cls the RegisteredHostContext
3086  * @param emsg the error message; NULL if host registration is successful
3087  */
3088 static void 
3089 registeredhost_registration_completion (void *cls, const char *emsg)
3090 {
3091   struct RegisteredHostContext *rhc = cls;
3092   struct GNUNET_CONFIGURATION_Handle *cfg;
3093   uint32_t peer2_host_id;
3094
3095   /* if (NULL != rhc->focc_dll_head) */
3096   /*   process_next_focc (rhc); */
3097   peer2_host_id = GNUNET_TESTBED_host_get_id_ (rhc->reg_host);
3098   GNUNET_assert (RHC_INIT == rhc->state);
3099   GNUNET_assert (NULL == rhc->sub_op);
3100   if ((NULL == rhc->gateway2)
3101       || ((peer2_host_id < slave_list_size) /* Check if we have the needed config */
3102           && (NULL != slave_list[peer2_host_id])))
3103   {
3104     rhc->state = RHC_LINK;
3105     cfg = (NULL == rhc->gateway2) ? our_config : slave_list[peer2_host_id]->cfg;
3106     rhc->sub_op =
3107         GNUNET_TESTBED_controller_link (rhc,
3108                                         rhc->gateway->controller,
3109                                         rhc->reg_host,
3110                                         rhc->host,
3111                                         cfg,
3112                                         GNUNET_NO);
3113     return;
3114   }
3115   rhc->state = RHC_GET_CFG;
3116   rhc->sub_op =  GNUNET_TESTBED_get_slave_config (rhc,
3117                                                   rhc->gateway2->controller,
3118                                                   rhc->reg_host);
3119 }
3120
3121
3122 /**
3123  * Iterator to match a registered host context
3124  *
3125  * @param cls pointer 2 pointer of RegisteredHostContext
3126  * @param key current key code
3127  * @param value value in the hash map
3128  * @return GNUNET_YES if we should continue to
3129  *         iterate,
3130  *         GNUNET_NO if not.
3131  */
3132 static int 
3133 reghost_match_iterator (void *cls,
3134                         const struct GNUNET_HashCode * key,
3135                         void *value)
3136 {
3137   struct RegisteredHostContext **rh = cls;
3138   struct RegisteredHostContext *rh_val = value;
3139
3140   if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
3141   {
3142     GNUNET_free (*rh);
3143     *rh = rh_val;
3144     return GNUNET_NO;
3145   }
3146   return GNUNET_YES;
3147 }
3148
3149
3150 /**
3151  * Function to generate the hashcode corresponding to a RegisteredHostContext
3152  *
3153  * @param reg_host the host which is being registered in RegisteredHostContext
3154  * @param host the host of the controller which has to connect to the above rhost
3155  * @return the hashcode
3156  */
3157 static struct GNUNET_HashCode
3158 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
3159             struct GNUNET_TESTBED_Host *host)
3160 {
3161   struct GNUNET_HashCode hash;
3162   uint32_t host_ids[2];
3163
3164   host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
3165   host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
3166   GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
3167   return hash;
3168 }
3169
3170
3171 /**
3172  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
3173  *
3174  * @param cls NULL
3175  * @param client identification of the client
3176  * @param message the actual message
3177  */
3178 static void
3179 handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
3180                         const struct GNUNET_MessageHeader *message)
3181 {
3182   const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
3183   const struct GNUNET_CORE_MessageHandler no_handlers[] = {
3184     {NULL, 0, 0}
3185   };
3186   struct Peer *peer;
3187   struct OverlayConnectContext *occ;
3188   struct GNUNET_TESTBED_Controller *peer2_controller;
3189   uint64_t operation_id;
3190   uint32_t p1;
3191   uint32_t p2; 
3192   uint32_t peer2_host_id;
3193
3194   msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
3195   p1 = ntohl (msg->peer1);
3196   p2 = ntohl (msg->peer2);
3197   peer2_host_id = ntohl (msg->peer2_host_id);
3198   GNUNET_assert (p1 < peer_list_size);
3199   GNUNET_assert (NULL != peer_list[p1]);
3200   peer = peer_list[p1];
3201   operation_id = GNUNET_ntohll (msg->operation_id);  
3202   LOG_DEBUG ("Received overlay connect for peers %u and %u with op id: 0x%lx\n",
3203              p1, p2, operation_id);
3204   if (GNUNET_YES == peer->is_remote)
3205   {
3206     struct ForwardedOperationContext *fopc;
3207     struct Route *route_to_peer2_host;
3208     struct Route *route_to_peer1_host;
3209
3210     LOG_DEBUG ("Forwarding overlay connect\n");
3211     route_to_peer2_host = NULL;
3212     route_to_peer1_host = NULL;
3213     route_to_peer2_host = find_dest_route (peer2_host_id);
3214     if ((NULL != route_to_peer2_host) 
3215         || (peer2_host_id == master_context->host_id))
3216     {
3217       /* Peer 2 either below us OR with us */
3218       route_to_peer1_host = 
3219           find_dest_route (peer_list[p1]->details.remote.remote_host_id);
3220       /* Because we get this message only if we know where peer 1 is */
3221       GNUNET_assert (NULL != route_to_peer1_host);
3222       if ((peer2_host_id == master_context->host_id) 
3223           || (route_to_peer2_host->dest != route_to_peer1_host->dest))
3224       {
3225         /* Peer2 is either with us OR peer1 and peer2 can be reached through
3226            different gateways */
3227         struct GNUNET_HashCode hash;
3228         struct RegisteredHostContext *rhc;
3229         int skip_focc;
3230
3231         rhc = GNUNET_malloc (sizeof (struct RegisteredHostContext));
3232         if (NULL != route_to_peer2_host)
3233           rhc->reg_host = host_list[route_to_peer2_host->dest];
3234         else
3235           rhc->reg_host = host_list[master_context->host_id];
3236         rhc->host = host_list[route_to_peer1_host->dest];
3237         GNUNET_assert (NULL != rhc->reg_host);
3238         GNUNET_assert (NULL != rhc->host);
3239         rhc->gateway = peer->details.remote.slave;
3240         rhc->gateway2 = (NULL == route_to_peer2_host) ? NULL :
3241             slave_list[route_to_peer2_host->dest];
3242         rhc->state = RHC_INIT;
3243         GNUNET_SERVER_client_keep (client);
3244         rhc->client = client;
3245         hash = hash_hosts (rhc->reg_host, rhc->host);
3246         skip_focc = GNUNET_NO;
3247         if ((GNUNET_NO == 
3248              GNUNET_CONTAINER_multihashmap_contains
3249              (peer->details.remote.slave->reghost_map, &hash))
3250             || (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_get_multiple
3251                 (peer->details.remote.slave->reghost_map, &hash,
3252                  reghost_match_iterator, &rhc)))
3253         {
3254           /* create and add a new registerd host context */
3255           /* add the focc to its queue */
3256           GNUNET_CONTAINER_multihashmap_put
3257               (peer->details.remote.slave->reghost_map,
3258                &hash, rhc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3259           GNUNET_assert (NULL != host_list[peer2_host_id]);
3260           queue_host_registration (peer->details.remote.slave,
3261                                    registeredhost_registration_completion, rhc,
3262                                    host_list[peer2_host_id]);
3263         }
3264         else {
3265           /* rhc is now set to the existing one from the hash map by
3266              reghost_match_iterator() */
3267           /* if queue is empty then ignore creating focc and proceed with
3268              normal forwarding */                 
3269           if (RHC_OL_CONNECT == rhc->state)
3270             skip_focc = GNUNET_YES;
3271         }
3272         if (GNUNET_NO == skip_focc)
3273         {
3274           struct ForwardedOverlayConnectContext *focc;
3275
3276           focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
3277           focc->peer1 = p1;
3278           focc->peer2 = p2;
3279           focc->peer2_host_id = peer2_host_id;
3280           focc->orig_msg = GNUNET_copy_message (message);
3281           focc->operation_id = operation_id;
3282           GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
3283                                             rhc->focc_dll_tail,
3284                                             focc);
3285           GNUNET_SERVER_receive_done (client, GNUNET_OK);
3286           return;
3287         }
3288       }
3289     }
3290     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
3291     GNUNET_SERVER_client_keep (client);
3292     fopc->client = client;
3293     fopc->operation_id = operation_id;
3294     fopc->type = OP_OVERLAY_CONNECT;
3295     fopc->opc = 
3296         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
3297                                                operation_id, message,
3298                                                &forwarded_operation_reply_relay,
3299                                                fopc);
3300     fopc->timeout_task =
3301         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
3302                                       fopc);
3303     GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
3304     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3305     return;
3306   }
3307
3308   peer2_controller = NULL;
3309   if ((p2 >= peer_list_size) || (NULL == peer_list[p2]))
3310   {   
3311     if ((peer2_host_id >= slave_list_size)
3312         || (NULL ==slave_list[peer2_host_id]))
3313     {
3314       LOG (GNUNET_ERROR_TYPE_WARNING,
3315            "Configuration of peer2's controller missing for connecting peers"
3316            "%u and %u\n", p1, p2);      
3317       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3318       return;
3319     }
3320     peer2_controller = slave_list[peer2_host_id]->controller;
3321     if (NULL == peer2_controller)
3322     {
3323       GNUNET_break (0);       /* What's going on? */
3324       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3325       return;
3326     }
3327   }
3328   else
3329   {
3330     if (GNUNET_YES == peer_list[p2]->is_remote)
3331       peer2_controller = peer_list[p2]->details.remote.slave->controller;
3332   }
3333   occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
3334   GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ);
3335   GNUNET_SERVER_client_keep (client);
3336   occ->client = client;
3337   occ->peer_id = p1;
3338   occ->other_peer_id = p2;
3339   occ->peer = peer_list[p1];
3340   occ->op_id = GNUNET_ntohll (msg->operation_id);
3341   occ->peer2_controller = peer2_controller;
3342   /* Get the identity of the second peer */
3343   if (NULL != occ->peer2_controller)
3344   {
3345     struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
3346
3347     cmsg.header.size = 
3348         htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
3349     cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG);
3350     cmsg.peer_id = msg->peer2;
3351     cmsg.operation_id = msg->operation_id;
3352     occ->opc = 
3353         GNUNET_TESTBED_forward_operation_msg_ (occ->peer2_controller,
3354                                                occ->op_id, &cmsg.header,
3355                                                &overlay_connect_get_config,
3356                                                occ);
3357     occ->emsg = 
3358         GNUNET_strdup ("Timeout while getting peer identity of peer B\n");
3359     occ->timeout_task =
3360         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
3361                                       (GNUNET_TIME_UNIT_SECONDS, 30),
3362                                       &timeout_overlay_connect, occ);
3363     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3364     return;
3365   }
3366   GNUNET_TESTING_peer_get_identity (peer_list[occ->other_peer_id]->details.local.peer,
3367                                     &occ->other_peer_identity);
3368   /* Connect to the core of 1st peer and wait for the 2nd peer to connect */
3369   occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
3370   occ->peer->reference_cnt++;
3371   occ->ch =
3372       GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
3373                            &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
3374                            GNUNET_NO, no_handlers);
3375   if (NULL == occ->ch)
3376     occ->timeout_task = 
3377         GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
3378   else
3379     occ->timeout_task =
3380         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
3381                                       (GNUNET_TIME_UNIT_SECONDS, 30),
3382                                       &timeout_overlay_connect, occ);
3383   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3384 }
3385
3386
3387 /**
3388  * Function to cleanup RequestOverlayConnectContext and any associated tasks
3389  * with it
3390  *
3391  * @param rocc the RequestOverlayConnectContext
3392  */
3393 static void
3394 cleanup_rocc (struct RequestOverlayConnectContext *rocc)
3395 {
3396   if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id)
3397     GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
3398   if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id)
3399     GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
3400   GNUNET_TRANSPORT_disconnect (rocc->th);
3401   GNUNET_free_non_null (rocc->hello);
3402   GNUNET_CONTAINER_DLL_remove (roccq_head, roccq_tail, rocc);
3403   GNUNET_free (rocc);
3404 }
3405
3406
3407 /**
3408  * Task to timeout rocc and cleanit up
3409  *
3410  * @param cls the RequestOverlayConnectContext
3411  * @param tc the TaskContext from scheduler
3412  */
3413 static void
3414 timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3415 {
3416   struct RequestOverlayConnectContext *rocc = cls;
3417   
3418   rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK;
3419   cleanup_rocc (rocc);
3420 }
3421
3422
3423 /**
3424  * Function called to notify transport users that another
3425  * peer connected to us.
3426  *
3427  * @param cls closure
3428  * @param new_peer the peer that connected
3429  * @param ats performance data
3430  * @param ats_count number of entries in ats (excluding 0-termination)
3431  */
3432 static void 
3433 transport_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
3434                           const struct GNUNET_ATS_Information * ats,
3435                           uint32_t ats_count)
3436 {
3437   struct RequestOverlayConnectContext *rocc = cls;
3438
3439   LOG_DEBUG ("Request Overlay connect notify\n");
3440   if (0 != memcmp (new_peer, &rocc->a_id, sizeof (struct GNUNET_PeerIdentity)))
3441     return;
3442   LOG_DEBUG ("Peer %4s connected\n", GNUNET_i2s (&rocc->a_id));
3443   cleanup_rocc (rocc);
3444 }
3445
3446
3447 /**
3448  * Task to offer the HELLO message to the peer and ask it to connect to the peer
3449  * whose identity is in RequestOverlayConnectContext
3450  *
3451  * @param cls the RequestOverlayConnectContext
3452  * @param tc the TaskContext from scheduler
3453  */
3454 static void
3455 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3456 {
3457   struct RequestOverlayConnectContext *rocc = cls;
3458
3459   rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK;
3460   GNUNET_TRANSPORT_offer_hello (rocc->th, rocc->hello, NULL, NULL);
3461   GNUNET_TRANSPORT_try_connect (rocc->th, &rocc->a_id);
3462   rocc->attempt_connect_task_id = 
3463       GNUNET_SCHEDULER_add_delayed 
3464       (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
3465                                       100 + GNUNET_CRYPTO_random_u32
3466                                       (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
3467        &attempt_connect_task, rocc);
3468 }
3469
3470
3471 /**
3472  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages
3473  *
3474  * @param cls NULL
3475  * @param client identification of the client
3476  * @param message the actual message
3477  */
3478 static void
3479 handle_overlay_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
3480                                 const struct GNUNET_MessageHeader *message)
3481 {
3482   const struct GNUNET_TESTBED_RequestConnectMessage *msg;
3483   struct RequestOverlayConnectContext *rocc;
3484   struct Peer *peer;
3485   uint32_t peer_id;
3486   uint16_t msize;
3487   uint16_t hsize;
3488   
3489   msize = ntohs (message->size);
3490   if (sizeof (struct GNUNET_TESTBED_RequestConnectMessage) >= msize)
3491   {
3492     GNUNET_break (0);
3493     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3494     return;
3495   }  
3496   msg = (const struct GNUNET_TESTBED_RequestConnectMessage *) message;
3497   if ((NULL == msg->hello) || 
3498       (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)))
3499   {
3500     GNUNET_break (0);
3501     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3502     return;
3503   }
3504   hsize = ntohs (msg->hello->size);
3505   if ((sizeof (struct GNUNET_TESTBED_RequestConnectMessage) + hsize) != msize)
3506   {
3507     GNUNET_break (0);
3508     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3509     return;
3510   }
3511   peer_id = ntohl (msg->peer);
3512   if ((peer_id >= peer_list_size) || (NULL == (peer = peer_list[peer_id])))
3513   {
3514     GNUNET_break_op (0);
3515     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3516     return;
3517   }
3518   if (GNUNET_YES == peer->is_remote)
3519   {
3520     struct GNUNET_MessageHeader *msg2;
3521     
3522     msg2 = GNUNET_copy_message (message);
3523     GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller, msg2);
3524     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3525     return;
3526   }
3527   rocc = GNUNET_malloc (sizeof (struct RequestOverlayConnectContext));
3528   GNUNET_CONTAINER_DLL_insert_tail (roccq_head, roccq_tail, rocc);
3529   rocc->th = GNUNET_TRANSPORT_connect (peer->details.local.cfg, NULL, rocc, 
3530                                        NULL, &transport_connect_notify, NULL);
3531   if (NULL == rocc->th)
3532   {
3533     GNUNET_break (0);
3534     GNUNET_free (rocc);
3535     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3536     return;
3537   }
3538   memcpy (&rocc->a_id, &msg->peer_identity,
3539           sizeof (struct GNUNET_PeerIdentity));
3540   rocc->hello = GNUNET_malloc (hsize);
3541   memcpy (rocc->hello, msg->hello, hsize);
3542   rocc->attempt_connect_task_id =
3543       GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
3544   rocc->timeout_rocc_task_id =
3545       GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_rocc_task, rocc);
3546   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3547 }
3548
3549
3550 /**
3551  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
3552  *
3553  * @param cls NULL
3554  * @param client identification of the client
3555  * @param message the actual message
3556  */
3557 static void
3558 handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client,
3559                          const struct GNUNET_MessageHeader *message)
3560 {
3561   struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
3562   struct Slave *slave;  
3563   struct GNUNET_TESTBED_SlaveConfiguration *reply;
3564   char *config;
3565   char *xconfig;
3566   size_t config_size;
3567   size_t xconfig_size;
3568   size_t reply_size;
3569   uint64_t op_id;
3570   uint32_t slave_id;
3571
3572   msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message;
3573   slave_id = ntohl (msg->slave_id);
3574   op_id = GNUNET_ntohll (msg->operation_id);
3575   if ((slave_list_size <= slave_id) || (NULL == slave_list[slave_id]))
3576   {
3577     /* FIXME: Add forwardings for this type of message here.. */
3578     send_operation_fail_msg (client, op_id, "Slave not found");
3579     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3580     return;
3581   }
3582   slave = slave_list[slave_id];
3583   if (NULL == slave->cfg)
3584   {
3585     send_operation_fail_msg (client, op_id,
3586                              "Configuration not found (slave not started by me)");
3587     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3588     return;
3589   }
3590   config = GNUNET_CONFIGURATION_serialize (slave->cfg, &config_size);
3591   xconfig_size = GNUNET_TESTBED_compress_config_ (config, config_size, 
3592                                                   &xconfig);
3593   GNUNET_free (config);  
3594   reply_size = xconfig_size + sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
3595   GNUNET_break (reply_size <= UINT16_MAX);
3596   GNUNET_break (config_size <= UINT16_MAX);
3597   reply = GNUNET_realloc (xconfig, reply_size);
3598   (void) memmove (&reply[1], reply, xconfig_size);
3599   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG);
3600   reply->header.size = htons ((uint16_t) reply_size);
3601   reply->slave_id = msg->slave_id;
3602   reply->operation_id = msg->operation_id;
3603   reply->config_size = htons ((uint16_t) config_size);
3604   queue_message (client, &reply->header);
3605   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3606 }
3607
3608
3609 /**
3610  * Iterator over hash map entries.
3611  *
3612  * @param cls closure
3613  * @param key current key code
3614  * @param value value in the hash map
3615  * @return GNUNET_YES if we should continue to
3616  *         iterate,
3617  *         GNUNET_NO if not.
3618  */
3619 static int
3620 ss_map_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
3621 {
3622   struct SharedService *ss = value;
3623
3624   GNUNET_assert (GNUNET_YES ==
3625                  GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
3626   GNUNET_free (ss->name);
3627   GNUNET_free (ss);
3628   return GNUNET_YES;
3629 }
3630
3631
3632 /**
3633  * Iterator for freeing hash map entries in a slave's reghost_map
3634  *
3635  * @param cls handle to the slave
3636  * @param key current key code
3637  * @param value value in the hash map
3638  * @return GNUNET_YES if we should continue to
3639  *         iterate,
3640  *         GNUNET_NO if not.
3641  */
3642 static int 
3643 reghost_free_iterator (void *cls,
3644                        const struct GNUNET_HashCode * key,
3645                        void *value)
3646 {
3647   struct Slave *slave = cls;
3648   struct RegisteredHostContext *rhc = value;
3649   struct ForwardedOverlayConnectContext *focc;
3650
3651   GNUNET_assert (GNUNET_YES ==
3652                  GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map,
3653                                                        key, value));
3654   while (NULL != (focc = rhc->focc_dll_head))
3655   {
3656     GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head,
3657                                  rhc->focc_dll_tail,
3658                                  focc);
3659     cleanup_focc (focc);
3660   }
3661   if (NULL != rhc->sub_op)
3662     GNUNET_TESTBED_operation_done (rhc->sub_op);
3663   if (NULL != rhc->client)
3664   GNUNET_SERVER_client_drop (rhc->client);
3665   GNUNET_free (value);
3666   return GNUNET_YES;
3667 }
3668
3669
3670 /**
3671  * Task to clean up and shutdown nicely
3672  *
3673  * @param cls NULL
3674  * @param tc the TaskContext from scheduler
3675  */
3676 static void
3677 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3678 {
3679   struct LCFContextQueue *lcfq;
3680   struct OverlayConnectContext *occ;
3681   struct RequestOverlayConnectContext *rocc;
3682   struct ForwardedOperationContext *fopc;
3683   uint32_t id;
3684
3685   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
3686   LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
3687   (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
3688                                                 NULL);
3689   GNUNET_CONTAINER_multihashmap_destroy (ss_map);
3690   /* cleanup any remaining forwarded operations */
3691   while (NULL != (fopc = fopcq_head))
3692   {
3693     GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc);
3694     GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc);
3695     if (GNUNET_SCHEDULER_NO_TASK != fopc->timeout_task)
3696       GNUNET_SCHEDULER_cancel (fopc->timeout_task);
3697     GNUNET_SERVER_client_drop (fopc->client);
3698     switch (fopc->type)
3699     {
3700     case OP_PEER_CREATE:
3701       GNUNET_free (fopc->cls);
3702       break;
3703     case OP_PEER_START:
3704     case OP_PEER_STOP:
3705     case OP_PEER_DESTROY:
3706     case OP_PEER_INFO:
3707     case OP_OVERLAY_CONNECT:
3708     case OP_LINK_CONTROLLERS:
3709     case OP_GET_SLAVE_CONFIG:
3710       break;
3711     case OP_FORWARDED:
3712       GNUNET_assert (0);
3713     };
3714     GNUNET_free (fopc);
3715   }
3716   if (NULL != lcfq_head)
3717   {
3718     if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
3719     {
3720       GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
3721       lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
3722     }
3723   }
3724   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
3725   for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
3726   {
3727     GNUNET_free (lcfq->lcf->msg);
3728     GNUNET_free (lcfq->lcf);
3729     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
3730     GNUNET_free (lcfq);
3731   }
3732   while (NULL != (occ = occq_head))
3733     cleanup_occ (occ);
3734   while (NULL != (rocc = roccq_head))
3735     cleanup_rocc (rocc);
3736   /* Clear peer list */
3737   for (id = 0; id < peer_list_size; id++)
3738     if (NULL != peer_list[id])
3739     {
3740       /* If destroy flag is set it means that this peer should have been
3741          destroyed by a context which we destroy before */
3742       GNUNET_break (GNUNET_NO == peer_list[id]->destroy_flag);
3743       /* counter should be zero as we free all contexts before */
3744       GNUNET_break (0 == peer_list[id]->reference_cnt);
3745       if (GNUNET_NO == peer_list[id]->is_remote)
3746       {
3747         if (GNUNET_YES == peer_list[id]->details.local.is_running)
3748           GNUNET_TESTING_peer_stop (peer_list[id]->details.local.peer);
3749         GNUNET_TESTING_peer_destroy (peer_list[id]->details.local.peer);
3750         GNUNET_CONFIGURATION_destroy (peer_list[id]->details.local.cfg);
3751       }
3752       GNUNET_free (peer_list[id]);
3753     }
3754   GNUNET_free_non_null (peer_list);
3755   /* Clear host list */
3756   for (id = 0; id < host_list_size; id++)
3757     if (NULL != host_list[id])
3758       GNUNET_TESTBED_host_destroy (host_list[id]);
3759   GNUNET_free_non_null (host_list);
3760   /* Clear route list */
3761   for (id = 0; id < route_list_size; id++)
3762     if (NULL != route_list[id])
3763       GNUNET_free (route_list[id]);
3764   GNUNET_free_non_null (route_list);
3765   /* Clear slave_list */
3766   for (id = 0; id < slave_list_size; id++)
3767     if (NULL != slave_list[id])
3768     {
3769       struct HostRegistration *hr_entry;
3770       
3771       while (NULL != (hr_entry = slave_list[id]->hr_dll_head))
3772       {
3773         GNUNET_CONTAINER_DLL_remove (slave_list[id]->hr_dll_head,
3774                                      slave_list[id]->hr_dll_tail,
3775                                      hr_entry);
3776         GNUNET_free (hr_entry);
3777       }
3778       if (NULL != slave_list[id]->rhandle)
3779         GNUNET_TESTBED_cancel_registration (slave_list[id]->rhandle);
3780       (void) GNUNET_CONTAINER_multihashmap_iterate (slave_list[id]->reghost_map,
3781                                                     reghost_free_iterator,
3782                                                     slave_list[id]);
3783       GNUNET_CONTAINER_multihashmap_destroy (slave_list[id]->reghost_map);
3784       if (NULL != slave_list[id]->cfg)
3785         GNUNET_CONFIGURATION_destroy (slave_list[id]->cfg);
3786       if (NULL != slave_list[id]->controller)
3787         GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
3788       if (NULL != slave_list[id]->controller_proc)
3789         GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
3790       GNUNET_free (slave_list[id]);
3791     }
3792   GNUNET_free_non_null (slave_list);
3793   if (NULL != master_context)
3794   {
3795     GNUNET_free_non_null (master_context->master_ip);
3796     if (NULL != master_context->system)
3797       GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
3798     GNUNET_free (master_context);
3799     master_context = NULL;
3800   }
3801   GNUNET_free_non_null (hostname);
3802   GNUNET_CONFIGURATION_destroy (our_config);
3803 }
3804
3805
3806 /**
3807  * Callback for client disconnect
3808  *
3809  * @param cls NULL
3810  * @param client the client which has disconnected
3811  */
3812 static void
3813 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
3814 {
3815   if (NULL == master_context)
3816     return;
3817   if (client == master_context->client)
3818   {
3819     LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
3820     /* should not be needed as we're terminated by failure to read
3821      * from stdin, but if stdin fails for some reason, this shouldn't
3822      * hurt for now --- might need to revise this later if we ever
3823      * decide that master connections might be temporarily down
3824      * for some reason */
3825     //GNUNET_SCHEDULER_shutdown ();
3826   }
3827 }
3828
3829
3830 /**
3831  * Testbed setup
3832  *
3833  * @param cls closure
3834  * @param server the initialized server
3835  * @param cfg configuration to use
3836  */
3837 static void
3838 testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
3839              const struct GNUNET_CONFIGURATION_Handle *cfg)
3840 {
3841   static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
3842     {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
3843     {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
3844     {&handle_configure_shared_service, NULL,
3845      GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
3846     {&handle_link_controllers, NULL,
3847      GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
3848     {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
3849     {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
3850      sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
3851     {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
3852      sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
3853     {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
3854      sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
3855     {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
3856      sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
3857     {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
3858      sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
3859     {&handle_overlay_request_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT,
3860      0},
3861     {handle_slave_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG,
3862      sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)},
3863     {NULL}
3864   };
3865
3866   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string 
3867                  (cfg, "testbed", "HOSTNAME", &hostname));
3868   our_config = GNUNET_CONFIGURATION_dup (cfg);
3869   GNUNET_SERVER_add_handlers (server, message_handlers);
3870   GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
3871   ss_map = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
3872   shutdown_task_id =
3873       GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_UNIT_FOREVER_REL,
3874                                                   GNUNET_SCHEDULER_PRIORITY_IDLE,
3875                                                   &shutdown_task, NULL);
3876   LOG_DEBUG ("Testbed startup complete\n");
3877   event_mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
3878 }
3879
3880
3881 /**
3882  * The starting point of execution
3883  */
3884 int
3885 main (int argc, char *const *argv)
3886 {
3887   //sleep (15);                 /* Debugging */
3888   return (GNUNET_OK ==
3889           GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE,
3890                               &testbed_run, NULL)) ? 0 : 1;
3891 }
3892
3893 /* end of gnunet-service-testbed.c */