1/2 part - inter-host overlay connect
[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   if (NULL != hostname)
1191     LOG_DEBUG ("-------hostname: %s\n", hostname);
1192   if (0 != username_length)
1193     LOG_DEBUG ("-------username: %s\n", username);
1194   else
1195   {
1196     LOG_DEBUG ("-------username: NULL\n");
1197     username = NULL;
1198   }
1199   LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
1200   host =
1201       GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
1202                                           ntohs (msg->ssh_port));
1203   GNUNET_assert (NULL != host);
1204   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1205   reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
1206   if (GNUNET_OK != host_list_add (host))
1207   {
1208     /* We are unable to add a host */
1209     emsg = "A host exists with given host-id";
1210     LOG_DEBUG ("%s: %u", emsg, host_id);
1211     GNUNET_TESTBED_host_destroy (host);
1212     reply_size += strlen (emsg) + 1;
1213     reply = GNUNET_malloc (reply_size);
1214     memcpy (&reply[1], emsg, strlen (emsg) + 1);
1215   }
1216   else
1217     reply = GNUNET_malloc (reply_size);
1218   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
1219   reply->header.size = htons (reply_size);
1220   reply->host_id = htonl (host_id);
1221   queue_message (client, &reply->header);
1222 }
1223
1224
1225 /**
1226  * Iterator over hash map entries.
1227  *
1228  * @param cls closure
1229  * @param key current key code
1230  * @param value value in the hash map
1231  * @return GNUNET_YES if we should continue to
1232  *         iterate,
1233  *         GNUNET_NO if not.
1234  */
1235 int
1236 ss_exists_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
1237 {
1238   struct SharedService *queried_ss = cls;
1239   struct SharedService *ss = value;
1240
1241   if (0 == strcmp (ss->name, queried_ss->name))
1242     return GNUNET_NO;
1243   else
1244     return GNUNET_YES;
1245 }
1246
1247
1248 /**
1249  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1250  *
1251  * @param cls NULL
1252  * @param client identification of the client
1253  * @param message the actual message
1254  */
1255 static void
1256 handle_configure_shared_service (void *cls, struct GNUNET_SERVER_Client *client,
1257                                  const struct GNUNET_MessageHeader *message)
1258 {
1259   const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1260   struct SharedService *ss;
1261   char *service_name;
1262   struct GNUNET_HashCode hash;
1263   uint16_t msg_size;
1264   uint16_t service_name_size;
1265
1266   msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
1267   msg_size = ntohs (message->size);
1268   if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
1269   {
1270     GNUNET_break (0);
1271     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1272     return;
1273   }
1274   service_name_size =
1275       msg_size - sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
1276   service_name = (char *) &msg[1];
1277   if ('\0' != service_name[service_name_size - 1])
1278   {
1279     GNUNET_break (0);
1280     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1281     return;
1282   }
1283   LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
1284              service_name, ntohl (msg->num_peers));
1285   if (ntohl (msg->host_id) != master_context->host_id)
1286   {
1287     route_message (ntohl (msg->host_id), message);
1288     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1289     return;
1290   }
1291   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1292   ss = GNUNET_malloc (sizeof (struct SharedService));
1293   ss->name = strdup (service_name);
1294   ss->num_shared = ntohl (msg->num_peers);
1295   GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
1296   if (GNUNET_SYSERR ==
1297       GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
1298                                                   &ss_exists_iterator, ss))
1299   {
1300     LOG (GNUNET_ERROR_TYPE_WARNING,
1301          "Service %s already configured as a shared service. "
1302          "Ignoring service sharing request \n", ss->name);
1303     GNUNET_free (ss->name);
1304     GNUNET_free (ss);
1305     return;
1306   }
1307   GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1308                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1309 }
1310
1311
1312 /**
1313  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1314  *
1315  * @param cls NULL
1316  * @param client identification of the client
1317  * @param message the actual message
1318  */
1319 static void
1320 handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
1321                          const struct GNUNET_MessageHeader *message)
1322 {
1323   const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1324   struct GNUNET_CONFIGURATION_Handle *cfg;
1325   struct LCFContextQueue *lcfq;
1326   struct Route *route;
1327   struct Route *new_route;
1328   char *config;
1329   uLongf dest_size;
1330   size_t config_size;
1331   uint32_t delegated_host_id;
1332   uint32_t slave_host_id;
1333   uint16_t msize;
1334
1335   if (NULL == master_context)
1336   {
1337     GNUNET_break (0);
1338     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1339     return;
1340   }
1341   msize = ntohs (message->size);
1342   if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
1343   {
1344     GNUNET_break (0);
1345     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1346     return;
1347   }
1348   msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
1349   delegated_host_id = ntohl (msg->delegated_host_id);
1350   if (delegated_host_id == master_context->host_id)
1351   {
1352     GNUNET_break (0);
1353     LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1354     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1355     return;
1356   }
1357   if ((delegated_host_id >= host_list_size) ||
1358       (NULL == host_list[delegated_host_id]))
1359   {
1360     LOG (GNUNET_ERROR_TYPE_WARNING, "Delegated host not registered with us\n");
1361     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1362     return;
1363   }
1364   slave_host_id = ntohl (msg->slave_host_id);
1365   if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
1366   {
1367     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host not registered with us\n");
1368     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1369     return;
1370   }
1371   if (slave_host_id == delegated_host_id)
1372   {
1373     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1374     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1375     return;
1376   }
1377
1378   if (slave_host_id == master_context->host_id) /* Link from us */
1379   {
1380     struct Slave *slave;
1381     struct LinkControllersContext *lcc;
1382
1383     msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1384     config_size = ntohs (msg->config_size);
1385     if ((delegated_host_id < slave_list_size) && (NULL != slave_list[delegated_host_id]))       /* We have already added */
1386     {
1387       LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
1388            delegated_host_id);
1389       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1390       return;
1391     }
1392     config = GNUNET_malloc (config_size);
1393     dest_size = (uLongf) config_size;
1394     if (Z_OK !=
1395         uncompress ((Bytef *) config, &dest_size, (const Bytef *) &msg[1],
1396                     (uLong) msize))
1397     {
1398       GNUNET_break (0);         /* Compression error */
1399       GNUNET_free (config);
1400       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1401       return;
1402     }
1403     if (config_size != dest_size)
1404     {
1405       LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
1406       GNUNET_free (config);
1407       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1408       return;
1409     }
1410     cfg = GNUNET_CONFIGURATION_create ();       /* Free here or in lcfcontext */
1411     if (GNUNET_OK !=
1412         GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
1413     {
1414       GNUNET_break (0);         /* Configuration parsing error */
1415       GNUNET_free (config);
1416       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1417       return;
1418     }
1419     GNUNET_free (config);
1420     if ((delegated_host_id < slave_list_size) &&
1421         (NULL != slave_list[delegated_host_id]))
1422     {
1423       GNUNET_break (0);         /* Configuration parsing error */
1424       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1425       return;
1426     }
1427     slave = GNUNET_malloc (sizeof (struct Slave));
1428     slave->host_id = delegated_host_id;
1429     slave_list_add (slave);
1430     if (1 != msg->is_subordinate)
1431     {
1432       slave->controller =
1433           GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1434                                              master_context->event_mask,
1435                                              &slave_event_callback, slave);
1436       GNUNET_CONFIGURATION_destroy (cfg);
1437       if (NULL != slave->controller)
1438         send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
1439       else
1440         send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1441                                  "Could not connect to delegated controller");
1442       GNUNET_SERVER_receive_done (client, GNUNET_OK);
1443       return;
1444     }
1445     lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
1446     lcc->operation_id = GNUNET_ntohll (msg->operation_id);
1447     GNUNET_SERVER_client_keep (client);
1448     lcc->client = client;
1449     lcc->slave = slave;
1450     slave->controller_proc =
1451         GNUNET_TESTBED_controller_start (master_context->master_ip,
1452                                          host_list[slave->host_id], cfg,
1453                                          &slave_status_callback, lcc);
1454     GNUNET_CONFIGURATION_destroy (cfg);
1455     new_route = GNUNET_malloc (sizeof (struct Route));
1456     new_route->dest = delegated_host_id;
1457     new_route->thru = master_context->host_id;
1458     route_list_add (new_route);
1459     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1460     return;
1461   }
1462
1463   /* Route the request */
1464   if (slave_host_id >= route_list_size)
1465   {
1466     LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1467     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1468     return;
1469   }
1470   lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1471   lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1472   lcfq->lcf->delegated_host_id = delegated_host_id;
1473   lcfq->lcf->slave_host_id = slave_host_id;
1474   route = find_dest_route (slave_host_id);
1475   GNUNET_assert (NULL != route);        /* because we add routes carefully */
1476   GNUNET_assert (route->dest < slave_list_size);
1477   GNUNET_assert (NULL != slave_list[route->dest]);
1478   lcfq->lcf->state = INIT;
1479   lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id);
1480   lcfq->lcf->gateway = slave_list[route->dest];
1481   lcfq->lcf->msg = GNUNET_malloc (msize);
1482   (void) memcpy (lcfq->lcf->msg, msg, msize);
1483   GNUNET_SERVER_client_keep (client);
1484   lcfq->lcf->client = client;
1485   if (NULL == lcfq_head)
1486   {
1487     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1488     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1489     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf);
1490   }
1491   else
1492     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1493   /* FIXME: Adding a new route should happen after the controllers are linked
1494    * successfully */
1495   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1496   new_route = GNUNET_malloc (sizeof (struct Route));
1497   new_route->dest = delegated_host_id;
1498   new_route->thru = route->dest;
1499   route_list_add (new_route);
1500 }
1501
1502
1503 /**
1504  * The task to be executed if the forwarded peer create operation has been
1505  * timed out
1506  *
1507  * @param cls the FowardedOperationContext
1508  * @param tc the TaskContext from the scheduler
1509  */
1510 static void
1511 peer_create_forward_timeout (void *cls,
1512                              const struct GNUNET_SCHEDULER_TaskContext *tc)
1513 {
1514   struct ForwardedOperationContext *fo_ctxt = cls;
1515
1516   /* send error msg to client */
1517   send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, "Timedout");
1518   GNUNET_SERVER_client_drop (fo_ctxt->client);
1519   GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc);
1520   GNUNET_free (fo_ctxt);
1521 }
1522
1523
1524 /**
1525  * Callback to be called when forwarded peer create operation is
1526  * successfull. We have to relay the reply msg back to the client
1527  *
1528  * @param cls ForwardedOperationContext
1529  * @param msg the peer create success message
1530  */
1531 static void
1532 peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
1533 {
1534   struct ForwardedOperationContext *fo_ctxt = cls;
1535   const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *success_msg;
1536   struct GNUNET_MessageHeader *dup_msg;
1537   struct Peer *peer;
1538   uint16_t msize;
1539
1540   GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task);
1541   if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS)
1542   {
1543     success_msg =
1544         (const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *) msg;
1545     peer = GNUNET_malloc (sizeof (struct Peer));
1546     peer->is_remote = GNUNET_YES;
1547     peer->id = ntohl (success_msg->peer_id);
1548     GNUNET_assert (NULL != fo_ctxt->cls);
1549     peer->details.remote.controller = fo_ctxt->cls;
1550     peer_list_add (peer);
1551   }
1552   msize = ntohs (msg->size);
1553   dup_msg = GNUNET_malloc (msize);
1554   (void) memcpy (dup_msg, msg, msize);
1555   queue_message (fo_ctxt->client, dup_msg);
1556   GNUNET_SERVER_client_drop (fo_ctxt->client);
1557   GNUNET_free (fo_ctxt);
1558 }
1559
1560
1561
1562 /**
1563  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
1564  *
1565  * @param cls NULL
1566  * @param client identification of the client
1567  * @param message the actual message
1568  */
1569 static void
1570 handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
1571                     const struct GNUNET_MessageHeader *message)
1572 {
1573   const struct GNUNET_TESTBED_PeerCreateMessage *msg;
1574   struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
1575   struct GNUNET_CONFIGURATION_Handle *cfg;
1576   struct ForwardedOperationContext *fo_ctxt;
1577   struct Route *route;
1578   struct Peer *peer;
1579   char *config;
1580   size_t dest_size;
1581   int ret;
1582   uint32_t config_size;
1583   uint32_t host_id;
1584   uint32_t peer_id;
1585   uint16_t msize;
1586
1587
1588   msize = ntohs (message->size);
1589   if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
1590   {
1591     GNUNET_break (0);           /* We need configuration */
1592     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1593     return;
1594   }
1595   msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
1596   host_id = ntohl (msg->host_id);
1597   peer_id = ntohl (msg->peer_id);
1598   if (UINT32_MAX == peer_id)
1599   {
1600     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1601                              "Cannot create peer with given ID");
1602     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1603     return;
1604   }
1605   if (host_id == master_context->host_id)
1606   {
1607     char *emsg;
1608
1609     /* We are responsible for this peer */
1610     msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1611     config_size = ntohl (msg->config_size);
1612     config = GNUNET_malloc (config_size);
1613     dest_size = config_size;
1614     if (Z_OK !=
1615         (ret =
1616          uncompress ((Bytef *) config, (uLongf *) & dest_size,
1617                      (const Bytef *) &msg[1], (uLong) msize)))
1618     {
1619       GNUNET_break (0);         /* uncompression error */
1620       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1621       return;
1622     }
1623     if (config_size != dest_size)
1624     {
1625       GNUNET_break (0);         /* Uncompressed config size mismatch */
1626       GNUNET_free (config);
1627       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1628       return;
1629     }
1630     cfg = GNUNET_CONFIGURATION_create ();
1631     if (GNUNET_OK !=
1632         GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
1633     {
1634       GNUNET_break (0);         /* Configuration parsing error */
1635       GNUNET_free (config);
1636       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1637       return;
1638     }
1639     GNUNET_free (config);
1640     peer = GNUNET_malloc (sizeof (struct Peer));
1641     peer->is_remote = GNUNET_NO;
1642     peer->details.local.cfg = cfg;
1643     peer->id = peer_id;
1644     LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
1645     peer->details.local.peer =
1646         GNUNET_TESTING_peer_configure (master_context->system,
1647                                        peer->details.local.cfg, peer->id,
1648                                        NULL /* Peer id */ ,
1649                                        &emsg);
1650     if (NULL == peer->details.local.peer)
1651     {
1652       LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
1653       GNUNET_free (emsg);
1654       GNUNET_free (peer);
1655       GNUNET_break (0);
1656       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1657       return;
1658     }
1659     peer->details.local.is_running = GNUNET_NO;
1660     peer_list_add (peer);
1661     reply =
1662         GNUNET_malloc (sizeof
1663                        (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1664     reply->header.size =
1665         htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1666     reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
1667     reply->peer_id = msg->peer_id;
1668     reply->operation_id = msg->operation_id;
1669     queue_message (client, &reply->header);
1670     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1671     return;
1672   }
1673
1674   /* Forward peer create request */
1675   route = find_dest_route (host_id);
1676   if (NULL == route)
1677   {
1678     GNUNET_break (0);
1679     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1680     return;
1681   }
1682   fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1683   GNUNET_SERVER_client_keep (client);
1684   fo_ctxt->client = client;
1685   fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
1686   fo_ctxt->cls = slave_list[route->dest]->controller;
1687   fo_ctxt->opc =
1688       GNUNET_TESTBED_forward_operation_msg_ (slave_list
1689                                              [route->dest]->controller,
1690                                              fo_ctxt->operation_id,
1691                                              &msg->header,
1692                                              peer_create_success_cb, fo_ctxt);
1693   fo_ctxt->timeout_task =
1694       GNUNET_SCHEDULER_add_delayed (TIMEOUT, &peer_create_forward_timeout,
1695                                     fo_ctxt);
1696
1697   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1698 }
1699
1700
1701 /**
1702  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1703  *
1704  * @param cls NULL
1705  * @param client identification of the client
1706  * @param message the actual message
1707  */
1708 static void
1709 handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
1710                      const struct GNUNET_MessageHeader *message)
1711 {
1712   const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
1713   struct ForwardedOperationContext *fopc;
1714   struct Peer *peer;
1715   uint32_t peer_id;
1716
1717   msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
1718   peer_id = ntohl (msg->peer_id);
1719   LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
1720              peer_id, GNUNET_ntohll (msg->operation_id));
1721   if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
1722   {
1723     LOG (GNUNET_ERROR_TYPE_ERROR,
1724          "Asked to destroy a non existent peer with id: %u\n", peer_id);
1725     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1726                              "Peer doesn't exist");
1727     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1728     return;
1729   }
1730   peer = peer_list[peer_id];
1731   if (GNUNET_YES == peer->is_remote)
1732   {
1733     /* Forward the destory message to sub controller */
1734     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1735     GNUNET_SERVER_client_keep (client);
1736     fopc->client = client;
1737     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
1738     fopc->opc =
1739         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
1740                                                fopc->operation_id, &msg->header,
1741                                                &forwarded_operation_reply_relay,
1742                                                fopc);
1743     fopc->timeout_task =
1744         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
1745                                       fopc);
1746     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1747     return;
1748   }
1749   GNUNET_TESTING_peer_destroy (peer->details.local.peer);
1750   GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
1751   peer_list_remove (peer);
1752   GNUNET_free (peer);
1753   send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
1754   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1755 }
1756
1757
1758 /**
1759  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1760  *
1761  * @param cls NULL
1762  * @param client identification of the client
1763  * @param message the actual message
1764  */
1765 static void
1766 handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
1767                    const struct GNUNET_MessageHeader *message)
1768 {
1769   const struct GNUNET_TESTBED_PeerStartMessage *msg;
1770   struct GNUNET_TESTBED_PeerEventMessage *reply;
1771   struct ForwardedOperationContext *fopc;
1772   struct Peer *peer;
1773   uint32_t peer_id;
1774
1775   msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
1776   peer_id = ntohl (msg->peer_id);
1777   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1778   {
1779     GNUNET_break (0);
1780     LOG (GNUNET_ERROR_TYPE_ERROR,
1781          "Asked to start a non existent peer with id: %u\n", peer_id);
1782     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1783     return;
1784   }
1785   peer = peer_list[peer_id];
1786   if (GNUNET_YES == peer->is_remote)
1787   {
1788     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1789     GNUNET_SERVER_client_keep (client);
1790     fopc->client = client;
1791     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
1792     fopc->opc =
1793         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
1794                                                fopc->operation_id, &msg->header,
1795                                                &forwarded_operation_reply_relay,
1796                                                fopc);
1797     fopc->timeout_task =
1798         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
1799                                       fopc);
1800     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1801     return;
1802   }
1803   if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer))
1804   {
1805     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1806                              "Failed to start");
1807     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1808     return;
1809   }
1810   peer->details.local.is_running = GNUNET_YES;
1811   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1812   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1813   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1814   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
1815   reply->host_id = htonl (master_context->host_id);
1816   reply->peer_id = msg->peer_id;
1817   reply->operation_id = msg->operation_id;
1818   queue_message (client, &reply->header);
1819   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1820 }
1821
1822
1823 /**
1824  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1825  *
1826  * @param cls NULL
1827  * @param client identification of the client
1828  * @param message the actual message
1829  */
1830 static void
1831 handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
1832                   const struct GNUNET_MessageHeader *message)
1833 {
1834   const struct GNUNET_TESTBED_PeerStopMessage *msg;
1835   struct GNUNET_TESTBED_PeerEventMessage *reply;
1836   struct ForwardedOperationContext *fopc;
1837   struct Peer *peer;
1838   uint32_t peer_id;
1839
1840   msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
1841   peer_id = ntohl (msg->peer_id);
1842   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1843   {
1844     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1845                              "Peer not found");
1846     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1847     return;
1848   }
1849   peer = peer_list[peer_id];
1850   if (GNUNET_YES == peer->is_remote)
1851   {
1852     fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1853     GNUNET_SERVER_client_keep (client);
1854     fopc->client = client;
1855     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
1856     fopc->opc =
1857         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.controller,
1858                                                fopc->operation_id, &msg->header,
1859                                                &forwarded_operation_reply_relay,
1860                                                fopc);
1861     fopc->timeout_task =
1862         GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_operation_timeout,
1863                                       fopc);
1864     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1865     return;
1866   }
1867   if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer->details.local.peer))
1868   {
1869     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1870                              "Peer not running");
1871     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1872     return;
1873   }
1874   peer->details.local.is_running = GNUNET_NO;
1875   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1876   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1877   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1878   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
1879   reply->host_id = htonl (master_context->host_id);
1880   reply->peer_id = msg->peer_id;
1881   reply->operation_id = msg->operation_id;
1882   queue_message (client, &reply->header);
1883   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1884 }
1885
1886
1887 /**
1888  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
1889  *
1890  * @param cls NULL
1891  * @param client identification of the client
1892  * @param message the actual message
1893  */
1894 static void
1895 handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
1896                         const struct GNUNET_MessageHeader *message)
1897 {
1898   const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
1899   struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
1900   struct Peer *peer;
1901   char *config;
1902   char *xconfig;
1903   size_t c_size;
1904   size_t xc_size;
1905   uint32_t peer_id;
1906   uint16_t msize;
1907
1908   msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
1909   peer_id = ntohl (msg->peer_id);
1910   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1911   {
1912     send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
1913                              "Peer not found");
1914     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1915     return;
1916   }
1917   peer = peer_list[peer_id];
1918   if (GNUNET_YES == peer->is_remote)
1919   {
1920     /* FIXME: forward to sub controller */
1921     GNUNET_break (0);
1922     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1923     return;
1924   }
1925   config =
1926       GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->details.local.cfg,
1927                                       &c_size);
1928   xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
1929   GNUNET_free (config);
1930   msize =
1931       xc_size +
1932       sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1933   reply = GNUNET_realloc (xconfig, msize);
1934   (void) memmove (&reply[1], reply, xc_size);
1935   reply->header.size = htons (msize);
1936   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
1937   reply->peer_id = msg->peer_id;
1938   reply->operation_id = msg->operation_id;
1939   GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->details.local.peer,
1940                                     &reply->peer_identity);
1941   reply->config_size = htons ((uint16_t) c_size);
1942   queue_message (client, &reply->header);
1943   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1944 }
1945
1946
1947 /**
1948  * Task for cleaing up overlay connect context structure
1949  *
1950  * @param cls the overlay connect context
1951  * @param tc the task context
1952  */
1953 static void
1954 occ_cleanup (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1955 {
1956   struct OverlayConnectContext *occ = cls;
1957
1958   LOG_DEBUG ("Cleaning up occ\n");
1959   GNUNET_free_non_null (occ->emsg);
1960   GNUNET_free_non_null (occ->hello);
1961   if (NULL != occ->opc)
1962     GNUNET_TESTBED_forward_operation_msg_cancel_ (occ->opc);
1963   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
1964     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
1965   if (NULL != occ->ch)
1966     GNUNET_CORE_disconnect (occ->ch);
1967   if (NULL != occ->ghh)
1968     GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
1969   if (NULL != occ->p1th)
1970     GNUNET_TRANSPORT_disconnect (occ->p1th);
1971   if (NULL != occ->p2th)
1972     GNUNET_TRANSPORT_disconnect (occ->p2th);
1973   GNUNET_free (occ);
1974 }
1975
1976
1977 /**
1978  * Task which will be run when overlay connect request has been timed out
1979  *
1980  * @param cls the OverlayConnectContext
1981  * @param tc the TaskContext
1982  */
1983 static void
1984 timeout_overlay_connect (void *cls,
1985                          const struct GNUNET_SCHEDULER_TaskContext *tc)
1986 {
1987   struct OverlayConnectContext *occ = cls;
1988
1989   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1990   send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
1991   GNUNET_SERVER_client_drop (occ->client);
1992   occ_cleanup (occ, tc);
1993 }
1994
1995
1996
1997 /**
1998  * Function called to notify transport users that another
1999  * peer connected to us.
2000  *
2001  * @param cls closure
2002  * @param new_peer the peer that connected
2003  * @param ats performance data
2004  * @param ats_count number of entries in ats (excluding 0-termination)
2005  */
2006 static void
2007 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
2008                         const struct GNUNET_ATS_Information *ats,
2009                         unsigned int ats_count)
2010 {
2011   struct OverlayConnectContext *occ = cls;
2012   struct GNUNET_TESTBED_ConnectionEventMessage *msg;
2013   char *new_peer_str;
2014   char *other_peer_str;
2015
2016   LOG_DEBUG ("Overlay connect notify\n");
2017   if (0 ==
2018       memcmp (new_peer, &occ->peer_identity,
2019               sizeof (struct GNUNET_PeerIdentity)))
2020     return;
2021   new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
2022   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2023   if (0 !=
2024       memcmp (new_peer, &occ->other_peer_identity,
2025               sizeof (struct GNUNET_PeerIdentity)))
2026   {
2027     LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n",
2028                new_peer_str, other_peer_str);
2029     GNUNET_free (new_peer_str);
2030     GNUNET_free (other_peer_str);
2031     return;
2032   }
2033   GNUNET_free (new_peer_str);
2034   LOG_DEBUG ("Peer %4s connected to peer %4s\n", other_peer_str, 
2035              GNUNET_i2s (&occ->peer_identity));
2036   GNUNET_free (other_peer_str);
2037   if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
2038   {
2039     GNUNET_SCHEDULER_cancel (occ->send_hello_task);
2040     occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2041   }
2042   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
2043   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2044   occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2045   GNUNET_free_non_null (occ->emsg);
2046   occ->emsg = NULL;
2047   if (NULL != occ->p2th)
2048     GNUNET_TRANSPORT_disconnect (occ->p2th);
2049   occ->p2th = NULL;
2050   LOG_DEBUG ("Peers connected - Sending overlay connect success\n");
2051   msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2052   msg->header.size =
2053       htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
2054   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT);
2055   msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
2056   msg->peer1 = htonl (occ->peer->id);
2057   msg->peer2 = htonl (occ->other_peer->id);
2058   msg->operation_id = GNUNET_htonll (occ->op_id);
2059   queue_message (occ->client, &msg->header);
2060   GNUNET_SERVER_client_drop (occ->client);
2061   GNUNET_SCHEDULER_add_now (&occ_cleanup, occ);
2062 }
2063
2064
2065 /**
2066  * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
2067  * peer 1.
2068  *
2069  * @param cls the OverlayConnectContext
2070  * @param tc the TaskContext from scheduler
2071  */
2072 static void
2073 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2074 {
2075   struct OverlayConnectContext *occ = cls;
2076   char *other_peer_str;
2077
2078   occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
2079   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
2080     return;
2081   GNUNET_assert (NULL != occ->hello);
2082   other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
2083   if (GNUNET_YES == occ->other_peer->is_remote)
2084   {
2085     struct GNUNET_TESTBED_RequestConnectMessage *msg;
2086     uint16_t msize;
2087     uint16_t hello_size;
2088
2089     LOG_DEBUG ("Offering HELLO of %s to %s via Remote Overlay Request\n", 
2090                GNUNET_i2s (&occ->peer_identity), other_peer_str);
2091     hello_size = ntohs (occ->hello->size);
2092     msize = sizeof (struct GNUNET_TESTBED_RequestConnectMessage) + hello_size;
2093     msg = GNUNET_malloc (msize);
2094     msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT);
2095     msg->header.size = htons (msize);
2096     msg->peer = htonl (occ->peer->id);
2097     msg->operation_id = GNUNET_htonll (occ->op_id);
2098     (void) memcpy (&msg->peer_identity, &occ->peer_identity,
2099                    sizeof (struct GNUNET_PeerIdentity));
2100     memcpy (msg->hello, occ->hello, hello_size);
2101     GNUNET_TESTBED_queue_message_ (occ->other_peer->details.remote.controller,
2102                                    &msg->header);
2103   }
2104   else
2105   {
2106     LOG_DEBUG ("Offering HELLO of %s to %s\n", 
2107                GNUNET_i2s (&occ->peer_identity), other_peer_str);
2108     GNUNET_TRANSPORT_offer_hello (occ->p2th, occ->hello, NULL, NULL);
2109     GNUNET_TRANSPORT_try_connect (occ->p2th, &occ->peer_identity);
2110   }
2111   GNUNET_free (other_peer_str);
2112   occ->send_hello_task =
2113       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &send_hello, occ);
2114 }
2115
2116 /**
2117  * Test for checking whether HELLO message is empty
2118  *
2119  * @param cls empty flag to set
2120  * @param address the HELLO
2121  * @param expiration expiration of the HELLO
2122  * @return
2123  */
2124 static int
2125 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
2126               struct GNUNET_TIME_Absolute expiration)
2127 {
2128   int *empty = cls;
2129
2130   *empty = GNUNET_NO;
2131   return GNUNET_OK;
2132 }
2133
2134
2135 /**
2136  * Function called whenever there is an update to the HELLO of peers in the
2137  * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
2138  * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
2139  *
2140  * @param cls closure
2141  * @param hello our updated HELLO
2142  */
2143 static void
2144 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
2145 {
2146   struct OverlayConnectContext *occ = cls;
2147   int empty;
2148   uint16_t msize;
2149
2150   msize = ntohs (hello->size);
2151   empty = GNUNET_YES;
2152   (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
2153                                          hello, GNUNET_NO, &test_address,
2154                                          &empty);
2155   if (GNUNET_YES == empty)
2156   {
2157     LOG_DEBUG ("HELLO of %s is empty\n", GNUNET_i2s (&occ->peer_identity));
2158     return;
2159   }
2160   LOG_DEBUG ("Received HELLO of %s\n", GNUNET_i2s (&occ->peer_identity));
2161   occ->hello = GNUNET_malloc (msize);
2162   memcpy (occ->hello, hello, msize);
2163   GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
2164   occ->ghh = NULL;
2165   GNUNET_TRANSPORT_disconnect (occ->p1th);
2166   occ->p1th = NULL;
2167   GNUNET_free_non_null (occ->emsg);
2168   if (GNUNET_NO == occ->other_peer->is_remote)
2169   {   
2170     occ->p2th =
2171         GNUNET_TRANSPORT_connect (occ->other_peer->details.local.cfg,
2172                                   &occ->other_peer_identity, NULL, NULL, NULL,
2173                                   NULL);
2174     if (NULL == occ->p2th)
2175     {
2176       GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of %s\n",
2177                        GNUNET_i2s (&occ->other_peer_identity));
2178       GNUNET_SCHEDULER_cancel (occ->timeout_task);
2179       occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2180       return;
2181     }
2182   }
2183   occ->emsg = GNUNET_strdup ("Timeout while offering HELLO to other peer");
2184   occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
2185 }
2186
2187
2188 /**
2189  * Function called after GNUNET_CORE_connect has succeeded (or failed
2190  * for good).  Note that the private key of the peer is intentionally
2191  * not exposed here; if you need it, your process should try to read
2192  * the private key file directly (which should work if you are
2193  * authorized...).
2194  *
2195  * @param cls closure
2196  * @param server handle to the server, NULL if we failed
2197  * @param my_identity ID of this peer, NULL if we failed
2198  */
2199 static void
2200 core_startup_cb (void *cls, struct GNUNET_CORE_Handle *server,
2201                  const struct GNUNET_PeerIdentity *my_identity)
2202 {
2203   struct OverlayConnectContext *occ = cls;
2204
2205   GNUNET_free_non_null (occ->emsg);
2206   occ->emsg = GNUNET_strdup ("Failed to connect to CORE\n");
2207   if ((NULL == server) || (NULL == my_identity))
2208     goto error_return;
2209   GNUNET_free (occ->emsg);
2210   occ->ch = server;
2211   occ->emsg = NULL;
2212   memcpy (&occ->peer_identity, my_identity,
2213           sizeof (struct GNUNET_PeerIdentity));
2214   occ->p1th =
2215       GNUNET_TRANSPORT_connect (occ->peer->details.local.cfg,
2216                                 &occ->peer_identity, NULL, NULL, NULL, NULL);
2217   if (NULL == occ->p1th)
2218   {
2219     GNUNET_asprintf (&occ->emsg, "Cannot connect to TRANSPORT of peers %4s",
2220                     GNUNET_i2s (&occ->peer_identity));
2221     goto error_return;
2222   }
2223   LOG_DEBUG ("Acquiring HELLO of peer %s\n", GNUNET_i2s (&occ->peer_identity));
2224   occ->emsg = GNUNET_strdup ("Timeout while acquiring HELLO message");
2225   occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th, &hello_update_cb, occ);
2226   return;
2227   
2228  error_return:
2229   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2230   occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2231   return;
2232 }
2233
2234
2235 /**
2236  * Callback to be called when forwarded get peer config operation as part of
2237  * overlay connect is successfull. Connection to Peer 1's core is made and is
2238  * checked for new connection from peer 2
2239  *
2240  * @param cls ForwardedOperationContext
2241  * @param msg the peer create success message
2242  */
2243 static void
2244 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
2245 {
2246   struct OverlayConnectContext *occ = cls;
2247   const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
2248   const struct GNUNET_CORE_MessageHandler no_handlers[] = {
2249     {NULL, 0, 0}
2250   };
2251
2252   occ->opc = NULL;
2253   if (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG != ntohs (msg->type))
2254     goto error_return;
2255   cmsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *)
2256       msg;
2257   memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
2258           sizeof (struct GNUNET_PeerIdentity));
2259   GNUNET_free_non_null (occ->emsg);
2260   occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
2261   occ->ch =
2262       GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
2263                            &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
2264                            GNUNET_NO, no_handlers);
2265   if (NULL == occ->ch)
2266     goto error_return;
2267   return;
2268
2269  error_return:
2270   GNUNET_SCHEDULER_cancel (occ->timeout_task);
2271   occ->timeout_task = 
2272       GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2273 }
2274
2275
2276 /**
2277  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
2278  *
2279  * @param cls NULL
2280  * @param client identification of the client
2281  * @param message the actual message
2282  */
2283 static void
2284 handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
2285                         const struct GNUNET_MessageHeader *message)
2286 {
2287   const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
2288   struct OverlayConnectContext *occ;
2289   const struct GNUNET_CORE_MessageHandler no_handlers[] = {
2290     {NULL, 0, 0}
2291   };
2292   uint32_t p1;
2293   uint32_t p2;
2294
2295   msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
2296   p1 = ntohl (msg->peer1);
2297   p2 = ntohl (msg->peer2);
2298   GNUNET_assert (p1 < peer_list_size);
2299   GNUNET_assert (NULL != peer_list[p1]);
2300   GNUNET_assert (p2 < peer_list_size);
2301   GNUNET_assert (NULL != peer_list[p2]);
2302   /* FIXME: Add cases where we have to forward overlay connect message to sub
2303    * controllers */
2304   GNUNET_assert (GNUNET_NO == peer_list[p1]->is_remote);
2305   occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
2306   GNUNET_SERVER_client_keep (client);
2307   occ->client = client;
2308   occ->peer = peer_list[p1];
2309   occ->other_peer = peer_list[p2];
2310   occ->op_id = GNUNET_ntohll (msg->operation_id);
2311   /* Get the identity of the second peer */
2312   if (GNUNET_YES == occ->other_peer->is_remote)
2313   {
2314     struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
2315
2316     cmsg.header.size = 
2317         htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
2318     cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG);
2319     cmsg.peer_id = msg->peer2;
2320     cmsg.operation_id = msg->operation_id;
2321     occ->opc = 
2322         GNUNET_TESTBED_forward_operation_msg_ (occ->other_peer->details.remote.controller,
2323                                                occ->op_id, &cmsg.header,
2324                                                &overlay_connect_get_config,
2325                                                occ);
2326     occ->emsg = 
2327         GNUNET_strdup ("Timeout while getting peer identity of peer B\n");
2328     occ->timeout_task =
2329         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
2330                                       (GNUNET_TIME_UNIT_SECONDS, 30),
2331                                       &timeout_overlay_connect, occ);
2332     return;
2333   }
2334   GNUNET_TESTING_peer_get_identity (occ->other_peer->details.local.peer,
2335                                     &occ->other_peer_identity);
2336   /* Connect to the core of 1st peer and wait for the 2nd peer to connect */
2337   occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
2338   occ->ch =
2339       GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
2340                            &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
2341                            GNUNET_NO, no_handlers);
2342   if (NULL == occ->ch)
2343     occ->timeout_task = 
2344         GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
2345   else
2346     occ->timeout_task =
2347         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
2348                                       (GNUNET_TIME_UNIT_SECONDS, 30),
2349                                       &timeout_overlay_connect, occ);
2350   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2351 }
2352
2353
2354 /**
2355  * Iterator over hash map entries.
2356  *
2357  * @param cls closure
2358  * @param key current key code
2359  * @param value value in the hash map
2360  * @return GNUNET_YES if we should continue to
2361  *         iterate,
2362  *         GNUNET_NO if not.
2363  */
2364 static int
2365 ss_map_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
2366 {
2367   struct SharedService *ss = value;
2368
2369   GNUNET_assert (GNUNET_YES ==
2370                  GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
2371   GNUNET_free (ss->name);
2372   GNUNET_free (ss);
2373   return GNUNET_YES;
2374 }
2375
2376
2377 /**
2378  * Task to clean up and shutdown nicely
2379  *
2380  * @param cls NULL
2381  * @param tc the TaskContext from scheduler
2382  */
2383 static void
2384 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2385 {
2386   struct LCFContextQueue *lcfq;
2387   uint32_t id;
2388
2389   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
2390   LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
2391   (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
2392                                                 NULL);
2393   GNUNET_CONTAINER_multihashmap_destroy (ss_map);
2394   if (NULL != lcfq_head)
2395   {
2396     if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
2397     {
2398       GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
2399       lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
2400     }
2401     if (NULL != lcfq_head->lcf->rhandle)
2402       GNUNET_TESTBED_cancel_registration (lcfq_head->lcf->rhandle);
2403   }
2404   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
2405   for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
2406   {
2407     GNUNET_free (lcfq->lcf->msg);
2408     GNUNET_free (lcfq->lcf);
2409     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
2410     GNUNET_free (lcfq);
2411   }
2412   /* Clear peer list */
2413   for (id = 0; id < peer_list_size; id++)
2414     if (NULL != peer_list[id])
2415     {
2416       if (GNUNET_NO == peer_list[id]->is_remote)
2417       {
2418         if (GNUNET_YES == peer_list[id]->details.local.is_running)
2419           GNUNET_TESTING_peer_stop (peer_list[id]->details.local.peer);
2420         GNUNET_TESTING_peer_destroy (peer_list[id]->details.local.peer);
2421         GNUNET_CONFIGURATION_destroy (peer_list[id]->details.local.cfg);
2422       }
2423       GNUNET_free (peer_list[id]);
2424     }
2425   GNUNET_free_non_null (peer_list);
2426   /* Clear host list */
2427   for (id = 0; id < host_list_size; id++)
2428     if (NULL != host_list[id])
2429       GNUNET_TESTBED_host_destroy (host_list[id]);
2430   GNUNET_free_non_null (host_list);
2431   /* Clear route list */
2432   for (id = 0; id < route_list_size; id++)
2433     if (NULL != route_list[id])
2434       GNUNET_free (route_list[id]);
2435   GNUNET_free_non_null (route_list);
2436   /* Clear slave_list */
2437   for (id = 0; id < slave_list_size; id++)
2438     if (NULL != slave_list[id])
2439     {
2440       if (NULL != slave_list[id]->controller)
2441         GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
2442       if (NULL != slave_list[id]->controller_proc)
2443         GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
2444     }
2445   if (NULL != master_context)
2446   {
2447     GNUNET_free_non_null (master_context->master_ip);
2448     if (NULL != master_context->system)
2449       GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
2450     GNUNET_free (master_context);
2451     master_context = NULL;
2452   }
2453 }
2454
2455
2456 /**
2457  * Callback for client disconnect
2458  *
2459  * @param cls NULL
2460  * @param client the client which has disconnected
2461  */
2462 static void
2463 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
2464 {
2465   if (NULL == master_context)
2466     return;
2467   if (client == master_context->client)
2468   {
2469     LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
2470     GNUNET_SERVER_client_drop (client);
2471     /* should not be needed as we're terminated by failure to read
2472      * from stdin, but if stdin fails for some reason, this shouldn't
2473      * hurt for now --- might need to revise this later if we ever
2474      * decide that master connections might be temporarily down
2475      * for some reason */
2476     //GNUNET_SCHEDULER_shutdown ();
2477   }
2478 }
2479
2480
2481 /**
2482  * Testbed setup
2483  *
2484  * @param cls closure
2485  * @param server the initialized server
2486  * @param cfg configuration to use
2487  */
2488 static void
2489 testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
2490              const struct GNUNET_CONFIGURATION_Handle *cfg)
2491 {
2492   static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
2493     {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
2494     {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
2495     {&handle_configure_shared_service, NULL,
2496      GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
2497     {&handle_link_controllers, NULL,
2498      GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
2499     {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
2500     {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
2501      sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
2502     {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
2503      sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
2504     {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
2505      sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
2506     {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
2507      sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
2508     {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
2509      sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
2510     {NULL}
2511   };
2512
2513   GNUNET_SERVER_add_handlers (server, message_handlers);
2514   GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
2515   ss_map = GNUNET_CONTAINER_multihashmap_create (5);
2516   shutdown_task_id =
2517       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
2518                                     &shutdown_task, NULL);
2519   LOG_DEBUG ("Testbed startup complete\n");
2520 }
2521
2522
2523 /**
2524  * The starting point of execution
2525  */
2526 int
2527 main (int argc, char *const *argv)
2528 {
2529   //sleep (15);                 /* Debugging */
2530   return (GNUNET_OK ==
2531           GNUNET_SERVICE_run (argc, argv, "testbed", GNUNET_SERVICE_OPTION_NONE,
2532                               &testbed_run, NULL)) ? 0 : 1;
2533 }
2534
2535 /* end of gnunet-service-testbed.c */