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