refined overlay connect and extended test case
[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 <zlib.h>
32
33 #include "gnunet_testbed_service.h"
34 #include "testbed.h"
35 #include "testbed_api.h"
36 #include "testbed_api_hosts.h"
37 #include "gnunet_testing_lib-new.h"
38
39 /**
40  * Generic logging
41  */
42 #define LOG(kind,...)                           \
43   GNUNET_log (kind, __VA_ARGS__)
44
45 /**
46  * Debug logging
47  */
48 #define LOG_DEBUG(...)                          \
49   LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
50
51
52 #define LIST_GROW_STEP 10
53
54 struct Context
55 {
56   /**
57    * The client handle associated with this context
58    */
59   struct GNUNET_SERVER_Client *client;
60
61   /**
62    * The network address of the master controller
63    */
64   char *master_ip;
65
66   /**
67    * The TESTING system handle for starting peers locally
68    */
69   struct GNUNET_TESTING_System *system;
70   
71   /**
72    * Event mask of event to be responded in this context
73    */
74   uint64_t event_mask;
75
76   /**
77    * Our host id according to this context
78    */
79   uint32_t host_id;
80 };
81
82
83 /**
84  * The message queue for sending messages to clients
85  */
86 struct MessageQueue
87 {
88   /**
89    * The message to be sent
90    */
91   struct GNUNET_MessageHeader *msg;
92
93   /**
94    * The client to send the message to
95    */
96   struct GNUNET_SERVER_Client *client;
97   
98   /**
99    * next pointer for DLL
100    */
101   struct MessageQueue *next;
102   
103   /**
104    * prev pointer for DLL
105    */
106   struct MessageQueue *prev;
107 };
108
109
110 /**
111  * The structure for identifying a shared service
112  */
113 struct SharedService
114 {
115   /**
116    * The name of the shared service
117    */
118   char *name;
119
120   /**
121    * Number of shared peers per instance of the shared service
122    */
123   uint32_t num_shared;
124
125   /**
126    * Number of peers currently sharing the service
127    */
128   uint32_t num_sharing;
129 };
130
131
132 /**
133  * A routing entry
134  */
135 struct Route
136 {
137   /**
138    * destination host
139    */
140   uint32_t dest;
141
142   /**
143    * The host destination is reachable thru
144    */
145   uint32_t thru;
146 };
147
148
149 /**
150  * Structure representing a connected(directly-linked) controller
151  */
152 struct Slave
153 {
154   /**
155    * The controller process handle if we had started the controller
156    */
157   struct GNUNET_TESTBED_ControllerProc *controller_proc;
158
159   /**
160    * The controller handle
161    */
162   struct GNUNET_TESTBED_Controller *controller;
163
164   /**
165    * The id of the host this controller is running on
166    */
167   uint32_t host_id;
168 };
169
170
171 /**
172  * States of LCFContext
173  */
174 enum LCFContextState
175   {
176     /**
177      * The Context has been initialized; Nothing has been done on it
178      */
179     INIT,
180
181     /**
182      * Delegated host has been registered at the forwarding controller
183      */
184     DELEGATED_HOST_REGISTERED,
185     
186     /**
187      * The slave host has been registred at the forwarding controller
188      */
189     SLAVE_HOST_REGISTERED,
190
191     /**
192      * The context has been finished (may have error)
193      */
194     FINISHED
195
196   };
197
198
199 /**
200  * Link controllers request forwarding context
201  */
202 struct LCFContext
203 {
204   /**
205    * The serialized and compressed configuration
206    */
207   char *sxcfg;
208
209   /**
210    * The gateway which will pass the link message to delegated host
211    */
212   struct Slave *gateway;
213
214   /**
215    * The host registration handle while registered hosts in this context
216    */
217   struct GNUNET_TESTBED_HostRegistrationHandle *rhandle;
218
219   /**
220    * The size of the compressed serialized configuration
221    */
222   size_t sxcfg_size;
223
224   /**
225    * The size of the uncompressed configuration
226    */
227   size_t scfg_size;
228
229   /**
230    * Should the delegated host be started by the slave host?
231    */
232   int is_subordinate;
233
234   /**
235    * The state of this context
236    */
237   enum LCFContextState state;
238
239   /**
240    * The delegated host
241    */
242   uint32_t delegated_host_id;
243
244   /**
245    * The slave host
246    */
247   uint32_t slave_host_id;
248
249 };
250
251
252 /**
253  * Structure of a queue entry in LCFContext request queue
254  */
255 struct LCFContextQueue
256 {
257   /**
258    * The LCFContext
259    */
260   struct LCFContext *lcf;
261
262   /**
263    * Head prt for DLL
264    */
265   struct LCFContextQueue *next;
266
267   /**
268    * Tail ptr for DLL
269    */
270   struct LCFContextQueue *prev;
271 };
272
273
274 /**
275  * A locally started peer
276  */
277 struct Peer
278 {
279   /**
280    * The peer handle from testing API
281    */
282   struct GNUNET_TESTING_Peer *peer;
283
284   /**
285    * The modified (by GNUNET_TESTING_peer_configure) configuration this peer is
286    * configured with
287    */
288   struct GNUNET_CONFIGURATION_Handle *cfg;
289
290   /**
291    * Our local reference id for this peer
292    */
293   uint32_t id;
294
295 };
296
297
298 /**
299  * State information for overlay connect context
300  */
301 enum OCCState
302   {
303     /**
304      * Initial state
305      */
306     OCC_STATE_INIT,
307
308     /**
309      * Peer 1 has connected to peer0
310      */
311     OCC_STATE_PEER0_SUCCESS,
312
313     /**
314      * Peer 2 has connected to peer1
315      */
316     OCC_STATE_PEER1_SUCCESS,
317
318   };
319
320
321 /**
322  * Context information for connecting 2 peers in overlay
323  */
324 struct OverlayConnectContext
325 {
326   /**
327    * The client which has requested for overlay connection
328    */
329   struct GNUNET_SERVER_Client *client;
330
331   /**
332    * peer 1 and peer2
333    */
334   struct Peer * peers[2];
335   
336   /**
337    * Transport handle of peers
338    */
339   struct GNUNET_TRANSPORT_Handle *peers_transport[2];
340   
341   /**
342    * HELLO of peers
343    */
344   struct GNUNET_MessageHeader *peers_hello[2];
345   
346   /**
347    * Get hello handle for peers
348    */
349   struct GNUNET_TRANSPORT_GetHelloHandle *peers_ghh[2];
350   
351   /**
352    * The peer identity of peers
353    */
354   struct GNUNET_PeerIdentity peers_identity[2];
355
356   /**
357    * The id of the operation responsible for creating this context
358    */
359   uint64_t op_id;
360
361   /**
362    * State information for determining whose HELLOs have been successfully
363    * exchanged
364    */
365   enum OCCState state;
366
367 };
368
369
370 /**
371  * Wrapper around OverlayConnectContext
372  */
373 struct OverlayConnectContextWrapper
374 {
375   /**
376    * The overlay connect context
377    */
378   struct OverlayConnectContext *occ;
379   
380   /**
381    * The peer number in reference; should be 0 or 1
382    */
383   unsigned int peer;
384 };
385
386
387 /**
388  * The master context; generated with the first INIT message
389  */
390 static struct Context *master_context;
391
392 /***********/
393 /* Handles */
394 /***********/
395
396 /**
397  * Current Transmit Handle; NULL if no notify transmit exists currently
398  */
399 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
400
401 /****************/
402 /* Lists & Maps */
403 /****************/
404
405 /**
406  * The head for the LCF queue
407  */
408 static struct LCFContextQueue *lcfq_head;
409
410 /**
411  * The tail for the LCF queue
412  */
413 static struct LCFContextQueue *lcfq_tail;
414
415 /**
416  * The message queue head
417  */
418 static struct MessageQueue *mq_head;
419
420 /**
421  * The message queue tail
422  */
423 static struct MessageQueue *mq_tail;
424
425 /**
426  * Array of host list
427  */
428 static struct GNUNET_TESTBED_Host **host_list;
429
430 /**
431  * A list of routes
432  */
433 static struct Route **route_list;
434
435 /**
436  * A list of directly linked neighbours
437  */
438 static struct Slave **slave_list;
439
440 /**
441  * A list of peers we own locally
442  */
443 static struct Peer **peer_list;
444
445 /**
446  * The hashmap of shared services
447  */
448 static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
449
450 /**
451  * The size of the host list
452  */
453 static uint32_t host_list_size;
454
455 /**
456  * The size of the route list
457  */
458 static uint32_t route_list_size;
459
460 /**
461  * The size of directly linked neighbours list
462  */
463 static uint32_t slave_list_size;
464
465 /**
466  * The size of the peer list
467  */
468 static uint32_t peer_list_size;
469
470 /*********/
471 /* Tasks */
472 /*********/
473
474 /**
475  * The lcf_task handle
476  */
477 static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
478
479 /**
480  * The shutdown task handle
481  */
482 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
483
484
485 /**
486  * Function called to notify a client about the connection begin ready to queue
487  * more data.  "buf" will be NULL and "size" zero if the connection was closed
488  * for writing in the meantime.
489  *
490  * @param cls NULL
491  * @param size number of bytes available in buf
492  * @param buf where the callee should write the message
493  * @return number of bytes written to buf
494  */
495 static size_t
496 transmit_ready_notify (void *cls, size_t size, void *buf)
497 {
498   struct MessageQueue *mq_entry;
499
500   transmit_handle = NULL;
501   mq_entry = mq_head;
502   GNUNET_assert (NULL != mq_entry);
503   if (0 == size)
504     return 0;
505   GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
506   size = ntohs (mq_entry->msg->size);
507   memcpy (buf, mq_entry->msg, size);
508   GNUNET_free (mq_entry->msg);
509   GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
510   GNUNET_free (mq_entry);
511   mq_entry = mq_head;
512   if (NULL != mq_entry)
513     transmit_handle = 
514       GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
515                                            ntohs (mq_entry->msg->size),
516                                            GNUNET_TIME_UNIT_FOREVER_REL,
517                                            &transmit_ready_notify, NULL);
518   return size;
519 }
520
521
522 /**
523  * Queues a message in send queue for sending to the service
524  *
525  * @param client the client to whom the queued message has to be sent
526  * @param msg the message to queue
527  */
528 static void
529 queue_message (struct GNUNET_SERVER_Client *client,
530                struct GNUNET_MessageHeader *msg)
531 {
532   struct MessageQueue *mq_entry;
533   uint16_t type;
534   uint16_t size;
535
536   type = ntohs (msg->type);
537   size = ntohs (msg->size);
538   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
539                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));                 
540   mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
541   mq_entry->msg = msg;
542   mq_entry->client = client;
543   LOG_DEBUG ( "Queueing message of type %u, size %u for sending\n", type,
544               ntohs (msg->size));
545   GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
546   if (NULL == transmit_handle)
547     transmit_handle = 
548       GNUNET_SERVER_notify_transmit_ready (client, size,
549                                            GNUNET_TIME_UNIT_FOREVER_REL,
550                                            &transmit_ready_notify, NULL);
551 }
552
553
554 /**
555  * Similar to GNUNET_realloc; however clears tail part of newly allocated memory
556  *
557  * @param ptr the memory block to realloc
558  * @param size the size of ptr
559  * @param new_size the size to which ptr has to be realloc'ed
560  * @return the newly reallocated memory block
561  */
562 static void *
563 TESTBED_realloc (void *ptr, size_t size, size_t new_size)
564 {
565   ptr = GNUNET_realloc (ptr, new_size);
566   if (new_size > size)
567     ptr = memset (ptr + size, 0, new_size - size);
568   return ptr;
569 }
570
571
572 /**
573  * Function to add a host to the current list of known hosts
574  *
575  * @param host the host to add 
576  * @return GNUNET_OK on success; GNUNET_SYSERR on failure due to host-id
577  *           already in use
578  */
579 static int
580 host_list_add (struct GNUNET_TESTBED_Host *host)
581 {
582   uint32_t host_id;
583
584   host_id = GNUNET_TESTBED_host_get_id_ (host);
585   if (host_list_size <= host_id)
586   {
587     host_list = 
588       TESTBED_realloc (host_list, 
589                        sizeof (struct GNUNET_TESTBED_Host *) * host_list_size,
590                        sizeof (struct GNUNET_TESTBED_Host *) *
591                        (host_list_size + LIST_GROW_STEP));
592     host_list_size += LIST_GROW_STEP;
593   }
594   if (NULL != host_list[host_id])
595   {
596     LOG_DEBUG ("A host with id: %u already exists\n", host_id);
597     return GNUNET_SYSERR;
598   }
599   host_list[host_id] = host;
600   return GNUNET_OK;
601 }
602
603
604 /**
605  * Adds a route to the route list
606  *
607  * @param route the route to add
608  */
609 static void
610 route_list_add (struct Route *route)
611 {
612   if (route->dest >= route_list_size)
613   {
614     route_list = 
615       TESTBED_realloc (route_list, 
616                        sizeof (struct Route *) * route_list_size,
617                        sizeof (struct Route *) * 
618                        (route_list_size + LIST_GROW_STEP));
619     route_list_size += LIST_GROW_STEP;
620   }
621   GNUNET_assert (NULL == route_list[route->dest]);
622   route_list[route->dest] = route;
623 }
624
625
626 /**
627  * Adds a slave to the slave array
628  *
629  * @param slave the slave controller to add
630  */
631 static void
632 slave_list_add (struct Slave *slave)
633 {
634   if (slave->host_id  >= slave_list_size)
635   {
636     slave_list = TESTBED_realloc (slave_list, 
637                                   sizeof (struct Slave *) *slave_list_size,
638                                   sizeof (struct Slave *) *
639                                   (slave_list_size + LIST_GROW_STEP));
640     slave_list_size += LIST_GROW_STEP;
641   }
642   GNUNET_assert (NULL == slave_list[slave->host_id]);
643   slave_list[slave->host_id] = slave;
644 }
645
646
647 /**
648  * Adds a peer to the peer array
649  *
650  * @param peer the peer to add
651  */
652 static void
653 peer_list_add (struct Peer *peer)
654 {
655   if (peer->id  >= peer_list_size)
656   {
657     peer_list = TESTBED_realloc (peer_list, 
658                                  sizeof (struct Peer *) * peer_list_size,
659                                  sizeof (struct Peer *) *
660                                  (peer_list_size + LIST_GROW_STEP));
661     peer_list_size += LIST_GROW_STEP;
662   }
663   GNUNET_assert (NULL == peer_list[peer->id]);
664   peer_list[peer->id] = peer;
665 }
666
667
668 /**
669  * Routes message to a host given its host_id
670  *
671  * @param host_id the id of the destination host
672  * @param msg the message to be routed
673  */
674 static void
675 route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
676 {
677   GNUNET_break (0);
678 }
679
680
681 /**
682  * The  Link Controller forwarding task
683  *
684  * @param cls the LCFContext
685  * @param tc the Task context from scheduler
686  */
687 static void
688 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
689
690
691 /**
692  * Completion callback for host registrations while forwarding Link Controller messages
693  *
694  * @param cls the LCFContext
695  * @param emsg the error message; NULL if host registration is successful
696  */
697 static void
698 lcf_proc_cc (void *cls, const char *emsg)
699 {
700   struct LCFContext *lcf = cls;
701
702   lcf->rhandle = NULL;
703   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
704   switch (lcf->state)
705   {
706   case INIT:
707     if (NULL != emsg)
708       goto registration_error;
709     lcf->state = DELEGATED_HOST_REGISTERED;
710     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
711     break;
712   case DELEGATED_HOST_REGISTERED:
713      if (NULL != emsg)
714       goto registration_error;
715      lcf->state = SLAVE_HOST_REGISTERED;
716      lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
717      break;
718   default:
719     GNUNET_assert (0);          /* Shouldn't reach here */
720   }  
721   return;
722
723  registration_error:
724   LOG (GNUNET_ERROR_TYPE_WARNING, 
725        "Host registration failed with message: %s\n", emsg);
726   lcf->state = FINISHED;
727   lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
728 }
729
730
731 /**
732  * The  Link Controller forwarding task
733  *
734  * @param cls the LCFContext
735  * @param tc the Task context from scheduler
736  */
737 static void
738 lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
739 {
740   struct LCFContext *lcf = cls;
741   struct LCFContextQueue *lcfq;
742
743   lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
744   switch (lcf->state)
745   {
746   case INIT:
747     if (GNUNET_NO ==
748         GNUNET_TESTBED_is_host_registered_ (host_list[lcf->delegated_host_id],
749                                             lcf->gateway->controller))
750     {
751       lcf->rhandle =
752         GNUNET_TESTBED_register_host (lcf->gateway->controller,
753                                       host_list[lcf->delegated_host_id],
754                                       lcf_proc_cc, lcf);
755     }
756     else
757     {
758       lcf->state = DELEGATED_HOST_REGISTERED;
759       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
760     }
761     break;
762   case DELEGATED_HOST_REGISTERED:
763     if (GNUNET_NO ==
764         GNUNET_TESTBED_is_host_registered_ (host_list[lcf->slave_host_id],
765                                             lcf->gateway->controller))
766     {
767       lcf->rhandle =
768         GNUNET_TESTBED_register_host (lcf->gateway->controller,
769                                       host_list[lcf->slave_host_id],
770                                       lcf_proc_cc, lcf);
771     }
772     else
773     {
774       lcf->state = SLAVE_HOST_REGISTERED;
775       lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
776     }
777     break;
778   case SLAVE_HOST_REGISTERED:
779     GNUNET_TESTBED_controller_link_2 (lcf->gateway->controller,
780                                       host_list[lcf->delegated_host_id],
781                                       host_list[lcf->slave_host_id],
782                                       lcf->sxcfg, lcf->sxcfg_size,
783                                       lcf->scfg_size,
784                                       lcf->is_subordinate);
785     lcf->state = FINISHED;
786     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
787     break;
788   case FINISHED:
789     lcfq = lcfq_head;
790     GNUNET_assert (lcfq->lcf == lcf);
791     GNUNET_free (lcf->sxcfg);
792     GNUNET_free (lcf);
793     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
794     GNUNET_free (lcfq);
795     if (NULL != lcfq_head)
796       lcf_proc_task_id = 
797         GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
798   }
799 }
800
801
802 /**
803  * Callback for event from slave controllers
804  *
805  * @param cls struct Slave *
806  * @param event information about the event
807  */
808 static void 
809 slave_event_callback(void *cls,
810                      const struct GNUNET_TESTBED_EventInformation *event)
811 {
812   GNUNET_break (0);
813 }
814
815
816 /**
817  * Callback to signal successfull startup of the controller process
818  *
819  * @param cls the closure from GNUNET_TESTBED_controller_start()
820  * @param cfg the configuration with which the controller has been started;
821  *          NULL if status is not GNUNET_OK
822  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
823  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
824  */
825 static void 
826 slave_status_callback (void *cls, 
827                        const struct GNUNET_CONFIGURATION_Handle *cfg,
828                        int status)
829 {
830   struct Slave *slave = cls;
831
832   if (GNUNET_SYSERR == status)
833   {
834     slave->controller_proc = NULL;
835     LOG (GNUNET_ERROR_TYPE_WARNING,
836          "Unexpected slave shutdown\n");
837     GNUNET_SCHEDULER_shutdown ();       /* We too shutdown */
838     return;
839   }
840   slave->controller =
841     GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
842                                        master_context->event_mask,
843                                        &slave_event_callback, slave);
844 }
845
846
847 /**
848  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_INIT messages
849  *
850  * @param cls NULL
851  * @param client identification of the client
852  * @param message the actual message
853  */
854 static void 
855 handle_init (void *cls,
856              struct GNUNET_SERVER_Client *client,
857              const struct GNUNET_MessageHeader *message)
858 {
859   const struct GNUNET_TESTBED_InitMessage *msg;
860   struct GNUNET_TESTBED_Host *host;
861   void *addr;
862   size_t addrlen;
863
864   if (NULL != master_context)
865   {
866     GNUNET_break (0);
867     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
868     return;
869   }
870   msg = (const struct GNUNET_TESTBED_InitMessage *) message;  
871   master_context = GNUNET_malloc (sizeof (struct Context));
872   master_context->client = client;
873   master_context->host_id = ntohl (msg->host_id);
874   GNUNET_assert (GNUNET_OK == 
875                  GNUNET_SERVER_client_get_address (client, &addr, &addrlen));
876   master_context->master_ip = GNUNET_malloc (NI_MAXHOST);
877   if (0 != getnameinfo (addr, addrlen, master_context->master_ip, NI_MAXHOST,
878                         NULL, 0, NI_NUMERICHOST))
879   {
880     LOG (GNUNET_ERROR_TYPE_WARNING,
881          "Cannot determine the ip of master controller: %s\n", STRERROR (errno));
882     GNUNET_free (addr);
883     GNUNET_free (master_context->master_ip);
884     GNUNET_assert (0);
885   }
886   GNUNET_free (addr);
887   if (0 == strcasecmp (master_context->master_ip, "localhost"))
888   {                             /* Hack for connections via unix sockets */
889     LOG_DEBUG ("May be using local sockets - assuming loopback for master ip\n");
890     GNUNET_free (master_context->master_ip);
891     master_context->master_ip = strdup ("127.0.0.1");
892   }
893   LOG_DEBUG ("Master Controller IP: %s\n", master_context->master_ip);
894   master_context->system = 
895     GNUNET_TESTING_system_create ("testbed", master_context->master_ip);
896   host = GNUNET_TESTBED_host_create_with_id (master_context->host_id,
897                                              NULL, NULL, 0);
898   host_list_add (host);
899   master_context->event_mask = GNUNET_ntohll (msg->event_mask);
900   GNUNET_SERVER_client_keep (client);
901   LOG_DEBUG ("Created master context with host ID: %u\n",
902              master_context->host_id);
903   GNUNET_SERVER_receive_done (client, GNUNET_OK);
904 }
905
906
907 /**
908  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
909  *
910  * @param cls NULL
911  * @param client identification of the client
912  * @param message the actual message
913  */
914 static void 
915 handle_add_host (void *cls,
916                  struct GNUNET_SERVER_Client *client,
917                  const struct GNUNET_MessageHeader *message)
918 {
919   struct GNUNET_TESTBED_Host *host;
920   const struct GNUNET_TESTBED_AddHostMessage *msg;
921   struct GNUNET_TESTBED_HostConfirmedMessage *reply;
922   char *username;
923   char *hostname;
924   char *emsg;
925   uint32_t host_id;
926   uint16_t username_length;
927   uint16_t hostname_length;
928   uint16_t reply_size;
929   uint16_t msize;
930   
931   msg = (const struct GNUNET_TESTBED_AddHostMessage *) message;
932   msize = ntohs (msg->header.size);
933   username = (char *) &(msg[1]);
934   username_length = ntohs (msg->user_name_length);
935   GNUNET_assert (msize > (sizeof (struct GNUNET_TESTBED_AddHostMessage)
936                           + username_length + 1)); /* msg must contain hostname */
937   if (0 != username_length)
938     GNUNET_assert ('\0' == username[username_length]);
939   username_length = (0 == username_length) ? 0 : username_length + 1;              
940   hostname = username + username_length;
941   hostname_length = msize - (sizeof (struct GNUNET_TESTBED_AddHostMessage)
942                              + username_length);
943   GNUNET_assert ('\0' == hostname[hostname_length - 1]);
944   GNUNET_assert (strlen (hostname) == hostname_length - 1);
945   host_id = ntohl (msg->host_id);
946   LOG_DEBUG ("Received ADDHOST message\n");
947   LOG_DEBUG ("-------host id: %u\n", host_id);
948   if (NULL != hostname) LOG_DEBUG ("-------hostname: %s\n", hostname);
949   if (0 != username_length) LOG_DEBUG ("-------username: %s\n", username);
950   else LOG_DEBUG ("-------username: NULL\n");
951   LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
952   host = GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
953                                              ntohs (msg->ssh_port));
954   GNUNET_SERVER_receive_done (client, GNUNET_OK);
955   reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
956   if (GNUNET_OK != host_list_add (host))
957   {    
958     /* We are unable to add a host */  
959     emsg = "A host exists with given host-id";
960     LOG_DEBUG ("%s: %u", emsg, host_id);
961     GNUNET_TESTBED_host_destroy (host);
962     reply_size += strlen (emsg) + 1;
963     reply = GNUNET_malloc (reply_size);
964     memcpy (&reply[1], emsg, strlen (emsg) + 1);
965   }
966   else
967     reply = GNUNET_malloc (reply_size);  
968   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM);
969   reply->header.size = htons (reply_size);
970   reply->host_id = htonl (host_id);  
971   queue_message (client, (struct GNUNET_MessageHeader *) reply);
972 }
973
974
975 /**
976  * Iterator over hash map entries.
977  *
978  * @param cls closure
979  * @param key current key code
980  * @param value value in the hash map
981  * @return GNUNET_YES if we should continue to
982  *         iterate,
983  *         GNUNET_NO if not.
984  */
985 int ss_exists_iterator (void *cls,
986                         const struct GNUNET_HashCode * key,
987                         void *value)
988 {
989   struct SharedService *queried_ss = cls;
990   struct SharedService *ss = value;
991
992   if (0 == strcmp (ss->name, queried_ss->name))
993     return GNUNET_NO;
994   else
995     return GNUNET_YES;
996 }
997
998
999 /**
1000  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
1001  *
1002  * @param cls NULL
1003  * @param client identification of the client
1004  * @param message the actual message
1005  */
1006 static void 
1007 handle_configure_shared_service (void *cls,
1008                                  struct GNUNET_SERVER_Client *client,
1009                                  const struct GNUNET_MessageHeader *message)
1010 {
1011   const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1012   struct SharedService *ss;
1013   char *service_name;
1014   struct GNUNET_HashCode hash;
1015   uint16_t msg_size;
1016   uint16_t service_name_size;
1017     
1018   msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
1019   msg_size = ntohs (message->size);
1020   if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
1021   {
1022     GNUNET_break (0);
1023     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1024     return;
1025   }
1026   service_name_size = msg_size - 
1027     sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
1028   service_name = (char *) &msg[1];
1029   if ('\0' != service_name[service_name_size - 1])
1030   {
1031     GNUNET_break (0);
1032     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1033     return;
1034   }
1035   LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
1036              service_name, ntohl (msg->num_peers));
1037   if (ntohl (msg->host_id) != master_context->host_id)
1038   {
1039     route_message (ntohl (msg->host_id), message);
1040     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1041     return;
1042   }
1043   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1044   ss = GNUNET_malloc (sizeof (struct SharedService));
1045   ss->name = strdup (service_name);
1046   ss->num_shared = ntohl (msg->num_peers);
1047   GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
1048   if (GNUNET_SYSERR == 
1049       GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
1050                                                   &ss_exists_iterator, ss))
1051   {
1052     LOG (GNUNET_ERROR_TYPE_WARNING,
1053          "Service %s already configured as a shared service. "
1054          "Ignoring service sharing request \n", ss->name);
1055     GNUNET_free (ss->name);
1056     GNUNET_free (ss);
1057     return;
1058   }
1059   GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
1060                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);  
1061 }
1062
1063
1064 /**
1065  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
1066  *
1067  * @param cls NULL
1068  * @param client identification of the client
1069  * @param message the actual message
1070  */
1071 static void 
1072 handle_link_controllers (void *cls,
1073                          struct GNUNET_SERVER_Client *client,
1074                          const struct GNUNET_MessageHeader *message)
1075 {
1076   const struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1077   struct GNUNET_CONFIGURATION_Handle *cfg;
1078   struct LCFContextQueue *lcfq;
1079   struct Route *route;
1080   struct Route *new_route;
1081   char *config;  
1082   uLongf dest_size;
1083   size_t config_size;
1084   uint32_t delegated_host_id;
1085   uint32_t slave_host_id;
1086   uint16_t msize;
1087    
1088   if (NULL == master_context)
1089   {
1090     GNUNET_break (0);
1091     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1092     return;
1093   }
1094   msize = ntohs (message->size);
1095   if (sizeof (struct GNUNET_TESTBED_ControllerLinkMessage) >= msize)
1096   {
1097     GNUNET_break (0);
1098     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1099     return;
1100   }
1101   msg = (const struct GNUNET_TESTBED_ControllerLinkMessage *) message;
1102   delegated_host_id = ntohl (msg->delegated_host_id);
1103   if (delegated_host_id == master_context->host_id)
1104   {
1105     GNUNET_break (0);
1106     LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
1107     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1108     return;
1109   }
1110   if ((delegated_host_id >= host_list_size) || 
1111       (NULL == host_list[delegated_host_id]))
1112   {
1113     LOG (GNUNET_ERROR_TYPE_WARNING, "Delegated host not registered with us\n");
1114     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1115     return;
1116   }
1117   slave_host_id = ntohl (msg->slave_host_id);
1118   if ((slave_host_id >= host_list_size) || (NULL == host_list[slave_host_id]))
1119   {
1120     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host not registered with us\n");
1121     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1122     return;
1123   }
1124   if (slave_host_id == delegated_host_id)
1125   {
1126     LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
1127     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1128     return;
1129   }
1130   msize -= sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1131   config_size = ntohs (msg->config_size);
1132   
1133   if (slave_host_id == master_context->host_id) /* Link from us */
1134   {
1135     struct Slave *slave;
1136
1137     if ((delegated_host_id < slave_list_size) && 
1138         (NULL != slave_list[delegated_host_id])) /* We have already added */
1139     {
1140       LOG (GNUNET_ERROR_TYPE_WARNING, "Host %u already connected\n",
1141            delegated_host_id);
1142       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1143       return;
1144     }    
1145     config = GNUNET_malloc (config_size);
1146     dest_size = (uLongf) config_size;    
1147     if (Z_OK != uncompress ((Bytef *) config, &dest_size,
1148                             (const Bytef *) &msg[1], (uLong) msize))
1149     {
1150       GNUNET_break (0);           /* Compression error */
1151       GNUNET_free (config);
1152       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1153       return;
1154     }
1155     if (config_size == dest_size)
1156     {
1157       LOG (GNUNET_ERROR_TYPE_WARNING, "Uncompressed config size mismatch\n");
1158       GNUNET_free (config);
1159       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1160       return;
1161     }
1162     cfg = GNUNET_CONFIGURATION_create (); /* Free here or in lcfcontext */
1163     if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1164                                                        GNUNET_NO))
1165     {
1166       GNUNET_break (0);           /* Configuration parsing error */
1167       GNUNET_free (config);
1168       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1169       return;
1170     }
1171     GNUNET_free (config);
1172     if ((delegated_host_id < slave_list_size) &&
1173         (NULL != slave_list[delegated_host_id]))
1174     {
1175       GNUNET_break (0);           /* Configuration parsing error */
1176       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1177       return;
1178     }
1179     slave = GNUNET_malloc (sizeof (struct Slave));
1180     slave->host_id = delegated_host_id;    
1181     slave_list_add (slave);    
1182     if (1 == msg->is_subordinate)
1183     {
1184       slave->controller_proc =
1185         GNUNET_TESTBED_controller_start (master_context->master_ip,
1186                                          host_list[slave->host_id],
1187                                          cfg, &slave_status_callback,
1188                                          slave);
1189     }
1190     else {
1191       slave->controller = 
1192         GNUNET_TESTBED_controller_connect (cfg, host_list[slave->host_id],
1193                                            master_context->event_mask,
1194                                            &slave_event_callback, slave);
1195     }
1196     GNUNET_CONFIGURATION_destroy (cfg);
1197     new_route = GNUNET_malloc (sizeof (struct Route));
1198     new_route->dest = delegated_host_id;
1199     new_route->thru = master_context->host_id;
1200     route_list_add (new_route);
1201     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1202     return;
1203   }
1204
1205   /* Route the request */
1206   if (slave_host_id >= route_list_size)
1207   {
1208     LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
1209     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1210     return;
1211   }
1212   lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
1213   lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
1214   lcfq->lcf->delegated_host_id = delegated_host_id;
1215   lcfq->lcf->slave_host_id = slave_host_id;
1216   while (NULL != (route = route_list[slave_host_id]))
1217   {
1218     if (route->thru == master_context->host_id)
1219       break;
1220     slave_host_id = route->thru;
1221   }
1222   GNUNET_assert (NULL != route); /* because we add routes carefully */
1223   GNUNET_assert (route->dest < slave_list_size);
1224   GNUNET_assert (NULL != slave_list[route->dest]);  
1225   lcfq->lcf->is_subordinate =
1226     (1 == msg->is_subordinate) ? GNUNET_YES : GNUNET_NO;
1227   lcfq->lcf->state = INIT;
1228   lcfq->lcf->gateway = slave_list[route->dest];
1229   lcfq->lcf->sxcfg_size = msize;
1230   lcfq->lcf->sxcfg = GNUNET_malloc (msize);
1231   lcfq->lcf->scfg_size = config_size;
1232   (void) memcpy (lcfq->lcf->sxcfg, &msg[1], msize);
1233   if (NULL == lcfq_head)
1234   {
1235     GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1236     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1237     lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq);
1238   }
1239   else
1240     GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
1241   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1242   new_route = GNUNET_malloc (sizeof (struct Route));
1243   new_route->dest = delegated_host_id;
1244   new_route->thru = route->dest;
1245   route_list_add (new_route);
1246 }
1247
1248
1249 /**
1250  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
1251  *
1252  * @param cls NULL
1253  * @param client identification of the client
1254  * @param message the actual message
1255  */
1256 static void 
1257 handle_peer_create (void *cls,
1258                     struct GNUNET_SERVER_Client *client,
1259                     const struct GNUNET_MessageHeader *message)
1260 {
1261   const struct GNUNET_TESTBED_PeerCreateMessage *msg;
1262   struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
1263   struct GNUNET_CONFIGURATION_Handle *cfg;
1264   char *config;
1265   size_t dest_size;
1266   int ret;
1267   uint32_t config_size;
1268   uint16_t msize;
1269   
1270
1271   msize = ntohs (message->size);
1272   if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
1273   {
1274     GNUNET_break (0);           /* We need configuration */
1275     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1276     return;
1277   }
1278   msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
1279   if (ntohl (msg->host_id) == master_context->host_id)
1280   {
1281     struct Peer *peer;
1282     char *emsg;
1283     
1284     /* We are responsible for this peer */
1285     msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1286     config_size = ntohl (msg->config_size);    
1287     config = GNUNET_malloc (config_size);
1288     dest_size = config_size;
1289     if (Z_OK != (ret = uncompress ((Bytef *) config, (uLongf *) &dest_size,
1290                                    (const Bytef *) &msg[1], (uLong) msize)))
1291     {
1292       GNUNET_break (0);           /* uncompression error */
1293       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1294       return;
1295     }
1296     if (config_size != dest_size)
1297     {
1298       GNUNET_break (0);/* Uncompressed config size mismatch */
1299       GNUNET_free (config);
1300       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1301       return;
1302     }
1303     cfg = GNUNET_CONFIGURATION_create ();
1304     if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg, config, config_size,
1305                                                        GNUNET_NO))
1306     {
1307       GNUNET_break (0);           /* Configuration parsing error */
1308       GNUNET_free (config);
1309       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1310       return;
1311     }
1312     GNUNET_free (config);
1313     peer = GNUNET_malloc (sizeof (struct Peer));
1314     peer->cfg = cfg;
1315     peer->id = ntohl (msg->peer_id);
1316     LOG_DEBUG ("Creating peer with id: %u\n", peer->id);
1317     peer->peer = GNUNET_TESTING_peer_configure (master_context->system, peer->cfg,
1318                                                 peer->id,
1319                                                 NULL /* Peer id */,
1320                                                 &emsg);
1321     if (NULL == peer->peer)
1322     {
1323       LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
1324       GNUNET_free (emsg);
1325       GNUNET_free (peer);
1326       GNUNET_break (0);
1327       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1328       return;
1329     }
1330     peer_list_add (peer);
1331     reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1332     reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1333     reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS);
1334     reply->peer_id = msg->peer_id;
1335     reply->operation_id = msg->operation_id;
1336     queue_message (client, &reply->header);
1337     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1338     return;
1339   }
1340
1341   /* FIXME: Forward the peer to other host */
1342   GNUNET_break (0);
1343   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1344 }
1345
1346
1347 /**
1348  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1349  *
1350  * @param cls NULL
1351  * @param client identification of the client
1352  * @param message the actual message
1353  */
1354 static void 
1355 handle_peer_destroy (void *cls,
1356                      struct GNUNET_SERVER_Client *client,
1357                      const struct GNUNET_MessageHeader *message)
1358 {
1359   const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
1360   struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *reply;
1361   uint32_t peer_id;
1362   uint32_t id;
1363   uint16_t reply_size;
1364   
1365   msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
1366   peer_id = ntohl (msg->peer_id);
1367   LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
1368              peer_id, GNUNET_ntohll (msg->operation_id));
1369   if ((peer_list_size <= peer_id) || (NULL == peer_list[peer_id]))
1370   {
1371     GNUNET_break (0);
1372     /* FIXME: Reply with failure event message or forward to slave controller */
1373     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1374     return;
1375   }  
1376   GNUNET_TESTING_peer_destroy (peer_list[peer_id]->peer);
1377   GNUNET_CONFIGURATION_destroy (peer_list[peer_id]->cfg);
1378   GNUNET_free (peer_list[peer_id]);
1379   peer_list[peer_id] = NULL;
1380   for (id = 0; id < LIST_GROW_STEP; id++)
1381   {
1382     if (((peer_id + id >= peer_list_size) ||
1383          (NULL != peer_list[peer_id])))
1384       break;
1385   }
1386   if (LIST_GROW_STEP == id)
1387   {
1388     peer_list_size -= LIST_GROW_STEP;
1389     peer_list = GNUNET_realloc (peer_list, peer_list_size);
1390   }
1391   reply_size = 
1392     sizeof (struct GNUNET_TESTBED_GenericOperationSuccessEventMessage);
1393   reply = GNUNET_malloc (reply_size);
1394   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS);
1395   reply->header.size = htons (reply_size);
1396   reply->operation_id = msg->operation_id;
1397   reply->event_type = htonl (GNUNET_TESTBED_ET_OPERATION_FINISHED);
1398   queue_message (client, &reply->header);
1399   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1400 }
1401
1402
1403 /**
1404  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1405  *
1406  * @param cls NULL
1407  * @param client identification of the client
1408  * @param message the actual message
1409  */
1410 static void 
1411 handle_peer_start (void *cls,
1412                    struct GNUNET_SERVER_Client *client,
1413                    const struct GNUNET_MessageHeader *message)
1414 {
1415   const struct GNUNET_TESTBED_PeerStartMessage *msg;
1416   struct GNUNET_TESTBED_PeerEventMessage *reply;
1417   uint32_t peer_id;
1418
1419   msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
1420   peer_id = ntohl (msg->peer_id);
1421   if ((peer_id >= peer_list_size) 
1422       || (NULL == peer_list[peer_id]))
1423   {
1424     GNUNET_break (0);
1425     /* FIXME: reply with failure message or forward to slave controller */
1426     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1427     return;
1428   }
1429   if (GNUNET_OK != GNUNET_TESTING_peer_start (peer_list[peer_id]->peer))
1430   {
1431     /* FIXME: return FAILURE message */
1432     GNUNET_break (0);
1433     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1434     return;
1435   }
1436   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1437   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1438   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1439   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
1440   reply->host_id = htonl (master_context->host_id);
1441   reply->peer_id = msg->peer_id;
1442   reply->operation_id = msg->operation_id;
1443   queue_message (client, &reply->header);
1444   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1445 }
1446
1447
1448 /**
1449  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
1450  *
1451  * @param cls NULL
1452  * @param client identification of the client
1453  * @param message the actual message
1454  */
1455 static void 
1456 handle_peer_stop (void *cls,
1457                   struct GNUNET_SERVER_Client *client,
1458                   const struct GNUNET_MessageHeader *message)
1459 {
1460   const struct GNUNET_TESTBED_PeerStopMessage *msg;
1461   struct GNUNET_TESTBED_PeerEventMessage *reply;
1462   uint32_t peer_id;
1463
1464   msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
1465   peer_id = ntohl (msg->peer_id);
1466   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1467   {
1468     GNUNET_break (0);           /* FIXME: route to slave? */
1469     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1470     return;
1471   }
1472   if (GNUNET_OK != GNUNET_TESTING_peer_stop (peer_list[peer_id]->peer))
1473   {
1474     /* FIXME: return FAILURE message */
1475     GNUNET_break (0);
1476     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1477     return;
1478   }
1479   reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1480   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT);
1481   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1482   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
1483   reply->host_id = htonl (master_context->host_id);
1484   reply->peer_id = msg->peer_id;
1485   reply->operation_id = msg->operation_id;
1486   queue_message (client, &reply->header);
1487   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1488 }
1489
1490
1491 /**
1492  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
1493  *
1494  * @param cls NULL
1495  * @param client identification of the client
1496  * @param message the actual message
1497  */
1498 static void 
1499 handle_peer_get_config (void *cls,
1500                         struct GNUNET_SERVER_Client *client,
1501                         const struct GNUNET_MessageHeader *message)
1502 {
1503   const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
1504   struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
1505   char *config;
1506   char *xconfig;
1507   size_t c_size;
1508   size_t xc_size;  
1509   uint32_t peer_id;
1510   uint16_t msize;
1511   
1512   msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
1513   peer_id = ntohl (msg->peer_id);
1514   if ((peer_id >= peer_list_size) || (NULL == peer_list[peer_id]))
1515   {
1516     /* FIXME: return FAILURE message */
1517     GNUNET_break (0);
1518     GNUNET_SERVER_receive_done (client, GNUNET_OK);
1519   }
1520   config = GNUNET_CONFIGURATION_serialize (peer_list[peer_id]->cfg,
1521                                            &c_size);
1522   xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
1523   GNUNET_free (config);
1524   msize = xc_size + sizeof (struct
1525                             GNUNET_TESTBED_PeerConfigurationInformationMessage);
1526   reply = GNUNET_realloc (xconfig, msize);
1527   (void) memmove (&reply[1], reply, xc_size);
1528   reply->header.size = htons (msize);
1529   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG);
1530   reply->peer_id = msg->peer_id;
1531   reply->operation_id = msg->operation_id;
1532   GNUNET_TESTING_peer_get_identity (peer_list[peer_id]->peer,
1533                                     &reply->peer_identity);
1534   reply->config_size = htons ((uint16_t) c_size);
1535   queue_message (client, &reply->header);
1536   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1537 }
1538
1539
1540 /**
1541  * Exchanges HELLO of peers among them
1542  *
1543  * @param occ the OverlayConnectContext to look into for HELLO messages
1544  */
1545 static void
1546 exchange_hellos (struct OverlayConnectContext *occ)
1547 {
1548   unsigned int peer;
1549
1550   GNUNET_assert (NULL != occ->peers_hello[0]);
1551   GNUNET_assert (NULL != occ->peers_hello[1]);
1552   LOG_DEBUG ("Exchanging hellos\n");
1553   for (peer = 0; peer < 2; peer++)
1554   {
1555     GNUNET_TRANSPORT_offer_hello (occ->peers_transport[peer], 
1556                                   occ->peers_hello[peer ^ 1],
1557                                   NULL, NULL);
1558     GNUNET_TRANSPORT_try_connect (occ->peers_transport[peer],
1559                                   &occ->peers_identity[peer ^ 1]);
1560     GNUNET_free (occ->peers_hello[peer ^ 1]);
1561   }
1562 }
1563
1564
1565 /**
1566  * Function called whenever there is an update to the
1567  * HELLO of peers in the OverlayConnectClosure
1568  *
1569  * @param cls closure
1570  * @param hello our updated HELLO
1571  */
1572 static void 
1573 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
1574 {
1575   struct OverlayConnectContextWrapper *occw = cls;
1576   struct OverlayConnectContext *occ;
1577   unsigned int peer;
1578   uint16_t msize;
1579     
1580   msize = ntohs (hello->size);
1581   peer = occw->peer;
1582   GNUNET_assert (peer <= 1);
1583   occ = occw->occ;
1584   occ->peers_hello[peer] = GNUNET_malloc (msize);
1585   memcpy (occ->peers_hello[peer], hello, msize);
1586   GNUNET_TRANSPORT_get_hello_cancel (occ->peers_ghh[peer]);
1587   occ->peers_ghh[peer] = NULL;
1588   if (NULL != occ->peers_hello[peer ^ 1])
1589     exchange_hellos (occ);
1590 }
1591
1592
1593 /**
1594  * Function called to notify transport users that another
1595  * peer connected to us.
1596  *
1597  * @param cls closure
1598  * @param new_peer the peer that connected
1599  * @param ats performance data
1600  * @param ats_count number of entries in ats (excluding 0-termination)
1601  */
1602 static void 
1603 overlay_connect_notify (void *cls,
1604                         const struct GNUNET_PeerIdentity * new_peer,
1605                         const struct GNUNET_ATS_Information * ats,
1606                         uint32_t ats_count)
1607 {
1608   struct OverlayConnectContextWrapper *occw = cls;
1609   struct OverlayConnectContext *occ;
1610   struct GNUNET_TESTBED_ConnectionEventMessage *msg;
1611   unsigned int peer;
1612
1613   peer = occw->peer;
1614   occ = occw->occ;
1615   if (0 != memcmp (new_peer, &occ->peers_identity[peer ^ 1],
1616                    sizeof (struct GNUNET_PeerIdentity)))
1617   {
1618     LOG_DEBUG ("Unexpected peer %4s connected to peer %4s\n",
1619                GNUNET_i2s (new_peer), 
1620                GNUNET_i2s (&occ->peers_identity[peer ^ 1]));
1621     return;
1622   }
1623   GNUNET_free (occw);
1624   LOG_DEBUG ("Peer %4s connected to peer %4s\n", GNUNET_i2s (new_peer),
1625              GNUNET_i2s (&occ->peers_identity[peer ^ 1]));
1626   GNUNET_TRANSPORT_disconnect (occ->peers_transport[peer]);
1627   occ->peers_transport[peer] = NULL;
1628   if (NULL != occ->peers_transport[peer ^ 1])
1629     return;
1630   /* Peers are connected - now send overlay connect success message */
1631   LOG_DEBUG ("Peers connected - Sending overlay connect success\n");
1632   msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1633   msg->header.size = htons (sizeof (struct
1634                                     GNUNET_TESTBED_ConnectionEventMessage));
1635   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT);
1636   msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
1637   msg->peer1 = occ->peers[0]->id;
1638   msg->peer2 = occ->peers[1]->id;
1639   msg->operation_id = GNUNET_htonll (occ->op_id);
1640   queue_message (occ->client, &msg->header);  
1641   GNUNET_SERVER_client_drop (occ->client);
1642   GNUNET_free (occ);  
1643 }
1644
1645
1646 /**
1647  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1648  *
1649  * @param cls NULL
1650  * @param client identification of the client
1651  * @param message the actual message
1652  */
1653 static void 
1654 handle_overlay_connect (void *cls,
1655                         struct GNUNET_SERVER_Client *client,
1656                         const struct GNUNET_MessageHeader *message)
1657 {
1658   const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1659   struct OverlayConnectContext *occ;
1660   struct OverlayConnectContextWrapper *occw;
1661   unsigned int peer;
1662   uint32_t p1;
1663   uint32_t p2;
1664
1665   msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1666   p1 = ntohl (msg->peer1);
1667   p2 = ntohl (msg->peer2);
1668   GNUNET_assert (p1 < peer_list_size);
1669   GNUNET_assert (NULL != peer_list[p1]);
1670   GNUNET_assert (p2 < peer_list_size);
1671   GNUNET_assert (NULL != peer_list[p2]);
1672   occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1673   GNUNET_SERVER_client_keep (client);
1674   occ->client = client;
1675   occ->state = OCC_STATE_INIT;
1676   occ->peers[0] = peer_list[p1];
1677   occ->peers[1] = peer_list[p2];
1678   occ->op_id = GNUNET_ntohll (msg->operation_id);
1679   for (peer = 0; peer < 2; peer++)
1680   {
1681     occw = GNUNET_malloc (sizeof (struct OverlayConnectContextWrapper));
1682     occw->occ = occ;
1683     occw->peer = peer;
1684     GNUNET_TESTING_peer_get_identity (occ->peers[peer]->peer, 
1685                                       &occ->peers_identity[peer]);
1686     occ->peers_transport[peer] = 
1687       GNUNET_TRANSPORT_connect (occ->peers[peer]->cfg,
1688                                 &occ->peers_identity[peer], occw, NULL,
1689                                 &overlay_connect_notify, NULL);
1690     occ->peers_ghh[peer] =
1691       GNUNET_TRANSPORT_get_hello (occ->peers_transport[peer], 
1692                                   &hello_update_cb, occw);
1693   }
1694   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1695 }
1696
1697
1698 /**
1699  * Iterator over hash map entries.
1700  *
1701  * @param cls closure
1702  * @param key current key code
1703  * @param value value in the hash map
1704  * @return GNUNET_YES if we should continue to
1705  *         iterate,
1706  *         GNUNET_NO if not.
1707  */
1708 static int 
1709 ss_map_free_iterator (void *cls,
1710                       const struct GNUNET_HashCode * key, void *value)
1711 {
1712   struct SharedService *ss = value;
1713
1714   GNUNET_assert (GNUNET_YES ==
1715                  GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
1716   GNUNET_free (ss->name);
1717   GNUNET_free (ss);
1718   return GNUNET_YES;
1719 }
1720
1721
1722 /**
1723  * Task to clean up and shutdown nicely
1724  *
1725  * @param cls NULL
1726  * @param tc the TaskContext from scheduler
1727  */
1728 static void
1729 shutdown_task (void *cls,
1730                const struct GNUNET_SCHEDULER_TaskContext *tc)
1731 {
1732   struct LCFContextQueue *lcfq;
1733   uint32_t id;
1734
1735   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
1736   LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
1737   (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
1738                                                 NULL);
1739   GNUNET_CONTAINER_multihashmap_destroy (ss_map);  
1740   if (NULL != lcfq_head)
1741   {
1742     if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
1743     {
1744       GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
1745       lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
1746     }
1747     if (NULL != lcfq_head->lcf->rhandle)
1748       GNUNET_TESTBED_cancel_registration (lcfq_head->lcf->rhandle);
1749   }
1750   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
1751   for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
1752   {
1753     GNUNET_free (lcfq->lcf->sxcfg);
1754     GNUNET_free (lcfq->lcf);
1755     GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
1756     GNUNET_free (lcfq);
1757   }
1758   /* Clear peer list */
1759   for (id = 0; id < peer_list_size; id++)
1760     if (NULL != peer_list[id])
1761     {
1762       GNUNET_TESTING_peer_destroy (peer_list[id]->peer);
1763       GNUNET_CONFIGURATION_destroy (peer_list[id]->cfg);
1764       GNUNET_free (peer_list[id]);
1765     }
1766   GNUNET_free_non_null (peer_list);
1767   /* Clear host list */
1768   for (id = 0; id < host_list_size; id++)
1769     if (NULL != host_list[id])
1770       GNUNET_TESTBED_host_destroy (host_list[id]);
1771   GNUNET_free_non_null (host_list);
1772   /* Clear route list */
1773   for (id = 0; id < route_list_size; id++)
1774     if (NULL != route_list[id])
1775       GNUNET_free (route_list[id]);
1776   GNUNET_free_non_null (route_list);
1777   /* Clear slave_list */
1778   for (id = 0; id < slave_list_size; id++)
1779     if (NULL != slave_list[id])
1780     {
1781       GNUNET_assert (NULL != slave_list[id]->controller);
1782       GNUNET_TESTBED_controller_disconnect (slave_list[id]->controller);
1783       if (NULL != slave_list[id]->controller_proc)
1784         GNUNET_TESTBED_controller_stop (slave_list[id]->controller_proc);
1785     }
1786   if (NULL != master_context)
1787   {  
1788     GNUNET_free_non_null (master_context->master_ip);
1789     if (NULL != master_context->system)
1790       GNUNET_TESTING_system_destroy (master_context->system, GNUNET_YES);
1791     GNUNET_free (master_context);
1792     master_context = NULL;
1793   }
1794 }
1795
1796
1797 /**
1798  * Callback for client disconnect
1799  *
1800  * @param cls NULL
1801  * @param client the client which has disconnected
1802  */
1803 static void
1804 client_disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client)
1805 {
1806   if (NULL == master_context)
1807     return;
1808   if (client == master_context->client)
1809   {
1810     LOG (GNUNET_ERROR_TYPE_DEBUG, "Master client disconnected\n");
1811     GNUNET_SERVER_client_drop (client);
1812     /* should not be needed as we're terminated by failure to read
1813        from stdin, but if stdin fails for some reason, this shouldn't 
1814        hurt for now --- might need to revise this later if we ever
1815        decide that master connections might be temporarily down 
1816        for some reason */
1817     //GNUNET_SCHEDULER_shutdown ();
1818   }
1819 }
1820
1821
1822 /**
1823  * Testbed setup
1824  *
1825  * @param cls closure
1826  * @param server the initialized server
1827  * @param cfg configuration to use
1828  */
1829 static void 
1830 testbed_run (void *cls,
1831              struct GNUNET_SERVER_Handle *server,
1832              const struct GNUNET_CONFIGURATION_Handle *cfg)
1833 {
1834   static const struct GNUNET_SERVER_MessageHandler message_handlers[] =
1835     {
1836       {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT,
1837        sizeof (struct GNUNET_TESTBED_InitMessage)},
1838       {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST, 0},
1839       {&handle_configure_shared_service, NULL,
1840        GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE, 0},
1841       {&handle_link_controllers, NULL,
1842        GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS, 0},
1843       {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER, 0},
1844       {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER,
1845        sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
1846       {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER,
1847        sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
1848       {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER,
1849        sizeof (struct GNUNET_TESTBED_PeerStopMessage)},      
1850       {&handle_peer_get_config, NULL, GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG,
1851        sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
1852       {&handle_overlay_connect, NULL, GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT,
1853        sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
1854       {NULL}
1855     };
1856
1857   GNUNET_SERVER_add_handlers (server,
1858                               message_handlers);
1859   GNUNET_SERVER_disconnect_notify (server,
1860                                    &client_disconnect_cb,
1861                                    NULL);
1862   ss_map = GNUNET_CONTAINER_multihashmap_create (5);
1863   shutdown_task_id = 
1864     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1865                                   &shutdown_task,
1866                                   NULL);
1867   LOG_DEBUG ("Testbed startup complete\n");
1868 }
1869
1870
1871 /**
1872  * The starting point of execution
1873  */
1874 int main (int argc, char *const *argv)
1875 {
1876   return
1877     (GNUNET_OK ==
1878      GNUNET_SERVICE_run (argc,
1879                          argv,
1880                          "testbed",
1881                          GNUNET_SERVICE_OPTION_NONE,
1882                          &testbed_run,
1883                          NULL)) ? 0 : 1;
1884 }