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