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