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