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