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