towards peer create forwarding
[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 #define LIST_GROW_STEP 10
55
56 struct Context
57 {
58   /**
59    * The client handle associated with this context
60    */
61   struct GNUNET_SERVER_Client *client;
62
63   /**
64    * The network address of the master controller
65    */
66   char *master_ip;
67
68   /**
69    * The TESTING system handle for starting peers locally
70    */
71   struct GNUNET_TESTING_System *system;
72   
73   /**
74    * Event mask of event to be responded in this context
75    */
76   uint64_t event_mask;
77
78   /**
79    * Our host id according to this context
80    */
81   uint32_t host_id;
82 };
83
84
85 /**
86  * The message queue for sending messages to clients
87  */
88 struct MessageQueue
89 {
90   /**
91    * The message to be sent
92    */
93   struct GNUNET_MessageHeader *msg;
94
95   /**
96    * The client to send the message to
97    */
98   struct GNUNET_SERVER_Client *client;
99   
100   /**
101    * next pointer for DLL
102    */
103   struct MessageQueue *next;
104   
105   /**
106    * prev pointer for DLL
107    */
108   struct MessageQueue *prev;
109 };
110
111
112 /**
113  * The structure for identifying a shared service
114  */
115 struct SharedService
116 {
117   /**
118    * The name of the shared service
119    */
120   char *name;
121
122   /**
123    * Number of shared peers per instance of the shared service
124    */
125   uint32_t num_shared;
126
127   /**
128    * Number of peers currently sharing the service
129    */
130   uint32_t num_sharing;
131 };
132
133
134 /**
135  * A routing entry
136  */
137 struct Route
138 {
139   /**
140    * destination host
141    */
142   uint32_t dest;
143
144   /**
145    * The host destination is reachable thru
146    */
147   uint32_t thru;
148 };
149
150
151 /**
152  * Structure representing a connected(directly-linked) controller
153  */
154 struct Slave
155 {
156   /**
157    * The controller process handle if we had started the controller
158    */
159   struct GNUNET_TESTBED_ControllerProc *controller_proc;
160
161   /**
162    * The controller handle
163    */
164   struct GNUNET_TESTBED_Controller *controller;
165
166   /**
167    * The id of the host this controller is running on
168    */
169   uint32_t host_id;
170 };
171
172
173 /**
174  * States of LCFContext
175  */
176 enum LCFContextState
177   {
178     /**
179      * The Context has been initialized; Nothing has been done on it
180      */
181     INIT,
182
183     /**
184      * Delegated host has been registered at the forwarding controller
185      */
186     DELEGATED_HOST_REGISTERED,
187     
188     /**
189      * The slave host has been registred at the forwarding controller
190      */
191     SLAVE_HOST_REGISTERED,
192
193     /**
194      * The context has been finished (may have error)
195      */
196     FINISHED
197
198   };
199
200
201 /**
202  * Link controllers request forwarding context
203  */
204 struct LCFContext
205 {
206   /**
207    * The serialized and compressed configuration
208    */
209   char *sxcfg;
210
211   /**
212    * The gateway which will pass the link message to delegated host
213    */
214   struct Slave *gateway;
215
216   /**
217    * The host registration handle while registered hosts in this context
218    */
219   struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
220
221   /**
222    * The size of the compressed serialized configuration
223    */
224   size_t sxcfg_size;
225
226   /**
227    * The size of the uncompressed configuration
228    */
229   size_t scfg_size;
230
231   /**
232    * Should the delegated host be started by the slave host?
233    */
234   int is_subordinate;
235
236   /**
237    * The state of this context
238    */
239   enum LCFContextState state;
240
241   /**
242    * The delegated host
243    */
244   uint32_t delegated_host_id;
245
246   /**
247    * The slave host
248    */
249   uint32_t slave_host_id;
250
251 };
252
253
254 /**
255  * Structure of a queue entry in LCFContext request queue
256  */
257 struct LCFContextQueue
258 {
259   /**
260    * The LCFContext
261    */
262   struct LCFContext *lcf;
263
264   /**
265    * Head prt for DLL
266    */
267   struct LCFContextQueue *next;
268
269   /**
270    * Tail ptr for DLL
271    */
272   struct LCFContextQueue *prev;
273 };
274
275
276 /**
277  * A locally started peer
278  */
279 struct Peer
280 {
281   /**
282    * The peer handle from testing API
283    */
284   struct GNUNET_TESTING_Peer *peer;
285
286   /**
287    * The modified (by GNUNET_TESTING_peer_configure) configuration this peer is
288    * configured with
289    */
290   struct GNUNET_CONFIGURATION_Handle *cfg;
291
292   /**
293    * Our local reference id for this peer
294    */
295   uint32_t id;
296
297 };
298
299
300 /**
301  * State information for overlay connect context
302  */
303 enum OCCState
304   {
305     /**
306      * Initial state
307      */
308     OCC_STATE_INIT,
309
310     /**
311      * Peer 1 has connected to peer0
312      */
313     OCC_STATE_PEER0_SUCCESS,
314
315     /**
316      * Peer 2 has connected to peer1
317      */
318     OCC_STATE_PEER1_SUCCESS,
319
320   };
321
322
323 /**
324  * Context information for connecting 2 peers in overlay
325  */
326 struct OverlayConnectContext
327 {
328   /**
329    * The client which has requested for overlay connection
330    */
331   struct GNUNET_SERVER_Client *client;
332
333   /**
334    * the peer which has to connect to the other peer
335    */
336   struct Peer *peer;
337
338   /**
339    * The other peer
340    */
341   struct Peer *other_peer;
342   
343   /**
344    * Transport handle of the first peer to offer second peer's HELLO
345    */
346   struct GNUNET_TRANSPORT_Handle *p1th;
347
348   /**
349    * Transport handle of other peer to get its HELLO
350    */
351   struct GNUNET_TRANSPORT_Handle *p2th;
352
353   /**
354    * Core handles of the peer which has to connect to other peer
355    */
356   struct GNUNET_CORE_Handle *ch;
357
358   /**
359    * HELLO of the other peer
360    */
361   struct GNUNET_MessageHeader *hello;
362   
363   /**
364    * Get hello handle for the other peer
365    */
366   struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
367
368   /**
369    * The error message we send if this overlay connect operation has timed out
370    */
371   char *emsg;
372   
373   /**
374    * The peer identity of the first peer
375    */
376   struct GNUNET_PeerIdentity peer_identity;
377
378   /**
379    * The peer identity of the other peer
380    */
381   struct GNUNET_PeerIdentity other_peer_identity;
382
383   /**
384    * The id of the operation responsible for creating this context
385    */
386   uint64_t op_id;
387
388   /**
389    * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
390    * connect to peer 2
391    */
392   GNUNET_SCHEDULER_TaskIdentifier send_hello_task;
393   
394   /**
395    * The id of the overlay connect timeout task
396    */
397   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
398
399   /**
400    * State information for determining whose HELLOs have been successfully
401    * exchanged
402    */
403   enum OCCState state;
404
405 };
406
407
408 /**
409  * Context data to be used when forwarding peer create messages
410  */
411 struct PeerCreateContext
412 {
413   /**
414    * The operation handle to peer create
415    */
416   struct GNUNET_TESTBED_operation *operation;
417
418   /**
419    * The ID of the operation which created this context
420    */
421   uint64_t operation_id;
422
423   /**
424    * The peer create timeout task id
425    */
426   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
427
428 };
429
430
431 /**
432  * The master context; generated with the first INIT message
433  */
434 static struct Context *master_context;
435
436 /***********/
437 /* Handles */
438 /***********/
439
440 /**
441  * Current Transmit Handle; NULL if no notify transmit exists currently
442  */
443 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
444
445 /****************/
446 /* Lists & Maps */
447 /****************/
448
449 /**
450  * The head for the LCF queue
451  */
452 static struct LCFContextQueue *lcfq_head;
453
454 /**
455  * The tail for the LCF queue
456  */
457 static struct LCFContextQueue *lcfq_tail;
458
459 /**
460  * The message queue head
461  */
462 static struct MessageQueue *mq_head;
463
464 /**
465  * The message queue tail
466  */
467 static struct MessageQueue *mq_tail;
468
469 /**
470  * Array of host list
471  */
472 static struct GNUNET_TESTBED_Host **host_list;
473
474 /**
475  * A list of routes
476  */
477 static struct Route **route_list;
478
479 /**
480  * A list of directly linked neighbours
481  */
482 static struct Slave **slave_list;
483
484 /**
485  * A list of peers we own locally
486  */
487 static struct Peer **peer_list;
488
489 /**
490  * The hashmap of shared services
491  */
492 static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
493
494 /**
495  * The size of the host list
496  */
497 static uint32_t host_list_size;
498
499 /**
500  * The size of the route list
501  */
502 static uint32_t route_list_size;
503
504 /**
505  * The size of directly linked neighbours list
506  */
507 static uint32_t slave_list_size;
508
509 /**
510  * The size of the peer list
511  */
512 static uint32_t peer_list_size;
513
514 /*********/
515 /* Tasks */
516 /*********/
517
518 /**
519  * The lcf_task handle
520  */
521 static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
522
523 /**
524  * The shutdown task handle
525  */
526 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
527
528
529 /**
530  * Function called to notify a client about the connection begin ready to queue
531  * more data.  "buf" will be NULL and "size" zero if the connection was closed
532  * for writing in the meantime.
533  *
534  * @param cls NULL
535  * @param size number of bytes available in buf
536  * @param buf where the callee should write the message
537  * @return number of bytes written to buf
538  */
539 static size_t
540 transmit_ready_notify (void *cls, size_t size, void *buf)
541 {
542   struct MessageQueue *mq_entry;
543
544   transmit_handle = NULL;
545   mq_entry = mq_head;
546   GNUNET_assert (NULL != mq_entry);
547   if (0 == size)
548     return 0;
549   GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
550   size = ntohs (mq_entry->msg->size);
551   memcpy (buf, mq_entry->msg, size);
552   GNUNET_free (mq_entry->msg);
553   GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
554   GNUNET_free (mq_entry);
555   mq_entry = mq_head;
556   if (NULL != mq_entry)
557     transmit_handle = 
558       GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
559                                            ntohs (mq_entry->msg->size),
560                                            GNUNET_TIME_UNIT_FOREVER_REL,
561                                            &transmit_ready_notify, NULL);
562   return size;
563 }
564
565
566 /**
567  * Queues a message in send queue for sending to the service
568  *
569  * @param client the client to whom the queued message has to be sent
570  * @param msg the message to queue
571  */
572 static void
573 queue_message (struct GNUNET_SERVER_Client *client,
574                struct GNUNET_MessageHeader *msg)
575 {
576   struct MessageQueue *mq_entry;
577   uint16_t type;
578   uint16_t size;
579
580   type = ntohs (msg->type);
581   size = ntohs (msg->size);
582   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
583                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));                 
584   mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
585   mq_entry->msg = msg;
586   mq_entry->client = client;
587   LOG_DEBUG ( "Queueing message of type %u, size %u for sending\n", type,
588               ntohs (msg->size));
589   GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
590   if (NULL == transmit_handle)
591     transmit_handle = 
592       GNUNET_SERVER_notify_transmit_ready (client, size,
593                                            GNUNET_TIME_UNIT_FOREVER_REL,
594                                            &transmit_ready_notify, NULL);
595 }
596
597
598 /**
599  * Similar to GNUNET_realloc; however clears tail part of newly allocated memory
600  *
601  * @param ptr the memory block to realloc
602  * @param size the size of ptr
603  * @param new_size the size to which ptr has to be realloc'ed
604  * @return the newly reallocated memory block
605  */
606 static void *
607 TESTBED_realloc (void *ptr, size_t size, size_t new_size)
608 {
609   ptr = GNUNET_realloc (ptr, new_size);
610   if (new_size > size)
611     ptr = memset (ptr + size, 0, new_size - size);
612   return ptr;
613 }
614
615
616 /**
617  * Function to add a host to the current list of known hosts
618  *
619  * @param host the host to add 
620  * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
621  *           already in use
622  */
623 static int
624 host_list_add (struct GNUNET_TESTBED_Host *host)
625 {
626   uint32_t host_id;
627
628   host_id = GNUNET_TESTBED_host_get_id_ (host);
629   if (host_list_size <= host_id)
630   {
631     host_list = 
632       TESTBED_realloc (host_list, 
633                        sizeof (struct GNUNET_TESTBED_Host *) * host_list_size,
634                        sizeof (struct GNUNET_TESTBED_Host *) *
635                        (host_list_size + LIST_GROW_STEP));
636     host_list_size += LIST_GROW_STEP;
637   }
638   if (NULL != host_list[host_id])
639   {
640     LOG_DEBUG ("A host with id: %u already exists\n", host_id);
641     return GNUNET_SYSERR;
642   }
643   host_list[host_id] = host;
644   return GNUNET_OK;
645 }
646
647
648 /**
649  * Adds a route to the route list
650  *
651  * @param route the route to add
652  */
653 static void
654 route_list_add (struct Route *route)
655 {
656   if (route->dest >= route_list_size)
657   {
658     route_list = 
659       TESTBED_realloc (route_list, 
660                        sizeof (struct Route *) * route_list_size,
661                        sizeof (struct Route *) * 
662                        (route_list_size + LIST_GROW_STEP));
663     route_list_size += LIST_GROW_STEP;
664   }
665   GNUNET_assert (NULL == route_list[route->dest]);
666   route_list[route->dest] = route;
667 }
668
669
670 /**
671  * Adds a slave to the slave array
672  *
673  * @param slave the slave controller to add
674  */
675 static void
676 slave_list_add (struct Slave *slave)
677 {
678   if (slave->host_id  >= slave_list_size)
679   {
680     slave_list = TESTBED_realloc (slave_list, 
681                                   sizeof (struct Slave *) *slave_list_size,
682                                   sizeof (struct Slave *) *
683                                   (slave_list_size + LIST_GROW_STEP));
684     slave_list_size += LIST_GROW_STEP;
685   }
686   GNUNET_assert (NULL == slave_list[slave->host_id]);
687   slave_list[slave->host_id] = slave;
688 }
689
690
691 /**
692  * Adds a peer to the peer array
693  *
694  * @param peer the peer to add
695  */
696 static void
697 peer_list_add (struct Peer *peer)
698 {
699   if (peer->id  >= peer_list_size)
700   {
701     peer_list = TESTBED_realloc (peer_list, 
702                                  sizeof (struct Peer *) * peer_list_size,
703                                  sizeof (struct Peer *) *
704                                  (peer_list_size + LIST_GROW_STEP));
705     peer_list_size += LIST_GROW_STEP;
706   }
707   GNUNET_assert (NULL == peer_list[peer->id]);
708   peer_list[peer->id] = peer;
709 }
710
711
712 /**
713  * Removes a the give peer from the peer array
714  *
715  * @param peer the peer to be removed
716  */
717 static void
718 peer_list_remove (struct Peer *peer)
719 {
720   uint32_t id;
721
722   peer_list[peer->id] = NULL;
723   while (peer_list_size >= LIST_GROW_STEP)
724   {
725     for (id = peer_list_size - 1;
726          id > peer_list_size - LIST_GROW_STEP; id--)
727       if (NULL != peer_list[id])
728         break;
729     if (id != peer_list_size - LIST_GROW_STEP)
730       break;
731     peer_list_size -= LIST_GROW_STEP;
732   }
733   peer_list = GNUNET_realloc (peer_list, sizeof (struct GNUNET_TESTBED_Peer*)
734                               * peer_list_size);
735 }
736
737
738 /**
739  * Finds the route with directly connected host as destination through which
740  * the destination host can be reached
741  *
742  * @param host_id the id of the destination host
743  * @return the route with directly connected destination host; NULL if no route
744  *           is found
745  */
746 static struct Route *
747 find_dest_route (uint32_t host_id)
748 {
749   struct Route *route;
750   
751   while(NULL != (route = route_list[host_id]))
752   {
753     if (route->thru == master_context->host_id)
754       break;
755     host_id = route->thru;
756   }
757   return route;
758 }
759
760
761 /**
762  * Routes message to a host given its host_id
763  *
764  * @param host_id the id of the destination host
765  * @param msg the message to be routed
766  */
767 static void
768 route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
769 {
770   GNUNET_break (0);
771 }
772
773
774 /**
775  * Send operation failure message to client
776  *
777  * @param client the client to which the failure message has to be sent to
778  * @param operation_id the id of the failed operation
779  * @param emsg the error message; can be NULL
780  */
781 static void
782 send_operation_fail_msg (struct GNUNET_SERVER_Client *client,
783                          uint64_t operation_id,
784                          const char *emsg)
785 {
786   struct GNUNET_TESTBED_OperationFailureEventMessage *msg;
787   uint16_t msize;
788   uint16_t emsg_len;
789   
790   msize = sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);  
791   emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1;
792   msize += emsg_len;
793   msg = GNUNET_malloc (msize);
794   msg->header.size = htons (msize);
795   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONEVENT);
796   msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
797   msg->operation_id = GNUNET_htonll (operation_id);
798   if (0 != emsg_len)
799     memcpy (&msg[1], emsg, emsg_len);
800   queue_message (client, &msg->header);
801 }
802
803
804 /**
805  * The  Link Controller forwarding task
806  *
807  * @param cls the LCFContext
808  * @param tc the Task context from scheduler
809  */
810 static void
811 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
812
813
814 /**
815  * Completion callback for host registrations while forwarding Link Controller messages
816  *
817  * @param cls the LCFContext
818  * @param emsg the error message; NULL if host registration is successful
819  */
820 static void
821 lcf_proc_cc (void *cls, const char *emsg)
822 {
823   struct LCFContext *lcf = cls;
824
825   lcf->rhandle = NULL;
826   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
827   switch (lcf->state)
828   {
829   case INIT:
830     if (NULL != emsg)
831       goto registration_error;
832     lcf->state = DELEGATED_HOST_REGISTERED;
833     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
834     break;
835   case DELEGATED_HOST_REGISTERED:
836      if (NULL != emsg)
837       goto registration_error;
838      lcf->state = SLAVE_HOST_REGISTERED;
839      lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
840      break;
841   default:
842     GNUNET_assert (0);          /* Shouldn't reach here */
843   }  
844   return;
845
846  registration_error:
847   LOG (GNUNET_ERROR_TYPE_WARNING, 
848        "Host registration failed with message: %s\n", emsg);
849   lcf->state = FINISHED;
850   lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
851 }
852
853
854 /**
855  * The  Link Controller forwarding task
856  *
857  * @param cls the LCFContext
858  * @param tc the Task context from scheduler
859  */
860 static void
861 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
862 {
863   struct LCFContext *lcf = cls;
864   struct LCFContextQueue *lcfq;
865
866   lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
867   switch (lcf->state)
868   {
869   case INIT:
870     if (GNUNET_NO ==
871         GNUNET_TESTBED_is_host_registered_ (host_list[lcf->delegated_host_id],
872                                             lcf->gateway->controller))
873     {
874       lcf->rhandle =
875         GNUNET_TESTBED_register_host (lcf->gateway->controller,
876                                       host_list[lcf->delegated_host_id],
877                                       lcf_proc_cc, lcf);
878     }
879     else
880     {
881       lcf->state = DELEGATED_HOST_REGISTERED;
882       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
883     }
884     break;
885   case DELEGATED_HOST_REGISTERED:
886     if (GNUNET_NO ==
887         GNUNET_TESTBED_is_host_registered_ (host_list[lcf->slave_host_id],
888                                             lcf->gateway->controller))
889     {
890       lcf->rhandle =
891         GNUNET_TESTBED_register_host (lcf->gateway->controller,
892                                       host_list[lcf->slave_host_id],
893                                       lcf_proc_cc, lcf);
894     }
895     else
896     {
897       lcf->state = SLAVE_HOST_REGISTERED;
898       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
899     }
900     break;
901   case SLAVE_HOST_REGISTERED:
902     GNUNET_TESTBED_controller_link_2 (lcf->gateway->controller,
903                                       host_list[lcf->delegated_host_id],
904                                       host_list[lcf->slave_host_id],
905                                       lcf->sxcfg, lcf->sxcfg_size,
906                                       lcf->scfg_size,
907                                       lcf->is_subordinate);
908     lcf->state = FINISHED;
909     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
910     break;
911   case FINISHED:
912     lcfq = lcfq_head;
913     GNUNET_assert (lcfq->lcf == lcf);
914     GNUNET_free (lcf->sxcfg);
915     GNUNET_free (lcf);
916     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
917     GNUNET_free (lcfq);
918     if (NULL != lcfq_head)
919       lcf_proc_task_id = 
920         GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
921   }
922 }
923
924
925 /**
926  * Callback for event from slave controllers
927  *
928  * @param cls struct Slave *
929  * @param event information about the event
930  */
931 static void 
932 slave_event_callback(void *cls,
933                      const struct GNUNET_TESTBED_EventInformation *event)
934 {
935   GNUNET_break (0);
936 }
937
938
939 /**
940  * Callback to signal successfull startup of the controller process
941  *
942  * @param cls the closure from GNUNET_TESTBED_controller_start()
943  * @param cfg the configuration with which the controller has been started;
944  *          NULL if status is not GNUNET_OK
945  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
946  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
947  */
948 static void 
949 slave_status_callback (void *cls, 
950                        const struct GNUNET_CONFIGURATION_Handle *cfg,
951                        int status)
952 {
953   struct Slave *slave = cls;
954
955   if (GNUNET_SYSERR == status)
956   {
957     slave->controller_proc = NULL;
958     LOG (GNUNET_ERROR_TYPE_WARNING,
959          "Unexpected slave shutdown\n");
960     GNUNET_SCHEDULER_shutdown ();       /* We too shutdown */
961     return;
962   }
963   slave->controller =
964     GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
965                                        master_context->event_mask,
966                                        &slave_event_callback, slave);
967 }
968
969
970 /**
971  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
972  *
973  * @param cls NULL
974  * @param client identification of the client
975  * @param message the actual message
976  */
977 static void 
978 handle_init (void *cls,
979              struct GNUNET_SERVER_Client *client,
980              const struct GNUNET_MessageHeader *message)
981 {
982   const struct GNUNET_TESTBED_InitMessage *msg;
983   struct GNUNET_TESTBED_Host *host;
984   const char *controller_hostname;
985   uint16_t msize;
986
987   if (NULL != master_context)
988   {
989     GNUNET_break (0);
990     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
991     return;
992   }
993   msg = (const struct GNUNET_TESTBED_InitMessage *) message;
994   msize = ntohs (message->size);
995   if (msize <= sizeof (struct GNUNET_TESTBED_InitMessage))
996   {
997     GNUNET_break (0);
998     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
999     return;
1000   }
1001   msize -= sizeof (struct GNUNET_TESTBED_InitMessage);  
1002   controller_hostname = (const char *) &msg[1];
1003   if ('\0' != controller_hostname[msize - 1])
1004   {
1005     GNUNET_break (0);
1006     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1007     return;
1008   }    
1009   master_context = GNUNET_malloc (sizeof (struct Context));
1010   master_context->client = client;
1011   master_context->host_id = ntohl (msg->host_id);
1012   master_context->master_ip = GNUNET_strdup (controller_hostname);  
1013   LOG_DEBUG ("Master Controller IP: %s\n", master_context->master_ip);
1014   master_context->system = 
1015     GNUNET_TESTING_system_create ("testbed", master_context->master_ip);
1016   host = GNUNET_TESTBED_host_create_with_id (master_context->host_id,
1017                                              NULL, NULL, 0);
1018   host_list_add (host);
1019   master_context->event_mask = GNUNET_ntohll (msg->event_mask);
1020   GNUNET_SERVER_client_keep (client);
1021   LOG_DEBUG ("Created master context with host ID: %u\n",
1022              master_context->host_id);
1023   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1024 }
1025
1026
1027 /**
1028  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1029  *
1030  * @param cls NULL
1031  * @param client identification of the client
1032  * @param message the actual message
1033  */
1034 static void 
1035 handle_add_host (void *cls,
1036                  struct GNUNET_SERVER_Client *client,
1037                  const struct GNUNET_MessageHeader *message)
1038 {
1039   struct GNUNET_TESTBED_Host *host;
1040   const struct GNUNET_TESTBED_AddHostMessage *msg;
1041   struct GNUNET_TESTBED_HostConfirmedMessage *reply;
1042   char *username;
1043   char *hostname;
1044   char *emsg;
1045   uint32_t host_id;
1046   uint16_t username_length;
1047   uint16_t hostname_length;
1048   uint16_t reply_size;
1049   uint16_t msize;
1050   
1051   msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
1052   msize = ntohs (msg->header.size);
1053   username = (char *) &(msg[1]);
1054   username_length = ntohs (msg->user_name_length);
1055   GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage)
1056                           + username_length + 1)); /* msg must contain hostname */
1057   if (0 != username_length)
1058     GNUNET_assert ('\0' == username[username_length]);
1059   username_length = (0 == username_length) ? 0 : username_length + 1;              
1060   hostname = username + username_length;
1061   hostname_length = msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage)
1062                              + username_length);
1063   GNUNET_assert ('\0' == hostname[hostname_length - 1]);
1064   GNUNET_assert (strlen (hostname) == hostname_length - 1);
1065   host_id = ntohl (msg->host_id);
1066   LOG_DEBUG ("Received ADDHOST message\n");
1067   LOG_DEBUG ("-------host id: %u\n", host_id);
1068   if (NULL != hostname) LOG_DEBUG ("-------hostname: %s\n", hostname);
1069   if (0 != username_length) LOG_DEBUG ("-------username: %s\n", username);
1070   else LOG_DEBUG ("-------username: NULL\n");
1071   LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
1072   host = GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
1073                                              ntohs (msg->ssh_port));
1074   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1075   reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
1076   if (GNUNET_OK != host_list_add (host))
1077   {    
1078     /* We are unable to add a host */  
1079     emsg = "A host exists with given host-id";
1080     LOG_DEBUG ("%s: %u", emsg, host_id);
1081     GNUNET_TESTBED_host_destroy (host);
1082     reply_size += strlen (emsg) + 1;
1083     reply = GNUNET_malloc (reply_size);
1084     memcpy (&reply[1], emsg, strlen (emsg) + 1);
1085   }
1086   else
1087     reply = GNUNET_malloc (reply_size);  
1088   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
1089   reply->header.size = htons (reply_size);
1090   reply->host_id = htonl (host_id);  
1091   queue_message (client, &reply->header);
1092 }
1093
1094
1095 /**
1096  * Iterator over hash map entries.
1097  *
1098  * @param cls closure
1099  * @param key current key code
1100  * @param value value in the hash map
1101  * @return GNUNET_YES if we should continue to
1102  *         iterate,
1103  *         GNUNET_NO if not.
1104  */
1105 int ss_exists_iterator (void *cls,
1106                         const struct GNUNET_HashCode * key,
1107                         void *value)
1108 {
1109   struct SharedService *queried_ss = cls;
1110   struct SharedService *ss = value;
1111
1112   if (0 == strcmp (ss->name, queried_ss->name))
1113     return GNUNET_NO;
1114   else
1115     return GNUNET_YES;
1116 }
1117
1118
1119 /**
1120  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1121  *
1122  * @param cls NULL
1123  * @param client identification of the client
1124  * @param message the actual message
1125  */
1126 static void 
1127 handle_configure_shared_service (void *cls,
1128                                  struct GNUNET_SERVER_Client *client,
1129                                  const struct GNUNET_MessageHeader *message)
1130 {
1131   const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1132   struct SharedService *ss;
1133   char *service_name;
1134   struct GNUNET_HashCode hash;
1135   uint16_t msg_size;
1136   uint16_t service_name_size;
1137     
1138   msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
1139   msg_size = ntohs (message->size);
1140   if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
1141   {
1142     GNUNET_break (0);
1143     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1144     return;
1145   }
1146   service_name_size = msg_size - 
1147     sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
1148   service_name = (char *) &msg[1];
1149   if ('\0' != service_name[service_name_size - 1])
1150   {
1151     GNUNET_break (0);
1152     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1153     return;
1154   }
1155   LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
1156              service_name, ntohl (msg->num_peers));
1157   if (ntohl (msg->host_id) != master_context->host_id)
1158   {
1159     route_message (ntohl (msg->host_id), message);
1160     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1161     return;
1162   }
1163   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1164   ss = GNUNET_malloc (sizeof (struct SharedService));
1165   ss->name = strdup (service_name);
1166   ss->num_shared = ntohl (msg->num_peers);
1167   GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
1168   if (GNUNET_SYSERR == 
1169       GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
1170                                                   &ss_exists_iterator, ss))
1171   {
1172     LOG (GNUNET_ERROR_TYPE_WARNING,
1173          "Service %s already configured as a shared service. "
1174          "Ignoring service sharing request \n", ss->name);
1175     GNUNET_free (ss->name);
1176     GNUNET_free (ss);
1177     return;
1178   }
1179   GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1180                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);  
1181 }
1182
1183
1184 /**
1185  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1186  *
1187  * @param cls NULL
1188  * @param client identification of the client
1189  * @param message the actual message
1190  */
1191 static void 
1192 handle_link_controllers (void *cls,
1193                          struct GNUNET_SERVER_Client *client,
1194                          const struct GNUNET_MessageHeader *message)
1195 {
1196   const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1197   struct GNUNET_CONFIGURATION_Handle *cfg;
1198   struct LCFContextQueue *lcfq;
1199   struct Route *route;
1200   struct Route *new_route;
1201   char *config;  
1202   uLongf dest_size;
1203   size_t config_size;
1204   uint32_t delegated_host_id;
1205   uint32_t slave_host_id;
1206   uint16_t msize;
1207    
1208   if (NULL == master_context)
1209   {
1210     GNUNET_break (0);
1211     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1212     return;
1213   }
1214   msize = ntohs (message->size);
1215   if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
1216   {
1217     GNUNET_break (0);
1218     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1219     return;
1220   }
1221   msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
1222   delegated_host_id = ntohl (msg->delegated_host_id);
1223   if (delegated_host_id == master_context->host_id)
1224   {
1225     GNUNET_break (0);
1226     LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1227     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1228     return;
1229   }
1230   if ((delegated_host_id >= host_list_size) || 
1231       (NULL == host_list[delegated_host_id]))
1232   {
1233     LOG (GNUNET_ERROR_TYPE_WARNING, "Delegated host not registered with us\n");
1234     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1235     return;
1236   }
1237   slave_host_id = ntohl (msg->slave_host_id);
1238   if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
1239   {
1240     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host not registered with us\n");
1241     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1242     return;
1243   }
1244   if (slave_host_id == delegated_host_id)
1245   {
1246     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1247     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1248     return;
1249   }
1250   msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1251   config_size = ntohs (msg->config_size);
1252   
1253   if (slave_host_id == master_context->host_id) /* Link from us */
1254   {
1255     struct Slave *slave;
1256
1257     if ((delegated_host_id < slave_list_size) && 
1258         (NULL != slave_list[delegated_host_id])) /* We have already added */
1259     {
1260       LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
1261            delegated_host_id);
1262       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1263       return;
1264     }    
1265     config = GNUNET_malloc (config_size);
1266     dest_size = (uLongf) config_size;    
1267     if (Z_OK != uncompress ((Bytef *) config, &dest_size,
1268                             (const Bytef *) &msg[1], (uLong) msize))
1269     {
1270       GNUNET_break (0);           /* Compression error */
1271       GNUNET_free (config);
1272       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1273       return;
1274     }
1275     if (config_size == dest_size)
1276     {
1277       LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
1278       GNUNET_free (config);
1279       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1280       return;
1281     }
1282     cfg = GNUNET_CONFIGURATION_create (); /* Free here or in lcfcontext */
1283     if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1284                                                        GNUNET_NO))
1285     {
1286       GNUNET_break (0);           /* Configuration parsing error */
1287       GNUNET_free (config);
1288       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1289       return;
1290     }
1291     GNUNET_free (config);
1292     if ((delegated_host_id < slave_list_size) &&
1293         (NULL != slave_list[delegated_host_id]))
1294     {
1295       GNUNET_break (0);           /* Configuration parsing error */
1296       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1297       return;
1298     }
1299     slave = GNUNET_malloc (sizeof (struct Slave));
1300     slave->host_id = delegated_host_id;    
1301     slave_list_add (slave);    
1302     if (1 == msg->is_subordinate)
1303     {
1304       slave->controller_proc =
1305         GNUNET_TESTBED_controller_start (master_context->master_ip,
1306                                          host_list[slave->host_id],
1307                                          cfg, &slave_status_callback,
1308                                          slave);
1309     }
1310     else {
1311       slave->controller = 
1312         GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1313                                            master_context->event_mask,
1314                                            &slave_event_callback, slave);
1315     }
1316     GNUNET_CONFIGURATION_destroy (cfg);
1317     new_route = GNUNET_malloc (sizeof (struct Route));
1318     new_route->dest = delegated_host_id;
1319     new_route->thru = master_context->host_id;
1320     route_list_add (new_route);
1321     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1322     return;
1323   }
1324
1325   /* Route the request */
1326   if (slave_host_id >= route_list_size)
1327   {
1328     LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1329     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1330     return;
1331   }
1332   lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1333   lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1334   lcfq->lcf->delegated_host_id = delegated_host_id;
1335   lcfq->lcf->slave_host_id = slave_host_id;
1336   route = find_dest_route (slave_host_id);
1337   GNUNET_assert (NULL != route); /* because we add routes carefully */
1338   GNUNET_assert (route->dest < slave_list_size);
1339   GNUNET_assert (NULL != slave_list[route->dest]);  
1340   lcfq->lcf->is_subordinate =
1341     (1 == msg->is_subordinate) ? GNUNET_YES : GNUNET_NO;
1342   lcfq->lcf->state = INIT;
1343   lcfq->lcf->gateway = slave_list[route->dest];
1344   lcfq->lcf->sxcfg_size = msize;
1345   lcfq->lcf->sxcfg = GNUNET_malloc (msize);
1346   lcfq->lcf->scfg_size = config_size;
1347   (void) memcpy (lcfq->lcf->sxcfg, &msg[1], msize);
1348   if (NULL == lcfq_head)
1349   {
1350     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1351     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1352     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq);
1353   }
1354   else
1355     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1356   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1357   new_route = GNUNET_malloc (sizeof (struct Route));
1358   new_route->dest = delegated_host_id;
1359   new_route->thru = route->dest;
1360   route_list_add (new_route);
1361 }
1362
1363
1364 /**
1365  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
1366  *
1367  * @param cls NULL
1368  * @param client identification of the client
1369  * @param message the actual message
1370  */
1371 static void 
1372 handle_peer_create (void *cls,
1373                     struct GNUNET_SERVER_Client *client,
1374                     const struct GNUNET_MessageHeader *message)
1375 {
1376   const struct GNUNET_TESTBED_PeerCreateMessage *msg;
1377   struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
1378   struct GNUNET_CONFIGURATION_Handle *cfg;
1379   struct PeerCreateContext *pc_ctxt;
1380   struct Route *route;
1381   char *config;
1382   size_t dest_size;
1383   int ret;
1384   uint32_t config_size;
1385   uint32_t host_id;
1386   uint16_t msize;
1387   
1388
1389   msize = ntohs (message->size);
1390   if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
1391   {
1392     GNUNET_break (0);           /* We need configuration */
1393     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1394     return;
1395   }
1396   msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
1397   host_id = ntohl (msg->host_id);
1398   if (host_id == master_context->host_id)
1399   {
1400     struct Peer *peer;
1401     char *emsg;
1402     
1403     /* We are responsible for this peer */
1404     msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1405     config_size = ntohl (msg->config_size);    
1406     config = GNUNET_malloc (config_size);
1407     dest_size = config_size;
1408     if (Z_OK != (ret = uncompress ((Bytef *) config, (uLongf *) &dest_size,
1409                                    (const Bytef *) &msg[1], (uLong) msize)))
1410     {
1411       GNUNET_break (0);           /* uncompression error */
1412       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1413       return;
1414     }
1415     if (config_size != dest_size)
1416     {
1417       GNUNET_break (0);/* Uncompressed config size mismatch */
1418       GNUNET_free (config);
1419       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1420       return;
1421     }
1422     cfg = GNUNET_CONFIGURATION_create ();
1423     if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1424                                                        GNUNET_NO))
1425     {
1426       GNUNET_break (0);           /* Configuration parsing error */
1427       GNUNET_free (config);
1428       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1429       return;
1430     }
1431     GNUNET_free (config);
1432     peer = GNUNET_malloc (sizeof (struct Peer));
1433     peer->cfg = cfg;
1434     peer->id = ntohl (msg->peer_id);
1435     LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
1436     peer->peer = GNUNET_TESTING_peer_configure (master_context->system, peer->cfg,
1437                                                 peer->id,
1438                                                 NULL /* Peer id */,
1439                                                 &emsg);
1440     if (NULL == peer->peer)
1441     {
1442       LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
1443       GNUNET_free (emsg);
1444       GNUNET_free (peer);
1445       GNUNET_break (0);
1446       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1447       return;
1448     }
1449     peer_list_add (peer);
1450     reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1451     reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1452     reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
1453     reply->peer_id = msg->peer_id;
1454     reply->operation_id = msg->operation_id;
1455     queue_message (client, &reply->header);
1456     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1457     return;
1458   }
1459   
1460   /* Forward peer create request */
1461   route = find_dest_route (host_id);
1462   if (NULL == route)
1463   {
1464     GNUNET_break (0);
1465     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1466     return;
1467   }
1468   pc_ctxt = GNUNET_malloc (sizeof (struct PeerCreateContext));
1469   pc_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
1470   /* To be continued .. :) */
1471 }
1472
1473
1474 /**
1475  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1476  *
1477  * @param cls NULL
1478  * @param client identification of the client
1479  * @param message the actual message
1480  */
1481 static void 
1482 handle_peer_destroy (void *cls,
1483                      struct GNUNET_SERVER_Client *client,
1484                      const struct GNUNET_MessageHeader *message)
1485 {
1486   const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
1487   struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *reply;
1488   struct Peer *peer;
1489   uint32_t peer_id;
1490   uint16_t reply_size;
1491   
1492   msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
1493   peer_id = ntohl (msg->peer_id);
1494   LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
1495              peer_id, GNUNET_ntohll (msg->operation_id));  
1496   if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
1497   {
1498     GNUNET_break (0);
1499     /* FIXME: Reply with failure event message or forward to slave controller */
1500     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1501     return;
1502   }
1503   peer = peer_list[peer_id];
1504   GNUNET_TESTING_peer_destroy (peer->peer);
1505   GNUNET_CONFIGURATION_destroy (peer->cfg);
1506   peer_list_remove (peer);
1507   GNUNET_free (peer);
1508   reply_size = 
1509     sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage);
1510   reply = GNUNET_malloc (reply_size);
1511   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS);
1512   reply->header.size = htons (reply_size);
1513   reply->operation_id = msg->operation_id;
1514   reply->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1515   queue_message (client, &reply->header);
1516   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1517 }
1518
1519
1520 /**
1521  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1522  *
1523  * @param cls NULL
1524  * @param client identification of the client
1525  * @param message the actual message
1526  */
1527 static void 
1528 handle_peer_start (void *cls,
1529                    struct GNUNET_SERVER_Client *client,
1530                    const struct GNUNET_MessageHeader *message)
1531 {
1532   const struct GNUNET_TESTBED_PeerStartMessage *msg;
1533   struct GNUNET_TESTBED_PeerEventMessage *reply;
1534   uint32_t peer_id;
1535
1536   msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
1537   peer_id = ntohl (msg->peer_id);
1538   if ((peer_id >= peer_list_size) 
1539       || (NULL == peer_list[peer_id]))
1540   {
1541     GNUNET_break (0);
1542     /* FIXME: reply with failure message or forward to slave controller */
1543     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1544     return;
1545   }
1546   if (GNUNET_OK != GNUNET_TESTING_peer_start (peer_list[peer_id]->peer))
1547   {
1548     /* FIXME: return FAILURE message */
1549     GNUNET_break (0);
1550     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1551     return;
1552   }
1553   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1554   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1555   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1556   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
1557   reply->host_id = htonl (master_context->host_id);
1558   reply->peer_id = msg->peer_id;
1559   reply->operation_id = msg->operation_id;
1560   queue_message (client, &reply->header);
1561   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1562 }
1563
1564
1565 /**
1566  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1567  *
1568  * @param cls NULL
1569  * @param client identification of the client
1570  * @param message the actual message
1571  */
1572 static void 
1573 handle_peer_stop (void *cls,
1574                   struct GNUNET_SERVER_Client *client,
1575                   const struct GNUNET_MessageHeader *message)
1576 {
1577   const struct GNUNET_TESTBED_PeerStopMessage *msg;
1578   struct GNUNET_TESTBED_PeerEventMessage *reply;
1579   uint32_t peer_id;
1580
1581   msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
1582   peer_id = ntohl (msg->peer_id);
1583   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1584   {
1585     GNUNET_break (0);           /* FIXME: route to slave? */
1586     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1587     return;
1588   }
1589   if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer_list[peer_id]->peer))
1590   {
1591     /* FIXME: return FAILURE message */
1592     GNUNET_break (0);
1593     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1594     return;
1595   }
1596   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1597   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1598   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1599   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
1600   reply->host_id = htonl (master_context->host_id);
1601   reply->peer_id = msg->peer_id;
1602   reply->operation_id = msg->operation_id;
1603   queue_message (client, &reply->header);
1604   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1605 }
1606
1607
1608 /**
1609  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
1610  *
1611  * @param cls NULL
1612  * @param client identification of the client
1613  * @param message the actual message
1614  */
1615 static void 
1616 handle_peer_get_config (void *cls,
1617                         struct GNUNET_SERVER_Client *client,
1618                         const struct GNUNET_MessageHeader *message)
1619 {
1620   const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
1621   struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
1622   char *config;
1623   char *xconfig;
1624   size_t c_size;
1625   size_t xc_size;  
1626   uint32_t peer_id;
1627   uint16_t msize;
1628   
1629   msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
1630   peer_id = ntohl (msg->peer_id);
1631   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1632   {
1633     /* FIXME: return FAILURE message */
1634     GNUNET_break (0);
1635     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1636   }
1637   config = GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->cfg,
1638                                            &c_size);
1639   xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
1640   GNUNET_free (config);
1641   msize = xc_size + sizeof (struct
1642                             GNUNET_TESTBED_PeerConfigurationInformationMessage);
1643   reply = GNUNET_realloc (xconfig, msize);
1644   (void) memmove (&reply[1], reply, xc_size);
1645   reply->header.size = htons (msize);
1646   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
1647   reply->peer_id = msg->peer_id;
1648   reply->operation_id = msg->operation_id;
1649   GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->peer,
1650                                     &reply->peer_identity);
1651   reply->config_size = htons ((uint16_t) c_size);
1652   queue_message (client, &reply->header);
1653   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1654 }
1655
1656
1657 /**
1658  * Task for cleaing up overlay connect context structure
1659  *
1660  * @param cls the overlay connect context
1661  * @param tc the task context
1662  */
1663 static void
1664 occ_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1665 {
1666   struct OverlayConnectContext *occ = cls;
1667
1668   GNUNET_free_non_null (occ->emsg);
1669   GNUNET_free_non_null (occ->hello);
1670   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
1671     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
1672   if (NULL != occ->ch)
1673     GNUNET_CORE_disconnect (occ->ch);
1674   if (NULL != occ->ghh)
1675     GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
1676   if (NULL != occ->p1th)
1677     GNUNET_TRANSPORT_disconnect (occ->p1th);
1678   if (NULL != occ->p2th)
1679     GNUNET_TRANSPORT_disconnect (occ->p2th);
1680   GNUNET_free (occ);
1681 }
1682
1683
1684 /**
1685  * Task which will be run when overlay connect request has been timed out
1686  *
1687  * @param 
1688  * @return 
1689  */
1690 static void
1691 timeout_overlay_connect (void *cls,
1692                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1693 {
1694   struct OverlayConnectContext *occ = cls;
1695
1696   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1697   send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
1698   GNUNET_SERVER_client_drop (occ->client);
1699   occ_cleanup (occ, tc);
1700 }
1701
1702
1703
1704 /**
1705  * Function called to notify transport users that another
1706  * peer connected to us.
1707  *
1708  * @param cls closure
1709  * @param new_peer the peer that connected
1710  * @param ats performance data
1711  * @param ats_count number of entries in ats (excluding 0-termination)
1712  */
1713 static void 
1714 overlay_connect_notify (void *cls,
1715                         const struct GNUNET_PeerIdentity * new_peer,
1716                         const struct GNUNET_ATS_Information * ats,
1717                         unsigned int ats_count)
1718 {
1719   struct OverlayConnectContext *occ = cls;
1720   struct GNUNET_TESTBED_ConnectionEventMessage *msg;
1721   char *new_peer_str;
1722   char *other_peer_str;
1723
1724   LOG_DEBUG ("Overlay connect notify\n");
1725   if (0 == memcmp (new_peer, &occ->peer_identity, 
1726                    sizeof (struct GNUNET_PeerIdentity)))
1727     return;
1728   new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
1729   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
1730   if (0 != memcmp (new_peer, &occ->other_peer_identity,
1731                    sizeof (struct GNUNET_PeerIdentity)))
1732   {
1733     LOG_DEBUG ("Unexpected peer %4s connected to peer %4s\n",
1734                new_peer_str, other_peer_str);
1735     GNUNET_free (new_peer_str);
1736     GNUNET_free (other_peer_str);
1737     return;
1738   }
1739   LOG_DEBUG ("Peer %4s connected to peer %4s\n", new_peer_str, other_peer_str);
1740   GNUNET_free (new_peer_str);
1741   GNUNET_free (other_peer_str);
1742   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
1743   {
1744     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
1745     occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
1746   }
1747   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
1748   GNUNET_SCHEDULER_cancel (occ->timeout_task);
1749   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1750   GNUNET_free_non_null (occ->emsg);
1751   occ->emsg = NULL;
1752   GNUNET_TRANSPORT_disconnect (occ->p1th);
1753   occ->p1th = NULL;
1754   /* Peer 1 has connected connect to peer2 - now send overlay connect success message */
1755   LOG_DEBUG ("Peers connected - Sending overlay connect success\n");
1756   msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1757   msg->header.size = htons (sizeof (struct
1758                                     GNUNET_TESTBED_ConnectionEventMessage));
1759   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT);
1760   msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
1761   msg->peer1 = htonl (occ->peer->id);
1762   msg->peer2 = htonl (occ->other_peer->id);
1763   msg->operation_id = GNUNET_htonll (occ->op_id);
1764   queue_message (occ->client, &msg->header);
1765   GNUNET_SERVER_client_drop (occ->client);
1766   GNUNET_SCHEDULER_add_now (&occ_cleanup, occ);
1767 }
1768
1769
1770 static void
1771 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1772 {
1773   struct OverlayConnectContext *occ = cls;
1774   char *other_peer_str;
1775
1776   occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
1777   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1778     return;
1779   GNUNET_assert (NULL != occ->hello);
1780   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
1781   LOG_DEBUG ("Offering HELLO of %s to %s\n", other_peer_str, GNUNET_i2s (&occ->peer_identity));
1782   GNUNET_free (other_peer_str);
1783   GNUNET_TRANSPORT_offer_hello (occ->p1th, occ->hello, NULL, NULL);
1784   GNUNET_TRANSPORT_try_connect (occ->p1th, &occ->other_peer_identity);
1785   occ->send_hello_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
1786                                                        &send_hello, occ);
1787 }
1788
1789 /**
1790  * Test for checking whether HELLO message is empty
1791  *
1792  * @param cls empty flag to set
1793  * @param address the HELLO
1794  * @param expiration expiration of the HELLO
1795  * @return 
1796  */
1797 static int
1798 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
1799               struct GNUNET_TIME_Absolute expiration)
1800 {
1801   int *empty = cls;
1802
1803   *empty = GNUNET_NO;
1804   return GNUNET_OK;
1805 }
1806
1807
1808 /**
1809  * Function called whenever there is an update to the
1810  * HELLO of peers in the OverlayConnectClosure
1811  *
1812  * @param cls closure
1813  * @param hello our updated HELLO
1814  */
1815 static void 
1816 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
1817 {
1818   struct OverlayConnectContext *occ = cls;
1819   int empty;
1820   uint16_t msize;
1821   
1822   msize = ntohs (hello->size);
1823   if (msize < 0)
1824   {
1825     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1826                 "HELLO message of peer %s is of size 0\n",
1827                 &occ->other_peer_identity);
1828     return;
1829   }
1830   empty = GNUNET_YES;
1831   (void) 
1832     GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) hello,
1833                                     GNUNET_NO, &test_address, &empty);
1834   if (GNUNET_YES == empty)
1835   {
1836     LOG_DEBUG ("HELLO of %s is empty\n", GNUNET_i2s (&occ->other_peer_identity));
1837     return;
1838   }
1839   LOG_DEBUG ("Received HELLO of %s\n", GNUNET_i2s (&occ->other_peer_identity));
1840   occ->hello = GNUNET_malloc (msize);
1841   memcpy (occ->hello, hello, msize);
1842   GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
1843   occ->ghh = NULL;
1844   GNUNET_TRANSPORT_disconnect (occ->p2th);
1845   occ->p2th = NULL;
1846   GNUNET_free_non_null (occ->emsg);  
1847   occ->emsg = GNUNET_strdup ("Timeout while offering HELLO to other peer");
1848   occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
1849 }
1850
1851
1852 /**
1853  * Function called after GNUNET_CORE_connect has succeeded (or failed
1854  * for good).  Note that the private key of the peer is intentionally
1855  * not exposed here; if you need it, your process should try to read
1856  * the private key file directly (which should work if you are
1857  * authorized...).
1858  *
1859  * @param cls closure
1860  * @param server handle to the server, NULL if we failed
1861  * @param my_identity ID of this peer, NULL if we failed
1862  */
1863 static void 
1864 core_startup_cb (void *cls, struct GNUNET_CORE_Handle * server,
1865                  const struct GNUNET_PeerIdentity *my_identity)
1866 {
1867   struct OverlayConnectContext *occ = cls;
1868
1869   GNUNET_free_non_null (occ->emsg);
1870   occ->emsg = NULL;
1871   memcpy (&occ->peer_identity, my_identity, sizeof (struct GNUNET_PeerIdentity));
1872   occ->p1th =
1873     GNUNET_TRANSPORT_connect (occ->peer->cfg, &occ->peer_identity, NULL, NULL,
1874                               NULL, NULL);
1875   /* Connect to the transport of 2nd peer and get its HELLO message */
1876   GNUNET_TESTING_peer_get_identity (occ->other_peer->peer,
1877                                     &occ->other_peer_identity);
1878   occ->p2th = 
1879     GNUNET_TRANSPORT_connect (occ->other_peer->cfg, &occ->other_peer_identity,
1880                               NULL, NULL, NULL, NULL);
1881   if ((NULL == occ->p1th) || (NULL == occ->p2th))
1882   {
1883     occ->emsg = GNUNET_strdup ("Cannot connect to TRANSPORTs of peers");
1884     goto send_failure;
1885   }
1886   LOG_DEBUG ("Acquiring HELLO of peer %s\n", GNUNET_i2s
1887              (&occ->other_peer_identity));
1888   occ->emsg = GNUNET_strdup ("Timeout while acquiring HELLO message");
1889   occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p2th, &hello_update_cb, occ);
1890   return;
1891
1892  send_failure:
1893   GNUNET_SCHEDULER_cancel (occ->timeout_task);
1894   occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);  
1895 }
1896
1897
1898 /**
1899  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1900  *
1901  * @param cls NULL
1902  * @param client identification of the client
1903  * @param message the actual message
1904  */
1905 static void 
1906 handle_overlay_connect (void *cls,
1907                         struct GNUNET_SERVER_Client *client,
1908                         const struct GNUNET_MessageHeader *message)
1909 {
1910   const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1911   struct OverlayConnectContext *occ;
1912   struct GNUNET_CORE_MessageHandler no_handlers[] = {
1913     {NULL, 0, 0}
1914   };
1915   uint32_t p1;
1916   uint32_t p2;
1917
1918   msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1919   p1 = ntohl (msg->peer1);
1920   p2 = ntohl (msg->peer2);
1921   GNUNET_assert (p1 < peer_list_size);
1922   GNUNET_assert (NULL != peer_list[p1]);
1923   GNUNET_assert (p2 < peer_list_size);
1924   GNUNET_assert (NULL != peer_list[p2]);
1925   occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1926   GNUNET_SERVER_client_keep (client);
1927   occ->client = client;
1928   occ->state = OCC_STATE_INIT;
1929   occ->peer = peer_list[p1];
1930   occ->other_peer = peer_list[p2];
1931   occ->op_id = GNUNET_ntohll (msg->operation_id);
1932   occ->timeout_task =
1933     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1934                                   (GNUNET_TIME_UNIT_SECONDS, 30),
1935                                   &timeout_overlay_connect, occ);   
1936   /* Connect to the core of 1st peer and wait for the 2nd peer to connect */
1937   occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
1938   occ->ch = 
1939     GNUNET_CORE_connect (occ->peer->cfg, occ, &core_startup_cb,
1940                          &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
1941                          GNUNET_NO, no_handlers);
1942   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1943 }
1944
1945
1946 /**
1947  * Iterator over hash map entries.
1948  *
1949  * @param cls closure
1950  * @param key current key code
1951  * @param value value in the hash map
1952  * @return GNUNET_YES if we should continue to
1953  *         iterate,
1954  *         GNUNET_NO if not.
1955  */
1956 static int 
1957 ss_map_free_iterator (void *cls,
1958                       const struct GNUNET_HashCode * key, void *value)
1959 {
1960   struct SharedService *ss = value;
1961
1962   GNUNET_assert (GNUNET_YES ==
1963                  GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
1964   GNUNET_free (ss->name);
1965   GNUNET_free (ss);
1966   return GNUNET_YES;
1967 }
1968
1969
1970 /**
1971  * Task to clean up and shutdown nicely
1972  *
1973  * @param cls NULL
1974  * @param tc the TaskContext from scheduler
1975  */
1976 static void
1977 shutdown_task (void *cls,
1978                const struct GNUNET_SCHEDULER_TaskContext *tc)
1979 {
1980   struct LCFContextQueue *lcfq;
1981   uint32_t id;
1982
1983   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
1984   LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
1985   (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
1986                                                 NULL);
1987   GNUNET_CONTAINER_multihashmap_destroy (ss_map);  
1988   if (NULL != lcfq_head)
1989   {
1990     if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
1991     {
1992       GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
1993       lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1994     }
1995     if (NULL != lcfq_head->lcf->rhandle)
1996       GNUNET_TESTBED_cancel_registration (lcfq_head->lcf->rhandle);
1997   }
1998   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1999   for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
2000   {
2001     GNUNET_free (lcfq->lcf->sxcfg);
2002     GNUNET_free (lcfq->lcf);
2003     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
2004     GNUNET_free (lcfq);
2005   }
2006   /* Clear peer list */
2007   for (id = 0; id < peer_list_size; id++)
2008     if (NULL != peer_list[id])
2009     {
2010       GNUNET_TESTING_peer_destroy (peer_list[id]->peer);
2011       GNUNET_CONFIGURATION_destroy (peer_list[id]->cfg);
2012       GNUNET_free (peer_list[id]);
2013     }
2014   GNUNET_free_non_null (peer_list);
2015   /* Clear host list */
2016   for (id = 0; id < host_list_size; id++)
2017     if (NULL != host_list[id])
2018       GNUNET_TESTBED_host_destroy (host_list[id]);
2019   GNUNET_free_non_null (host_list);
2020   /* Clear route list */
2021   for (id = 0; id < route_list_size; id++)
2022     if (NULL != route_list[id])
2023       GNUNET_free (route_list[id]);
2024   GNUNET_free_non_null (route_list);
2025   /* Clear slave_list */
2026   for (id = 0; id < slave_list_size; id++)
2027     if (NULL != slave_list[id])
2028     {
2029       GNUNET_assert (NULL != slave_list[id]->controller);
2030       GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
2031       if (NULL != slave_list[id]->controller_proc)
2032         GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
2033     }
2034   if (NULL != master_context)
2035   {  
2036     GNUNET_free_non_null (master_context->master_ip);
2037     if (NULL != master_context->system)
2038       GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
2039     GNUNET_free (master_context);
2040     master_context = NULL;
2041   }
2042 }
2043
2044
2045 /**
2046  * Callback for client disconnect
2047  *
2048  * @param cls NULL
2049  * @param client the client which has disconnected
2050  */
2051 static void
2052 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
2053 {
2054   if (NULL == master_context)
2055     return;
2056   if (client == master_context->client)
2057   {
2058     LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
2059     GNUNET_SERVER_client_drop (client);
2060     /* should not be needed as we're terminated by failure to read
2061        from stdin, but if stdin fails for some reason, this shouldn't 
2062        hurt for now --- might need to revise this later if we ever
2063        decide that master connections might be temporarily down 
2064        for some reason */
2065     //GNUNET_SCHEDULER_shutdown ();
2066   }
2067 }
2068
2069
2070 /**
2071  * Testbed setup
2072  *
2073  * @param cls closure
2074  * @param server the initialized server
2075  * @param cfg configuration to use
2076  */
2077 static void 
2078 testbed_run (void *cls,
2079              struct GNUNET_SERVER_Handle *server,
2080              const struct GNUNET_CONFIGURATION_Handle *cfg)
2081 {
2082   static const struct GNUNET_SERVER_MessageHandler message_handlers[] =
2083     {
2084       {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
2085       {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
2086       {&handle_configure_shared_service, NULL,
2087        GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
2088       {&handle_link_controllers, NULL,
2089        GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
2090       {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
2091       {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
2092        sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
2093       {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
2094        sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
2095       {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
2096        sizeof (struct GNUNET_TESTBED_PeerStopMessage)},      
2097       {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
2098        sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
2099       {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
2100        sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
2101       {NULL}
2102     };
2103
2104   GNUNET_SERVER_add_handlers (server,
2105                               message_handlers);
2106   GNUNET_SERVER_disconnect_notify (server,
2107                                    &client_disconnect_cb,
2108                                    NULL);
2109   ss_map = GNUNET_CONTAINER_multihashmap_create (5);
2110   shutdown_task_id = 
2111     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
2112                                   &shutdown_task,
2113                                   NULL);
2114   LOG_DEBUG ("Testbed startup complete\n");
2115 }
2116
2117
2118 /**
2119  * The starting point of execution
2120  */
2121 int main (int argc, char *const *argv)
2122 {
2123   //sleep (30);                 /* Debugging */
2124   return
2125     (GNUNET_OK ==
2126      GNUNET_SERVICE_run (argc,
2127                          argv,
2128                          "testbed",
2129                          GNUNET_SERVICE_OPTION_NONE,
2130                          &testbed_run,
2131                          NULL)) ? 0 : 1;
2132 }