removed peer destroy. May leak memory, but anyway we need that till the end
[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   if (0 != username_length)
1485     username_length++;
1486   /* msg must contain hostname */
1487   GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1488                           username_length + 1));
1489   if (0 != username_length)
1490     GNUNET_assert ('\0' == username[username_length - 1]);
1491   hostname = username + username_length;
1492   hostname_length =
1493       msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length);
1494   GNUNET_assert ('\0' == hostname[hostname_length - 1]);
1495   GNUNET_assert (strlen (hostname) == hostname_length - 1);
1496   host_id = ntohl (msg->host_id);
1497   LOG_DEBUG ("Received ADDHOST message\n");
1498   LOG_DEBUG ("-------host id: %u\n", host_id);
1499   LOG_DEBUG ("-------hostname: %s\n", hostname);
1500   if (0 != username_length)
1501     LOG_DEBUG ("-------username: %s\n", username);
1502   else
1503   {
1504     LOG_DEBUG ("-------username: NULL\n");
1505     username = NULL;
1506   }
1507   LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
1508   host =
1509       GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
1510                                           ntohs (msg->ssh_port));
1511   GNUNET_assert (NULL != host);
1512   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1513   reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
1514   if (GNUNET_OK != host_list_add (host))
1515   {
1516     /* We are unable to add a host */
1517     emsg = "A host exists with given host-id";
1518     LOG_DEBUG ("%s: %u", emsg, host_id);
1519     GNUNET_TESTBED_host_destroy (host);
1520     reply_size += strlen (emsg) + 1;
1521     reply = GNUNET_malloc (reply_size);
1522     memcpy (&reply[1], emsg, strlen (emsg) + 1);
1523   }
1524   else
1525     reply = GNUNET_malloc (reply_size);
1526   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
1527   reply->header.size = htons (reply_size);
1528   reply->host_id = htonl (host_id);
1529   queue_message (client, &reply->header);
1530 }
1531
1532
1533 /**
1534  * Iterator over hash map entries.
1535  *
1536  * @param cls closure
1537  * @param key current key code
1538  * @param value value in the hash map
1539  * @return GNUNET_YES if we should continue to
1540  *         iterate,
1541  *         GNUNET_NO if not.
1542  */
1543 int
1544 ss_exists_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
1545 {
1546   struct SharedService *queried_ss = cls;
1547   struct SharedService *ss = value;
1548
1549   if (0 == strcmp (ss->name, queried_ss->name))
1550     return GNUNET_NO;
1551   else
1552     return GNUNET_YES;
1553 }
1554
1555
1556 /**
1557  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1558  *
1559  * @param cls NULL
1560  * @param client identification of the client
1561  * @param message the actual message
1562  */
1563 static void
1564 handle_configure_shared_service (void *cls, struct GNUNET_SERVER_Client *client,
1565                                  const struct GNUNET_MessageHeader *message)
1566 {
1567   const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1568   struct SharedService *ss;
1569   char *service_name;
1570   struct GNUNET_HashCode hash;
1571   uint16_t msg_size;
1572   uint16_t service_name_size;
1573
1574   msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
1575   msg_size = ntohs (message->size);
1576   if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
1577   {
1578     GNUNET_break (0);
1579     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1580     return;
1581   }
1582   service_name_size =
1583       msg_size - sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
1584   service_name = (char *) &msg[1];
1585   if ('\0' != service_name[service_name_size - 1])
1586   {
1587     GNUNET_break (0);
1588     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1589     return;
1590   }
1591   LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
1592              service_name, ntohl (msg->num_peers));
1593   if (ntohl (msg->host_id) != master_context->host_id)
1594   {
1595     route_message (ntohl (msg->host_id), message);
1596     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1597     return;
1598   }
1599   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1600   ss = GNUNET_malloc (sizeof (struct SharedService));
1601   ss->name = strdup (service_name);
1602   ss->num_shared = ntohl (msg->num_peers);
1603   GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
1604   if (GNUNET_SYSERR ==
1605       GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
1606                                                   &ss_exists_iterator, ss))
1607   {
1608     LOG (GNUNET_ERROR_TYPE_WARNING,
1609          "Service %s already configured as a shared service. "
1610          "Ignoring service sharing request \n", ss->name);
1611     GNUNET_free (ss->name);
1612     GNUNET_free (ss);
1613     return;
1614   }
1615   GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1616                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1617 }
1618
1619
1620 /**
1621  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1622  *
1623  * @param cls NULL
1624  * @param client identification of the client
1625  * @param message the actual message
1626  */
1627 static void
1628 handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
1629                          const struct GNUNET_MessageHeader *message)
1630 {
1631   const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1632   struct GNUNET_CONFIGURATION_Handle *cfg;
1633   struct LCFContextQueue *lcfq;
1634   struct Route *route;
1635   struct Route *new_route;
1636   char *config;
1637   uLongf dest_size;
1638   size_t config_size;
1639   uint32_t delegated_host_id;
1640   uint32_t slave_host_id;
1641   uint16_t msize;
1642
1643   if (NULL == master_context)
1644   {
1645     GNUNET_break (0);
1646     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1647     return;
1648   }
1649   msize = ntohs (message->size);
1650   if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
1651   {
1652     GNUNET_break (0);
1653     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1654     return;
1655   }
1656   msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
1657   delegated_host_id = ntohl (msg->delegated_host_id);
1658   if (delegated_host_id == master_context->host_id)
1659   {
1660     GNUNET_break (0);
1661     LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1662     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1663     return;
1664   }
1665   if ((delegated_host_id >= host_list_size) ||
1666       (NULL == host_list[delegated_host_id]))
1667   {
1668     LOG (GNUNET_ERROR_TYPE_WARNING,
1669          "Delegated host %u not registered with us\n", delegated_host_id);
1670     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1671     return;
1672   }
1673   slave_host_id = ntohl (msg->slave_host_id);
1674   if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
1675   {
1676     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n",
1677          slave_host_id);
1678     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1679     return;
1680   }
1681   if (slave_host_id == delegated_host_id)
1682   {
1683     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1684     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1685     return;
1686   }
1687
1688   if (slave_host_id == master_context->host_id) /* Link from us */
1689   {
1690     struct Slave *slave;
1691     struct LinkControllersContext *lcc;
1692
1693     msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1694     config_size = ntohs (msg->config_size);
1695     if ((delegated_host_id < slave_list_size) && (NULL != slave_list[delegated_host_id]))       /* We have already added */
1696     {
1697       LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
1698            delegated_host_id);
1699       GNUNET_SERVER_receive_done (client, GNUNET_OK);
1700       return;
1701     }
1702     config = GNUNET_malloc (config_size);
1703     dest_size = (uLongf) config_size;
1704     if (Z_OK !=
1705         uncompress ((Bytef *) config, &dest_size, (const Bytef *) &msg[1],
1706                     (uLong) msize))
1707     {
1708       GNUNET_break (0);         /* Compression error */
1709       GNUNET_free (config);
1710       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1711       return;
1712     }
1713     if (config_size != dest_size)
1714     {
1715       LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
1716       GNUNET_free (config);
1717       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1718       return;
1719     }
1720     cfg = GNUNET_CONFIGURATION_create ();       /* Free here or in lcfcontext */
1721     if (GNUNET_OK !=
1722         GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
1723     {
1724       GNUNET_break (0);         /* Configuration parsing error */
1725       GNUNET_free (config);
1726       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1727       return;
1728     }
1729     GNUNET_free (config);
1730     if ((delegated_host_id < slave_list_size) &&
1731         (NULL != slave_list[delegated_host_id]))
1732     {
1733       GNUNET_break (0);         /* Configuration parsing error */
1734       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1735       return;
1736     }
1737     slave = GNUNET_malloc (sizeof (struct Slave));
1738     slave->host_id = delegated_host_id;
1739     slave_list_add (slave);
1740     if (1 != msg->is_subordinate)
1741     {
1742       slave->controller =
1743           GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1744                                              event_mask,
1745                                              &slave_event_callback, slave);
1746       slave->cfg = cfg;
1747       if (NULL != slave->controller)
1748         send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
1749       else
1750         send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1751                                  "Could not connect to delegated controller");
1752       GNUNET_SERVER_receive_done (client, GNUNET_OK);
1753       return;
1754     }
1755     lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
1756     lcc->operation_id = GNUNET_ntohll (msg->operation_id);
1757     GNUNET_SERVER_client_keep (client);
1758     lcc->client = client;
1759     slave->lcc = lcc;
1760     slave->controller_proc =
1761         GNUNET_TESTBED_controller_start (master_context->master_ip,
1762                                          host_list[slave->host_id], cfg,
1763                                          &slave_status_callback, slave);
1764     GNUNET_CONFIGURATION_destroy (cfg);
1765     new_route = GNUNET_malloc (sizeof (struct Route));
1766     new_route->dest = delegated_host_id;
1767     new_route->thru = master_context->host_id;
1768     route_list_add (new_route);
1769     return;
1770   }
1771
1772   /* Route the request */
1773   if (slave_host_id >= route_list_size)
1774   {
1775     LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1776     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1777     return;
1778   }
1779   lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1780   lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1781   lcfq->lcf->delegated_host_id = delegated_host_id;
1782   lcfq->lcf->slave_host_id = slave_host_id;
1783   route = find_dest_route (slave_host_id);
1784   GNUNET_assert (NULL != route);        /* because we add routes carefully */
1785   GNUNET_assert (route->dest < slave_list_size);
1786   GNUNET_assert (NULL != slave_list[route->dest]);
1787   lcfq->lcf->state = INIT;
1788   lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id);
1789   lcfq->lcf->gateway = slave_list[route->dest];
1790   lcfq->lcf->msg = GNUNET_malloc (msize);
1791   (void) memcpy (lcfq->lcf->msg, msg, msize);
1792   GNUNET_SERVER_client_keep (client);
1793   lcfq->lcf->client = client;
1794   if (NULL == lcfq_head)
1795   {
1796     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1797     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1798     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf);
1799   }
1800   else
1801     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1802   /* FIXME: Adding a new route should happen after the controllers are linked
1803    * successfully */
1804   if (1 != msg->is_subordinate)
1805   {
1806     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1807     return;
1808   }
1809   if ((delegated_host_id < route_list_size)
1810       && (NULL != route_list[delegated_host_id]))
1811   {
1812     GNUNET_break_op (0);        /* Are you trying to link delegated host twice
1813                                    with is subordinate flag set to GNUNET_YES? */
1814     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1815     return;
1816   }
1817   new_route = GNUNET_malloc (sizeof (struct Route));
1818   new_route->dest = delegated_host_id;
1819   new_route->thru = route->dest;
1820   route_list_add (new_route);
1821   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1822 }
1823
1824
1825 /**
1826  * The task to be executed if the forwarded peer create operation has been
1827  * timed out
1828  *
1829  * @param cls the FowardedOperationContext
1830  * @param tc the TaskContext from the scheduler
1831  */
1832 static void
1833 peer_create_forward_timeout (void *cls,
1834                              const struct GNUNET_SCHEDULER_TaskContext *tc)
1835 {
1836   struct ForwardedOperationContext *fo_ctxt = cls;
1837
1838   /* send error msg to client */
1839   GNUNET_free (fo_ctxt->cls);
1840   send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, "Timedout");
1841   GNUNET_SERVER_client_drop (fo_ctxt->client);
1842   GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc);
1843   GNUNET_free (fo_ctxt);
1844 }
1845
1846
1847 /**
1848  * Callback to be called when forwarded peer create operation is
1849  * successfull. We have to relay the reply msg back to the client
1850  *
1851  * @param cls ForwardedOperationContext
1852  * @param msg the peer create success message
1853  */
1854 static void
1855 peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
1856 {
1857   struct ForwardedOperationContext *fo_ctxt = cls;
1858   const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *success_msg;
1859   struct GNUNET_MessageHeader *dup_msg;
1860   struct Peer *remote_peer;
1861   uint16_t msize;
1862
1863   GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task);
1864   if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS)
1865   {
1866     success_msg =
1867         (const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *) msg;
1868     GNUNET_assert (NULL != fo_ctxt->cls);
1869     remote_peer = fo_ctxt->cls;
1870     GNUNET_assert (remote_peer->details.remote.remote_host_id
1871                    == ntohl (success_msg->peer_id));
1872     peer_list_add (remote_peer);
1873   }
1874   msize = ntohs (msg->size);
1875   dup_msg = GNUNET_malloc (msize);
1876   (void) memcpy (dup_msg, msg, msize);
1877   queue_message (fo_ctxt->client, dup_msg);
1878   GNUNET_SERVER_client_drop (fo_ctxt->client);
1879   GNUNET_free (fo_ctxt);
1880 }
1881
1882
1883
1884 /**
1885  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
1886  *
1887  * @param cls NULL
1888  * @param client identification of the client
1889  * @param message the actual message
1890  */
1891 static void
1892 handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
1893                     const struct GNUNET_MessageHeader *message)
1894 {
1895   const struct GNUNET_TESTBED_PeerCreateMessage *msg;
1896   struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
1897   struct GNUNET_CONFIGURATION_Handle *cfg;
1898   struct ForwardedOperationContext *fo_ctxt;
1899   struct Route *route;
1900   struct Peer *peer;
1901   char *config;
1902   size_t dest_size;
1903   int ret;
1904   uint32_t config_size;
1905   uint32_t host_id;
1906   uint32_t peer_id;
1907   uint16_t msize;
1908
1909
1910   msize = ntohs (message->size);
1911   if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
1912   {
1913     GNUNET_break (0);           /* We need configuration */
1914     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1915     return;
1916   }
1917   msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
1918   host_id = ntohl (msg->host_id);
1919   peer_id = ntohl (msg->peer_id);
1920   if (UINT32_MAX == peer_id)
1921   {
1922     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1923                              "Cannot create peer with given ID");
1924     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1925     return;
1926   }
1927   if (host_id == master_context->host_id)
1928   {
1929     char *emsg;
1930
1931     /* We are responsible for this peer */
1932     msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1933     config_size = ntohl (msg->config_size);
1934     config = GNUNET_malloc (config_size);
1935     dest_size = config_size;
1936     if (Z_OK !=
1937         (ret =
1938          uncompress ((Bytef *) config, (uLongf *) & dest_size,
1939                      (const Bytef *) &msg[1], (uLong) msize)))
1940     {
1941       GNUNET_break (0);         /* uncompression error */
1942       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1943       return;
1944     }
1945     if (config_size != dest_size)
1946     {
1947       GNUNET_break (0);         /* Uncompressed config size mismatch */
1948       GNUNET_free (config);
1949       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1950       return;
1951     }
1952     cfg = GNUNET_CONFIGURATION_create ();
1953     if (GNUNET_OK !=
1954         GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
1955     {
1956       GNUNET_break (0);         /* Configuration parsing error */
1957       GNUNET_free (config);
1958       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1959       return;
1960     }
1961     GNUNET_free (config);
1962     peer = GNUNET_malloc (sizeof (struct Peer));
1963     peer->is_remote = GNUNET_NO;
1964     peer->details.local.cfg = cfg;
1965     peer->id = peer_id;
1966     LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
1967     peer->details.local.peer =
1968         GNUNET_TESTING_peer_configure (master_context->system,
1969                                        peer->details.local.cfg, peer->id,
1970                                        NULL /* Peer id */ ,
1971                                        &emsg);
1972     if (NULL == peer->details.local.peer)
1973     {
1974       LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
1975       GNUNET_free (emsg);
1976       GNUNET_free (peer);
1977       GNUNET_break (0);
1978       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1979       return;
1980     }
1981     peer->details.local.is_running = GNUNET_NO;
1982     peer_list_add (peer);
1983     reply =
1984         GNUNET_malloc (sizeof
1985                        (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1986     reply->header.size =
1987         htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1988     reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
1989     reply->peer_id = msg->peer_id;
1990     reply->operation_id = msg->operation_id;
1991     queue_message (client, &reply->header);
1992     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1993     return;
1994   }
1995
1996   /* Forward peer create request */
1997   route = find_dest_route (host_id);
1998   if (NULL == route)
1999   {
2000     GNUNET_break (0);
2001     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2002     return;
2003   }
2004
2005   peer = GNUNET_malloc (sizeof (struct Peer));
2006   peer->is_remote = GNUNET_YES;
2007   peer->id = peer_id;
2008   peer->details.remote.controller = slave_list[route->dest]->controller;
2009   peer->details.remote.remote_host_id = host_id;
2010   fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2011   GNUNET_SERVER_client_keep (client);
2012   fo_ctxt->client = client;
2013   fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
2014   fo_ctxt->cls = peer; //slave_list[route->dest]->controller;
2015   fo_ctxt->opc =
2016       GNUNET_TESTBED_forward_operation_msg_ (slave_list [route->dest]->controller,
2017                                              fo_ctxt->operation_id,
2018                                              &msg->header,
2019                                              peer_create_success_cb, fo_ctxt);
2020   fo_ctxt->timeout_task =
2021       GNUNET_SCHEDULER_add_delayed (TIMEOUT, &peer_create_forward_timeout,
2022                                     fo_ctxt);
2023   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2024 }
2025
2026
2027 /**
2028  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2029  *
2030  * @param cls NULL
2031  * @param client identification of the client
2032  * @param message the actual message
2033  */
2034 static void
2035 handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
2036                      const struct GNUNET_MessageHeader *message)
2037 {
2038   const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
2039   struct ForwardedOperationContext *fopc;
2040   struct Peer *peer;
2041   uint32_t peer_id;
2042
2043   msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
2044   peer_id = ntohl (msg->peer_id);
2045   LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
2046              peer_id, GNUNET_ntohll (msg->operation_id));
2047   if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
2048   {
2049     LOG (GNUNET_ERROR_TYPE_ERROR,
2050          "Asked to destroy a non existent peer with id: %u\n", peer_id);
2051     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2052                              "Peer doesn't exist");
2053     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2054     return;
2055   }
2056   peer = peer_list[peer_id];
2057   if (GNUNET_YES == peer->is_remote)
2058   {
2059     /* Forward the destory message to sub controller */
2060     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2061     GNUNET_SERVER_client_keep (client);
2062     fopc->client = client;
2063     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2064     fopc->opc =
2065         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
2066                                                fopc->operation_id, &msg->header,
2067                                                &forwarded_operation_reply_relay,
2068                                                fopc);
2069     fopc->timeout_task =
2070         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2071                                       fopc);
2072     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2073     return;
2074   }
2075   GNUNET_TESTING_peer_destroy (peer->details.local.peer);
2076   GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
2077   peer_list_remove (peer);
2078   GNUNET_free (peer);
2079   send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
2080   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2081 }
2082
2083
2084 /**
2085  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2086  *
2087  * @param cls NULL
2088  * @param client identification of the client
2089  * @param message the actual message
2090  */
2091 static void
2092 handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
2093                    const struct GNUNET_MessageHeader *message)
2094 {
2095   const struct GNUNET_TESTBED_PeerStartMessage *msg;
2096   struct GNUNET_TESTBED_PeerEventMessage *reply;
2097   struct ForwardedOperationContext *fopc;
2098   struct Peer *peer;
2099   uint32_t peer_id;
2100
2101   msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
2102   peer_id = ntohl (msg->peer_id);
2103   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2104   {
2105     GNUNET_break (0);
2106     LOG (GNUNET_ERROR_TYPE_ERROR,
2107          "Asked to start a non existent peer with id: %u\n", peer_id);
2108     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2109     return;
2110   }
2111   peer = peer_list[peer_id];
2112   if (GNUNET_YES == peer->is_remote)
2113   {
2114     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2115     GNUNET_SERVER_client_keep (client);
2116     fopc->client = client;
2117     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2118     fopc->opc =
2119         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
2120                                                fopc->operation_id, &msg->header,
2121                                                &forwarded_operation_reply_relay,
2122                                                fopc);
2123     fopc->timeout_task =
2124         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2125                                       fopc);
2126     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2127     return;
2128   }
2129   if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer))
2130   {
2131     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2132                              "Failed to start");
2133     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2134     return;
2135   }
2136   peer->details.local.is_running = GNUNET_YES;
2137   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2138   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
2139   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2140   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
2141   reply->host_id = htonl (master_context->host_id);
2142   reply->peer_id = msg->peer_id;
2143   reply->operation_id = msg->operation_id;
2144   queue_message (client, &reply->header);
2145   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2146 }
2147
2148
2149 /**
2150  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2151  *
2152  * @param cls NULL
2153  * @param client identification of the client
2154  * @param message the actual message
2155  */
2156 static void
2157 handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
2158                   const struct GNUNET_MessageHeader *message)
2159 {
2160   const struct GNUNET_TESTBED_PeerStopMessage *msg;
2161   struct GNUNET_TESTBED_PeerEventMessage *reply;
2162   struct ForwardedOperationContext *fopc;
2163   struct Peer *peer;
2164   uint32_t peer_id;
2165
2166   msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
2167   peer_id = ntohl (msg->peer_id);
2168   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2169   {
2170     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2171                              "Peer not found");
2172     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2173     return;
2174   }
2175   peer = peer_list[peer_id];
2176   if (GNUNET_YES == peer->is_remote)
2177   {
2178     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2179     GNUNET_SERVER_client_keep (client);
2180     fopc->client = client;
2181     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2182     fopc->opc =
2183         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
2184                                                fopc->operation_id, &msg->header,
2185                                                &forwarded_operation_reply_relay,
2186                                                fopc);
2187     fopc->timeout_task =
2188         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2189                                       fopc);
2190     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2191     return;
2192   }
2193   if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer->details.local.peer))
2194   {
2195     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2196                              "Peer not running");
2197     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2198     return;
2199   }
2200   peer->details.local.is_running = GNUNET_NO;
2201   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2202   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
2203   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2204   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
2205   reply->host_id = htonl (master_context->host_id);
2206   reply->peer_id = msg->peer_id;
2207   reply->operation_id = msg->operation_id;
2208   queue_message (client, &reply->header);
2209   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2210 }
2211
2212
2213 /**
2214  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
2215  *
2216  * @param cls NULL
2217  * @param client identification of the client
2218  * @param message the actual message
2219  */
2220 static void
2221 handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
2222                         const struct GNUNET_MessageHeader *message)
2223 {
2224   const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
2225   struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
2226   struct Peer *peer;
2227   char *config;
2228   char *xconfig;
2229   size_t c_size;
2230   size_t xc_size;
2231   uint32_t peer_id;
2232   uint16_t msize;
2233
2234   msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
2235   peer_id = ntohl (msg->peer_id);
2236   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2237   {
2238     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2239                              "Peer not found");
2240     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2241     return;
2242   }
2243   peer = peer_list[peer_id];
2244   if (GNUNET_YES == peer->is_remote)
2245   {
2246     struct ForwardedOperationContext *fopc;
2247     
2248     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2249     GNUNET_SERVER_client_keep (client);
2250     fopc->client = client;
2251     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2252     fopc->opc =
2253         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
2254                                                fopc->operation_id, &msg->header,
2255                                                &forwarded_operation_reply_relay,
2256                                                fopc);
2257     fopc->timeout_task =
2258         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2259                                       fopc);    
2260     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2261     return;
2262   }
2263   config =
2264       GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->details.local.cfg,
2265                                       &c_size);
2266   xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
2267   GNUNET_free (config);
2268   msize =
2269       xc_size +
2270       sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2271   reply = GNUNET_realloc (xconfig, msize);
2272   (void) memmove (&reply[1], reply, xc_size);
2273   reply->header.size = htons (msize);
2274   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
2275   reply->peer_id = msg->peer_id;
2276   reply->operation_id = msg->operation_id;
2277   GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->details.local.peer,
2278                                     &reply->peer_identity);
2279   reply->config_size = htons ((uint16_t) c_size);
2280   queue_message (client, &reply->header);
2281   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2282 }
2283
2284
2285 /**
2286  * Task for cleaing up overlay connect context structure
2287  *
2288  * @param cls the overlay connect context
2289  * @param tc the task context
2290  */
2291 static void
2292 occ_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2293 {
2294   struct OverlayConnectContext *occ = cls;
2295
2296   LOG_DEBUG ("Cleaning up occ\n");
2297   GNUNET_free_non_null (occ->emsg);
2298   GNUNET_free_non_null (occ->hello);
2299   GNUNET_SERVER_client_drop (occ->client);
2300   if (NULL != occ->opc)
2301     GNUNET_TESTBED_forward_operation_msg_cancel_ (occ->opc);
2302   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
2303     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
2304   if (NULL != occ->ch)
2305     GNUNET_CORE_disconnect (occ->ch);
2306   if (NULL != occ->ghh)
2307     GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
2308   if (NULL != occ->p1th)
2309     GNUNET_TRANSPORT_disconnect (occ->p1th);
2310   if (NULL != occ->p2th)
2311     GNUNET_TRANSPORT_disconnect (occ->p2th);
2312   GNUNET_free (occ);
2313 }
2314
2315
2316 /**
2317  * Task which will be run when overlay connect request has been timed out
2318  *
2319  * @param cls the OverlayConnectContext
2320  * @param tc the TaskContext
2321  */
2322 static void
2323 timeout_overlay_connect (void *cls,
2324                          const struct GNUNET_SCHEDULER_TaskContext *tc)
2325 {
2326   struct OverlayConnectContext *occ = cls;
2327
2328   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2329   send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
2330   occ_cleanup (occ, tc);
2331 }
2332
2333
2334
2335 /**
2336  * Function called to notify transport users that another
2337  * peer connected to us.
2338  *
2339  * @param cls closure
2340  * @param new_peer the peer that connected
2341  * @param ats performance data
2342  * @param ats_count number of entries in ats (excluding 0-termination)
2343  */
2344 static void
2345 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
2346                         const struct GNUNET_ATS_Information *ats,
2347                         unsigned int ats_count)
2348 {
2349   struct OverlayConnectContext *occ = cls;
2350   struct GNUNET_TESTBED_ConnectionEventMessage *msg;
2351   char *new_peer_str;
2352   char *other_peer_str;
2353
2354   LOG_DEBUG ("Overlay connect notify\n");
2355   if (0 ==
2356       memcmp (new_peer, &occ->peer_identity,
2357               sizeof (struct GNUNET_PeerIdentity)))
2358     return;
2359   new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
2360   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2361   if (0 !=
2362       memcmp (new_peer, &occ->other_peer_identity,
2363               sizeof (struct GNUNET_PeerIdentity)))
2364   {
2365     LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n",
2366                new_peer_str, other_peer_str);
2367     GNUNET_free (new_peer_str);
2368     GNUNET_free (other_peer_str);
2369     return;
2370   }
2371   GNUNET_free (new_peer_str);
2372   LOG_DEBUG ("Peer %4s connected to peer %4s\n", other_peer_str, 
2373              GNUNET_i2s (&occ->peer_identity));
2374   GNUNET_free (other_peer_str);
2375   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
2376   {
2377     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
2378     occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2379   }
2380   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
2381   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2382   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2383   GNUNET_free_non_null (occ->emsg);
2384   occ->emsg = NULL;
2385   if (NULL != occ->p2th)
2386     GNUNET_TRANSPORT_disconnect (occ->p2th);
2387   occ->p2th = NULL;
2388   LOG_DEBUG ("Peers connected - Sending overlay connect success\n");
2389   msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2390   msg->header.size =
2391       htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2392   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT);
2393   msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
2394   msg->peer1 = htonl (occ->peer_id);
2395   msg->peer2 = htonl (occ->other_peer_id);
2396   msg->operation_id = GNUNET_htonll (occ->op_id);
2397   queue_message (occ->client, &msg->header);
2398   GNUNET_SCHEDULER_add_now (&occ_cleanup, occ);
2399 }
2400
2401
2402 /**
2403  * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
2404  * peer 1.
2405  *
2406  * @param cls the OverlayConnectContext
2407  * @param tc the TaskContext from scheduler
2408  */
2409 static void
2410 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2411 {
2412   struct OverlayConnectContext *occ = cls;
2413   char *other_peer_str;
2414
2415   occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2416   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2417     return;
2418   GNUNET_assert (NULL != occ->hello);
2419   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2420   if (NULL != occ->peer2_controller)
2421   {
2422     struct GNUNET_TESTBED_RequestConnectMessage *msg;
2423     uint16_t msize;
2424     uint16_t hello_size;
2425
2426     LOG_DEBUG ("Offering HELLO of %s to %s via Remote Overlay Request\n", 
2427                GNUNET_i2s (&occ->peer_identity), other_peer_str);
2428     hello_size = ntohs (occ->hello->size);
2429     msize = sizeof (struct GNUNET_TESTBED_RequestConnectMessage) + hello_size;
2430     msg = GNUNET_malloc (msize);
2431     msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT);
2432     msg->header.size = htons (msize);
2433     msg->peer = htonl (occ->other_peer_id);
2434     msg->operation_id = GNUNET_htonll (occ->op_id);
2435     (void) memcpy (&msg->peer_identity, &occ->peer_identity,
2436                    sizeof (struct GNUNET_PeerIdentity));
2437     memcpy (msg->hello, occ->hello, hello_size);
2438     GNUNET_TESTBED_queue_message_ (occ->peer2_controller, &msg->header);
2439   }
2440   else
2441   {
2442     LOG_DEBUG ("Offering HELLO of %s to %s\n", 
2443                GNUNET_i2s (&occ->peer_identity), other_peer_str);
2444     GNUNET_TRANSPORT_offer_hello (occ->p2th, occ->hello, NULL, NULL);
2445     GNUNET_TRANSPORT_try_connect (occ->p2th, &occ->peer_identity);
2446     occ->send_hello_task =
2447         GNUNET_SCHEDULER_add_delayed
2448         (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
2449                                         100 * (pow (2, occ->retries++))),
2450          &send_hello, occ);
2451   }
2452   GNUNET_free (other_peer_str);  
2453 }
2454
2455 /**
2456  * Test for checking whether HELLO message is empty
2457  *
2458  * @param cls empty flag to set
2459  * @param address the HELLO
2460  * @param expiration expiration of the HELLO
2461  * @return
2462  */
2463 static int
2464 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
2465               struct GNUNET_TIME_Absolute expiration)
2466 {
2467   int *empty = cls;
2468
2469   *empty = GNUNET_NO;
2470   return GNUNET_OK;
2471 }
2472
2473
2474 /**
2475  * Function called whenever there is an update to the HELLO of peers in the
2476  * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
2477  * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
2478  *
2479  * @param cls closure
2480  * @param hello our updated HELLO
2481  */
2482 static void
2483 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
2484 {
2485   struct OverlayConnectContext *occ = cls;
2486   int empty;
2487   uint16_t msize;
2488
2489   msize = ntohs (hello->size);
2490   empty = GNUNET_YES;
2491   (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
2492                                          hello, GNUNET_NO, &test_address,
2493                                          &empty);
2494   if (GNUNET_YES == empty)
2495   {
2496     LOG_DEBUG ("HELLO of %s is empty\n", GNUNET_i2s (&occ->peer_identity));
2497     return;
2498   }
2499   LOG_DEBUG ("Received HELLO of %s\n", GNUNET_i2s (&occ->peer_identity));
2500   occ->hello = GNUNET_malloc (msize);
2501   memcpy (occ->hello, hello, msize);
2502   GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
2503   occ->ghh = NULL;
2504   GNUNET_TRANSPORT_disconnect (occ->p1th);
2505   occ->p1th = NULL;
2506   GNUNET_free_non_null (occ->emsg);
2507   if (NULL == occ->peer2_controller)
2508   {   
2509     occ->p2th =
2510         GNUNET_TRANSPORT_connect (peer_list[occ->other_peer_id]->details.local.cfg,
2511                                   &occ->other_peer_identity, NULL, NULL, NULL,
2512                                   NULL);
2513     if (NULL == occ->p2th)
2514     {
2515       GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of %s\n",
2516                        GNUNET_i2s (&occ->other_peer_identity));
2517       GNUNET_SCHEDULER_cancel (occ->timeout_task);
2518       occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2519       return;
2520     }
2521   }
2522   occ->emsg = GNUNET_strdup ("Timeout while offering HELLO to other peer");
2523   occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
2524 }
2525
2526
2527 /**
2528  * Function called after GNUNET_CORE_connect has succeeded (or failed
2529  * for good).  Note that the private key of the peer is intentionally
2530  * not exposed here; if you need it, your process should try to read
2531  * the private key file directly (which should work if you are
2532  * authorized...).
2533  *
2534  * @param cls closure
2535  * @param server handle to the server, NULL if we failed
2536  * @param my_identity ID of this peer, NULL if we failed
2537  */
2538 static void
2539 core_startup_cb (void *cls, struct GNUNET_CORE_Handle *server,
2540                  const struct GNUNET_PeerIdentity *my_identity)
2541 {
2542   struct OverlayConnectContext *occ = cls;
2543
2544   GNUNET_free_non_null (occ->emsg);
2545   occ->emsg = GNUNET_strdup ("Failed to connect to CORE\n");
2546   if ((NULL == server) || (NULL == my_identity))
2547     goto error_return;
2548   GNUNET_free (occ->emsg);
2549   occ->ch = server;
2550   occ->emsg = NULL;
2551   memcpy (&occ->peer_identity, my_identity,
2552           sizeof (struct GNUNET_PeerIdentity));
2553   occ->p1th =
2554       GNUNET_TRANSPORT_connect (occ->peer->details.local.cfg,
2555                                 &occ->peer_identity, NULL, NULL, NULL, NULL);
2556   if (NULL == occ->p1th)
2557   {
2558     GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of peers %4s",
2559                     GNUNET_i2s (&occ->peer_identity));
2560     goto error_return;
2561   }
2562   LOG_DEBUG ("Acquiring HELLO of peer %s\n", GNUNET_i2s (&occ->peer_identity));
2563   occ->emsg = GNUNET_strdup ("Timeout while acquiring HELLO message");
2564   occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th, &hello_update_cb, occ);
2565   return;
2566   
2567  error_return:
2568   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2569   occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2570   return;
2571 }
2572
2573
2574 /**
2575  * Callback to be called when forwarded get peer config operation as part of
2576  * overlay connect is successfull. Connection to Peer 1's core is made and is
2577  * checked for new connection from peer 2
2578  *
2579  * @param cls ForwardedOperationContext
2580  * @param msg the peer create success message
2581  */
2582 static void
2583 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
2584 {
2585   struct OverlayConnectContext *occ = cls;
2586   const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
2587   const struct GNUNET_CORE_MessageHandler no_handlers[] = {
2588     {NULL, 0, 0}
2589   };
2590
2591   occ->opc = NULL;
2592   if (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG != ntohs (msg->type))
2593     goto error_return;
2594   cmsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *)
2595       msg;
2596   memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
2597           sizeof (struct GNUNET_PeerIdentity));
2598   GNUNET_free_non_null (occ->emsg);
2599   occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
2600   occ->ch =
2601       GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
2602                            &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
2603                            GNUNET_NO, no_handlers);
2604   if (NULL == occ->ch)
2605     goto error_return;
2606   return;
2607
2608  error_return:
2609   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2610   occ->timeout_task = 
2611       GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2612 }
2613
2614
2615 /**
2616  * This callback is a part of overlay connect operation. This will be run when
2617  * the registration operation of peer2's controller is completed at peer1's
2618  * controller
2619  *
2620  * @param cls the ForwardedOverlayConnectContext
2621  * @param emsg the error message in case of any failure; NULL if host
2622  *          registration is successfull.
2623  */
2624 static void
2625 focc_reg_completion_cc (void *cls, const char *emsg)
2626 {
2627   struct ForwardedOverlayConnectContext *focc = cls;
2628   struct GNUNET_CONFIGURATION_Handle *cfg;
2629
2630   GNUNET_assert (FOCC_REGISTER == focc->state);
2631   focc->rhandle = NULL;
2632   GNUNET_assert (NULL == focc->sub_op);
2633   LOG_DEBUG ("Registering peer2's host successful\n");
2634   if ((NULL == focc->gateway2)
2635       || ((focc->peer2_host_id < slave_list_size) /* Check if we have the needed config */
2636           && (NULL != slave_list[focc->peer2_host_id])))
2637   {
2638     focc->state = FOCC_LINK;
2639     cfg = (NULL == focc->gateway2) ? 
2640         our_config : slave_list[focc->peer2_host_id]->cfg;
2641     focc->sub_op = 
2642         GNUNET_TESTBED_controller_link_ (focc,
2643                                          focc->gateway,
2644                                          focc->peer2_host_id,
2645                                          peer_list[focc->peer1]->details.remote.remote_host_id,
2646                                          cfg,
2647                                          GNUNET_NO);
2648     return;
2649   }
2650   focc->state = FOCC_GET_CFG;
2651   focc->sub_op = GNUNET_TESTBED_get_slave_config_ (focc, focc->gateway2,
2652                                                    focc->peer2_host_id);
2653 }
2654
2655
2656 /**
2657  * Callback to be called when forwarded overlay connection operation has a reply
2658  * from the sub-controller successfull. We have to relay the reply msg back to
2659  * the client
2660  *
2661  * @param cls ForwardedOperationContext
2662  * @param msg the peer create success message
2663  */
2664 static void
2665 forwarded_overlay_connect_listener (void *cls,
2666                                     const struct GNUNET_MessageHeader *msg)
2667 {
2668   struct ForwardedOperationContext *fopc = cls;
2669   struct ForwardedOverlayConnectContext *focc;
2670
2671   focc = fopc->cls;
2672   if (NULL == focc)
2673   {
2674     forwarded_operation_reply_relay (cls, msg);
2675     return;
2676   }
2677   switch (focc->state)
2678   {
2679   case FOCC_INIT:
2680     if (GNUNET_MESSAGE_TYPE_TESTBED_NEEDCONTROLLERCONFIG != ntohs (msg->type))
2681     {
2682       GNUNET_break (0);  /* Something failed; you may check output of
2683                             sub-controllers */
2684       cleanup_focc (focc);
2685       forwarded_operation_reply_relay (cls, msg);
2686       return;
2687     }
2688     LOG_DEBUG ("Registering peer2's host\n");
2689     focc->state = FOCC_REGISTER;
2690     focc->rhandle =
2691         GNUNET_TESTBED_register_host (focc->gateway,
2692                                       host_list[focc->peer2_host_id],
2693                                       focc_reg_completion_cc, focc);
2694     break;
2695   default:
2696     GNUNET_assert (0);
2697   }
2698   GNUNET_SERVER_client_drop (fopc->client);
2699   GNUNET_SCHEDULER_cancel (fopc->timeout_task);
2700   fopc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2701   GNUNET_free (fopc);
2702 }
2703
2704
2705 /**
2706  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
2707  *
2708  * @param cls NULL
2709  * @param client identification of the client
2710  * @param message the actual message
2711  */
2712 static void
2713 handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
2714                         const struct GNUNET_MessageHeader *message)
2715 {
2716   const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
2717   struct OverlayConnectContext *occ;
2718   const struct GNUNET_CORE_MessageHandler no_handlers[] = {
2719     {NULL, 0, 0}
2720   };
2721   struct Peer *peer;
2722   uint64_t operation_id;
2723   uint32_t p1;
2724   uint32_t p2; 
2725   uint32_t peer2_host_id;
2726
2727   msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
2728   p1 = ntohl (msg->peer1);
2729   p2 = ntohl (msg->peer2);
2730   peer2_host_id = ntohl (msg->peer2_host_id);
2731   GNUNET_assert (p1 < peer_list_size);
2732   GNUNET_assert (NULL != peer_list[p1]);
2733   peer = peer_list[p1];
2734   operation_id = GNUNET_ntohll (msg->operation_id);  
2735   if (GNUNET_YES == peer->is_remote)
2736   {
2737     struct ForwardedOperationContext *fopc;
2738     struct Route *route_to_peer2_host;
2739     struct Route *route_to_peer1_host;
2740
2741     LOG_DEBUG ("Forwarding overlay connect\n");
2742     GNUNET_SERVER_client_keep (client);
2743     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2744     fopc->client = client;
2745     fopc->operation_id = operation_id;
2746     route_to_peer2_host = NULL;
2747     route_to_peer1_host = NULL;
2748     route_to_peer2_host = find_dest_route (peer2_host_id);
2749     if ((NULL != route_to_peer2_host) 
2750         || (peer2_host_id == master_context->host_id))
2751     {
2752       route_to_peer1_host = 
2753           find_dest_route (peer_list[p1]->details.remote.remote_host_id);
2754       GNUNET_assert (NULL != route_to_peer1_host);
2755       if ((peer2_host_id == master_context->host_id) 
2756           || (route_to_peer2_host->dest != route_to_peer1_host->dest))
2757       {
2758         struct ForwardedOverlayConnectContext *focc;
2759         uint16_t msize;
2760
2761         msize = sizeof (struct GNUNET_TESTBED_OverlayConnectMessage);
2762         focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
2763         focc->gateway = peer->details.remote.controller;
2764         focc->gateway2 = (NULL == route_to_peer2_host) ? NULL :
2765             slave_list[route_to_peer2_host->dest]->controller;
2766         focc->peer1 = p1;
2767         focc->peer2 = p2;
2768         focc->peer2_host_id = peer2_host_id;
2769         focc->state = FOCC_INIT;
2770         focc->orig_msg = GNUNET_malloc (msize);
2771         (void) memcpy (focc->orig_msg, message, msize);
2772         GNUNET_SERVER_client_keep (client);
2773         focc->client = client;
2774         focc->operation_id = operation_id;
2775         fopc->cls = focc;
2776       }
2777     }
2778     fopc->opc = 
2779         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
2780                                                operation_id, message,
2781                                                &forwarded_overlay_connect_listener,
2782                                                fopc);
2783     fopc->timeout_task =
2784         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2785                                       fopc);
2786     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2787     return;
2788   }
2789   occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
2790   GNUNET_SERVER_client_keep (client);
2791   occ->client = client;
2792   occ->peer_id = p1;
2793   occ->other_peer_id = p2;
2794   occ->peer = peer_list[p1];
2795   occ->op_id = GNUNET_ntohll (msg->operation_id);  
2796   if ((p2 >= peer_list_size) || (NULL == peer_list[p2]))
2797   {   
2798     if ((peer2_host_id >= slave_list_size)
2799         || (NULL ==slave_list[peer2_host_id]))
2800     {
2801       struct GNUNET_TESTBED_NeedControllerConfig *reply;
2802
2803       GNUNET_free (occ);
2804       reply = GNUNET_malloc (sizeof (struct
2805                                      GNUNET_TESTBED_NeedControllerConfig)); 
2806       reply->header.size = htons (sizeof (struct
2807                                           GNUNET_TESTBED_NeedControllerConfig));
2808       reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_NEEDCONTROLLERCONFIG);
2809       reply->controller_host_id = msg->peer2_host_id;
2810       reply->operation_id = msg->operation_id;
2811       queue_message (client, &reply->header);      
2812       GNUNET_SERVER_receive_done (client, GNUNET_OK);
2813       return;
2814     }
2815     else
2816     {
2817       occ->peer2_controller = slave_list[peer2_host_id]->controller;
2818       if (NULL == occ->peer2_controller)
2819       {
2820         GNUNET_break (0);       /* What's going on? */
2821         GNUNET_SERVER_client_drop (client);
2822         GNUNET_free (occ);
2823         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2824         return;
2825       }
2826     }
2827   }
2828   else
2829   {
2830     if (GNUNET_YES == peer_list[occ->other_peer_id]->is_remote)
2831       occ->peer2_controller = peer_list[occ->other_peer_id]->details.remote.controller;
2832   }
2833   /* Get the identity of the second peer */
2834   if (NULL != occ->peer2_controller)
2835   {
2836     struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
2837
2838     cmsg.header.size = 
2839         htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
2840     cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG);
2841     cmsg.peer_id = msg->peer2;
2842     cmsg.operation_id = msg->operation_id;
2843     occ->opc = 
2844         GNUNET_TESTBED_forward_operation_msg_ (occ->peer2_controller,
2845                                                occ->op_id, &cmsg.header,
2846                                                &overlay_connect_get_config,
2847                                                occ);
2848     occ->emsg = 
2849         GNUNET_strdup ("Timeout while getting peer identity of peer B\n");
2850     occ->timeout_task =
2851         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
2852                                       (GNUNET_TIME_UNIT_SECONDS, 30),
2853                                       &timeout_overlay_connect, occ);
2854     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2855     return;
2856   }
2857   GNUNET_TESTING_peer_get_identity (peer_list[occ->other_peer_id]->details.local.peer,
2858                                     &occ->other_peer_identity);
2859   /* Connect to the core of 1st peer and wait for the 2nd peer to connect */
2860   occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
2861   occ->ch =
2862       GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
2863                            &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
2864                            GNUNET_NO, no_handlers);
2865   if (NULL == occ->ch)
2866     occ->timeout_task = 
2867         GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2868   else
2869     occ->timeout_task =
2870         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
2871                                       (GNUNET_TIME_UNIT_SECONDS, 30),
2872                                       &timeout_overlay_connect, occ);
2873   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2874 }
2875
2876
2877 /**
2878  * Function to cleanup RequestOverlayConnectContext and any associated tasks
2879  * with it
2880  *
2881  * @param rocc the RequestOverlayConnectContext
2882  */
2883 static void
2884 cleanup_rocc (struct RequestOverlayConnectContext *rocc)
2885 {
2886   if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id)
2887     GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
2888   if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id)
2889     GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
2890   GNUNET_TRANSPORT_disconnect (rocc->th);
2891   GNUNET_free_non_null (rocc->hello);
2892   GNUNET_free (rocc);
2893 }
2894
2895
2896 /**
2897  * Task to timeout rocc and cleanit up
2898  *
2899  * @param cls the RequestOverlayConnectContext
2900  * @param tc the TaskContext from scheduler
2901  */
2902 static void
2903 timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2904 {
2905   struct RequestOverlayConnectContext *rocc = cls;
2906   
2907   rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK;
2908   cleanup_rocc (rocc);
2909 }
2910
2911
2912 /**
2913  * Function called to notify transport users that another
2914  * peer connected to us.
2915  *
2916  * @param cls closure
2917  * @param new_peer the peer that connected
2918  * @param ats performance data
2919  * @param ats_count number of entries in ats (excluding 0-termination)
2920  */
2921 static void 
2922 transport_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
2923                           const struct GNUNET_ATS_Information * ats,
2924                           uint32_t ats_count)
2925 {
2926   struct RequestOverlayConnectContext *rocc = cls;
2927
2928   LOG_DEBUG ("Request Overlay connect notify\n");
2929   if (0 != memcmp (new_peer, &rocc->a_id, sizeof (struct GNUNET_PeerIdentity)))
2930     return;
2931   LOG_DEBUG ("Peer %4s connected\n", GNUNET_i2s (&rocc->a_id));
2932   cleanup_rocc (rocc);
2933 }
2934
2935
2936 /**
2937  * Task to offer the HELLO message to the peer and ask it to connect to the peer
2938  * whose identity is in RequestOverlayConnectContext
2939  *
2940  * @param cls the RequestOverlayConnectContext
2941  * @param tc the TaskContext from scheduler
2942  */
2943 static void
2944 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2945 {
2946   struct RequestOverlayConnectContext *rocc = cls;
2947
2948   rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK;
2949   GNUNET_TRANSPORT_offer_hello (rocc->th, rocc->hello, NULL, NULL);
2950   GNUNET_TRANSPORT_try_connect (rocc->th, &rocc->a_id);
2951   rocc->attempt_connect_task_id = 
2952       GNUNET_SCHEDULER_add_delayed 
2953       (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
2954                                       100 * (pow (2, rocc->retries++))),
2955        &attempt_connect_task, rocc);
2956 }
2957
2958
2959 /**
2960  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages
2961  *
2962  * @param cls NULL
2963  * @param client identification of the client
2964  * @param message the actual message
2965  */
2966 static void
2967 handle_overlay_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
2968                                 const struct GNUNET_MessageHeader *message)
2969 {
2970   const struct GNUNET_TESTBED_RequestConnectMessage *msg;
2971   struct RequestOverlayConnectContext *rocc;
2972   struct Peer *peer;
2973   uint32_t peer_id;
2974   uint16_t msize;
2975   uint16_t hsize;
2976   
2977   msize = ntohs (message->size);
2978   if (sizeof (struct GNUNET_TESTBED_RequestConnectMessage) >= msize)
2979   {
2980     GNUNET_break (0);
2981     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2982     return;
2983   }  
2984   msg = (const struct GNUNET_TESTBED_RequestConnectMessage *) message;
2985   if ((NULL == msg->hello) || 
2986       (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)))
2987   {
2988     GNUNET_break (0);
2989     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2990     return;
2991   }
2992   hsize = ntohs (msg->hello->size);
2993   if ((sizeof (struct GNUNET_TESTBED_RequestConnectMessage) + hsize) != msize)
2994   {
2995     GNUNET_break (0);
2996     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2997     return;
2998   }
2999   peer_id = ntohl (msg->peer);
3000   if ((peer_id >= peer_list_size) || (NULL == (peer = peer_list[peer_id])))
3001   {
3002     GNUNET_break_op (0);
3003     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3004     return;
3005   }
3006   if (GNUNET_YES == peer->is_remote)
3007   {
3008     struct GNUNET_MessageHeader *msg2;
3009     
3010     msg2 = GNUNET_malloc (msize);
3011     (void) memcpy (msg2, message, msize);
3012     GNUNET_TESTBED_queue_message_ (peer->details.remote.controller, msg2);
3013     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3014     return;
3015   }
3016   rocc = GNUNET_malloc (sizeof (struct RequestOverlayConnectContext));
3017   rocc->th = GNUNET_TRANSPORT_connect (peer->details.local.cfg, NULL, rocc, 
3018                                        NULL, &transport_connect_notify, NULL);
3019   if (NULL == rocc->th)
3020   {
3021     GNUNET_break (0);
3022     GNUNET_free (rocc);
3023     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3024     return;
3025   }
3026   memcpy (&rocc->a_id, &msg->peer_identity,
3027           sizeof (struct GNUNET_PeerIdentity));
3028   rocc->hello = GNUNET_malloc (hsize);
3029   memcpy (rocc->hello, msg->hello, hsize);
3030   rocc->attempt_connect_task_id =
3031       GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
3032   rocc->timeout_rocc_task_id =
3033       GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_rocc_task, rocc);
3034   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3035 }
3036
3037
3038 /**
3039  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
3040  *
3041  * @param cls NULL
3042  * @param client identification of the client
3043  * @param message the actual message
3044  */
3045 static void
3046 handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client,
3047                          const struct GNUNET_MessageHeader *message)
3048 {
3049   struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
3050   struct Slave *slave;  
3051   struct GNUNET_TESTBED_SlaveConfiguration *reply;
3052   char *config;
3053   char *xconfig;
3054   size_t config_size;
3055   size_t xconfig_size;
3056   size_t reply_size;
3057   uint64_t op_id;
3058   uint32_t slave_id;
3059
3060   msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message;
3061   slave_id = ntohl (msg->slave_id);
3062   op_id = GNUNET_ntohll (msg->operation_id);
3063   if ((slave_list_size <= slave_id) || (NULL == slave_list[slave_id]))
3064   {
3065     send_operation_fail_msg (client, op_id, "Slave not found");
3066     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3067     return;
3068   }
3069   slave = slave_list[slave_id];
3070   if (NULL == slave->cfg)
3071   {
3072     send_operation_fail_msg (client, op_id,
3073                              "Configuration not found (slave not started by me)");
3074     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3075     return;
3076   }
3077   config = GNUNET_CONFIGURATION_serialize (slave->cfg, &config_size);
3078   xconfig_size = GNUNET_TESTBED_compress_config_ (config, config_size, 
3079                                                   &xconfig);
3080   GNUNET_free (config);  
3081   reply_size = xconfig_size + sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
3082   GNUNET_break (reply_size <= UINT16_MAX);
3083   GNUNET_break (config_size <= UINT16_MAX);
3084   reply = GNUNET_realloc (xconfig, reply_size);
3085   (void) memmove (&reply[1], reply, xconfig_size);
3086   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG);
3087   reply->header.size = htons ((uint16_t) reply_size);
3088   reply->slave_id = msg->slave_id;
3089   reply->operation_id = msg->operation_id;
3090   reply->config_size = htons ((uint16_t) config_size);
3091   queue_message (client, &reply->header);
3092   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3093 }
3094
3095
3096 /**
3097  * Iterator over hash map entries.
3098  *
3099  * @param cls closure
3100  * @param key current key code
3101  * @param value value in the hash map
3102  * @return GNUNET_YES if we should continue to
3103  *         iterate,
3104  *         GNUNET_NO if not.
3105  */
3106 static int
3107 ss_map_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
3108 {
3109   struct SharedService *ss = value;
3110
3111   GNUNET_assert (GNUNET_YES ==
3112                  GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
3113   GNUNET_free (ss->name);
3114   GNUNET_free (ss);
3115   return GNUNET_YES;
3116 }
3117
3118
3119 /**
3120  * Task to clean up and shutdown nicely
3121  *
3122  * @param cls NULL
3123  * @param tc the TaskContext from scheduler
3124  */
3125 static void
3126 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3127 {
3128   struct LCFContextQueue *lcfq;
3129   uint32_t id;
3130
3131   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
3132   LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
3133   (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
3134                                                 NULL);
3135   GNUNET_CONTAINER_multihashmap_destroy (ss_map);
3136   if (NULL != lcfq_head)
3137   {
3138     if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
3139     {
3140       GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
3141       lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
3142     }
3143     if (NULL != lcfq_head->lcf->rhandle)
3144       GNUNET_TESTBED_cancel_registration (lcfq_head->lcf->rhandle);
3145   }
3146   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
3147   for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
3148   {
3149     GNUNET_free (lcfq->lcf->msg);
3150     GNUNET_free (lcfq->lcf);
3151     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
3152     GNUNET_free (lcfq);
3153   }
3154   /* Clear peer list */
3155   for (id = 0; id < peer_list_size; id++)
3156     if (NULL != peer_list[id])
3157     {
3158       if (GNUNET_NO == peer_list[id]->is_remote)
3159       {
3160         if (GNUNET_YES == peer_list[id]->details.local.is_running)
3161           GNUNET_TESTING_peer_stop (peer_list[id]->details.local.peer);
3162         GNUNET_TESTING_peer_destroy (peer_list[id]->details.local.peer);
3163         GNUNET_CONFIGURATION_destroy (peer_list[id]->details.local.cfg);
3164       }
3165       GNUNET_free (peer_list[id]);
3166     }
3167   GNUNET_free_non_null (peer_list);
3168   /* Clear host list */
3169   for (id = 0; id < host_list_size; id++)
3170     if (NULL != host_list[id])
3171       GNUNET_TESTBED_host_destroy (host_list[id]);
3172   GNUNET_free_non_null (host_list);
3173   /* Clear route list */
3174   for (id = 0; id < route_list_size; id++)
3175     if (NULL != route_list[id])
3176       GNUNET_free (route_list[id]);
3177   GNUNET_free_non_null (route_list);
3178   /* Clear slave_list */
3179   for (id = 0; id < slave_list_size; id++)
3180     if (NULL != slave_list[id])
3181     {
3182       if (NULL != slave_list[id]->cfg)
3183         GNUNET_CONFIGURATION_destroy (slave_list[id]->cfg);
3184       if (NULL != slave_list[id]->controller)
3185         GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
3186       if (NULL != slave_list[id]->controller_proc)
3187         GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
3188       GNUNET_free (slave_list[id]);
3189     }
3190   GNUNET_free_non_null (slave_list);
3191   if (NULL != master_context)
3192   {
3193     GNUNET_free_non_null (master_context->master_ip);
3194     if (NULL != master_context->system)
3195       GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
3196     GNUNET_free (master_context);
3197     master_context = NULL;
3198   }
3199   GNUNET_free_non_null (hostname);
3200   GNUNET_CONFIGURATION_destroy (our_config);
3201 }
3202
3203
3204 /**
3205  * Callback for client disconnect
3206  *
3207  * @param cls NULL
3208  * @param client the client which has disconnected
3209  */
3210 static void
3211 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
3212 {
3213   if (NULL == master_context)
3214     return;
3215   if (client == master_context->client)
3216   {
3217     LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
3218     GNUNET_SERVER_client_drop (client);
3219     /* should not be needed as we're terminated by failure to read
3220      * from stdin, but if stdin fails for some reason, this shouldn't
3221      * hurt for now --- might need to revise this later if we ever
3222      * decide that master connections might be temporarily down
3223      * for some reason */
3224     //GNUNET_SCHEDULER_shutdown ();
3225   }
3226 }
3227
3228
3229 /**
3230  * Testbed setup
3231  *
3232  * @param cls closure
3233  * @param server the initialized server
3234  * @param cfg configuration to use
3235  */
3236 static void
3237 testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
3238              const struct GNUNET_CONFIGURATION_Handle *cfg)
3239 {
3240   static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
3241     {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
3242     {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
3243     {&handle_configure_shared_service, NULL,
3244      GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
3245     {&handle_link_controllers, NULL,
3246      GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
3247     {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
3248     {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
3249      sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
3250     {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
3251      sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
3252     {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
3253      sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
3254     {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
3255      sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
3256     {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
3257      sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
3258     {&handle_overlay_request_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT,
3259      0},
3260     {handle_slave_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG,
3261      sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)},
3262     {NULL}
3263   };
3264
3265   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string 
3266                  (cfg, "testbed", "HOSTNAME", &hostname));
3267   our_config = GNUNET_CONFIGURATION_dup (cfg);
3268   GNUNET_SERVER_add_handlers (server, message_handlers);
3269   GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
3270   ss_map = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
3271   shutdown_task_id =
3272       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
3273                                     &shutdown_task, NULL);
3274   LOG_DEBUG ("Testbed startup complete\n");
3275   event_mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
3276 }
3277
3278
3279 /**
3280  * The starting point of execution
3281  */
3282 int
3283 main (int argc, char *const *argv)
3284 {
3285   //sleep (15);                 /* Debugging */
3286   return (GNUNET_OK ==
3287           GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE,
3288                               &testbed_run, NULL)) ? 0 : 1;
3289 }
3290
3291 /* end of gnunet-service-testbed.c */