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