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