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