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