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