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