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