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