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