-helper service shutdown fixes; overlay connect message
[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 <zlib.h>
32
33 #include "gnunet_testbed_service.h"
34 #include "testbed.h"
35 #include "testbed_api.h"
36 #include "testbed_api_hosts.h"
37 #include "gnunet_testing_lib-new.h"
38
39 /**
40  * Generic logging
41  */
42 #define LOG(kind,...)                           \
43   GNUNET_log (kind, __VA_ARGS__)
44
45 /**
46  * Debug logging
47  */
48 #define LOG_DEBUG(...)                          \
49   LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
50
51
52 #define LIST_GROW_STEP 10
53
54 struct Context
55 {
56   /**
57    * The client handle associated with this context
58    */
59   struct GNUNET_SERVER_Client *client;
60
61   /**
62    * The network address of the master controller
63    */
64   char *master_ip;
65
66   /**
67    * The TESTING system handle for starting peers locally
68    */
69   struct GNUNET_TESTING_System *system;
70   
71   /**
72    * Event mask of event to be responded in this context
73    */
74   uint64_t event_mask;
75
76   /**
77    * Our host id according to this context
78    */
79   uint32_t host_id;
80 };
81
82
83 /**
84  * The message queue for sending messages to clients
85  */
86 struct MessageQueue
87 {
88   /**
89    * The message to be sent
90    */
91   struct GNUNET_MessageHeader *msg;
92
93   /**
94    * The client to send the message to
95    */
96   struct GNUNET_SERVER_Client *client;
97   
98   /**
99    * next pointer for DLL
100    */
101   struct MessageQueue *next;
102   
103   /**
104    * prev pointer for DLL
105    */
106   struct MessageQueue *prev;
107 };
108
109
110 /**
111  * The structure for identifying a shared service
112  */
113 struct SharedService
114 {
115   /**
116    * The name of the shared service
117    */
118   char *name;
119
120   /**
121    * Number of shared peers per instance of the shared service
122    */
123   uint32_t num_shared;
124
125   /**
126    * Number of peers currently sharing the service
127    */
128   uint32_t num_sharing;
129 };
130
131
132 /**
133  * A routing entry
134  */
135 struct Route
136 {
137   /**
138    * destination host
139    */
140   uint32_t dest;
141
142   /**
143    * The host destination is reachable thru
144    */
145   uint32_t thru;
146 };
147
148
149 /**
150  * Structure representing a connected(directly-linked) controller
151  */
152 struct Slave
153 {
154   /**
155    * The controller process handle if we had started the controller
156    */
157   struct GNUNET_TESTBED_ControllerProc *controller_proc;
158
159   /**
160    * The controller handle
161    */
162   struct GNUNET_TESTBED_Controller *controller;
163
164   /**
165    * The id of the host this controller is running on
166    */
167   uint32_t host_id;
168 };
169
170
171 /**
172  * Slave startup context
173  */
174 struct SlaveContext
175 {
176   /**
177    * The slave corresponding to this context
178    */
179   struct Slave *slave;
180
181   /**
182    * The configuration used as a template while startup
183    */
184   struct GNUNET_CONFIGURATION_Handle *cfg;
185 };
186
187
188 /**
189  * States of LCFContext
190  */
191 enum LCFContextState
192   {
193     /**
194      * The Context has been initialized; Nothing has been done on it
195      */
196     INIT,
197
198     /**
199      * Delegated host has been registered at the forwarding controller
200      */
201     DELEGATED_HOST_REGISTERED,
202     
203     /**
204      * The context has been finished (may have error)
205      */
206     FINISHED
207
208   };
209
210
211 /**
212  * Link controllers request forwarding context
213  */
214 struct LCFContext
215 {
216   /**
217    * The serialized and compressed configuration
218    */
219   char *sxcfg;
220
221   /**
222    * The gateway which will pass the link message to delegated host
223    */
224   struct Slave *gateway;
225
226   /**
227    * The host registration handle while registered hosts in this context
228    */
229   struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
230
231   /**
232    * The size of the compressed serialized configuration
233    */
234   size_t sxcfg_size;
235
236   /**
237    * The size of the uncompressed configuration
238    */
239   size_t scfg_size;
240
241   /**
242    * Should the delegated host be started by the slave host?
243    */
244   int is_subordinate;
245
246   /**
247    * The state of this context
248    */
249   enum LCFContextState state;
250
251   /**
252    * The delegated host
253    */
254   uint32_t delegated_host_id;
255   
256
257 };
258
259
260 /**
261  * Structure of a queue entry in LCFContext request queue
262  */
263 struct LCFContextQueue
264 {
265   /**
266    * The LCFContext
267    */
268   struct LCFContext *lcf;
269
270   /**
271    * Head prt for DLL
272    */
273   struct LCFContextQueue *next;
274
275   /**
276    * Tail ptr for DLL
277    */
278   struct LCFContextQueue *prev;
279 };
280
281
282 /**
283  * A locally started peer
284  */
285 struct Peer
286 {
287   /**
288    * The peer handle from testing API
289    */
290   struct GNUNET_TESTING_Peer *peer;
291
292   /**
293    * The modified (by GNUNET_TESTING_peer_configure) configuration this peer is
294    * configured with
295    */
296   struct GNUNET_CONFIGURATION_Handle *cfg;
297
298   /**
299    * Our local reference id for this peer
300    */
301   uint32_t id;
302
303 };
304
305
306 /**
307  * Context information for connecting 2 peers in overlay
308  */
309 struct OverlayConnectContext
310 {
311   /**
312    * peer 1
313    */
314   struct Peer *peer1;
315   
316   /**
317    * peer 2
318    */
319   struct Peer *peer2;
320
321   /**
322    * Transport handle of peer1
323    */
324   struct GNUNET_TRANSPORT_Handle *peer1_transport;
325   
326   /**
327    * Transport handle of peer2
328    */
329   struct GNUNET_TRANSPORT_Handle *peer2_transport;
330   
331   /**
332    * HELLO of peer1
333    */
334   struct GNUNET_MessageHeader *peer1_hello;
335   
336   /**
337    * HELLO of peer2
338    */
339   struct GNUNET_MessageHeader *peer2_hello;
340
341   /**
342    * Get hello handle for peer1
343    */
344   struct GNUNET_TRANSPORT_GetHelloHandle *peer1_ghh;
345   
346   /**
347    * Get hello handle for peer2
348    */
349   struct GNUNET_TRANSPORT_GetHelloHandle *peer2_ghh;
350 };
351
352
353 /**
354  * The master context; generated with the first INIT message
355  */
356 static struct Context *master_context;
357
358 /***********/
359 /* Handles */
360 /***********/
361
362 /**
363  * Current Transmit Handle; NULL if no notify transmit exists currently
364  */
365 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
366
367 /****************/
368 /* Lists & Maps */
369 /****************/
370
371 /**
372  * The head for the LCF queue
373  */
374 static struct LCFContextQueue *lcfq_head;
375
376 /**
377  * The tail for the LCF queue
378  */
379 static struct LCFContextQueue *lcfq_tail;
380
381 /**
382  * The message queue head
383  */
384 static struct MessageQueue *mq_head;
385
386 /**
387  * The message queue tail
388  */
389 static struct MessageQueue *mq_tail;
390
391 /**
392  * Array of host list
393  */
394 static struct GNUNET_TESTBED_Host **host_list;
395
396 /**
397  * A list of routes
398  */
399 static struct Route **route_list;
400
401 /**
402  * A list of directly linked neighbours
403  */
404 static struct Slave **slave_list;
405
406 /**
407  * A list of peers we own locally
408  */
409 static struct Peer **peer_list;
410
411 /**
412  * The hashmap of shared services
413  */
414 static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
415
416 /**
417  * The size of the host list
418  */
419 static uint32_t host_list_size;
420
421 /**
422  * The size of the route list
423  */
424 static uint32_t route_list_size;
425
426 /**
427  * The size of directly linked neighbours list
428  */
429 static uint32_t slave_list_size;
430
431 /**
432  * The size of the peer list
433  */
434 static uint32_t peer_list_size;
435
436 /*********/
437 /* Tasks */
438 /*********/
439
440 /**
441  * The lcf_task handle
442  */
443 static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
444
445 /**
446  * The shutdown task handle
447  */
448 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
449
450
451 /**
452  * Function called to notify a client about the connection begin ready to queue
453  * more data.  "buf" will be NULL and "size" zero if the connection was closed
454  * for writing in the meantime.
455  *
456  * @param cls NULL
457  * @param size number of bytes available in buf
458  * @param buf where the callee should write the message
459  * @return number of bytes written to buf
460  */
461 static size_t
462 transmit_ready_notify (void *cls, size_t size, void *buf)
463 {
464   struct MessageQueue *mq_entry;
465
466   transmit_handle = NULL;
467   mq_entry = mq_head;
468   GNUNET_assert (NULL != mq_entry);
469   if (0 == size)
470     return 0;
471   GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
472   size = ntohs (mq_entry->msg->size);
473   memcpy (buf, mq_entry->msg, size);
474   GNUNET_free (mq_entry->msg);
475   GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
476   GNUNET_free (mq_entry);
477   mq_entry = mq_head;
478   if (NULL != mq_entry)
479     transmit_handle = 
480       GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
481                                            ntohs (mq_entry->msg->size),
482                                            GNUNET_TIME_UNIT_FOREVER_REL,
483                                            &transmit_ready_notify, NULL);
484   return size;
485 }
486
487
488 /**
489  * Queues a message in send queue for sending to the service
490  *
491  * @param client the client to whom the queued message has to be sent
492  * @param msg the message to queue
493  */
494 static void
495 queue_message (struct GNUNET_SERVER_Client *client,
496                struct GNUNET_MessageHeader *msg)
497 {
498   struct MessageQueue *mq_entry;
499   uint16_t type;
500   uint16_t size;
501
502   type = ntohs (msg->type);
503   size = ntohs (msg->size);
504   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
505                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));                 
506   mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
507   mq_entry->msg = msg;
508   mq_entry->client = client;
509   LOG_DEBUG ( "Queueing message of type %u, size %u for sending\n", type,
510               ntohs (msg->size));
511   GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
512   if (NULL == transmit_handle)
513     transmit_handle = 
514       GNUNET_SERVER_notify_transmit_ready (client, size,
515                                            GNUNET_TIME_UNIT_FOREVER_REL,
516                                            &transmit_ready_notify, NULL);
517 }
518
519
520 /**
521  * Similar to GNUNET_realloc; however clears tail part of newly allocated memory
522  *
523  * @param ptr the memory block to realloc
524  * @param size the size of ptr
525  * @param new_size the size to which ptr has to be realloc'ed
526  * @return the newly reallocated memory block
527  */
528 static void *
529 TESTBED_realloc (void *ptr, size_t size, size_t new_size)
530 {
531   ptr = GNUNET_realloc (ptr, new_size);
532   if (new_size > size)
533     ptr = memset (ptr + size, 0, new_size - size);
534   return ptr;
535 }
536
537
538 /**
539  * Function to add a host to the current list of known hosts
540  *
541  * @param host the host to add 
542  * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
543  *           already in use
544  */
545 static int
546 host_list_add (struct GNUNET_TESTBED_Host *host)
547 {
548   uint32_t host_id;
549
550   host_id = GNUNET_TESTBED_host_get_id_ (host);
551   if (host_list_size <= host_id)
552   {
553     host_list = 
554       TESTBED_realloc (host_list, 
555                        sizeof (struct GNUNET_TESTBED_Host *) * host_list_size,
556                        sizeof (struct GNUNET_TESTBED_Host *) *
557                        (host_list_size + LIST_GROW_STEP));
558     host_list_size += LIST_GROW_STEP;
559   }
560   if (NULL != host_list[host_id])
561   {
562     LOG_DEBUG ("A host with id: %u already exists\n", host_id);
563     return GNUNET_SYSERR;
564   }
565   host_list[host_id] = host;
566   return GNUNET_OK;
567 }
568
569
570 /**
571  * Adds a route to the route list
572  *
573  * @param route the route to add
574  */
575 static void
576 route_list_add (struct Route *route)
577 {
578   if (route->dest >= route_list_size)
579   {
580     route_list = 
581       TESTBED_realloc (route_list, 
582                        sizeof (struct Route *) * route_list_size,
583                        sizeof (struct Route *) * 
584                        (route_list_size + LIST_GROW_STEP));
585     route_list_size += LIST_GROW_STEP;
586   }
587   GNUNET_assert (NULL == route_list[route->dest]);
588   route_list[route->dest] = route;
589 }
590
591
592 /**
593  * Adds a slave to the slave array
594  *
595  * @param slave the slave controller to add
596  */
597 static void
598 slave_list_add (struct Slave *slave)
599 {
600   if (slave->host_id  >= slave_list_size)
601   {
602     slave_list = TESTBED_realloc (slave_list, 
603                                   sizeof (struct Slave *) *slave_list_size,
604                                   sizeof (struct Slave *) *
605                                   (slave_list_size + LIST_GROW_STEP));
606     slave_list_size += LIST_GROW_STEP;
607   }
608   GNUNET_assert (NULL == slave_list[slave->host_id]);
609   slave_list[slave->host_id] = slave;
610 }
611
612
613 /**
614  * Adds a peer to the peer array
615  *
616  * @param peer the peer to add
617  */
618 static void
619 peer_list_add (struct Peer *peer)
620 {
621   if (peer->id  >= peer_list_size)
622   {
623     peer_list = TESTBED_realloc (peer_list, 
624                                  sizeof (struct Peer *) * peer_list_size,
625                                  sizeof (struct Peer *) *
626                                  (peer_list_size + LIST_GROW_STEP));
627     peer_list_size += LIST_GROW_STEP;
628   }
629   GNUNET_assert (NULL == peer_list[peer->id]);
630   peer_list[peer->id] = peer;
631 }
632
633
634 /**
635  * Routes message to a host given its host_id
636  *
637  * @param host_id the id of the destination host
638  * @param msg the message to be routed
639  */
640 static void
641 route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
642 {
643   GNUNET_break (0);
644 }
645
646
647 /**
648  * The  Link Controller forwarding task
649  *
650  * @param cls the LCFContext
651  * @param tc the Task context from scheduler
652  */
653 static void
654 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
655
656
657 /**
658  * Completion callback for host registrations while forwarding Link Controller messages
659  *
660  * @param cls the LCFContext
661  * @param emsg the error message; NULL if host registration is successful
662  */
663 static void
664 lcf_proc_cc (void *cls, const char *emsg)
665 {
666   struct LCFContext *lcf = cls;
667
668   lcf->rhandle = NULL;
669   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
670   switch (lcf->state)
671   {
672   case INIT:
673     if (NULL != emsg)
674     {
675       LOG (GNUNET_ERROR_TYPE_WARNING, 
676            "Host registration failed with message: %s\n", emsg);
677       lcf->state = FINISHED;
678       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
679       return;
680     }
681     lcf->state = DELEGATED_HOST_REGISTERED;
682     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
683     break;
684   default:
685     GNUNET_assert (0);          /* Shouldn't reach here */
686   }  
687 }
688
689
690 /**
691  * The  Link Controller forwarding task
692  *
693  * @param cls the LCFContext
694  * @param tc the Task context from scheduler
695  */
696 static void
697 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
698 {
699   struct LCFContext *lcf = cls;
700   struct LCFContextQueue *lcfq;
701
702   lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
703   switch (lcf->state)
704   {
705   case INIT:
706     if (GNUNET_NO ==
707         GNUNET_TESTBED_is_host_registered_ (host_list[lcf->delegated_host_id],
708                                             lcf->gateway->controller))
709     {
710       lcf->rhandle =
711         GNUNET_TESTBED_register_host (lcf->gateway->controller,
712                                       host_list[lcf->delegated_host_id],
713                                       lcf_proc_cc, lcf);                                                   
714     }
715     else
716     {
717       lcf->state = DELEGATED_HOST_REGISTERED;
718       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
719     }
720     break;
721   case DELEGATED_HOST_REGISTERED:
722     GNUNET_TESTBED_controller_link_2 (lcf->gateway->controller,
723                                       host_list[lcf->delegated_host_id],
724                                       host_list[lcf->gateway->host_id],
725                                       lcf->sxcfg, lcf->sxcfg_size,
726                                       lcf->scfg_size,
727                                       lcf->is_subordinate);
728     lcf->state = FINISHED;
729   case FINISHED:   
730     lcfq = lcfq_head;
731     GNUNET_assert (lcfq->lcf == lcf);
732     GNUNET_free (lcf->sxcfg);
733     GNUNET_free (lcf);
734     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
735     GNUNET_free (lcfq);
736     if (NULL != lcfq_head)
737       lcf_proc_task_id = 
738         GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
739   }
740 }
741
742
743 /**
744  * Callback for event from slave controllers
745  *
746  * @param cls struct Slave *
747  * @param event information about the event
748  */
749 static void 
750 slave_event_callback(void *cls,
751                      const struct GNUNET_TESTBED_EventInformation *event)
752 {
753   GNUNET_break (0);
754 }
755
756
757 /**
758  * Callback to signal successfull startup of the controller process
759  *
760  * @param cls the closure from GNUNET_TESTBED_controller_start()
761  * @param cfg the configuration with which the controller has been started;
762  *          NULL if status is not GNUNET_OK
763  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
764  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
765  */
766 static void 
767 slave_status_callback (void *cls, 
768                        const struct GNUNET_CONFIGURATION_Handle *cfg,
769                        int status)
770 {
771   struct SlaveContext *sc = cls;
772
773   if (GNUNET_SYSERR == status)
774   {
775     sc->slave->controller_proc = NULL;
776     LOG (GNUNET_ERROR_TYPE_WARNING,
777          "Unexpected slave shutdown\n");
778     GNUNET_SCHEDULER_shutdown ();       /* We too shutdown */
779     return;
780   }
781   GNUNET_CONFIGURATION_destroy (sc->cfg);
782   sc->slave->controller =
783     GNUNET_TESTBED_controller_connect (cfg, host_list[sc->slave->host_id],
784                                        master_context->event_mask,
785                                        &slave_event_callback, sc->slave);
786   GNUNET_free (sc);
787 }
788
789
790 /**
791  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
792  *
793  * @param cls NULL
794  * @param client identification of the client
795  * @param message the actual message
796  */
797 static void 
798 handle_init (void *cls,
799              struct GNUNET_SERVER_Client *client,
800              const struct GNUNET_MessageHeader *message)
801 {
802   const struct GNUNET_TESTBED_InitMessage *msg;
803   struct GNUNET_TESTBED_Host *host;
804   void *addr;
805   size_t addrlen;
806
807   if (NULL != master_context)
808   {
809     GNUNET_break (0);
810     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
811     return;
812   }
813   msg = (const struct GNUNET_TESTBED_InitMessage *) message;  
814   master_context = GNUNET_malloc (sizeof (struct Context));
815   master_context->client = client;
816   master_context->host_id = ntohl (msg->host_id);
817   GNUNET_assert (GNUNET_OK == 
818                  GNUNET_SERVER_client_get_address (client, &addr, &addrlen));
819   master_context->master_ip = GNUNET_malloc (NI_MAXHOST);
820   if (0 != getnameinfo (addr, addrlen, master_context->master_ip, NI_MAXHOST,
821                         NULL, 0, NI_NUMERICHOST))
822   {
823     LOG (GNUNET_ERROR_TYPE_WARNING,
824          "Cannot determine the ip of master controller: %s\n", STRERROR (errno));
825     GNUNET_free (addr);
826     GNUNET_free (master_context->master_ip);
827     GNUNET_assert (0);
828   }
829   GNUNET_free (addr);
830   if (0 == strcasecmp (master_context->master_ip, "localhost"))
831   {                             /* Hack for connections via unix sockets */
832     LOG_DEBUG ("May be using local sockets - assuming loopback for master ip\n");
833     GNUNET_free (master_context->master_ip);
834     master_context->master_ip = strdup ("127.0.0.1");
835   }
836   LOG_DEBUG ("Master Controller IP: %s\n", master_context->master_ip);
837   master_context->system = 
838     GNUNET_TESTING_system_create ("testbed", master_context->master_ip);
839   host = GNUNET_TESTBED_host_create_with_id (master_context->host_id,
840                                              NULL, NULL, 0);
841   host_list_add (host);
842   master_context->event_mask = GNUNET_ntohll (msg->event_mask);
843   GNUNET_SERVER_client_keep (client);
844   LOG_DEBUG ("Created master context with host ID: %u\n",
845              master_context->host_id);
846   GNUNET_SERVER_receive_done (client, GNUNET_OK);
847 }
848
849
850 /**
851  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
852  *
853  * @param cls NULL
854  * @param client identification of the client
855  * @param message the actual message
856  */
857 static void 
858 handle_add_host (void *cls,
859                  struct GNUNET_SERVER_Client *client,
860                  const struct GNUNET_MessageHeader *message)
861 {
862   struct GNUNET_TESTBED_Host *host;
863   const struct GNUNET_TESTBED_AddHostMessage *msg;
864   struct GNUNET_TESTBED_HostConfirmedMessage *reply;
865   char *username;
866   char *hostname;
867   char *emsg;
868   uint32_t host_id;
869   uint16_t username_length;
870   uint16_t hostname_length;
871   uint16_t reply_size;
872   
873   msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
874   username_length = ntohs (msg->user_name_length);
875   username_length = (0 == username_length) ? 0 : username_length + 1;
876   username = (char *) &(msg[1]);
877   hostname = username + username_length;
878   if (ntohs (message->size) <=
879       (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length))
880   {
881     GNUNET_break (0);
882     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
883     return;
884   }
885   hostname_length = ntohs (message->size)
886     - (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length);
887   if (strlen (hostname) != hostname_length - 1)
888   {
889     GNUNET_break (0);
890     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
891     return;
892   }
893   host_id = ntohl (msg->host_id);
894   LOG_DEBUG ("Received ADDHOST message\n");
895   LOG_DEBUG ("-------host id: %u\n", host_id);
896   if (NULL != hostname) LOG_DEBUG ("-------hostname: %s\n", hostname);
897   if (0 != username_length) LOG_DEBUG ("-------username: %s\n", username);
898   else LOG_DEBUG ("-------username: NULL\n");
899   LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
900   host = GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
901                                              ntohs (msg->ssh_port));
902   GNUNET_SERVER_receive_done (client, GNUNET_OK);
903   reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
904   if (GNUNET_OK != host_list_add (host))
905   {    
906     /* We are unable to add a host */  
907     emsg = "A host exists with given host-id";
908     LOG_DEBUG ("%s: %u", emsg, host_id);
909     GNUNET_TESTBED_host_destroy (host);
910     reply_size += strlen (emsg) + 1;
911     reply = GNUNET_malloc (reply_size);
912     memcpy (&reply[1], emsg, strlen (emsg) + 1);
913   }
914   else
915     reply = GNUNET_malloc (reply_size);  
916   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
917   reply->header.size = htons (reply_size);
918   reply->host_id = htonl (host_id);  
919   queue_message (client, (struct GNUNET_MessageHeader *) reply);
920 }
921
922
923 /**
924  * Iterator over hash map entries.
925  *
926  * @param cls closure
927  * @param key current key code
928  * @param value value in the hash map
929  * @return GNUNET_YES if we should continue to
930  *         iterate,
931  *         GNUNET_NO if not.
932  */
933 int ss_exists_iterator (void *cls,
934                         const struct GNUNET_HashCode * key,
935                         void *value)
936 {
937   struct SharedService *queried_ss = cls;
938   struct SharedService *ss = value;
939
940   if (0 == strcmp (ss->name, queried_ss->name))
941     return GNUNET_NO;
942   else
943     return GNUNET_YES;
944 }
945
946
947 /**
948  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
949  *
950  * @param cls NULL
951  * @param client identification of the client
952  * @param message the actual message
953  */
954 static void 
955 handle_configure_shared_service (void *cls,
956                                  struct GNUNET_SERVER_Client *client,
957                                  const struct GNUNET_MessageHeader *message)
958 {
959   const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
960   struct SharedService *ss;
961   char *service_name;
962   struct GNUNET_HashCode hash;
963   uint16_t msg_size;
964   uint16_t service_name_size;
965     
966   msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
967   msg_size = ntohs (message->size);
968   if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
969   {
970     GNUNET_break (0);
971     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
972     return;
973   }
974   service_name_size = msg_size - 
975     sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
976   service_name = (char *) &msg[1];
977   if ('\0' != service_name[service_name_size - 1])
978   {
979     GNUNET_break (0);
980     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
981     return;
982   }
983   LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
984              service_name, ntohl (msg->num_peers));
985   if (ntohl (msg->host_id) != master_context->host_id)
986   {
987     route_message (ntohl (msg->host_id), message);
988     GNUNET_SERVER_receive_done (client, GNUNET_OK);
989     return;
990   }
991   GNUNET_SERVER_receive_done (client, GNUNET_OK);
992   ss = GNUNET_malloc (sizeof (struct SharedService));
993   ss->name = strdup (service_name);
994   ss->num_shared = ntohl (msg->num_peers);
995   GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
996   if (GNUNET_SYSERR == 
997       GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
998                                                   &ss_exists_iterator, ss))
999   {
1000     LOG (GNUNET_ERROR_TYPE_WARNING,
1001          "Service %s already configured as a shared service. "
1002          "Ignoring service sharing request \n", ss->name);
1003     GNUNET_free (ss->name);
1004     GNUNET_free (ss);
1005     return;
1006   }
1007   GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1008                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);  
1009 }
1010
1011
1012 /**
1013  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1014  *
1015  * @param cls NULL
1016  * @param client identification of the client
1017  * @param message the actual message
1018  */
1019 static void 
1020 handle_link_controllers (void *cls,
1021                          struct GNUNET_SERVER_Client *client,
1022                          const struct GNUNET_MessageHeader *message)
1023 {
1024   const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1025   struct GNUNET_CONFIGURATION_Handle *cfg;
1026   struct SlaveContext *sc;
1027   struct LCFContextQueue *lcfq;
1028   struct Route *route;
1029   struct Route *new_route;
1030   char *config;  
1031   uLongf dest_size;
1032   size_t config_size;
1033   uint32_t delegated_host_id;
1034   uint32_t slave_host_id;
1035   uint16_t msize;
1036    
1037   if (NULL == master_context)
1038   {
1039     GNUNET_break (0);
1040     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1041     return;
1042   }
1043   msize = ntohs (message->size);
1044   if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
1045   {
1046     GNUNET_break (0);
1047     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1048     return;
1049   }
1050   msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
1051   delegated_host_id = ntohl (msg->delegated_host_id);
1052   if (delegated_host_id == master_context->host_id)
1053   {
1054     GNUNET_break (0);
1055     LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1056     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1057     return;
1058   }
1059   if ((delegated_host_id >= host_list_size) || 
1060       (NULL == host_list[delegated_host_id]))
1061   {
1062     LOG (GNUNET_ERROR_TYPE_WARNING, "Delegated host not registered with us\n");
1063     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1064     return;
1065   }
1066   slave_host_id = ntohl (msg->slave_host_id);
1067   if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
1068   {
1069     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host not registered with us\n");
1070     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1071     return;
1072   }
1073   if (slave_host_id == delegated_host_id)
1074   {
1075     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1076     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1077     return;
1078   }
1079   msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1080   config_size = ntohs (msg->config_size);
1081   
1082   if (slave_host_id == master_context->host_id) /* Link from us */
1083   {
1084     struct Slave *slave;
1085
1086     if ((delegated_host_id < slave_list_size) && 
1087         (NULL != slave_list[delegated_host_id])) /* We have already added */
1088     {
1089       LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
1090            delegated_host_id);
1091       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1092       return;
1093     }    
1094     config = GNUNET_malloc (config_size);
1095     dest_size = (uLongf) config_size;    
1096     if (Z_OK != uncompress ((Bytef *) config, &dest_size,
1097                             (const Bytef *) &msg[1], (uLong) msize))
1098     {
1099       GNUNET_break (0);           /* Compression error */
1100       GNUNET_free (config);
1101       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1102       return;
1103     }
1104     if (config_size == dest_size)
1105     {
1106       LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
1107       GNUNET_free (config);
1108       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1109     }
1110     cfg = GNUNET_CONFIGURATION_create (); /* Free here or in lcfcontext */
1111     if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1112                                                        GNUNET_NO))
1113     {
1114       GNUNET_break (0);           /* Configuration parsing error */
1115       GNUNET_free (config);
1116       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1117       return;
1118     }
1119     GNUNET_free (config);
1120     if ((delegated_host_id < slave_list_size) &&
1121         (NULL != slave_list[delegated_host_id]))
1122     {
1123       GNUNET_break (0);           /* Configuration parsing error */
1124       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1125       return;
1126     }
1127     slave = GNUNET_malloc (sizeof (struct Slave));
1128     slave->host_id = delegated_host_id;
1129     slave_list_add (slave);
1130     sc = GNUNET_malloc (sizeof (struct SlaveContext));
1131     sc->slave = slave;
1132     sc->cfg = cfg;
1133     if (1 == msg->is_subordinate)
1134     {
1135       slave->controller_proc =
1136         GNUNET_TESTBED_controller_start (master_context->master_ip,
1137                                          host_list[slave->host_id],
1138                                          cfg, &slave_status_callback,
1139                                          sc);
1140     }    
1141     new_route = GNUNET_malloc (sizeof (struct Route));
1142     new_route->dest = delegated_host_id;
1143     new_route->thru = master_context->host_id;
1144     route_list_add (new_route);
1145     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1146     return;
1147   }
1148
1149   /* Route the request */
1150   if (slave_host_id >= route_list_size)
1151   {
1152     LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1153     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1154     return;
1155   }
1156   while (NULL != (route = route_list[slave_host_id]))
1157   {
1158     if (route->thru == master_context->host_id)
1159       break;
1160     slave_host_id = route->thru;
1161   }
1162   GNUNET_assert (NULL != route); /* because we add routes carefully */
1163   GNUNET_assert (route->dest < slave_list_size);
1164   GNUNET_assert (NULL != slave_list[route->dest]);  
1165   lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1166   lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1167   lcfq->lcf->delegated_host_id = delegated_host_id;
1168   lcfq->lcf->is_subordinate =
1169     (1 == msg->is_subordinate) ? GNUNET_YES : GNUNET_NO;
1170   lcfq->lcf->state = INIT;
1171   lcfq->lcf->gateway = slave_list[route->dest];
1172   lcfq->lcf->sxcfg_size = msize;
1173   lcfq->lcf->sxcfg = GNUNET_malloc (msize);
1174   lcfq->lcf->scfg_size = config_size;
1175   (void) memcpy (lcfq->lcf->sxcfg, &msg[1], msize);
1176   if (NULL == lcfq_head)
1177   {
1178     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1179     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1180     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq);
1181   }
1182   else
1183     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1184   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1185   new_route = GNUNET_malloc (sizeof (struct Route));
1186   new_route->dest = delegated_host_id;
1187   new_route->thru = route->dest;
1188   route_list_add (new_route);
1189 }
1190
1191
1192 /**
1193  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
1194  *
1195  * @param cls NULL
1196  * @param client identification of the client
1197  * @param message the actual message
1198  */
1199 static void 
1200 handle_peer_create (void *cls,
1201                     struct GNUNET_SERVER_Client *client,
1202                     const struct GNUNET_MessageHeader *message)
1203 {
1204   const struct GNUNET_TESTBED_PeerCreateMessage *msg;
1205   struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
1206   struct GNUNET_CONFIGURATION_Handle *cfg;
1207   char *config;
1208   size_t dest_size;
1209   int ret;
1210   uint32_t config_size;
1211   uint16_t msize;
1212   
1213
1214   msize = ntohs (message->size);
1215   if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
1216   {
1217     GNUNET_break (0);           /* We need configuration */
1218     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1219     return;
1220   }
1221   msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
1222   if (ntohl (msg->host_id) == master_context->host_id)
1223   {
1224     struct Peer *peer;
1225     char *emsg;
1226     
1227     /* We are responsible for this peer */
1228     msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1229     config_size = ntohl (msg->config_size);    
1230     config = GNUNET_malloc (config_size);
1231     dest_size = config_size;
1232     if (Z_OK != (ret = uncompress ((Bytef *) config, (uLongf *) &dest_size,
1233                                    (const Bytef *) &msg[1], (uLong) msize)))
1234     {
1235       GNUNET_break (0);           /* uncompression error */
1236       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1237       return;
1238     }
1239     if (config_size != dest_size)
1240     {
1241       GNUNET_break (0);/* Uncompressed config size mismatch */
1242       GNUNET_free (config);
1243       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1244       return;
1245     }
1246     cfg = GNUNET_CONFIGURATION_create ();
1247     if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1248                                                        GNUNET_NO))
1249     {
1250       GNUNET_break (0);           /* Configuration parsing error */
1251       GNUNET_free (config);
1252       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1253       return;
1254     }
1255     GNUNET_free (config);
1256     peer = GNUNET_malloc (sizeof (struct Peer));
1257     peer->cfg = cfg;
1258     peer->id = ntohl (msg->peer_id);
1259     LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
1260     peer->peer = GNUNET_TESTING_peer_configure (master_context->system, peer->cfg,
1261                                                 peer->id,
1262                                                 NULL /* Peer id */,
1263                                                 &emsg);
1264     if (NULL == peer->peer)
1265     {
1266       LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
1267       GNUNET_free (emsg);
1268       GNUNET_break (0);
1269       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1270       return;
1271     }
1272     peer_list_add (peer);
1273     reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1274     reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1275     reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
1276     reply->peer_id = msg->peer_id;
1277     reply->operation_id = msg->operation_id;
1278     queue_message (client, &reply->header);
1279     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1280     return;
1281   }
1282
1283   /* FIXME: Forward the peer to other host */
1284   GNUNET_break (0);
1285   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1286 }
1287
1288
1289 /**
1290  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1291  *
1292  * @param cls NULL
1293  * @param client identification of the client
1294  * @param message the actual message
1295  */
1296 static void 
1297 handle_peer_destroy (void *cls,
1298                      struct GNUNET_SERVER_Client *client,
1299                      const struct GNUNET_MessageHeader *message)
1300 {
1301   const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
1302   struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *reply;
1303   uint32_t peer_id;
1304   uint32_t id;
1305   uint16_t reply_size;
1306   
1307   msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
1308   peer_id = ntohl (msg->peer_id);
1309   LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
1310              peer_id, GNUNET_ntohll (msg->operation_id));
1311   if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
1312   {
1313     GNUNET_break (0);
1314     /* FIXME: Reply with failure event message or forward to slave controller */
1315     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1316     return;
1317   }  
1318   GNUNET_TESTING_peer_destroy (peer_list[peer_id]->peer);
1319   GNUNET_CONFIGURATION_destroy (peer_list[peer_id]->cfg);
1320   GNUNET_free (peer_list[peer_id]);
1321   peer_list[peer_id] = NULL;
1322   for (id = 0; id < LIST_GROW_STEP; id++)
1323   {
1324     if (((peer_id + id >= peer_list_size) ||
1325          (NULL != peer_list[peer_id])))
1326       break;
1327   }
1328   if (LIST_GROW_STEP == id)
1329   {
1330     peer_list_size -= LIST_GROW_STEP;
1331     peer_list = GNUNET_realloc (peer_list, peer_list_size);
1332   }
1333   reply_size = 
1334     sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage);
1335   reply = GNUNET_malloc (reply_size);
1336   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS);
1337   reply->header.size = htons (reply_size);
1338   reply->operation_id = msg->operation_id;
1339   reply->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1340   queue_message (client, &reply->header);
1341   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1342 }
1343
1344
1345 /**
1346  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1347  *
1348  * @param cls NULL
1349  * @param client identification of the client
1350  * @param message the actual message
1351  */
1352 static void 
1353 handle_peer_start (void *cls,
1354                    struct GNUNET_SERVER_Client *client,
1355                    const struct GNUNET_MessageHeader *message)
1356 {
1357   const struct GNUNET_TESTBED_PeerStartMessage *msg;
1358   struct GNUNET_TESTBED_PeerEventMessage *reply;
1359   uint32_t peer_id;
1360
1361   msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
1362   peer_id = ntohl (msg->peer_id);
1363   if ((peer_id >= peer_list_size) 
1364       || (NULL == peer_list[peer_id]))
1365   {
1366     GNUNET_break (0);
1367     /* FIXME: reply with failure message or forward to slave controller */
1368     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1369     return;
1370   }
1371   if (GNUNET_OK != GNUNET_TESTING_peer_start (peer_list[peer_id]->peer))
1372   {
1373     /* FIXME: return FAILURE message */
1374     GNUNET_break (0);
1375     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1376     return;
1377   }
1378   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1379   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1380   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1381   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
1382   reply->host_id = htonl (master_context->host_id);
1383   reply->peer_id = msg->peer_id;
1384   reply->operation_id = msg->operation_id;
1385   queue_message (client, &reply->header);
1386   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1387 }
1388
1389
1390 /**
1391  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1392  *
1393  * @param cls NULL
1394  * @param client identification of the client
1395  * @param message the actual message
1396  */
1397 static void 
1398 handle_peer_stop (void *cls,
1399                   struct GNUNET_SERVER_Client *client,
1400                   const struct GNUNET_MessageHeader *message)
1401 {
1402   const struct GNUNET_TESTBED_PeerStopMessage *msg;
1403   struct GNUNET_TESTBED_PeerEventMessage *reply;
1404   uint32_t peer_id;
1405
1406   msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
1407   peer_id = ntohl (msg->peer_id);
1408   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1409   {
1410     GNUNET_break (0);           /* FIXME: route to slave? */
1411     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1412     return;
1413   }
1414   if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer_list[peer_id]->peer))
1415   {
1416     /* FIXME: return FAILURE message */
1417     GNUNET_break (0);
1418     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1419     return;
1420   }
1421   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1422   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1423   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1424   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
1425   reply->host_id = htonl (master_context->host_id);
1426   reply->peer_id = msg->peer_id;
1427   reply->operation_id = msg->operation_id;
1428   queue_message (client, &reply->header);
1429   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1430 }
1431
1432
1433 /**
1434  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
1435  *
1436  * @param cls NULL
1437  * @param client identification of the client
1438  * @param message the actual message
1439  */
1440 static void 
1441 handle_peer_get_config (void *cls,
1442                         struct GNUNET_SERVER_Client *client,
1443                         const struct GNUNET_MessageHeader *message)
1444 {
1445   const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
1446   struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
1447   char *config;
1448   char *xconfig;
1449   size_t c_size;
1450   size_t xc_size;  
1451   uint32_t peer_id;
1452   uint16_t msize;
1453   
1454   msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
1455   peer_id = ntohl (msg->peer_id);
1456   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1457   {
1458     /* FIXME: return FAILURE message */
1459     GNUNET_break (0);
1460     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1461   }
1462   config = GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->cfg,
1463                                            &c_size);
1464   xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
1465   GNUNET_free (config);
1466   msize = xc_size + sizeof (struct
1467                             GNUNET_TESTBED_PeerConfigurationInformationMessage);
1468   reply = GNUNET_realloc (xconfig, msize);
1469   (void) memmove (&reply[1], reply, xc_size);
1470   reply->header.size = htons (msize);
1471   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
1472   reply->peer_id = msg->peer_id;
1473   reply->operation_id = msg->operation_id;
1474   GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->peer,
1475                                     &reply->peer_identity);
1476   reply->config_size = htons ((uint16_t) c_size);
1477   queue_message (client, &reply->header);
1478   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1479 }
1480
1481
1482
1483 /**
1484  * Function called whenever there is an update to the
1485  * HELLO of this peer.
1486  *
1487  * @param cls closure
1488  * @param hello our updated HELLO
1489  */
1490 static void 
1491 hello_update_cb (void *cls,
1492                  const struct GNUNET_MessageHeader *hello)
1493 {
1494   GNUNET_break(0);  
1495 }
1496
1497
1498 /**
1499  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1500  *
1501  * @param cls NULL
1502  * @param client identification of the client
1503  * @param message the actual message
1504  */
1505 static void 
1506 handle_overlay_connect (void *cls,
1507                         struct GNUNET_SERVER_Client *client,
1508                         const struct GNUNET_MessageHeader *message)
1509 {
1510   const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1511   struct OverlayConnectContext *occ;
1512   uint32_t p1;
1513   uint32_t p2;
1514
1515   msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1516   p1 = ntohl (msg->peer1);
1517   p2 = ntohl (msg->peer2);
1518   GNUNET_assert (p1 < peer_list_size);
1519   GNUNET_assert (NULL != peer_list[p1]);
1520   GNUNET_assert (p2 < peer_list_size);
1521   GNUNET_assert (NULL != peer_list[p2]);
1522   occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1523   occ->peer1 = peer_list[p1];
1524   occ->peer2 = peer_list[p2];
1525   occ->peer1_transport = GNUNET_TRANSPORT_connect (occ->peer1->cfg, NULL, occ,
1526                                                    NULL, NULL, NULL);
1527   occ->peer2_transport = GNUNET_TRANSPORT_connect (occ->peer2->cfg, NULL, occ,
1528                                                    NULL, NULL, NULL);
1529   occ->peer1_ghh = GNUNET_TRANSPORT_get_hello (occ->peer1_transport, &hello_update_cb, occ);
1530   occ->peer2_ghh = GNUNET_TRANSPORT_get_hello (occ->peer2_transport, &hello_update_cb, occ);
1531 }
1532
1533
1534 /**
1535  * Iterator over hash map entries.
1536  *
1537  * @param cls closure
1538  * @param key current key code
1539  * @param value value in the hash map
1540  * @return GNUNET_YES if we should continue to
1541  *         iterate,
1542  *         GNUNET_NO if not.
1543  */
1544 static int 
1545 ss_map_free_iterator (void *cls,
1546                       const struct GNUNET_HashCode * key, void *value)
1547 {
1548   struct SharedService *ss = value;
1549
1550   GNUNET_assert (GNUNET_YES ==
1551                  GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
1552   GNUNET_free (ss->name);
1553   GNUNET_free (ss);
1554   return GNUNET_YES;
1555 }
1556
1557
1558 /**
1559  * Task to clean up and shutdown nicely
1560  *
1561  * @param cls NULL
1562  * @param tc the TaskContext from scheduler
1563  */
1564 static void
1565 shutdown_task (void *cls,
1566                const struct GNUNET_SCHEDULER_TaskContext *tc)
1567 {
1568   struct LCFContextQueue *lcfq;
1569   uint32_t id;
1570
1571   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
1572   LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
1573   (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
1574                                                 NULL);
1575   GNUNET_CONTAINER_multihashmap_destroy (ss_map);  
1576   if (NULL != lcfq_head)
1577   {
1578     if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
1579     {
1580       GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
1581       lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1582     }
1583     if (NULL != lcfq_head->lcf->rhandle)
1584       GNUNET_TESTBED_cancel_registration (lcfq_head->lcf->rhandle);
1585   }
1586   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1587   for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
1588   {
1589     GNUNET_free (lcfq->lcf->sxcfg);
1590     GNUNET_free (lcfq->lcf);
1591     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
1592     GNUNET_free (lcfq);
1593   }
1594   /* Clear peer list */
1595   for (id = 0; id < peer_list_size; id++)
1596     if (NULL != peer_list[id])
1597     {
1598       GNUNET_TESTING_peer_destroy (peer_list[id]->peer);
1599       GNUNET_CONFIGURATION_destroy (peer_list[id]->cfg);
1600       GNUNET_free (peer_list[id]);
1601     }
1602   GNUNET_free_non_null (peer_list);
1603   /* Clear host list */
1604   for (id = 0; id < host_list_size; id++)
1605     if (NULL != host_list[id])
1606       GNUNET_TESTBED_host_destroy (host_list[id]);
1607   GNUNET_free_non_null (host_list);
1608   /* Clear route list */
1609   for (id = 0; id < route_list_size; id++)
1610     if (NULL != route_list[id])
1611       GNUNET_free (route_list[id]);
1612   GNUNET_free_non_null (route_list);
1613   /* Clear slave_list */
1614   for (id = 0; id < slave_list_size; id++)
1615     if (NULL != slave_list[id])
1616     {
1617       GNUNET_assert (NULL != slave_list[id]->controller);
1618       GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
1619       if (NULL != slave_list[id]->controller_proc)
1620         GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
1621     }
1622   if (NULL != master_context)
1623   {  
1624     GNUNET_free_non_null (master_context->master_ip);
1625     if (NULL != master_context->system)
1626       GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
1627     GNUNET_free (master_context);
1628     master_context = NULL;
1629   }
1630 }
1631
1632
1633 /**
1634  * Callback for client disconnect
1635  *
1636  * @param cls NULL
1637  * @param client the client which has disconnected
1638  */
1639 static void
1640 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
1641 {
1642   if (NULL == master_context)
1643     return;
1644   if (client == master_context->client)
1645   {
1646     LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
1647     GNUNET_SERVER_client_drop (client);
1648     /* should not be needed as we're terminated by failure to read
1649        from stdin, but if stdin fails for some reason, this shouldn't 
1650        hurt for now --- might need to revise this later if we ever
1651        decide that master connections might be temporarily down 
1652        for some reason */
1653     //GNUNET_SCHEDULER_shutdown ();
1654   }
1655 }
1656
1657
1658 /**
1659  * Testbed setup
1660  *
1661  * @param cls closure
1662  * @param server the initialized server
1663  * @param cfg configuration to use
1664  */
1665 static void 
1666 testbed_run (void *cls,
1667              struct GNUNET_SERVER_Handle *server,
1668              const struct GNUNET_CONFIGURATION_Handle *cfg)
1669 {
1670   static const struct GNUNET_SERVER_MessageHandler message_handlers[] =
1671     {
1672       {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT,
1673        sizeof (struct GNUNET_TESTBED_InitMessage)},
1674       {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
1675       {&handle_configure_shared_service, NULL,
1676        GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
1677       {&handle_link_controllers, NULL,
1678        GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
1679       {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
1680       {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
1681        sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
1682       {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
1683        sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
1684       {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
1685        sizeof (struct GNUNET_TESTBED_PeerStopMessage)},      
1686       {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
1687        sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
1688       {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
1689        sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
1690       {NULL}
1691     };
1692
1693   GNUNET_SERVER_add_handlers (server,
1694                               message_handlers);
1695   GNUNET_SERVER_disconnect_notify (server,
1696                                    &client_disconnect_cb,
1697                                    NULL);
1698   ss_map = GNUNET_CONTAINER_multihashmap_create (5);
1699   shutdown_task_id = 
1700     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1701                                   &shutdown_task,
1702                                   NULL);
1703   LOG_DEBUG ("Testbed startup complete\n");
1704 }
1705
1706
1707 /**
1708  * The starting point of execution
1709  */
1710 int main (int argc, char *const *argv)
1711 {
1712   return
1713     (GNUNET_OK ==
1714      GNUNET_SERVICE_run (argc,
1715                          argv,
1716                          "testbed",
1717                          GNUNET_SERVICE_OPTION_NONE,
1718                          &testbed_run,
1719                          NULL)) ? 0 : 1;
1720 }