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