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