host registration queues in slave handles
[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  * By how much should the arrays lists grow
55  */
56 #define LIST_GROW_STEP 10
57
58 /**
59  * Default timeout for operations which may take some time
60  */
61 #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
62
63 /**
64  * The main context information associated with the client which started us
65  */
66 struct Context
67 {
68   /**
69    * The client handle associated with this context
70    */
71   struct GNUNET_SERVER_Client *client;
72
73   /**
74    * The network address of the master controller
75    */
76   char *master_ip;
77
78   /**
79    * The TESTING system handle for starting peers locally
80    */
81   struct GNUNET_TESTING_System *system;
82   
83   /**
84    * Our host id according to this context
85    */
86   uint32_t host_id;
87 };
88
89
90 /**
91  * The message queue for sending messages to clients
92  */
93 struct MessageQueue
94 {
95   /**
96    * The message to be sent
97    */
98   struct GNUNET_MessageHeader *msg;
99
100   /**
101    * The client to send the message to
102    */
103   struct GNUNET_SERVER_Client *client;
104
105   /**
106    * next pointer for DLL
107    */
108   struct MessageQueue *next;
109
110   /**
111    * prev pointer for DLL
112    */
113   struct MessageQueue *prev;
114 };
115
116
117 /**
118  * The structure for identifying a shared service
119  */
120 struct SharedService
121 {
122   /**
123    * The name of the shared service
124    */
125   char *name;
126
127   /**
128    * Number of shared peers per instance of the shared service
129    */
130   uint32_t num_shared;
131
132   /**
133    * Number of peers currently sharing the service
134    */
135   uint32_t num_sharing;
136 };
137
138
139 /**
140  * A routing entry
141  */
142 struct Route
143 {
144   /**
145    * destination host
146    */
147   uint32_t dest;
148
149   /**
150    * The destination host is reachable thru
151    */
152   uint32_t thru;
153 };
154
155
156 /**
157  * Context information used while linking controllers
158  */
159 struct LinkControllersContext;
160
161
162 /**
163  * A DLL of host registrations to be made
164  */
165 struct HostRegistration
166 {
167   /**
168    * next registration in the DLL
169    */
170   struct HostRegistration *next;
171
172   /**
173    * previous registration in the DLL
174    */
175   struct HostRegistration *prev;
176
177   /**
178    * The callback to call after this registration's status is available
179    */
180   GNUNET_TESTBED_HostRegistrationCompletion cb;
181
182   /**
183    * The closure for the above callback
184    */
185   void *cb_cls;
186
187   /**
188    * The host that has to be registered
189    */
190   struct GNUNET_TESTBED_Host *host;
191 };
192
193
194 /**
195  * Structure representing a connected(directly-linked) controller
196  */
197 struct Slave
198 {
199   /**
200    * The controller process handle if we had started the controller
201    */
202   struct GNUNET_TESTBED_ControllerProc *controller_proc;
203
204   /**
205    * The controller handle
206    */
207   struct GNUNET_TESTBED_Controller *controller;
208
209   /**
210    * The configuration of the slave. Cannot be NULL
211    */
212   struct GNUNET_CONFIGURATION_Handle *cfg;
213
214   /**
215    * handle to lcc which is associated with this slave startup. Should be set to
216    * NULL when the slave has successfully started up
217    */
218   struct LinkControllersContext *lcc;
219
220   /**
221    * Head of the host registration DLL
222    */
223   struct HostRegistration *hr_dll_head;
224
225   /**
226    * Tail of the host registration DLL
227    */
228   struct HostRegistration *hr_dll_tail;
229
230   /**
231    * The current host registration handle
232    */
233   struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
234
235   /**
236    * The id of the host this controller is running on
237    */
238   uint32_t host_id;
239
240 };
241
242
243 /**
244  * States of LCFContext
245  */
246 enum LCFContextState
247 {
248   /**
249    * The Context has been initialized; Nothing has been done on it
250    */
251   INIT,
252
253   /**
254    * Delegated host has been registered at the forwarding controller
255    */
256   DELEGATED_HOST_REGISTERED,
257   
258   /**
259    * The slave host has been registred at the forwarding controller
260    */
261   SLAVE_HOST_REGISTERED,
262   
263   /**
264    * The context has been finished (may have error)
265    */
266   FINISHED
267 };
268
269
270 /**
271  * Link controllers request forwarding context
272  */
273 struct LCFContext
274 {
275   /**
276    * The gateway which will pass the link message to delegated host
277    */
278   struct Slave *gateway;
279
280   /**
281    * The controller link message that has to be forwarded to
282    */
283   struct GNUNET_TESTBED_ControllerLinkMessage *msg;
284
285   /**
286    * The client which has asked to perform this operation
287    */
288   struct GNUNET_SERVER_Client *client;
289
290   /**
291    * The id of the operation which created this context
292    */
293   uint64_t operation_id;
294
295   /**
296    * The state of this context
297    */
298   enum LCFContextState state;
299
300   /**
301    * The delegated host
302    */
303   uint32_t delegated_host_id;
304
305   /**
306    * The slave host
307    */
308   uint32_t slave_host_id;
309
310 };
311
312
313 /**
314  * Structure of a queue entry in LCFContext request queue
315  */
316 struct LCFContextQueue
317 {
318   /**
319    * The LCFContext
320    */
321   struct LCFContext *lcf;
322
323   /**
324    * Head prt for DLL
325    */
326   struct LCFContextQueue *next;
327
328   /**
329    * Tail ptr for DLL
330    */
331   struct LCFContextQueue *prev;
332 };
333
334
335 /**
336  * A peer
337  */
338 struct Peer
339 {
340   union
341   {
342     struct
343     {
344       /**
345        * The peer handle from testing API
346        */
347       struct GNUNET_TESTING_Peer *peer;
348
349       /**
350        * The modified (by GNUNET_TESTING_peer_configure) configuration this
351        * peer is configured with
352        */
353       struct GNUNET_CONFIGURATION_Handle *cfg;
354       
355       /**
356        * Is the peer running
357        */
358       int is_running;
359
360     } local;
361
362     struct
363     {
364       /**
365        * The slave this peer is started through
366        */
367       struct Slave *slave;
368
369       /**
370        * The id of the remote host this peer is running on
371        */
372       uint32_t remote_host_id;
373
374     } remote;
375
376   } details;
377
378   /**
379    * Is this peer locally created?
380    */
381   int is_remote;
382
383   /**
384    * Our local reference id for this peer
385    */
386   uint32_t id;
387
388 };
389
390
391 /**
392  * Context information for connecting 2 peers in overlay
393  */
394 struct OverlayConnectContext
395 {
396   /**
397    * The client which has requested for overlay connection
398    */
399   struct GNUNET_SERVER_Client *client;
400
401   /**
402    * the peer which has to connect to the other peer
403    */
404   struct Peer *peer;
405
406   /**
407    * Transport handle of the first peer to get its HELLO
408    */
409   struct GNUNET_TRANSPORT_Handle *p1th;
410
411   /**
412    * Transport handle of other peer to offer first peer's HELLO
413    */
414   struct GNUNET_TRANSPORT_Handle *p2th;
415
416   /**
417    * Core handles of the first peer; used to notify when second peer connects to it
418    */
419   struct GNUNET_CORE_Handle *ch;
420
421   /**
422    * HELLO of the other peer
423    */
424   struct GNUNET_MessageHeader *hello;
425
426   /**
427    * Get hello handle to acquire HELLO of first peer
428    */
429   struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
430
431   /**
432    * The error message we send if this overlay connect operation has timed out
433    */
434   char *emsg;
435
436   /**
437    * Operation context for suboperations
438    */
439   struct OperationContext *opc;
440
441   /**
442    * Controller of peer 2; NULL if the peer is local
443    */
444   struct GNUNET_TESTBED_Controller *peer2_controller;
445
446   /**
447    * The peer identity of the first peer
448    */
449   struct GNUNET_PeerIdentity peer_identity;
450
451   /**
452    * The peer identity of the other peer
453    */
454   struct GNUNET_PeerIdentity other_peer_identity;
455
456   /**
457    * The id of the operation responsible for creating this context
458    */
459   uint64_t op_id;
460
461   /**
462    * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
463    * connect to peer 2
464    */
465   GNUNET_SCHEDULER_TaskIdentifier send_hello_task;
466
467   /**
468    * The id of the overlay connect timeout task
469    */
470   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
471
472   /**
473    * The id of peer A
474    */
475   uint32_t peer_id;
476
477   /**
478    * The id of peer B
479    */
480   uint32_t other_peer_id;
481
482   /**
483    * Number of times we tried to send hello; used to increase delay in offering
484    * hellos
485    */
486   uint16_t retries;
487 };
488
489
490 /**
491  * Context information for RequestOverlayConnect
492  * operations. RequestOverlayConnect is used when peers A, B reside on different
493  * hosts and the host controller for peer B is asked by the host controller of
494  * peer A to make peer B connect to peer A
495  */
496 struct RequestOverlayConnectContext
497 {
498   /**
499    * The transport handle of peer B
500    */
501   struct GNUNET_TRANSPORT_Handle *th;
502   
503   /**
504    * Peer A's HELLO
505    */
506   struct GNUNET_MessageHeader *hello;
507
508   /**
509    * The peer identity of peer A
510    */
511   struct GNUNET_PeerIdentity a_id;
512
513   /**
514    * Task for offering HELLO of A to B and doing try_connect
515    */
516   GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task_id;
517   
518   /**
519    * Task to timeout RequestOverlayConnect
520    */
521   GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id;
522   
523   /**
524    * Number of times we tried to send hello; used to increase delay in offering
525    * hellos
526    */
527   uint16_t retries;
528   
529 };
530
531
532 /**
533  * Context information for operations forwarded to subcontrollers
534  */
535 struct ForwardedOperationContext
536 {
537   /**
538    * The generated operation context
539    */
540   struct OperationContext *opc;
541
542   /**
543    * The client to which we have to reply
544    */
545   struct GNUNET_SERVER_Client *client;
546
547   /**
548    * Closure pointer
549    */
550   void *cls;
551
552   /**
553    * Task ID for the timeout task
554    */
555   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
556
557   /**
558    * The id of the operation that has been forwarded
559    */
560   uint64_t operation_id;
561
562 };
563
564
565 /**
566  * Context information used while linking controllers
567  */
568 struct LinkControllersContext
569 {
570   /**
571    * The client which initiated the link controller operation
572    */
573   struct GNUNET_SERVER_Client *client;
574
575   /**
576    * The ID of the operation
577    */
578   uint64_t operation_id;
579
580 };
581
582
583 /**
584  * Context information to used during operations which forward the overlay
585  * connect message
586  */
587 struct ForwardedOverlayConnectContext
588 {
589   /**
590    * The gateway to which this operation is forwarded to
591    */
592   struct Slave *gateway;
593
594   /**
595    * The gateway through which peer2's controller can be reached
596    */
597   struct Slave *gateway2;
598
599   /**
600    * Handle for sub-operations
601    */
602   struct GNUNET_TESTBED_Operation *sub_op;
603
604   /**
605    * The client which initiated the link controller operation
606    */
607   struct GNUNET_SERVER_Client *client;
608
609   /**
610    * A copy of the original overlay connect message
611    */
612   struct GNUNET_MessageHeader *orig_msg;
613
614   /**
615    * The id of the operation which created this context information
616    */
617   uint64_t operation_id;
618
619   /**
620    * Id of the timeout task;
621    */
622   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
623   
624   /**
625    * Enumeration of states for this context
626    */
627   enum FOCCState {
628
629     /**
630      * The initial state
631      */
632     FOCC_INIT = 0,
633
634     /**
635      * State where we attempt to register peer2's controller with peer1's controller
636      */
637     FOCC_REGISTER,
638
639     /**
640      * State where we attempt to get peer2's controller configuration
641      */
642     FOCC_GET_CFG,
643
644     /**
645      * State where we attempt to link the controller of peer 1 to the controller
646      * of peer2
647      */
648     FOCC_LINK,
649
650     /**
651      * State where we attempt to do the overlay connection again
652      */
653     FOCC_OL_CONNECT
654     
655   } state;
656
657   /**
658    * the id of peer 1
659    */
660   uint32_t peer1;
661   
662   /**
663    * The id of peer 2
664    */
665   uint32_t peer2;
666   
667   /**
668    * Id of the host where peer2 is running
669    */
670   uint32_t peer2_host_id;
671 };
672
673
674
675 /**
676  * The master context; generated with the first INIT message
677  */
678 static struct Context *master_context;
679
680 /**
681  * Our hostname; we give this to all the peers we start
682  */
683 static char *hostname;
684
685
686 /***********/
687 /* Handles */
688 /***********/
689
690 /**
691  * Our configuration
692  */
693 static struct GNUNET_CONFIGURATION_Handle *our_config;
694
695 /**
696  * Current Transmit Handle; NULL if no notify transmit exists currently
697  */
698 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
699
700 /****************/
701 /* Lists & Maps */
702 /****************/
703
704 /**
705  * The head for the LCF queue
706  */
707 static struct LCFContextQueue *lcfq_head;
708
709 /**
710  * The tail for the LCF queue
711  */
712 static struct LCFContextQueue *lcfq_tail;
713
714 /**
715  * The message queue head
716  */
717 static struct MessageQueue *mq_head;
718
719 /**
720  * The message queue tail
721  */
722 static struct MessageQueue *mq_tail;
723
724 /**
725  * Array of hosts
726  */
727 static struct GNUNET_TESTBED_Host **host_list;
728
729 /**
730  * A list of routes
731  */
732 static struct Route **route_list;
733
734 /**
735  * A list of directly linked neighbours
736  */
737 static struct Slave **slave_list;
738
739 /**
740  * A list of peers we know about
741  */
742 static struct Peer **peer_list;
743
744 /**
745  * The hashmap of shared services
746  */
747 static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
748
749 /**
750  * The event mask for the events we listen from sub-controllers
751  */
752 static uint64_t event_mask;
753
754 /**
755  * The size of the host list
756  */
757 static uint32_t host_list_size;
758
759 /**
760  * The size of the route list
761  */
762 static uint32_t route_list_size;
763
764 /**
765  * The size of directly linked neighbours list
766  */
767 static uint32_t slave_list_size;
768
769 /**
770  * The size of the peer list
771  */
772 static uint32_t peer_list_size;
773
774 /*********/
775 /* Tasks */
776 /*********/
777
778 /**
779  * The lcf_task handle
780  */
781 static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
782
783 /**
784  * The shutdown task handle
785  */
786 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
787
788
789 /**
790  * Function called to notify a client about the connection begin ready to queue
791  * more data.  "buf" will be NULL and "size" zero if the connection was closed
792  * for writing in the meantime.
793  *
794  * @param cls NULL
795  * @param size number of bytes available in buf
796  * @param buf where the callee should write the message
797  * @return number of bytes written to buf
798  */
799 static size_t
800 transmit_ready_notify (void *cls, size_t size, void *buf)
801 {
802   struct MessageQueue *mq_entry;
803
804   transmit_handle = NULL;
805   mq_entry = mq_head;
806   GNUNET_assert (NULL != mq_entry);
807   if (0 == size)
808     return 0;
809   GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
810   size = ntohs (mq_entry->msg->size);
811   memcpy (buf, mq_entry->msg, size);
812   GNUNET_free (mq_entry->msg);
813   GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
814   GNUNET_free (mq_entry);
815   mq_entry = mq_head;
816   if (NULL != mq_entry)
817     transmit_handle =
818         GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
819                                              ntohs (mq_entry->msg->size),
820                                              GNUNET_TIME_UNIT_FOREVER_REL,
821                                              &transmit_ready_notify, NULL);
822   return size;
823 }
824
825
826 /**
827  * Queues a message in send queue for sending to the service
828  *
829  * @param client the client to whom the queued message has to be sent
830  * @param msg the message to queue
831  */
832 static void
833 queue_message (struct GNUNET_SERVER_Client *client,
834                struct GNUNET_MessageHeader *msg)
835 {
836   struct MessageQueue *mq_entry;
837   uint16_t type;
838   uint16_t size;
839
840   type = ntohs (msg->type);
841   size = ntohs (msg->size);
842   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
843                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
844   mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
845   mq_entry->msg = msg;
846   mq_entry->client = client;
847   LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", type,
848              ntohs (msg->size));
849   GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
850   if (NULL == transmit_handle)
851     transmit_handle =
852         GNUNET_SERVER_notify_transmit_ready (client, size,
853                                              GNUNET_TIME_UNIT_FOREVER_REL,
854                                              &transmit_ready_notify, NULL);
855 }
856
857
858 /**
859  * Similar to GNUNET_realloc; however clears tail part of newly allocated memory
860  *
861  * @param ptr the memory block to realloc
862  * @param size the size of ptr
863  * @param new_size the size to which ptr has to be realloc'ed
864  * @return the newly reallocated memory block
865  */
866 static void *
867 TESTBED_realloc (void *ptr, size_t size, size_t new_size)
868 {
869   ptr = GNUNET_realloc (ptr, new_size);
870   if (new_size > size)
871     (void) memset (ptr + size, 0, new_size - size);
872   return ptr;
873 }
874
875
876 /**
877  * Function to add a host to the current list of known hosts
878  *
879  * @param host the host to add
880  * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
881  *           already in use
882  */
883 static int
884 host_list_add (struct GNUNET_TESTBED_Host *host)
885 {
886   uint32_t host_id;
887   uint32_t orig_size;
888
889   host_id = GNUNET_TESTBED_host_get_id_ (host);
890   orig_size = host_list_size;  
891   if (host_list_size <= host_id)
892   {
893     while (host_list_size <= host_id)
894       host_list_size += LIST_GROW_STEP;
895     host_list =
896         TESTBED_realloc (host_list,
897                          sizeof (struct GNUNET_TESTBED_Host *) * orig_size,
898                          sizeof (struct GNUNET_TESTBED_Host *)
899                          * host_list_size);
900   }
901   if (NULL != host_list[host_id])
902   {
903     LOG_DEBUG ("A host with id: %u already exists\n", host_id);
904     return GNUNET_SYSERR;
905   }
906   host_list[host_id] = host;
907   return GNUNET_OK;
908 }
909
910
911 /**
912  * Adds a route to the route list
913  *
914  * @param route the route to add
915  */
916 static void
917 route_list_add (struct Route *route)
918 {
919   uint32_t orig_size;
920
921   orig_size = route_list_size;  
922   if (route->dest >= route_list_size)
923   {
924     while (route->dest >= route_list_size)
925       route_list_size += LIST_GROW_STEP;
926     route_list =
927         TESTBED_realloc (route_list,
928                          sizeof (struct Route *) * orig_size,
929                          sizeof (struct Route *) * route_list_size);
930   }
931   GNUNET_assert (NULL == route_list[route->dest]);
932   route_list[route->dest] = route;
933 }
934
935
936 /**
937  * Adds a slave to the slave array
938  *
939  * @param slave the slave controller to add
940  */
941 static void
942 slave_list_add (struct Slave *slave)
943 {
944   if (slave->host_id >= slave_list_size)
945   {
946     slave_list =
947         TESTBED_realloc (slave_list, sizeof (struct Slave *) * slave_list_size,
948                          sizeof (struct Slave *) * (slave_list_size +
949                                                     LIST_GROW_STEP));
950     slave_list_size += LIST_GROW_STEP;
951   }
952   GNUNET_assert (NULL == slave_list[slave->host_id]);
953   slave_list[slave->host_id] = slave;
954 }
955
956
957 /**
958  * Adds a peer to the peer array
959  *
960  * @param peer the peer to add
961  */
962 static void
963 peer_list_add (struct Peer *peer)
964 {
965   uint32_t orig_size;
966
967   orig_size = peer_list_size;
968   if (peer->id >= peer_list_size)
969   {
970     while (peer->id >= peer_list_size)
971       peer_list_size += LIST_GROW_STEP;
972     peer_list =
973         TESTBED_realloc (peer_list, sizeof (struct Peer *) * orig_size,
974                          sizeof (struct Peer *) * peer_list_size);
975   }  
976   GNUNET_assert (NULL == peer_list[peer->id]);
977   peer_list[peer->id] = peer;
978 }
979
980
981 /**
982  * Removes a the give peer from the peer array
983  *
984  * @param peer the peer to be removed
985  */
986 static void
987 peer_list_remove (struct Peer *peer)
988 {
989   uint32_t id;
990   uint32_t orig_size;
991
992   peer_list[peer->id] = NULL;
993   orig_size = peer_list_size;
994   while (peer_list_size >= LIST_GROW_STEP)
995   {
996     for (id = peer_list_size - 1;
997          (id >= peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); id--)
998       if (NULL != peer_list[id])
999         break;
1000     if (id != ((peer_list_size - LIST_GROW_STEP) - 1))
1001       break;
1002     peer_list_size -= LIST_GROW_STEP;
1003   }
1004   if (orig_size == peer_list_size)
1005     return;
1006   peer_list =
1007       GNUNET_realloc (peer_list, sizeof (struct Peer *) * peer_list_size);
1008 }
1009
1010
1011 /**
1012  * Finds the route with directly connected host as destination through which
1013  * the destination host can be reached
1014  *
1015  * @param host_id the id of the destination host
1016  * @return the route with directly connected destination host; NULL if no route
1017  *           is found
1018  */
1019 static struct Route *
1020 find_dest_route (uint32_t host_id)
1021 {
1022   struct Route *route;
1023
1024   if (route_list_size <= host_id)
1025     return NULL;
1026   while (NULL != (route = route_list[host_id]))
1027   {
1028     if (route->thru == master_context->host_id)
1029       break;
1030     host_id = route->thru;
1031   }
1032   return route;
1033 }
1034
1035
1036 /**
1037  * Routes message to a host given its host_id
1038  *
1039  * @param host_id the id of the destination host
1040  * @param msg the message to be routed
1041  */
1042 static void
1043 route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
1044 {
1045   GNUNET_break (0);
1046 }
1047
1048
1049 /**
1050  * Send operation failure message to client
1051  *
1052  * @param client the client to which the failure message has to be sent to
1053  * @param operation_id the id of the failed operation
1054  * @param emsg the error message; can be NULL
1055  */
1056 static void
1057 send_operation_fail_msg (struct GNUNET_SERVER_Client *client,
1058                          uint64_t operation_id, const char *emsg)
1059 {
1060   struct GNUNET_TESTBED_OperationFailureEventMessage *msg;
1061   uint16_t msize;
1062   uint16_t emsg_len;
1063
1064   msize = sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
1065   emsg_len = (NULL == emsg) ? 0 : strlen (emsg) + 1;
1066   msize += emsg_len;
1067   msg = GNUNET_malloc (msize);
1068   msg->header.size = htons (msize);
1069   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT);
1070   msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1071   msg->operation_id = GNUNET_htonll (operation_id);
1072   if (0 != emsg_len)
1073     memcpy (&msg[1], emsg, emsg_len);
1074   queue_message (client, &msg->header);
1075 }
1076
1077
1078 /**
1079  * Function to send generic operation success message to given client
1080  *
1081  * @param client the client to send the message to
1082  * @param operation_id the id of the operation which was successful
1083  */
1084 static void
1085 send_operation_success_msg (struct GNUNET_SERVER_Client *client,
1086                             uint64_t operation_id)
1087 {
1088   struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg;
1089   uint16_t msize;
1090
1091   msize = sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage);
1092   msg = GNUNET_malloc (msize);
1093   msg->header.size = htons (msize);
1094   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS);
1095   msg->operation_id = GNUNET_htonll (operation_id);
1096   msg->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1097   queue_message (client, &msg->header);
1098 }
1099
1100
1101 /**
1102  * Callback which will be called to after a host registration succeeded or failed
1103  *
1104  * @param cls the handle to the slave at which the registration is completed
1105  * @param emsg the error message; NULL if host registration is successful
1106  */
1107 static void 
1108 hr_completion (void *cls, const char *emsg);
1109
1110
1111 /**
1112  * Attempts to register the next host in the host registration queue
1113  *
1114  * @param slave the slave controller whose host registration queue is checked
1115  *          for host registrations
1116  */
1117 static void
1118 register_next_host (struct Slave *slave)
1119 {
1120   struct HostRegistration *hr;
1121   
1122   hr = slave->hr_dll_head;
1123   GNUNET_assert (NULL != hr);
1124   GNUNET_assert (NULL == slave->rhandle);
1125   slave->rhandle = GNUNET_TESTBED_register_host (slave->controller,
1126                                                  hr->host,
1127                                                  hr_completion,
1128                                                  slave);
1129 }
1130
1131
1132 /**
1133  * Callback which will be called to after a host registration succeeded or failed
1134  *
1135  * @param cls the handle to the slave at which the registration is completed
1136  * @param emsg the error message; NULL if host registration is successful
1137  */
1138 static void 
1139 hr_completion (void *cls, const char *emsg)
1140 {
1141   struct Slave *slave = cls;
1142   struct HostRegistration *hr;
1143
1144   slave->rhandle = NULL;
1145   hr = slave->hr_dll_head;
1146   GNUNET_assert (NULL != hr);
1147   GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head,
1148                                slave->hr_dll_tail,
1149                                hr);
1150   if (NULL != hr->cb)
1151     hr->cb (hr->cb_cls, emsg);
1152   GNUNET_free (hr);
1153   if ((NULL == slave->rhandle) && (NULL != slave->hr_dll_head))
1154     register_next_host (slave);
1155 }
1156
1157
1158 /**
1159  * Adds a host registration's request to a slave's registration queue
1160  *
1161  * @param slave the slave controller at which the given host has to be
1162  *          registered 
1163  * @param cb the host registration completion callback
1164  * @param cb_cls the closure for the host registration completion callback
1165  * @param host the host which has to be registered
1166  */
1167 static void
1168 queue_host_registration (struct Slave *slave,
1169                          GNUNET_TESTBED_HostRegistrationCompletion cb,
1170                          void *cb_cls,
1171                          struct GNUNET_TESTBED_Host *host)
1172 {
1173   struct HostRegistration *hr;
1174   int call_register;
1175
1176   hr = GNUNET_malloc (sizeof (struct HostRegistration));
1177   hr->cb = cb;
1178   hr->cb_cls = cb_cls;
1179   hr->host = host;
1180   call_register = (NULL == slave->hr_dll_head) ? GNUNET_YES : GNUNET_NO;
1181   GNUNET_CONTAINER_DLL_insert_tail (slave->hr_dll_head,
1182                                     slave->hr_dll_tail,
1183                                     hr);
1184   if (GNUNET_YES == call_register)
1185     register_next_host (slave);
1186 }
1187
1188
1189 /**
1190  * The  Link Controller forwarding task
1191  *
1192  * @param cls the LCFContext
1193  * @param tc the Task context from scheduler
1194  */
1195 static void
1196 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1197
1198
1199 /**
1200  * Completion callback for host registrations while forwarding Link Controller messages
1201  *
1202  * @param cls the LCFContext
1203  * @param emsg the error message; NULL if host registration is successful
1204  */
1205 static void
1206 lcf_proc_cc (void *cls, const char *emsg)
1207 {
1208   struct LCFContext *lcf = cls;
1209
1210   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1211   switch (lcf->state)
1212   {
1213   case INIT:
1214     if (NULL != emsg)
1215       goto registration_error;
1216     lcf->state = DELEGATED_HOST_REGISTERED;
1217     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1218     break;
1219   case DELEGATED_HOST_REGISTERED:
1220     if (NULL != emsg)
1221       goto registration_error;
1222     lcf->state = SLAVE_HOST_REGISTERED;
1223     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1224     break;
1225   default:
1226     GNUNET_assert (0);          /* Shouldn't reach here */
1227   }
1228   return;
1229
1230  registration_error:
1231   LOG (GNUNET_ERROR_TYPE_WARNING, "Host registration failed with message: %s\n",
1232        emsg);
1233   lcf->state = FINISHED;
1234   lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1235 }
1236
1237
1238 /**
1239  * Callback to be called when forwarded link controllers operation is
1240  * successfull. We have to relay the reply msg back to the client
1241  *
1242  * @param cls ForwardedOperationContext
1243  * @param msg the peer create success message
1244  */
1245 static void
1246 forwarded_operation_reply_relay (void *cls,
1247                                  const struct GNUNET_MessageHeader *msg)
1248 {
1249   struct ForwardedOperationContext *fopc = cls;
1250   struct GNUNET_MessageHeader *dup_msg;
1251   uint16_t msize;
1252
1253   msize = ntohs (msg->size);
1254   LOG_DEBUG ("Relaying message with type: %u, size: %u\n", ntohs (msg->type),
1255              msize);
1256   dup_msg = GNUNET_malloc (msize);
1257   (void) memcpy (dup_msg, msg, msize);
1258   queue_message (fopc->client, dup_msg);
1259   GNUNET_SERVER_client_drop (fopc->client);
1260   GNUNET_SCHEDULER_cancel (fopc->timeout_task);
1261   GNUNET_free (fopc);
1262 }
1263
1264
1265 /**
1266  * Task to free resources when forwarded link controllers has been timedout
1267  *
1268  * @param cls the ForwardedOperationContext
1269  * @param tc the task context from scheduler
1270  */
1271 static void
1272 forwarded_operation_timeout (void *cls,
1273                              const struct GNUNET_SCHEDULER_TaskContext *tc)
1274 {
1275   struct ForwardedOperationContext *fopc = cls;
1276
1277   GNUNET_TESTBED_forward_operation_msg_cancel_ (fopc->opc);
1278   LOG (GNUNET_ERROR_TYPE_WARNING, "A forwarded operation has timed out\n");
1279   send_operation_fail_msg (fopc->client, fopc->operation_id, "Timeout");
1280   GNUNET_SERVER_client_drop (fopc->client);
1281   GNUNET_free (fopc);
1282 }
1283
1284
1285 /**
1286  * The  Link Controller forwarding task
1287  *
1288  * @param cls the LCFContext
1289  * @param tc the Task context from scheduler
1290  */
1291 static void
1292 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1293 {
1294   struct LCFContext *lcf = cls;
1295   struct LCFContextQueue *lcfq;
1296   struct ForwardedOperationContext *fopc;
1297
1298   lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1299   switch (lcf->state)
1300   {
1301   case INIT:
1302     if (GNUNET_NO ==
1303         GNUNET_TESTBED_is_host_registered_ (host_list[lcf->delegated_host_id],
1304                                             lcf->gateway->controller))
1305     {
1306       queue_host_registration (lcf->gateway,
1307                                lcf_proc_cc, lcf,
1308                                host_list[lcf->delegated_host_id]);
1309     }
1310     else
1311     {
1312       lcf->state = DELEGATED_HOST_REGISTERED;
1313       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1314     }
1315     break;
1316   case DELEGATED_HOST_REGISTERED:
1317     if (GNUNET_NO ==
1318         GNUNET_TESTBED_is_host_registered_ (host_list[lcf->slave_host_id],
1319                                             lcf->gateway->controller))
1320     {
1321       queue_host_registration (lcf->gateway,
1322                                lcf_proc_cc, lcf,
1323                                host_list[lcf->slave_host_id]);
1324     }
1325     else
1326     {
1327       lcf->state = SLAVE_HOST_REGISTERED;
1328       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1329     }
1330     break;
1331   case SLAVE_HOST_REGISTERED:
1332     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1333     fopc->client = lcf->client;
1334     fopc->operation_id = lcf->operation_id;
1335     fopc->opc =
1336         GNUNET_TESTBED_forward_operation_msg_ (lcf->gateway->controller,
1337                                                lcf->operation_id,
1338                                                &lcf->msg->header,
1339                                                &forwarded_operation_reply_relay,
1340                                                fopc);
1341     fopc->timeout_task =
1342         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
1343                                       fopc);
1344     lcf->state = FINISHED;
1345     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
1346     break;
1347   case FINISHED:
1348     lcfq = lcfq_head;
1349     GNUNET_assert (lcfq->lcf == lcf);
1350     GNUNET_free (lcf->msg);
1351     GNUNET_free (lcf);
1352     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
1353     GNUNET_free (lcfq);
1354     if (NULL != lcfq_head)
1355       lcf_proc_task_id =
1356           GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
1357   }
1358 }
1359
1360
1361 /**
1362  * Callback to be called when forwarded overlay connection operation has a reply
1363  * from the sub-controller successfull. We have to relay the reply msg back to
1364  * the client
1365  *
1366  * @param cls ForwardedOperationContext
1367  * @param msg the peer create success message
1368  */
1369 static void
1370 forwarded_overlay_connect_listener (void *cls,
1371                                     const struct GNUNET_MessageHeader *msg);
1372
1373
1374 /**
1375  * Cleans up ForwardedOverlayConnectContext
1376  *
1377  * @param focc the ForwardedOverlayConnectContext to cleanup
1378  */
1379 static void
1380 cleanup_focc (struct ForwardedOverlayConnectContext *focc)
1381 {
1382   if (GNUNET_SCHEDULER_NO_TASK != focc->timeout_task)
1383     GNUNET_SCHEDULER_cancel (focc->timeout_task);
1384   if (NULL != focc->sub_op)
1385     GNUNET_TESTBED_operation_done (focc->sub_op);
1386   if (NULL != focc->client)
1387     GNUNET_SERVER_client_drop (focc->client);
1388   GNUNET_free_non_null (focc->orig_msg);
1389   GNUNET_free (focc);
1390 }
1391
1392 /**
1393  * Callback for event from slave controllers
1394  *
1395  * @param cls struct Slave *
1396  * @param event information about the event
1397  */
1398 static void
1399 slave_event_callback (void *cls,
1400                       const struct GNUNET_TESTBED_EventInformation *event)
1401 {
1402   struct ForwardedOverlayConnectContext *focc;
1403   struct ForwardedOperationContext *fopc;
1404   struct GNUNET_CONFIGURATION_Handle *slave_cfg;
1405   struct GNUNET_TESTBED_Operation *old_op;
1406   char *emsg;
1407
1408   /* We currently only get here when doing overlay connect operations and that
1409      too while trying out sub operations */
1410   GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
1411   focc = event->details.operation_finished.op_cls;
1412   LOG_DEBUG ("Operation successful\n");
1413   if (NULL != event->details.operation_finished.emsg)
1414   {
1415     GNUNET_asprintf (&emsg, "Failure executing suboperation: %s",
1416                      event->details.operation_finished.emsg);
1417     send_operation_fail_msg (focc->client, focc->operation_id,
1418                              emsg);
1419     GNUNET_free (emsg);
1420     cleanup_focc (focc);
1421     return;
1422   }
1423   switch (focc->state)
1424   {
1425   case FOCC_GET_CFG:
1426     slave_cfg = event->details.operation_finished.generic;
1427     old_op = focc->sub_op;
1428     focc->state = FOCC_LINK;
1429     focc->sub_op = GNUNET_TESTBED_controller_link_ (focc,
1430                                                     focc->gateway->controller,
1431                                                     focc->peer2_host_id,
1432                                                     peer_list[focc->peer1]->details.remote.remote_host_id,
1433                                                     slave_cfg,
1434                                                     GNUNET_NO);
1435     GNUNET_TESTBED_operation_done (old_op);
1436     break;
1437   case FOCC_LINK:
1438     LOG_DEBUG ("OL: Linking controllers successfull\n");
1439     GNUNET_TESTBED_operation_done (focc->sub_op);
1440     focc->sub_op = NULL;
1441     focc->state = FOCC_OL_CONNECT;
1442     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1443     fopc->client = focc->client;
1444     focc->client = NULL;
1445     fopc->operation_id = focc->operation_id;
1446     fopc->cls = NULL;
1447     fopc->opc =
1448         GNUNET_TESTBED_forward_operation_msg_ (focc->gateway->controller,
1449                                                focc->operation_id, focc->orig_msg,
1450                                                &forwarded_operation_reply_relay,
1451                                                fopc);
1452     GNUNET_free (focc->orig_msg);
1453     focc->orig_msg = NULL;
1454     fopc->timeout_task =
1455         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
1456                                       fopc);
1457     cleanup_focc (focc);
1458     break;
1459   default:
1460     GNUNET_assert (0);
1461   }
1462   return;
1463 }
1464
1465
1466 /**
1467  * Callback to signal successfull startup of the controller process
1468  *
1469  * @param cls the handle to the slave whose status is to be found here
1470  * @param cfg the configuration with which the controller has been started;
1471  *          NULL if status is not GNUNET_OK
1472  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
1473  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
1474  */
1475 static void
1476 slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
1477                        int status)
1478 {
1479   struct Slave *slave = cls;
1480   struct LinkControllersContext *lcc;
1481
1482   lcc = slave->lcc;
1483   if (GNUNET_SYSERR == status)
1484   {
1485     slave->controller_proc = NULL;
1486     slave_list[slave->host_id] = NULL;
1487     if (NULL != slave->cfg)
1488       GNUNET_CONFIGURATION_destroy (slave->cfg);
1489     GNUNET_free (slave);
1490     slave = NULL;
1491     LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n");
1492     GNUNET_SCHEDULER_shutdown ();       /* We too shutdown */
1493     goto clean_lcc;
1494   }
1495   slave->controller =
1496       GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1497                                          event_mask,
1498                                          &slave_event_callback, slave);
1499   if (NULL != slave->controller)
1500   {
1501     send_operation_success_msg (lcc->client, lcc->operation_id);
1502     slave->cfg = GNUNET_CONFIGURATION_dup (cfg);
1503   }
1504   else
1505   {
1506     send_operation_fail_msg (lcc->client, lcc->operation_id,
1507                              "Could not connect to delegated controller");
1508     GNUNET_TESTBED_controller_stop (slave->controller_proc);
1509     slave_list[slave->host_id] = NULL;
1510     GNUNET_free (slave);
1511     slave = NULL;
1512   }
1513
1514  clean_lcc:
1515   if (NULL != lcc)
1516   {
1517     if (NULL != lcc->client)
1518     {
1519       GNUNET_SERVER_receive_done (lcc->client, GNUNET_OK);
1520       GNUNET_SERVER_client_drop (lcc->client);
1521       lcc->client = NULL;
1522     }
1523     GNUNET_free (lcc);
1524   }
1525   if (NULL != slave)
1526     slave->lcc = NULL;
1527 }
1528
1529
1530 /**
1531  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
1532  *
1533  * @param cls NULL
1534  * @param client identification of the client
1535  * @param message the actual message
1536  */
1537 static void
1538 handle_init (void *cls, struct GNUNET_SERVER_Client *client,
1539              const struct GNUNET_MessageHeader *message)
1540 {
1541   const struct GNUNET_TESTBED_InitMessage *msg;
1542   struct GNUNET_TESTBED_Host *host;
1543   const char *controller_hostname;
1544   uint16_t msize;
1545
1546   if (NULL != master_context)
1547   {
1548     LOG_DEBUG ("We are being connected to laterally\n");
1549     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1550     return;
1551   }
1552   msg = (const struct GNUNET_TESTBED_InitMessage *) message;
1553   msize = ntohs (message->size);
1554   if (msize <= sizeof (struct GNUNET_TESTBED_InitMessage))
1555   {
1556     GNUNET_break (0);
1557     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1558     return;
1559   }
1560   msize -= sizeof (struct GNUNET_TESTBED_InitMessage);
1561   controller_hostname = (const char *) &msg[1];
1562   if ('\0' != controller_hostname[msize - 1])
1563   {
1564     GNUNET_break (0);
1565     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1566     return;
1567   }
1568   master_context = GNUNET_malloc (sizeof (struct Context));
1569   master_context->client = client;
1570   master_context->host_id = ntohl (msg->host_id);
1571   master_context->master_ip = GNUNET_strdup (controller_hostname);
1572   LOG_DEBUG ("Master Controller IP: %s\n", master_context->master_ip);
1573   master_context->system =
1574       GNUNET_TESTING_system_create ("testbed", master_context->master_ip, hostname);
1575   host =
1576       GNUNET_TESTBED_host_create_with_id (master_context->host_id,
1577                                           master_context->master_ip,
1578                                           NULL,
1579                                           0);
1580   host_list_add (host);
1581   GNUNET_SERVER_client_keep (client);
1582   LOG_DEBUG ("Created master context with host ID: %u\n",
1583              master_context->host_id);
1584   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1585 }
1586
1587
1588 /**
1589  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1590  *
1591  * @param cls NULL
1592  * @param client identification of the client
1593  * @param message the actual message
1594  */
1595 static void
1596 handle_add_host (void *cls, struct GNUNET_SERVER_Client *client,
1597                  const struct GNUNET_MessageHeader *message)
1598 {
1599   struct GNUNET_TESTBED_Host *host;
1600   const struct GNUNET_TESTBED_AddHostMessage *msg;
1601   struct GNUNET_TESTBED_HostConfirmedMessage *reply;
1602   char *username;
1603   char *hostname;
1604   char *emsg;
1605   uint32_t host_id;
1606   uint16_t username_length;
1607   uint16_t hostname_length;
1608   uint16_t reply_size;
1609   uint16_t msize;
1610
1611   msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
1612   msize = ntohs (msg->header.size);
1613   username = (char *) &msg[1];
1614   username_length = ntohs (msg->user_name_length);
1615   if (0 != username_length)
1616     username_length++;
1617   /* msg must contain hostname */
1618   GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1619                           username_length + 1));
1620   if (0 != username_length)
1621     GNUNET_assert ('\0' == username[username_length - 1]);
1622   hostname = username + username_length;
1623   hostname_length =
1624       msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage) + username_length);
1625   GNUNET_assert ('\0' == hostname[hostname_length - 1]);
1626   GNUNET_assert (strlen (hostname) == hostname_length - 1);
1627   host_id = ntohl (msg->host_id);
1628   LOG_DEBUG ("Received ADDHOST %u message\n", host_id);
1629   LOG_DEBUG ("-------host id: %u\n", host_id);
1630   LOG_DEBUG ("-------hostname: %s\n", hostname);
1631   if (0 != username_length)
1632     LOG_DEBUG ("-------username: %s\n", username);
1633   else
1634   {
1635     LOG_DEBUG ("-------username: NULL\n");
1636     username = NULL;
1637   }
1638   LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
1639   host =
1640       GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
1641                                           ntohs (msg->ssh_port));
1642   GNUNET_assert (NULL != host);
1643   reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
1644   if (GNUNET_OK != host_list_add (host))
1645   {
1646     /* We are unable to add a host */
1647     emsg = "A host exists with given host-id";
1648     LOG_DEBUG ("%s: %u", emsg, host_id);
1649     GNUNET_TESTBED_host_destroy (host);
1650     reply_size += strlen (emsg) + 1;
1651     reply = GNUNET_malloc (reply_size);
1652     memcpy (&reply[1], emsg, strlen (emsg) + 1);
1653   }
1654   else
1655   {
1656     LOG_DEBUG ("Added host %u at %u\n",
1657                host_id, master_context->host_id);
1658     reply = GNUNET_malloc (reply_size);
1659   }
1660   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
1661   reply->header.size = htons (reply_size);
1662   reply->host_id = htonl (host_id);
1663   queue_message (client, &reply->header);
1664   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1665 }
1666
1667
1668 /**
1669  * Iterator over hash map entries.
1670  *
1671  * @param cls closure
1672  * @param key current key code
1673  * @param value value in the hash map
1674  * @return GNUNET_YES if we should continue to
1675  *         iterate,
1676  *         GNUNET_NO if not.
1677  */
1678 int
1679 ss_exists_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
1680 {
1681   struct SharedService *queried_ss = cls;
1682   struct SharedService *ss = value;
1683
1684   if (0 == strcmp (ss->name, queried_ss->name))
1685     return GNUNET_NO;
1686   else
1687     return GNUNET_YES;
1688 }
1689
1690
1691 /**
1692  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1693  *
1694  * @param cls NULL
1695  * @param client identification of the client
1696  * @param message the actual message
1697  */
1698 static void
1699 handle_configure_shared_service (void *cls, struct GNUNET_SERVER_Client *client,
1700                                  const struct GNUNET_MessageHeader *message)
1701 {
1702   const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1703   struct SharedService *ss;
1704   char *service_name;
1705   struct GNUNET_HashCode hash;
1706   uint16_t msg_size;
1707   uint16_t service_name_size;
1708
1709   msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
1710   msg_size = ntohs (message->size);
1711   if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
1712   {
1713     GNUNET_break (0);
1714     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1715     return;
1716   }
1717   service_name_size =
1718       msg_size - sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
1719   service_name = (char *) &msg[1];
1720   if ('\0' != service_name[service_name_size - 1])
1721   {
1722     GNUNET_break (0);
1723     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1724     return;
1725   }
1726   LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
1727              service_name, ntohl (msg->num_peers));
1728   if (ntohl (msg->host_id) != master_context->host_id)
1729   {
1730     route_message (ntohl (msg->host_id), message);
1731     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1732     return;
1733   }
1734   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1735   ss = GNUNET_malloc (sizeof (struct SharedService));
1736   ss->name = strdup (service_name);
1737   ss->num_shared = ntohl (msg->num_peers);
1738   GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
1739   if (GNUNET_SYSERR ==
1740       GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
1741                                                   &ss_exists_iterator, ss))
1742   {
1743     LOG (GNUNET_ERROR_TYPE_WARNING,
1744          "Service %s already configured as a shared service. "
1745          "Ignoring service sharing request \n", ss->name);
1746     GNUNET_free (ss->name);
1747     GNUNET_free (ss);
1748     return;
1749   }
1750   GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1751                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1752 }
1753
1754
1755 /**
1756  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1757  *
1758  * @param cls NULL
1759  * @param client identification of the client
1760  * @param message the actual message
1761  */
1762 static void
1763 handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
1764                          const struct GNUNET_MessageHeader *message)
1765 {
1766   const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1767   struct GNUNET_CONFIGURATION_Handle *cfg;
1768   struct LCFContextQueue *lcfq;
1769   struct Route *route;
1770   struct Route *new_route;
1771   char *config;
1772   uLongf dest_size;
1773   size_t config_size;
1774   uint32_t delegated_host_id;
1775   uint32_t slave_host_id;
1776   uint16_t msize;
1777
1778   if (NULL == master_context)
1779   {
1780     GNUNET_break (0);
1781     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1782     return;
1783   }
1784   msize = ntohs (message->size);
1785   if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
1786   {
1787     GNUNET_break (0);
1788     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1789     return;
1790   }
1791   msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
1792   delegated_host_id = ntohl (msg->delegated_host_id);
1793   if (delegated_host_id == master_context->host_id)
1794   {
1795     GNUNET_break (0);
1796     LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1797     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1798     return;
1799   }
1800   if ((delegated_host_id >= host_list_size) ||
1801       (NULL == host_list[delegated_host_id]))
1802   {
1803     LOG (GNUNET_ERROR_TYPE_WARNING,
1804          "Delegated host %u not registered with us\n", delegated_host_id);
1805     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1806     return;
1807   }
1808   slave_host_id = ntohl (msg->slave_host_id);
1809   if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
1810   {
1811     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n",
1812          slave_host_id);
1813     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1814     return;
1815   }
1816   if (slave_host_id == delegated_host_id)
1817   {
1818     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1819     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1820     return;
1821   }
1822
1823   if (slave_host_id == master_context->host_id) /* Link from us */
1824   {
1825     struct Slave *slave;
1826     struct LinkControllersContext *lcc;
1827
1828     msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1829     config_size = ntohs (msg->config_size);
1830     if ((delegated_host_id < slave_list_size) && (NULL != slave_list[delegated_host_id]))       /* We have already added */
1831     {
1832       LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
1833            delegated_host_id);
1834       GNUNET_SERVER_receive_done (client, GNUNET_OK);
1835       return;
1836     }
1837     config = GNUNET_malloc (config_size);
1838     dest_size = (uLongf) config_size;
1839     if (Z_OK !=
1840         uncompress ((Bytef *) config, &dest_size, (const Bytef *) &msg[1],
1841                     (uLong) msize))
1842     {
1843       GNUNET_break (0);         /* Compression error */
1844       GNUNET_free (config);
1845       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1846       return;
1847     }
1848     if (config_size != dest_size)
1849     {
1850       LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
1851       GNUNET_free (config);
1852       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1853       return;
1854     }
1855     cfg = GNUNET_CONFIGURATION_create ();       /* Free here or in lcfcontext */
1856     if (GNUNET_OK !=
1857         GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
1858     {
1859       GNUNET_break (0);         /* Configuration parsing error */
1860       GNUNET_free (config);
1861       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1862       return;
1863     }
1864     GNUNET_free (config);
1865     if ((delegated_host_id < slave_list_size) &&
1866         (NULL != slave_list[delegated_host_id]))
1867     {
1868       GNUNET_break (0);         /* Configuration parsing error */
1869       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1870       return;
1871     }
1872     slave = GNUNET_malloc (sizeof (struct Slave));
1873     slave->host_id = delegated_host_id;
1874     slave_list_add (slave);
1875     if (1 != msg->is_subordinate)
1876     {
1877       slave->controller =
1878           GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1879                                              event_mask,
1880                                              &slave_event_callback, slave);
1881       slave->cfg = cfg;
1882       if (NULL != slave->controller)
1883         send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
1884       else
1885         send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1886                                  "Could not connect to delegated controller");
1887       GNUNET_SERVER_receive_done (client, GNUNET_OK);
1888       return;
1889     }
1890     lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
1891     lcc->operation_id = GNUNET_ntohll (msg->operation_id);
1892     GNUNET_SERVER_client_keep (client);
1893     lcc->client = client;
1894     slave->lcc = lcc;
1895     slave->controller_proc =
1896         GNUNET_TESTBED_controller_start (master_context->master_ip,
1897                                          host_list[slave->host_id], cfg,
1898                                          &slave_status_callback, slave);
1899     GNUNET_CONFIGURATION_destroy (cfg);
1900     new_route = GNUNET_malloc (sizeof (struct Route));
1901     new_route->dest = delegated_host_id;
1902     new_route->thru = master_context->host_id;
1903     route_list_add (new_route);
1904     return;
1905   }
1906
1907   /* Route the request */
1908   if (slave_host_id >= route_list_size)
1909   {
1910     LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1911     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1912     return;
1913   }
1914   lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1915   lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1916   lcfq->lcf->delegated_host_id = delegated_host_id;
1917   lcfq->lcf->slave_host_id = slave_host_id;
1918   route = find_dest_route (slave_host_id);
1919   GNUNET_assert (NULL != route);        /* because we add routes carefully */
1920   GNUNET_assert (route->dest < slave_list_size);
1921   GNUNET_assert (NULL != slave_list[route->dest]);
1922   lcfq->lcf->state = INIT;
1923   lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id);
1924   lcfq->lcf->gateway = slave_list[route->dest];
1925   lcfq->lcf->msg = GNUNET_malloc (msize);
1926   (void) memcpy (lcfq->lcf->msg, msg, msize);
1927   GNUNET_SERVER_client_keep (client);
1928   lcfq->lcf->client = client;
1929   if (NULL == lcfq_head)
1930   {
1931     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1932     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1933     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf);
1934   }
1935   else
1936     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1937   /* FIXME: Adding a new route should happen after the controllers are linked
1938    * successfully */
1939   if (1 != msg->is_subordinate)
1940   {
1941     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1942     return;
1943   }
1944   if ((delegated_host_id < route_list_size)
1945       && (NULL != route_list[delegated_host_id]))
1946   {
1947     GNUNET_break_op (0);        /* Are you trying to link delegated host twice
1948                                    with is subordinate flag set to GNUNET_YES? */
1949     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1950     return;
1951   }
1952   new_route = GNUNET_malloc (sizeof (struct Route));
1953   new_route->dest = delegated_host_id;
1954   new_route->thru = route->dest;
1955   route_list_add (new_route);
1956   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1957 }
1958
1959
1960 /**
1961  * The task to be executed if the forwarded peer create operation has been
1962  * timed out
1963  *
1964  * @param cls the FowardedOperationContext
1965  * @param tc the TaskContext from the scheduler
1966  */
1967 static void
1968 peer_create_forward_timeout (void *cls,
1969                              const struct GNUNET_SCHEDULER_TaskContext *tc)
1970 {
1971   struct ForwardedOperationContext *fo_ctxt = cls;
1972
1973   /* send error msg to client */
1974   GNUNET_free (fo_ctxt->cls);
1975   send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, "Timedout");
1976   GNUNET_SERVER_client_drop (fo_ctxt->client);
1977   GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc);
1978   GNUNET_free (fo_ctxt);
1979 }
1980
1981
1982 /**
1983  * Callback to be called when forwarded peer create operation is
1984  * successfull. We have to relay the reply msg back to the client
1985  *
1986  * @param cls ForwardedOperationContext
1987  * @param msg the peer create success message
1988  */
1989 static void
1990 peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
1991 {
1992   struct ForwardedOperationContext *fo_ctxt = cls;
1993   struct GNUNET_MessageHeader *dup_msg;
1994   struct Peer *remote_peer;
1995   uint16_t msize;
1996
1997   GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task);
1998   if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS)
1999   {
2000     GNUNET_assert (NULL != fo_ctxt->cls);
2001     remote_peer = fo_ctxt->cls;
2002     peer_list_add (remote_peer);
2003   }
2004   msize = ntohs (msg->size);
2005   dup_msg = GNUNET_malloc (msize);
2006   (void) memcpy (dup_msg, msg, msize);
2007   queue_message (fo_ctxt->client, dup_msg);
2008   GNUNET_SERVER_client_drop (fo_ctxt->client);
2009   GNUNET_free (fo_ctxt);
2010 }
2011
2012
2013
2014 /**
2015  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
2016  *
2017  * @param cls NULL
2018  * @param client identification of the client
2019  * @param message the actual message
2020  */
2021 static void
2022 handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
2023                     const struct GNUNET_MessageHeader *message)
2024 {
2025   const struct GNUNET_TESTBED_PeerCreateMessage *msg;
2026   struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
2027   struct GNUNET_CONFIGURATION_Handle *cfg;
2028   struct ForwardedOperationContext *fo_ctxt;
2029   struct Route *route;
2030   struct Peer *peer;
2031   char *config;
2032   size_t dest_size;
2033   int ret;
2034   uint32_t config_size;
2035   uint32_t host_id;
2036   uint32_t peer_id;
2037   uint16_t msize;
2038
2039
2040   msize = ntohs (message->size);
2041   if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
2042   {
2043     GNUNET_break (0);           /* We need configuration */
2044     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2045     return;
2046   }
2047   msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
2048   host_id = ntohl (msg->host_id);
2049   peer_id = ntohl (msg->peer_id);
2050   if (UINT32_MAX == peer_id)
2051   {
2052     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2053                              "Cannot create peer with given ID");
2054     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2055     return;
2056   }
2057   if (host_id == master_context->host_id)
2058   {
2059     char *emsg;
2060
2061     /* We are responsible for this peer */
2062     msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
2063     config_size = ntohl (msg->config_size);
2064     config = GNUNET_malloc (config_size);
2065     dest_size = config_size;
2066     if (Z_OK !=
2067         (ret =
2068          uncompress ((Bytef *) config, (uLongf *) & dest_size,
2069                      (const Bytef *) &msg[1], (uLong) msize)))
2070     {
2071       GNUNET_break (0);         /* uncompression error */
2072       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2073       return;
2074     }
2075     if (config_size != dest_size)
2076     {
2077       GNUNET_break (0);         /* Uncompressed config size mismatch */
2078       GNUNET_free (config);
2079       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2080       return;
2081     }
2082     cfg = GNUNET_CONFIGURATION_create ();
2083     if (GNUNET_OK !=
2084         GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
2085     {
2086       GNUNET_break (0);         /* Configuration parsing error */
2087       GNUNET_free (config);
2088       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2089       return;
2090     }
2091     GNUNET_free (config);
2092     peer = GNUNET_malloc (sizeof (struct Peer));
2093     peer->is_remote = GNUNET_NO;
2094     peer->details.local.cfg = cfg;
2095     peer->id = peer_id;
2096     LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
2097     peer->details.local.peer =
2098         GNUNET_TESTING_peer_configure (master_context->system,
2099                                        peer->details.local.cfg, peer->id,
2100                                        NULL /* Peer id */ ,
2101                                        &emsg);
2102     if (NULL == peer->details.local.peer)
2103     {
2104       LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
2105       GNUNET_free (emsg);
2106       GNUNET_free (peer);
2107       GNUNET_break (0);
2108       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2109       return;
2110     }
2111     peer->details.local.is_running = GNUNET_NO;
2112     peer_list_add (peer);
2113     reply =
2114         GNUNET_malloc (sizeof
2115                        (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
2116     reply->header.size =
2117         htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
2118     reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
2119     reply->peer_id = msg->peer_id;
2120     reply->operation_id = msg->operation_id;
2121     queue_message (client, &reply->header);
2122     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2123     return;
2124   }
2125
2126   /* Forward peer create request */
2127   route = find_dest_route (host_id);
2128   if (NULL == route)
2129   {
2130     GNUNET_break (0);
2131     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2132     return;
2133   }
2134
2135   peer = GNUNET_malloc (sizeof (struct Peer));
2136   peer->is_remote = GNUNET_YES;
2137   peer->id = peer_id;
2138   peer->details.remote.slave = slave_list[route->dest];
2139   peer->details.remote.remote_host_id = host_id;
2140   fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2141   GNUNET_SERVER_client_keep (client);
2142   fo_ctxt->client = client;
2143   fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
2144   fo_ctxt->cls = peer; //slave_list[route->dest]->controller;
2145   fo_ctxt->opc =
2146       GNUNET_TESTBED_forward_operation_msg_ (slave_list [route->dest]->controller,
2147                                              fo_ctxt->operation_id,
2148                                              &msg->header,
2149                                              peer_create_success_cb, fo_ctxt);
2150   fo_ctxt->timeout_task =
2151       GNUNET_SCHEDULER_add_delayed (TIMEOUT, &peer_create_forward_timeout,
2152                                     fo_ctxt);
2153   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2154 }
2155
2156
2157 /**
2158  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2159  *
2160  * @param cls NULL
2161  * @param client identification of the client
2162  * @param message the actual message
2163  */
2164 static void
2165 handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
2166                      const struct GNUNET_MessageHeader *message)
2167 {
2168   const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
2169   struct ForwardedOperationContext *fopc;
2170   struct Peer *peer;
2171   uint32_t peer_id;
2172
2173   msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
2174   peer_id = ntohl (msg->peer_id);
2175   LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
2176              peer_id, GNUNET_ntohll (msg->operation_id));
2177   if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
2178   {
2179     LOG (GNUNET_ERROR_TYPE_ERROR,
2180          "Asked to destroy a non existent peer with id: %u\n", peer_id);
2181     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2182                              "Peer doesn't exist");
2183     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2184     return;
2185   }
2186   peer = peer_list[peer_id];
2187   if (GNUNET_YES == peer->is_remote)
2188   {
2189     /* Forward the destory message to sub controller */
2190     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2191     GNUNET_SERVER_client_keep (client);
2192     fopc->client = client;
2193     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2194     fopc->opc = 
2195         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2196                                                fopc->operation_id, &msg->header,
2197                                                &forwarded_operation_reply_relay,
2198                                                fopc);
2199     fopc->timeout_task =
2200         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2201                                       fopc);
2202     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2203     return;
2204   }
2205   GNUNET_TESTING_peer_destroy (peer->details.local.peer);
2206   GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
2207   peer_list_remove (peer);
2208   GNUNET_free (peer);
2209   send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
2210   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2211 }
2212
2213
2214 /**
2215  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2216  *
2217  * @param cls NULL
2218  * @param client identification of the client
2219  * @param message the actual message
2220  */
2221 static void
2222 handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
2223                    const struct GNUNET_MessageHeader *message)
2224 {
2225   const struct GNUNET_TESTBED_PeerStartMessage *msg;
2226   struct GNUNET_TESTBED_PeerEventMessage *reply;
2227   struct ForwardedOperationContext *fopc;
2228   struct Peer *peer;
2229   uint32_t peer_id;
2230
2231   msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
2232   peer_id = ntohl (msg->peer_id);
2233   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2234   {
2235     GNUNET_break (0);
2236     LOG (GNUNET_ERROR_TYPE_ERROR,
2237          "Asked to start a non existent peer with id: %u\n", peer_id);
2238     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2239     return;
2240   }
2241   peer = peer_list[peer_id];
2242   if (GNUNET_YES == peer->is_remote)
2243   {
2244     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2245     GNUNET_SERVER_client_keep (client);
2246     fopc->client = client;
2247     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2248     fopc->opc =
2249         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2250                                                fopc->operation_id, &msg->header,
2251                                                &forwarded_operation_reply_relay,
2252                                                fopc);
2253     fopc->timeout_task =
2254         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2255                                       fopc);
2256     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2257     return;
2258   }
2259   if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer))
2260   {
2261     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2262                              "Failed to start");
2263     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2264     return;
2265   }
2266   peer->details.local.is_running = GNUNET_YES;
2267   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2268   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
2269   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2270   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
2271   reply->host_id = htonl (master_context->host_id);
2272   reply->peer_id = msg->peer_id;
2273   reply->operation_id = msg->operation_id;
2274   queue_message (client, &reply->header);
2275   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2276 }
2277
2278
2279 /**
2280  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
2281  *
2282  * @param cls NULL
2283  * @param client identification of the client
2284  * @param message the actual message
2285  */
2286 static void
2287 handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
2288                   const struct GNUNET_MessageHeader *message)
2289 {
2290   const struct GNUNET_TESTBED_PeerStopMessage *msg;
2291   struct GNUNET_TESTBED_PeerEventMessage *reply;
2292   struct ForwardedOperationContext *fopc;
2293   struct Peer *peer;
2294   uint32_t peer_id;
2295
2296   msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
2297   peer_id = ntohl (msg->peer_id);
2298   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2299   {
2300     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2301                              "Peer not found");
2302     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2303     return;
2304   }
2305   peer = peer_list[peer_id];
2306   if (GNUNET_YES == peer->is_remote)
2307   {
2308     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2309     GNUNET_SERVER_client_keep (client);
2310     fopc->client = client;
2311     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2312     fopc->opc =
2313         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2314                                                fopc->operation_id, &msg->header,
2315                                                &forwarded_operation_reply_relay,
2316                                                fopc);
2317     fopc->timeout_task =
2318         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2319                                       fopc);
2320     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2321     return;
2322   }
2323   if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer->details.local.peer))
2324   {
2325     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2326                              "Peer not running");
2327     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2328     return;
2329   }
2330   peer->details.local.is_running = GNUNET_NO;
2331   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2332   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
2333   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
2334   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
2335   reply->host_id = htonl (master_context->host_id);
2336   reply->peer_id = msg->peer_id;
2337   reply->operation_id = msg->operation_id;
2338   queue_message (client, &reply->header);
2339   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2340 }
2341
2342
2343 /**
2344  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
2345  *
2346  * @param cls NULL
2347  * @param client identification of the client
2348  * @param message the actual message
2349  */
2350 static void
2351 handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
2352                         const struct GNUNET_MessageHeader *message)
2353 {
2354   const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
2355   struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
2356   struct Peer *peer;
2357   char *config;
2358   char *xconfig;
2359   size_t c_size;
2360   size_t xc_size;
2361   uint32_t peer_id;
2362   uint16_t msize;
2363
2364   msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
2365   peer_id = ntohl (msg->peer_id);
2366   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
2367   {
2368     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
2369                              "Peer not found");
2370     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2371     return;
2372   }
2373   peer = peer_list[peer_id];
2374   if (GNUNET_YES == peer->is_remote)
2375   {
2376     struct ForwardedOperationContext *fopc;
2377     
2378     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2379     GNUNET_SERVER_client_keep (client);
2380     fopc->client = client;
2381     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
2382     fopc->opc =
2383         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2384                                                fopc->operation_id, &msg->header,
2385                                                &forwarded_operation_reply_relay,
2386                                                fopc);
2387     fopc->timeout_task =
2388         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2389                                       fopc);    
2390     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2391     return;
2392   }
2393   config =
2394       GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->details.local.cfg,
2395                                       &c_size);
2396   xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
2397   GNUNET_free (config);
2398   msize =
2399       xc_size +
2400       sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2401   reply = GNUNET_realloc (xconfig, msize);
2402   (void) memmove (&reply[1], reply, xc_size);
2403   reply->header.size = htons (msize);
2404   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
2405   reply->peer_id = msg->peer_id;
2406   reply->operation_id = msg->operation_id;
2407   GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->details.local.peer,
2408                                     &reply->peer_identity);
2409   reply->config_size = htons ((uint16_t) c_size);
2410   queue_message (client, &reply->header);
2411   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2412 }
2413
2414
2415 /**
2416  * Task for cleaing up overlay connect context structure
2417  *
2418  * @param cls the overlay connect context
2419  * @param tc the task context
2420  */
2421 static void
2422 occ_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2423 {
2424   struct OverlayConnectContext *occ = cls;
2425
2426   LOG_DEBUG ("Cleaning up occ\n");
2427   GNUNET_free_non_null (occ->emsg);
2428   GNUNET_free_non_null (occ->hello);
2429   GNUNET_SERVER_client_drop (occ->client);
2430   if (NULL != occ->opc)
2431     GNUNET_TESTBED_forward_operation_msg_cancel_ (occ->opc);
2432   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
2433     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
2434   if (NULL != occ->ch)
2435     GNUNET_CORE_disconnect (occ->ch);
2436   if (NULL != occ->ghh)
2437     GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
2438   if (NULL != occ->p1th)
2439     GNUNET_TRANSPORT_disconnect (occ->p1th);
2440   if (NULL != occ->p2th)
2441     GNUNET_TRANSPORT_disconnect (occ->p2th);
2442   GNUNET_free (occ);
2443 }
2444
2445
2446 /**
2447  * Task which will be run when overlay connect request has been timed out
2448  *
2449  * @param cls the OverlayConnectContext
2450  * @param tc the TaskContext
2451  */
2452 static void
2453 timeout_overlay_connect (void *cls,
2454                          const struct GNUNET_SCHEDULER_TaskContext *tc)
2455 {
2456   struct OverlayConnectContext *occ = cls;
2457
2458   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2459   LOG (GNUNET_ERROR_TYPE_WARNING,
2460        "Timeout while connecting peers %u and %u\n",
2461        occ->peer_id, occ->other_peer_id);
2462   send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
2463   occ_cleanup (occ, tc);
2464 }
2465
2466
2467
2468 /**
2469  * Function called to notify transport users that another
2470  * peer connected to us.
2471  *
2472  * @param cls closure
2473  * @param new_peer the peer that connected
2474  * @param ats performance data
2475  * @param ats_count number of entries in ats (excluding 0-termination)
2476  */
2477 static void
2478 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
2479                         const struct GNUNET_ATS_Information *ats,
2480                         unsigned int ats_count)
2481 {
2482   struct OverlayConnectContext *occ = cls;
2483   struct GNUNET_TESTBED_ConnectionEventMessage *msg;
2484   char *new_peer_str;
2485   char *other_peer_str;
2486
2487   LOG_DEBUG ("Overlay connect notify\n");
2488   if (0 ==
2489       memcmp (new_peer, &occ->peer_identity,
2490               sizeof (struct GNUNET_PeerIdentity)))
2491     return;
2492   new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
2493   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2494   if (0 !=
2495       memcmp (new_peer, &occ->other_peer_identity,
2496               sizeof (struct GNUNET_PeerIdentity)))
2497   {
2498     LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n",
2499                new_peer_str, other_peer_str);
2500     GNUNET_free (new_peer_str);
2501     GNUNET_free (other_peer_str);
2502     return;
2503   }
2504   GNUNET_free (new_peer_str);
2505   LOG_DEBUG ("Peer %4s connected to peer %4s\n", other_peer_str, 
2506              GNUNET_i2s (&occ->peer_identity));
2507   GNUNET_free (other_peer_str);
2508   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
2509   {
2510     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
2511     occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2512   }
2513   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
2514   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2515   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2516   GNUNET_free_non_null (occ->emsg);
2517   occ->emsg = NULL;
2518   if (NULL != occ->p2th)
2519     GNUNET_TRANSPORT_disconnect (occ->p2th);
2520   occ->p2th = NULL;
2521   LOG_DEBUG ("Peers connected - Sending overlay connect success\n");
2522   msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2523   msg->header.size =
2524       htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2525   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT);
2526   msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
2527   msg->peer1 = htonl (occ->peer_id);
2528   msg->peer2 = htonl (occ->other_peer_id);
2529   msg->operation_id = GNUNET_htonll (occ->op_id);
2530   queue_message (occ->client, &msg->header);
2531   GNUNET_SCHEDULER_add_now (&occ_cleanup, occ);
2532 }
2533
2534
2535 /**
2536  * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
2537  * peer 1.
2538  *
2539  * @param cls the OverlayConnectContext
2540  * @param tc the TaskContext from scheduler
2541  */
2542 static void
2543 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2544 {
2545   struct OverlayConnectContext *occ = cls;
2546   char *other_peer_str;
2547
2548   occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2549   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2550     return;
2551   GNUNET_assert (NULL != occ->hello);
2552   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2553   if (NULL != occ->peer2_controller)
2554   {
2555     struct GNUNET_TESTBED_RequestConnectMessage *msg;
2556     uint16_t msize;
2557     uint16_t hello_size;
2558
2559     LOG_DEBUG ("Offering HELLO of %s to %s via Remote Overlay Request\n", 
2560                GNUNET_i2s (&occ->peer_identity), other_peer_str);
2561     hello_size = ntohs (occ->hello->size);
2562     msize = sizeof (struct GNUNET_TESTBED_RequestConnectMessage) + hello_size;
2563     msg = GNUNET_malloc (msize);
2564     msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT);
2565     msg->header.size = htons (msize);
2566     msg->peer = htonl (occ->other_peer_id);
2567     msg->operation_id = GNUNET_htonll (occ->op_id);
2568     (void) memcpy (&msg->peer_identity, &occ->peer_identity,
2569                    sizeof (struct GNUNET_PeerIdentity));
2570     memcpy (msg->hello, occ->hello, hello_size);
2571     GNUNET_TESTBED_queue_message_ (occ->peer2_controller, &msg->header);
2572   }
2573   else
2574   {
2575     LOG_DEBUG ("Offering HELLO of %s to %s\n", 
2576                GNUNET_i2s (&occ->peer_identity), other_peer_str);
2577     GNUNET_TRANSPORT_offer_hello (occ->p2th, occ->hello, NULL, NULL);
2578     GNUNET_TRANSPORT_try_connect (occ->p2th, &occ->peer_identity);
2579     occ->send_hello_task =
2580         GNUNET_SCHEDULER_add_delayed
2581         (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
2582                                         100 * (pow (2, occ->retries++))),
2583          &send_hello, occ);
2584   }
2585   GNUNET_free (other_peer_str);  
2586 }
2587
2588 /**
2589  * Test for checking whether HELLO message is empty
2590  *
2591  * @param cls empty flag to set
2592  * @param address the HELLO
2593  * @param expiration expiration of the HELLO
2594  * @return
2595  */
2596 static int
2597 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
2598               struct GNUNET_TIME_Absolute expiration)
2599 {
2600   int *empty = cls;
2601
2602   *empty = GNUNET_NO;
2603   return GNUNET_OK;
2604 }
2605
2606
2607 /**
2608  * Function called whenever there is an update to the HELLO of peers in the
2609  * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
2610  * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
2611  *
2612  * @param cls closure
2613  * @param hello our updated HELLO
2614  */
2615 static void
2616 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
2617 {
2618   struct OverlayConnectContext *occ = cls;
2619   int empty;
2620   uint16_t msize;
2621
2622   msize = ntohs (hello->size);
2623   empty = GNUNET_YES;
2624   (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
2625                                          hello, GNUNET_NO, &test_address,
2626                                          &empty);
2627   if (GNUNET_YES == empty)
2628   {
2629     LOG_DEBUG ("HELLO of %s is empty\n", GNUNET_i2s (&occ->peer_identity));
2630     return;
2631   }
2632   LOG_DEBUG ("Received HELLO of %s\n", GNUNET_i2s (&occ->peer_identity));
2633   occ->hello = GNUNET_malloc (msize);
2634   memcpy (occ->hello, hello, msize);
2635   GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
2636   occ->ghh = NULL;
2637   GNUNET_TRANSPORT_disconnect (occ->p1th);
2638   occ->p1th = NULL;
2639   GNUNET_free_non_null (occ->emsg);
2640   if (NULL == occ->peer2_controller)
2641   {   
2642     occ->p2th =
2643         GNUNET_TRANSPORT_connect (peer_list[occ->other_peer_id]->details.local.cfg,
2644                                   &occ->other_peer_identity, NULL, NULL, NULL,
2645                                   NULL);
2646     if (NULL == occ->p2th)
2647     {
2648       GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of %s\n",
2649                        GNUNET_i2s (&occ->other_peer_identity));
2650       GNUNET_SCHEDULER_cancel (occ->timeout_task);
2651       occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2652       return;
2653     }
2654   }
2655   occ->emsg = GNUNET_strdup ("Timeout while offering HELLO to other peer");
2656   occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
2657 }
2658
2659
2660 /**
2661  * Function called after GNUNET_CORE_connect has succeeded (or failed
2662  * for good).  Note that the private key of the peer is intentionally
2663  * not exposed here; if you need it, your process should try to read
2664  * the private key file directly (which should work if you are
2665  * authorized...).
2666  *
2667  * @param cls closure
2668  * @param server handle to the server, NULL if we failed
2669  * @param my_identity ID of this peer, NULL if we failed
2670  */
2671 static void
2672 core_startup_cb (void *cls, struct GNUNET_CORE_Handle *server,
2673                  const struct GNUNET_PeerIdentity *my_identity)
2674 {
2675   struct OverlayConnectContext *occ = cls;
2676
2677   GNUNET_free_non_null (occ->emsg);
2678   occ->emsg = GNUNET_strdup ("Failed to connect to CORE\n");
2679   if ((NULL == server) || (NULL == my_identity))
2680     goto error_return;
2681   GNUNET_free (occ->emsg);
2682   occ->ch = server;
2683   occ->emsg = NULL;
2684   memcpy (&occ->peer_identity, my_identity,
2685           sizeof (struct GNUNET_PeerIdentity));
2686   occ->p1th =
2687       GNUNET_TRANSPORT_connect (occ->peer->details.local.cfg,
2688                                 &occ->peer_identity, NULL, NULL, NULL, NULL);
2689   if (NULL == occ->p1th)
2690   {
2691     GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of peers %4s",
2692                     GNUNET_i2s (&occ->peer_identity));
2693     goto error_return;
2694   }
2695   LOG_DEBUG ("Acquiring HELLO of peer %s\n", GNUNET_i2s (&occ->peer_identity));
2696   occ->emsg = GNUNET_strdup ("Timeout while acquiring HELLO message");
2697   occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th, &hello_update_cb, occ);
2698   return;
2699   
2700  error_return:
2701   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2702   occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2703   return;
2704 }
2705
2706
2707 /**
2708  * Callback to be called when forwarded get peer config operation as part of
2709  * overlay connect is successfull. Connection to Peer 1's core is made and is
2710  * checked for new connection from peer 2
2711  *
2712  * @param cls ForwardedOperationContext
2713  * @param msg the peer create success message
2714  */
2715 static void
2716 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
2717 {
2718   struct OverlayConnectContext *occ = cls;
2719   const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
2720   const struct GNUNET_CORE_MessageHandler no_handlers[] = {
2721     {NULL, 0, 0}
2722   };
2723
2724   occ->opc = NULL;
2725   if (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG != ntohs (msg->type))
2726     goto error_return;
2727   cmsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *)
2728       msg;
2729   memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
2730           sizeof (struct GNUNET_PeerIdentity));
2731   GNUNET_free_non_null (occ->emsg);
2732   occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
2733   occ->ch =
2734       GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
2735                            &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
2736                            GNUNET_NO, no_handlers);
2737   if (NULL == occ->ch)
2738     goto error_return;
2739   return;
2740
2741  error_return:
2742   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2743   occ->timeout_task = 
2744       GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2745 }
2746
2747
2748 /**
2749  * This callback is a part of overlay connect operation. This will be run when
2750  * the registration operation of peer2's controller is completed at peer1's
2751  * controller
2752  *
2753  * @param cls the ForwardedOverlayConnectContext
2754  * @param emsg the error message in case of any failure; NULL if host
2755  *          registration is successfull.
2756  */
2757 static void
2758 focc_reg_completion_cc (void *cls, const char *emsg)
2759 {
2760   struct ForwardedOverlayConnectContext *focc = cls;
2761   struct GNUNET_CONFIGURATION_Handle *cfg;
2762
2763   GNUNET_assert (FOCC_REGISTER == focc->state);
2764   GNUNET_assert (NULL == focc->sub_op);
2765   LOG_DEBUG ("[%u -> %u] Registering peer2's host successful\n",
2766              focc->peer1, focc->peer2);
2767   if ((NULL == focc->gateway2)
2768       || ((focc->peer2_host_id < slave_list_size) /* Check if we have the needed config */
2769           && (NULL != slave_list[focc->peer2_host_id])))
2770   {
2771     focc->state = FOCC_LINK;
2772     cfg = (NULL == focc->gateway2) ? 
2773         our_config : slave_list[focc->peer2_host_id]->cfg;
2774     focc->sub_op = 
2775         GNUNET_TESTBED_controller_link_ (focc,
2776                                          focc->gateway->controller,
2777                                          focc->peer2_host_id,
2778                                          peer_list[focc->peer1]->details.remote.remote_host_id,
2779                                          cfg,
2780                                          GNUNET_NO);
2781     return;
2782   }
2783   focc->state = FOCC_GET_CFG;
2784   focc->sub_op = GNUNET_TESTBED_get_slave_config_ (focc, focc->gateway2->controller,
2785                                                    focc->peer2_host_id);
2786 }
2787
2788
2789 /**
2790  * Callback to be called when forwarded overlay connection operation has a reply
2791  * from the sub-controller successfull. We have to relay the reply msg back to
2792  * the client
2793  *
2794  * @param cls ForwardedOperationContext
2795  * @param msg the peer create success message
2796  */
2797 static void
2798 forwarded_overlay_connect_listener (void *cls,
2799                                     const struct GNUNET_MessageHeader *msg)
2800 {
2801   struct ForwardedOperationContext *fopc = cls;
2802   struct ForwardedOverlayConnectContext *focc;
2803
2804   focc = fopc->cls;
2805   if (NULL == focc)
2806   {
2807     forwarded_operation_reply_relay (cls, msg);
2808     return;
2809   }
2810   switch (focc->state)
2811   {
2812   case FOCC_INIT:
2813     if (GNUNET_MESSAGE_TYPE_TESTBED_NEEDCONTROLLERCONFIG != ntohs (msg->type))
2814     {
2815       GNUNET_break (0);  /* Something failed; you may check output of
2816                             sub-controllers */
2817       cleanup_focc (focc);
2818       forwarded_operation_reply_relay (cls, msg);
2819       return;
2820     }
2821     LOG_DEBUG ("[%u -> %u] Registering peer2's host %u at %u\n",
2822                focc->peer1, focc->peer2, focc->peer2_host_id,
2823                peer_list[focc->peer1]->details.remote.remote_host_id);
2824     focc->state = FOCC_REGISTER;
2825     queue_host_registration (focc->gateway,
2826                              focc_reg_completion_cc,
2827                              focc,
2828                              host_list[focc->peer2_host_id]);
2829     break;
2830   default:
2831     GNUNET_assert (0);
2832   }
2833   GNUNET_SERVER_client_drop (fopc->client);
2834   GNUNET_SCHEDULER_cancel (fopc->timeout_task);
2835   fopc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2836   GNUNET_free (fopc);
2837 }
2838
2839
2840 /**
2841  * Timeout task for cancelling a forwarded overlay connect connect
2842  *
2843  * @param cls the ForwardedOverlayConnectContext
2844  * @param tc the task context from the scheduler
2845  */
2846 static void
2847 forwarded_overlay_connect_timeout (void *cls,
2848                                    const struct GNUNET_SCHEDULER_TaskContext
2849                                    *tc)
2850 {
2851   struct ForwardedOverlayConnectContext *focc = cls;
2852
2853   focc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2854   LOG_DEBUG ("Overlay linking between peers %u and %u failed during state %u\n",
2855              focc->peer1, focc->peer2, focc->state);
2856   send_operation_fail_msg (focc->client, focc->operation_id, "Timeout");
2857   cleanup_focc (focc);
2858 }
2859
2860
2861 /**
2862  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
2863  *
2864  * @param cls NULL
2865  * @param client identification of the client
2866  * @param message the actual message
2867  */
2868 static void
2869 handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
2870                         const struct GNUNET_MessageHeader *message)
2871 {
2872   const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
2873   struct OverlayConnectContext *occ;
2874   const struct GNUNET_CORE_MessageHandler no_handlers[] = {
2875     {NULL, 0, 0}
2876   };
2877   struct Peer *peer;
2878   uint64_t operation_id;
2879   uint32_t p1;
2880   uint32_t p2; 
2881   uint32_t peer2_host_id;
2882
2883   msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
2884   p1 = ntohl (msg->peer1);
2885   p2 = ntohl (msg->peer2);
2886   peer2_host_id = ntohl (msg->peer2_host_id);
2887   GNUNET_assert (p1 < peer_list_size);
2888   GNUNET_assert (NULL != peer_list[p1]);
2889   peer = peer_list[p1];
2890   operation_id = GNUNET_ntohll (msg->operation_id);  
2891   LOG_DEBUG ("Received overlay connect for peers %u and %u with op id: 0x%lx\n",
2892              p1, p2, operation_id);
2893   if (GNUNET_YES == peer->is_remote)
2894   {
2895     struct ForwardedOperationContext *fopc;
2896     struct Route *route_to_peer2_host;
2897     struct Route *route_to_peer1_host;
2898
2899     LOG_DEBUG ("Forwarding overlay connect\n");
2900     GNUNET_SERVER_client_keep (client);
2901     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
2902     fopc->client = client;
2903     fopc->operation_id = operation_id;
2904     route_to_peer2_host = NULL;
2905     route_to_peer1_host = NULL;
2906     route_to_peer2_host = find_dest_route (peer2_host_id);
2907     if ((NULL != route_to_peer2_host) 
2908         || (peer2_host_id == master_context->host_id))
2909     {
2910       route_to_peer1_host = 
2911           find_dest_route (peer_list[p1]->details.remote.remote_host_id);
2912       GNUNET_assert (NULL != route_to_peer1_host);
2913       if ((peer2_host_id == master_context->host_id) 
2914           || (route_to_peer2_host->dest != route_to_peer1_host->dest))
2915       {
2916         struct ForwardedOverlayConnectContext *focc;
2917         uint16_t msize;
2918
2919         msize = sizeof (struct GNUNET_TESTBED_OverlayConnectMessage);
2920         focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
2921         focc->gateway = peer->details.remote.slave;
2922         focc->gateway2 = (NULL == route_to_peer2_host) ? NULL :
2923             slave_list[route_to_peer2_host->dest];
2924         focc->peer1 = p1;
2925         focc->peer2 = p2;
2926         focc->peer2_host_id = peer2_host_id;
2927         focc->state = FOCC_INIT;
2928         focc->orig_msg = GNUNET_malloc (msize);
2929         (void) memcpy (focc->orig_msg, message, msize);
2930         GNUNET_SERVER_client_keep (client);
2931         focc->client = client;
2932         focc->operation_id = operation_id;
2933         fopc->cls = focc;
2934         focc->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
2935                                                            &forwarded_overlay_connect_timeout,
2936                                                            focc);
2937       }
2938     }
2939     fopc->opc = 
2940         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.slave->controller,
2941                                                operation_id, message,
2942                                                &forwarded_overlay_connect_listener,
2943                                                fopc);
2944     fopc->timeout_task =
2945         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
2946                                       fopc);
2947     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2948     return;
2949   }
2950   occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
2951   GNUNET_SERVER_client_keep (client);
2952   occ->client = client;
2953   occ->peer_id = p1;
2954   occ->other_peer_id = p2;
2955   occ->peer = peer_list[p1];
2956   occ->op_id = GNUNET_ntohll (msg->operation_id);  
2957   if ((p2 >= peer_list_size) || (NULL == peer_list[p2]))
2958   {   
2959     if ((peer2_host_id >= slave_list_size)
2960         || (NULL ==slave_list[peer2_host_id]))
2961     {
2962       struct GNUNET_TESTBED_NeedControllerConfig *reply;
2963
2964       LOG_DEBUG ("Need controller configuration for connecting peers %u and %u\n",
2965                  occ->peer_id, occ->other_peer_id);
2966       GNUNET_free (occ);
2967       reply = GNUNET_malloc (sizeof (struct
2968                                      GNUNET_TESTBED_NeedControllerConfig)); 
2969       reply->header.size = htons (sizeof (struct
2970                                           GNUNET_TESTBED_NeedControllerConfig));
2971       reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_NEEDCONTROLLERCONFIG);
2972       reply->controller_host_id = msg->peer2_host_id;
2973       reply->operation_id = msg->operation_id;
2974       queue_message (client, &reply->header);      
2975       GNUNET_SERVER_receive_done (client, GNUNET_OK);
2976       return;
2977     }
2978     else
2979     {
2980       occ->peer2_controller = slave_list[peer2_host_id]->controller;
2981       if (NULL == occ->peer2_controller)
2982       {
2983         GNUNET_break (0);       /* What's going on? */
2984         GNUNET_SERVER_client_drop (client);
2985         GNUNET_free (occ);
2986         GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2987         return;
2988       }
2989     }
2990   }
2991   else
2992   {
2993     if (GNUNET_YES == peer_list[occ->other_peer_id]->is_remote)
2994       occ->peer2_controller = peer_list[occ->other_peer_id]->details.remote.slave->controller;
2995   }
2996   /* Get the identity of the second peer */
2997   if (NULL != occ->peer2_controller)
2998   {
2999     struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
3000
3001     cmsg.header.size = 
3002         htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
3003     cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG);
3004     cmsg.peer_id = msg->peer2;
3005     cmsg.operation_id = msg->operation_id;
3006     occ->opc = 
3007         GNUNET_TESTBED_forward_operation_msg_ (occ->peer2_controller,
3008                                                occ->op_id, &cmsg.header,
3009                                                &overlay_connect_get_config,
3010                                                occ);
3011     occ->emsg = 
3012         GNUNET_strdup ("Timeout while getting peer identity of peer B\n");
3013     occ->timeout_task =
3014         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
3015                                       (GNUNET_TIME_UNIT_SECONDS, 30),
3016                                       &timeout_overlay_connect, occ);
3017     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3018     return;
3019   }
3020   GNUNET_TESTING_peer_get_identity (peer_list[occ->other_peer_id]->details.local.peer,
3021                                     &occ->other_peer_identity);
3022   /* Connect to the core of 1st peer and wait for the 2nd peer to connect */
3023   occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
3024   occ->ch =
3025       GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
3026                            &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
3027                            GNUNET_NO, no_handlers);
3028   if (NULL == occ->ch)
3029     occ->timeout_task = 
3030         GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
3031   else
3032     occ->timeout_task =
3033         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
3034                                       (GNUNET_TIME_UNIT_SECONDS, 30),
3035                                       &timeout_overlay_connect, occ);
3036   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3037 }
3038
3039
3040 /**
3041  * Function to cleanup RequestOverlayConnectContext and any associated tasks
3042  * with it
3043  *
3044  * @param rocc the RequestOverlayConnectContext
3045  */
3046 static void
3047 cleanup_rocc (struct RequestOverlayConnectContext *rocc)
3048 {
3049   if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id)
3050     GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
3051   if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id)
3052     GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
3053   GNUNET_TRANSPORT_disconnect (rocc->th);
3054   GNUNET_free_non_null (rocc->hello);
3055   GNUNET_free (rocc);
3056 }
3057
3058
3059 /**
3060  * Task to timeout rocc and cleanit up
3061  *
3062  * @param cls the RequestOverlayConnectContext
3063  * @param tc the TaskContext from scheduler
3064  */
3065 static void
3066 timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3067 {
3068   struct RequestOverlayConnectContext *rocc = cls;
3069   
3070   rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK;
3071   cleanup_rocc (rocc);
3072 }
3073
3074
3075 /**
3076  * Function called to notify transport users that another
3077  * peer connected to us.
3078  *
3079  * @param cls closure
3080  * @param new_peer the peer that connected
3081  * @param ats performance data
3082  * @param ats_count number of entries in ats (excluding 0-termination)
3083  */
3084 static void 
3085 transport_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
3086                           const struct GNUNET_ATS_Information * ats,
3087                           uint32_t ats_count)
3088 {
3089   struct RequestOverlayConnectContext *rocc = cls;
3090
3091   LOG_DEBUG ("Request Overlay connect notify\n");
3092   if (0 != memcmp (new_peer, &rocc->a_id, sizeof (struct GNUNET_PeerIdentity)))
3093     return;
3094   LOG_DEBUG ("Peer %4s connected\n", GNUNET_i2s (&rocc->a_id));
3095   cleanup_rocc (rocc);
3096 }
3097
3098
3099 /**
3100  * Task to offer the HELLO message to the peer and ask it to connect to the peer
3101  * whose identity is in RequestOverlayConnectContext
3102  *
3103  * @param cls the RequestOverlayConnectContext
3104  * @param tc the TaskContext from scheduler
3105  */
3106 static void
3107 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3108 {
3109   struct RequestOverlayConnectContext *rocc = cls;
3110
3111   rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK;
3112   GNUNET_TRANSPORT_offer_hello (rocc->th, rocc->hello, NULL, NULL);
3113   GNUNET_TRANSPORT_try_connect (rocc->th, &rocc->a_id);
3114   rocc->attempt_connect_task_id = 
3115       GNUNET_SCHEDULER_add_delayed 
3116       (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
3117                                       100 * (pow (2, rocc->retries++))),
3118        &attempt_connect_task, rocc);
3119 }
3120
3121
3122 /**
3123  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages
3124  *
3125  * @param cls NULL
3126  * @param client identification of the client
3127  * @param message the actual message
3128  */
3129 static void
3130 handle_overlay_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
3131                                 const struct GNUNET_MessageHeader *message)
3132 {
3133   const struct GNUNET_TESTBED_RequestConnectMessage *msg;
3134   struct RequestOverlayConnectContext *rocc;
3135   struct Peer *peer;
3136   uint32_t peer_id;
3137   uint16_t msize;
3138   uint16_t hsize;
3139   
3140   msize = ntohs (message->size);
3141   if (sizeof (struct GNUNET_TESTBED_RequestConnectMessage) >= msize)
3142   {
3143     GNUNET_break (0);
3144     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3145     return;
3146   }  
3147   msg = (const struct GNUNET_TESTBED_RequestConnectMessage *) message;
3148   if ((NULL == msg->hello) || 
3149       (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)))
3150   {
3151     GNUNET_break (0);
3152     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3153     return;
3154   }
3155   hsize = ntohs (msg->hello->size);
3156   if ((sizeof (struct GNUNET_TESTBED_RequestConnectMessage) + hsize) != msize)
3157   {
3158     GNUNET_break (0);
3159     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3160     return;
3161   }
3162   peer_id = ntohl (msg->peer);
3163   if ((peer_id >= peer_list_size) || (NULL == (peer = peer_list[peer_id])))
3164   {
3165     GNUNET_break_op (0);
3166     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3167     return;
3168   }
3169   if (GNUNET_YES == peer->is_remote)
3170   {
3171     struct GNUNET_MessageHeader *msg2;
3172     
3173     msg2 = GNUNET_malloc (msize);
3174     (void) memcpy (msg2, message, msize);
3175     GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller, msg2);
3176     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3177     return;
3178   }
3179   rocc = GNUNET_malloc (sizeof (struct RequestOverlayConnectContext));
3180   rocc->th = GNUNET_TRANSPORT_connect (peer->details.local.cfg, NULL, rocc, 
3181                                        NULL, &transport_connect_notify, NULL);
3182   if (NULL == rocc->th)
3183   {
3184     GNUNET_break (0);
3185     GNUNET_free (rocc);
3186     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3187     return;
3188   }
3189   memcpy (&rocc->a_id, &msg->peer_identity,
3190           sizeof (struct GNUNET_PeerIdentity));
3191   rocc->hello = GNUNET_malloc (hsize);
3192   memcpy (rocc->hello, msg->hello, hsize);
3193   rocc->attempt_connect_task_id =
3194       GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
3195   rocc->timeout_rocc_task_id =
3196       GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_rocc_task, rocc);
3197   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3198 }
3199
3200
3201 /**
3202  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
3203  *
3204  * @param cls NULL
3205  * @param client identification of the client
3206  * @param message the actual message
3207  */
3208 static void
3209 handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client,
3210                          const struct GNUNET_MessageHeader *message)
3211 {
3212   struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
3213   struct Slave *slave;  
3214   struct GNUNET_TESTBED_SlaveConfiguration *reply;
3215   char *config;
3216   char *xconfig;
3217   size_t config_size;
3218   size_t xconfig_size;
3219   size_t reply_size;
3220   uint64_t op_id;
3221   uint32_t slave_id;
3222
3223   msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message;
3224   slave_id = ntohl (msg->slave_id);
3225   op_id = GNUNET_ntohll (msg->operation_id);
3226   if ((slave_list_size <= slave_id) || (NULL == slave_list[slave_id]))
3227   {
3228     send_operation_fail_msg (client, op_id, "Slave not found");
3229     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3230     return;
3231   }
3232   slave = slave_list[slave_id];
3233   if (NULL == slave->cfg)
3234   {
3235     send_operation_fail_msg (client, op_id,
3236                              "Configuration not found (slave not started by me)");
3237     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3238     return;
3239   }
3240   config = GNUNET_CONFIGURATION_serialize (slave->cfg, &config_size);
3241   xconfig_size = GNUNET_TESTBED_compress_config_ (config, config_size, 
3242                                                   &xconfig);
3243   GNUNET_free (config);  
3244   reply_size = xconfig_size + sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
3245   GNUNET_break (reply_size <= UINT16_MAX);
3246   GNUNET_break (config_size <= UINT16_MAX);
3247   reply = GNUNET_realloc (xconfig, reply_size);
3248   (void) memmove (&reply[1], reply, xconfig_size);
3249   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG);
3250   reply->header.size = htons ((uint16_t) reply_size);
3251   reply->slave_id = msg->slave_id;
3252   reply->operation_id = msg->operation_id;
3253   reply->config_size = htons ((uint16_t) config_size);
3254   queue_message (client, &reply->header);
3255   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3256 }
3257
3258
3259 /**
3260  * Iterator over hash map entries.
3261  *
3262  * @param cls closure
3263  * @param key current key code
3264  * @param value value in the hash map
3265  * @return GNUNET_YES if we should continue to
3266  *         iterate,
3267  *         GNUNET_NO if not.
3268  */
3269 static int
3270 ss_map_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
3271 {
3272   struct SharedService *ss = value;
3273
3274   GNUNET_assert (GNUNET_YES ==
3275                  GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
3276   GNUNET_free (ss->name);
3277   GNUNET_free (ss);
3278   return GNUNET_YES;
3279 }
3280
3281
3282 /**
3283  * Task to clean up and shutdown nicely
3284  *
3285  * @param cls NULL
3286  * @param tc the TaskContext from scheduler
3287  */
3288 static void
3289 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3290 {
3291   struct LCFContextQueue *lcfq;
3292   uint32_t id;
3293
3294   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
3295   LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
3296   (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
3297                                                 NULL);
3298   GNUNET_CONTAINER_multihashmap_destroy (ss_map);
3299   if (NULL != lcfq_head)
3300   {
3301     if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
3302     {
3303       GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
3304       lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
3305     }
3306   }
3307   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
3308   for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
3309   {
3310     GNUNET_free (lcfq->lcf->msg);
3311     GNUNET_free (lcfq->lcf);
3312     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
3313     GNUNET_free (lcfq);
3314   }
3315   /* Clear peer list */
3316   for (id = 0; id < peer_list_size; id++)
3317     if (NULL != peer_list[id])
3318     {
3319       if (GNUNET_NO == peer_list[id]->is_remote)
3320       {
3321         if (GNUNET_YES == peer_list[id]->details.local.is_running)
3322           GNUNET_TESTING_peer_stop (peer_list[id]->details.local.peer);
3323         GNUNET_TESTING_peer_destroy (peer_list[id]->details.local.peer);
3324         GNUNET_CONFIGURATION_destroy (peer_list[id]->details.local.cfg);
3325       }
3326       GNUNET_free (peer_list[id]);
3327     }
3328   GNUNET_free_non_null (peer_list);
3329   /* Clear host list */
3330   for (id = 0; id < host_list_size; id++)
3331     if (NULL != host_list[id])
3332       GNUNET_TESTBED_host_destroy (host_list[id]);
3333   GNUNET_free_non_null (host_list);
3334   /* Clear route list */
3335   for (id = 0; id < route_list_size; id++)
3336     if (NULL != route_list[id])
3337       GNUNET_free (route_list[id]);
3338   GNUNET_free_non_null (route_list);
3339   /* Clear slave_list */
3340   for (id = 0; id < slave_list_size; id++)
3341     if (NULL != slave_list[id])
3342     {
3343       struct HostRegistration *hr_entry;
3344       
3345       while (NULL != (hr_entry = slave_list[id]->hr_dll_head))
3346       {
3347         GNUNET_CONTAINER_DLL_remove (slave_list[id]->hr_dll_head,
3348                                      slave_list[id]->hr_dll_tail,
3349                                      hr_entry);
3350         GNUNET_free (hr_entry);
3351       }
3352       if (NULL != slave_list[id]->rhandle)
3353         GNUNET_TESTBED_cancel_registration (slave_list[id]->rhandle);
3354       if (NULL != slave_list[id]->cfg)
3355         GNUNET_CONFIGURATION_destroy (slave_list[id]->cfg);
3356       if (NULL != slave_list[id]->controller)
3357         GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
3358       if (NULL != slave_list[id]->controller_proc)
3359         GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
3360       GNUNET_free (slave_list[id]);
3361     }
3362   GNUNET_free_non_null (slave_list);
3363   if (NULL != master_context)
3364   {
3365     GNUNET_free_non_null (master_context->master_ip);
3366     if (NULL != master_context->system)
3367       GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
3368     GNUNET_free (master_context);
3369     master_context = NULL;
3370   }
3371   GNUNET_free_non_null (hostname);
3372   GNUNET_CONFIGURATION_destroy (our_config);
3373 }
3374
3375
3376 /**
3377  * Callback for client disconnect
3378  *
3379  * @param cls NULL
3380  * @param client the client which has disconnected
3381  */
3382 static void
3383 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
3384 {
3385   if (NULL == master_context)
3386     return;
3387   if (client == master_context->client)
3388   {
3389     LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
3390     GNUNET_SERVER_client_drop (client);
3391     /* should not be needed as we're terminated by failure to read
3392      * from stdin, but if stdin fails for some reason, this shouldn't
3393      * hurt for now --- might need to revise this later if we ever
3394      * decide that master connections might be temporarily down
3395      * for some reason */
3396     //GNUNET_SCHEDULER_shutdown ();
3397   }
3398 }
3399
3400
3401 /**
3402  * Testbed setup
3403  *
3404  * @param cls closure
3405  * @param server the initialized server
3406  * @param cfg configuration to use
3407  */
3408 static void
3409 testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
3410              const struct GNUNET_CONFIGURATION_Handle *cfg)
3411 {
3412   static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
3413     {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
3414     {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
3415     {&handle_configure_shared_service, NULL,
3416      GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
3417     {&handle_link_controllers, NULL,
3418      GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
3419     {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
3420     {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
3421      sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
3422     {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
3423      sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
3424     {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
3425      sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
3426     {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
3427      sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
3428     {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
3429      sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
3430     {&handle_overlay_request_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT,
3431      0},
3432     {handle_slave_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG,
3433      sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)},
3434     {NULL}
3435   };
3436
3437   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string 
3438                  (cfg, "testbed", "HOSTNAME", &hostname));
3439   our_config = GNUNET_CONFIGURATION_dup (cfg);
3440   GNUNET_SERVER_add_handlers (server, message_handlers);
3441   GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
3442   ss_map = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
3443   shutdown_task_id =
3444       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
3445                                     &shutdown_task, NULL);
3446   LOG_DEBUG ("Testbed startup complete\n");
3447   event_mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
3448 }
3449
3450
3451 /**
3452  * The starting point of execution
3453  */
3454 int
3455 main (int argc, char *const *argv)
3456 {
3457   //sleep (15);                 /* Debugging */
3458   return (GNUNET_OK ==
3459           GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE,
3460                               &testbed_run, NULL)) ? 0 : 1;
3461 }
3462
3463 /* end of gnunet-service-testbed.c */