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