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