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