ad77003fcc501adee2fcc7c9efe24d5fe36e8f07
[oweals/gnunet.git] / src / testbed / testbed_api.c
1 /*
2       This file is part of GNUnet
3       (C) 2008--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 3, 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/testbed_api.c
23  * @brief API for accessing the GNUnet testing service.
24  *        This library is supposed to make it easier to write
25  *        testcases and script large-scale benchmarks.
26  * @author Christian Grothoff
27  * @author Sree Harsha Totakura
28  */
29
30
31 #include "platform.h"
32 #include "gnunet_testbed_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_transport_service.h"
36 #include "gnunet_hello_lib.h"
37 #include <zlib.h>
38
39 #include "testbed.h"
40 #include "testbed_api.h"
41 #include "testbed_api_hosts.h"
42 #include "testbed_api_peers.h"
43 #include "testbed_api_operations.h"
44 #include "testbed_api_sd.h"
45
46 /**
47  * Generic logging shorthand
48  */
49 #define LOG(kind, ...)                          \
50   GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
51
52 /**
53  * Debug logging
54  */
55 #define LOG_DEBUG(...)                          \
56   LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__);
57
58 /**
59  * Relative time seconds shorthand
60  */
61 #define TIME_REL_SECS(sec) \
62   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
63
64
65 /**
66  * Default server message sending retry timeout
67  */
68 #define TIMEOUT_REL TIME_REL_SECS(1)
69
70
71 /**
72  * Handle for controller process
73  */
74 struct GNUNET_TESTBED_ControllerProc
75 {
76   /**
77    * The process handle
78    */
79   struct GNUNET_HELPER_Handle *helper;
80
81   /**
82    * The arguments used to start the helper
83    */
84   char **helper_argv;
85
86   /**
87    * The host where the helper is run
88    */
89   struct GNUNET_TESTBED_Host *host;
90
91   /**
92    * The controller error callback
93    */
94   GNUNET_TESTBED_ControllerStatusCallback cb;
95
96   /**
97    * The closure for the above callback
98    */
99   void *cls;
100
101   /**
102    * The send handle for the helper
103    */
104   struct GNUNET_HELPER_SendHandle *shandle;
105
106   /**
107    * The message corresponding to send handle
108    */
109   struct GNUNET_MessageHeader *msg;
110
111   /**
112    * The configuration of the running testbed service
113    */
114   struct GNUNET_CONFIGURATION_Handle *cfg;
115
116 };
117
118
119 /**
120  * The message queue for sending messages to the controller service
121  */
122 struct MessageQueue
123 {
124   /**
125    * The message to be sent
126    */
127   struct GNUNET_MessageHeader *msg;
128
129   /**
130    * next pointer for DLL
131    */
132   struct MessageQueue *next;
133
134   /**
135    * prev pointer for DLL
136    */
137   struct MessageQueue *prev;
138 };
139
140
141 /**
142  * Structure for a controller link
143  */
144 struct ControllerLink
145 {
146   /**
147    * The next ptr for DLL
148    */
149   struct ControllerLink *next;
150
151   /**
152    * The prev ptr for DLL
153    */
154   struct ControllerLink *prev;
155
156   /**
157    * The host which will be referred in the peer start request. This is the
158    * host where the peer should be started
159    */
160   struct GNUNET_TESTBED_Host *delegated_host;
161
162   /**
163    * The host which will contacted to delegate the peer start request
164    */
165   struct GNUNET_TESTBED_Host *slave_host;
166
167   /**
168    * The configuration to be used to connect to slave host
169    */
170   const struct GNUNET_CONFIGURATION_Handle *slave_cfg;
171
172   /**
173    * GNUNET_YES if the slave should be started (and stopped) by us; GNUNET_NO
174    * if we are just allowed to use the slave via TCP/IP
175    */
176   int is_subordinate;
177 };
178
179
180 /**
181  * handle for host registration
182  */
183 struct GNUNET_TESTBED_HostRegistrationHandle
184 {
185   /**
186    * The host being registered
187    */
188   struct GNUNET_TESTBED_Host *host;
189
190   /**
191    * The controller at which this host is being registered
192    */
193   struct GNUNET_TESTBED_Controller *c;
194
195   /**
196    * The Registartion completion callback
197    */
198   GNUNET_TESTBED_HostRegistrationCompletion cc;
199
200   /**
201    * The closure for above callback
202    */
203   void *cc_cls;
204 };
205
206
207 /**
208  * Context data for forwarded Operation
209  */
210 struct ForwardedOperationData
211 {
212
213   /**
214    * The callback to call when reply is available
215    */
216   GNUNET_CLIENT_MessageHandler cc;
217
218   /**
219    * The closure for the above callback
220    */
221   void *cc_cls;
222
223 };
224
225
226 /**
227  * Context data for get slave config operations
228  */
229 struct GetSlaveConfigData
230 {
231   /**
232    * The id of the slave controller
233    */
234   uint32_t slave_id;
235
236 };
237
238
239 /**
240  * Context data for controller link operations
241  */
242 struct ControllerLinkData
243 {
244   /**
245    * The controller link message
246    */
247   struct GNUNET_TESTBED_ControllerLinkMessage *msg;
248
249 };
250
251
252 /**
253  * This variable is set to the operation that has been last marked as done. It
254  * is used to verify whether the state associated with an operation is valid
255  * after the first notify callback is called. Such checks are necessary for
256  * certain operations where we have 2 notify callbacks. Examples are
257  * OP_PEER_CREATE, OP_PEER_START/STOP, OP_OVERLAY_CONNECT.
258  *
259  * This variable should ONLY be used to compare; it is a dangling pointer!!
260  */
261 static const struct GNUNET_TESTBED_Operation *last_finished_operation;
262
263
264 /**
265  * Returns the operation context with the given id if found in the Operation
266  * context queues of the controller
267  *
268  * @param c the controller whose queues are searched
269  * @param id the id which has to be checked
270  * @return the matching operation context; NULL if no match found
271  */
272 static struct OperationContext *
273 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
274 {
275   struct OperationContext *opc;
276
277   for (opc = c->ocq_head; NULL != opc; opc = opc->next)
278   {
279     if (id == opc->id)
280       return opc;
281   }
282   return NULL;
283 }
284
285
286 /**
287  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
288  * controller (testbed service)
289  *
290  * @param c the controller handler
291  * @param msg message received
292  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
293  *           not
294  */
295 static int
296 handle_addhostconfirm (struct GNUNET_TESTBED_Controller *c,
297                        const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
298 {
299   struct GNUNET_TESTBED_HostRegistrationHandle *rh;
300   char *emsg;
301   uint16_t msg_size;
302
303   rh = c->rh;
304   if (NULL == rh)
305   {
306     return GNUNET_OK;
307   }
308   if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
309   {
310     LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
311                GNUNET_TESTBED_host_get_id_ (rh->host), ntohl (msg->host_id));
312     return GNUNET_OK;
313   }
314   c->rh = NULL;
315   msg_size = ntohs (msg->header.size);
316   if (sizeof (struct GNUNET_TESTBED_HostConfirmedMessage) == msg_size)
317   {
318     LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id));
319     GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c);
320     rh->cc (rh->cc_cls, NULL);
321     GNUNET_free (rh);
322     return GNUNET_OK;
323   }
324   /* We have an error message */
325   emsg = (char *) &msg[1];
326   if ('\0' !=
327       emsg[msg_size - sizeof (struct GNUNET_TESTBED_HostConfirmedMessage)])
328   {
329     GNUNET_break (0);
330     GNUNET_free (rh);
331     return GNUNET_NO;
332   }
333   LOG (GNUNET_ERROR_TYPE_ERROR, _("Adding host %u failed with error: %s\n"),
334        ntohl (msg->host_id), emsg);
335   rh->cc (rh->cc_cls, emsg);
336   GNUNET_free (rh);
337   return GNUNET_OK;
338 }
339
340
341 /**
342  * Handler for forwarded operations
343  *
344  * @param c the controller handle
345  * @param opc the opearation context
346  * @param msg the message
347  */
348 static void
349 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
350                                 struct OperationContext *opc,
351                                 const struct GNUNET_MessageHeader *msg)
352 {
353   struct ForwardedOperationData *fo_data;
354
355   fo_data = opc->data;
356   if (NULL != fo_data->cc)
357     fo_data->cc (fo_data->cc_cls, msg);
358   GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
359   GNUNET_free (fo_data);
360   GNUNET_free (opc);
361 }
362
363
364 /**
365  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
366  * controller (testbed service)
367  *
368  * @param c the controller handler
369  * @param msg message received
370  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
371  *           not
372  */
373 static int
374 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
375                   const struct
376                   GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
377 {
378   struct OperationContext *opc;
379   struct GNUNET_TESTBED_EventInformation event;
380   uint64_t op_id;
381
382   op_id = GNUNET_ntohll (msg->operation_id);
383   LOG_DEBUG ("Operation %lu successful\n", op_id);
384   if (NULL == (opc = find_opc (c, op_id)))
385   {
386     LOG_DEBUG ("Operation not found\n");
387     return GNUNET_YES;
388   }
389   event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
390   event.details.operation_finished.operation = opc->op;
391   event.details.operation_finished.op_cls = opc->op_cls;
392   event.details.operation_finished.emsg = NULL;
393   event.details.operation_finished.generic = NULL;
394   switch (opc->type)
395   {
396   case OP_FORWARDED:
397   {
398     handle_forwarded_operation_msg (c, opc,
399                                     (const struct GNUNET_MessageHeader *) msg);
400     return GNUNET_YES;
401   }
402     break;
403   case OP_PEER_DESTROY:
404   {
405     struct GNUNET_TESTBED_Peer *peer;
406
407     peer = opc->data;
408     GNUNET_free (peer);
409     opc->data = NULL;
410     //PEERDESTROYDATA
411   }
412     break;
413   case OP_LINK_CONTROLLERS:
414   {
415     struct ControllerLinkData *data;
416
417     data = opc->data;
418     GNUNET_assert (NULL != data);
419     GNUNET_free (data);
420     opc->data = NULL;
421   }
422     break;
423   default:
424     GNUNET_assert (0);
425   }
426   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
427   opc->state = OPC_STATE_FINISHED;
428   if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
429   {
430     if (NULL != c->cc)
431       c->cc (c->cc_cls, &event);
432   }
433   else
434     LOG_DEBUG ("Not calling callback\n");
435   return GNUNET_YES;
436 }
437
438
439 /**
440  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
441  * controller (testbed service)
442  *
443  * @param c the controller handle
444  * @param msg message received
445  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
446  *           not
447  */
448 static int
449 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
450                             const struct
451                             GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
452 {
453   struct OperationContext *opc;
454   struct PeerCreateData *data;
455   struct GNUNET_TESTBED_Peer *peer;
456   GNUNET_TESTBED_PeerCreateCallback cb;
457   void *cls;
458   uint64_t op_id;
459
460   GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
461                  ntohs (msg->header.size));
462   op_id = GNUNET_ntohll (msg->operation_id);
463   if (NULL == (opc = find_opc (c, op_id)))
464   {
465     LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
466     return GNUNET_YES;
467   }
468   if (OP_FORWARDED == opc->type)
469   {
470     handle_forwarded_operation_msg (c, opc,
471                                     (const struct GNUNET_MessageHeader *) msg);
472     return GNUNET_YES;
473   }
474   GNUNET_assert (OP_PEER_CREATE == opc->type);
475   GNUNET_assert (NULL != opc->data);
476   data = opc->data;
477   GNUNET_assert (NULL != data->peer);
478   peer = data->peer;
479   GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
480   peer->state = PS_CREATED;
481   cb = data->cb;
482   cls = data->cls;
483   GNUNET_free (opc->data);
484   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
485   opc->state = OPC_STATE_FINISHED;
486   if (NULL != cb)
487     cb (cls, peer, NULL);
488   return GNUNET_YES;
489 }
490
491
492 /**
493  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
494  * controller (testbed service)
495  *
496  * @param c the controller handler
497  * @param msg message received
498  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
499  *           not
500  */
501 static int
502 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
503                    const struct GNUNET_TESTBED_PeerEventMessage *msg)
504 {
505   struct OperationContext *opc;
506   struct GNUNET_TESTBED_Peer *peer;
507   struct PeerEventData *data;
508   GNUNET_TESTBED_PeerChurnCallback pcc;
509   void *pcc_cls;
510   struct GNUNET_TESTBED_EventInformation event;
511   uint64_t op_id;
512
513   GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
514                  ntohs (msg->header.size));
515   op_id = GNUNET_ntohll (msg->operation_id);
516   if (NULL == (opc = find_opc (c, op_id)))
517   {
518     LOG_DEBUG ("Operation not found\n");
519     return GNUNET_YES;
520   }
521   if (OP_FORWARDED == opc->type)
522   {
523     handle_forwarded_operation_msg (c, opc,
524                                     (const struct GNUNET_MessageHeader *) msg);
525     return GNUNET_YES;
526   }
527   GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
528   data = opc->data;
529   GNUNET_assert (NULL != data);
530   peer = data->peer;
531   GNUNET_assert (NULL != peer);
532   event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
533   switch (event.type)
534   {
535   case GNUNET_TESTBED_ET_PEER_START:
536     peer->state = PS_STARTED;
537     event.details.peer_start.host = peer->host;
538     event.details.peer_start.peer = peer;
539     break;
540   case GNUNET_TESTBED_ET_PEER_STOP:
541     peer->state = PS_STOPPED;
542     event.details.peer_stop.peer = peer;
543     break;
544   default:
545     GNUNET_assert (0);          /* We should never reach this state */
546   }
547   pcc = data->pcc;
548   pcc_cls = data->pcc_cls;
549   GNUNET_free (data);
550   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
551   opc->state = OPC_STATE_FINISHED;
552   if (0 !=
553       ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
554        c->event_mask))
555   {
556     if (NULL != c->cc)
557       c->cc (c->cc_cls, &event);
558   }
559   if (NULL != pcc)
560     pcc (pcc_cls, NULL);
561   return GNUNET_YES;
562 }
563
564
565 /**
566  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
567  * controller (testbed service)
568  *
569  * @param c the controller handler
570  * @param msg message received
571  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
572  *           not
573  */
574 static int
575 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
576                       const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
577 {
578   struct OperationContext *opc;
579   struct OverlayConnectData *data;
580   GNUNET_TESTBED_OperationCompletionCallback cb;
581   void *cb_cls;
582   struct GNUNET_TESTBED_EventInformation event;
583   uint64_t op_id;
584
585   op_id = GNUNET_ntohll (msg->operation_id);
586   if (NULL == (opc = find_opc (c, op_id)))
587   {
588     LOG_DEBUG ("Operation not found\n");
589     return GNUNET_YES;
590   }
591   if (OP_FORWARDED == opc->type)
592   {
593     handle_forwarded_operation_msg (c, opc,
594                                     (const struct GNUNET_MessageHeader *) msg);
595     return GNUNET_YES;
596   }
597   GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
598   data = opc->data;
599   GNUNET_assert (NULL != data);
600   GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
601                  (ntohl (msg->peer2) == data->p2->unique_id));
602   event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
603   switch (event.type)
604   {
605   case GNUNET_TESTBED_ET_CONNECT:
606     event.details.peer_connect.peer1 = data->p1;
607     event.details.peer_connect.peer2 = data->p2;
608     break;
609   case GNUNET_TESTBED_ET_DISCONNECT:
610     GNUNET_assert (0);          /* FIXME: implement */
611     break;
612   default:
613     GNUNET_assert (0);          /* Should never reach here */
614     break;
615   }
616   cb = data->cb;
617   cb_cls = data->cb_cls;
618   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
619   opc->state = OPC_STATE_FINISHED;
620   if (NULL != cb)
621     cb (cb_cls, opc->op, NULL);
622   if (0 !=
623       ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
624        c->event_mask))
625   {
626     if (NULL != c->cc)
627       c->cc (c->cc_cls, &event);
628   }
629   return GNUNET_YES;
630 }
631
632
633 /**
634  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
635  * controller (testbed service)
636  *
637  * @param c the controller handler
638  * @param msg message received
639  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
640  *           not
641  */
642 static int
643 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
644                     const struct
645                     GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
646 {
647   struct OperationContext *opc;
648   struct GNUNET_TESTBED_Peer *peer;
649   struct PeerInfoData *data;
650   struct GNUNET_TESTBED_PeerInformation *pinfo;
651   GNUNET_TESTBED_PeerInfoCallback cb;
652   void *cb_cls;
653   uint64_t op_id;
654
655   op_id = GNUNET_ntohll (msg->operation_id);
656   if (NULL == (opc = find_opc (c, op_id)))
657   {
658     LOG_DEBUG ("Operation not found\n");
659     return GNUNET_YES;
660   }
661   if (OP_FORWARDED == opc->type)
662   {
663     handle_forwarded_operation_msg (c, opc,
664                                     (const struct GNUNET_MessageHeader *) msg);
665     return GNUNET_YES;
666   }
667   data = opc->data;
668   GNUNET_assert (NULL != data);
669   peer = data->peer;
670   GNUNET_assert (NULL != peer);
671   GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
672   pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
673   pinfo->pit = data->pit;
674   cb = data->cb;
675   cb_cls = data->cb_cls;
676   GNUNET_free (data);
677   opc->data = NULL;
678   switch (pinfo->pit)
679   {
680   case GNUNET_TESTBED_PIT_IDENTITY:
681     pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
682     (void) memcpy (pinfo->result.id, &msg->peer_identity,
683                    sizeof (struct GNUNET_PeerIdentity));
684     break;
685   case GNUNET_TESTBED_PIT_CONFIGURATION:
686     pinfo->result.cfg =         /* Freed in oprelease_peer_getinfo */
687         GNUNET_TESTBED_extract_config_ (&msg->header);
688     break;
689   case GNUNET_TESTBED_PIT_GENERIC:
690     GNUNET_assert (0);          /* never reach here */
691     break;
692   }
693   opc->data = pinfo;
694   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
695   opc->state = OPC_STATE_FINISHED;
696   if (NULL != cb)
697     cb (cb_cls, opc->op, pinfo, NULL);
698   return GNUNET_YES;
699 }
700
701
702 /**
703  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
704  * controller (testbed service)
705  *
706  * @param c the controller handler
707  * @param msg message received
708  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
709  *           not
710  */
711 static int
712 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
713                       const struct GNUNET_TESTBED_OperationFailureEventMessage
714                       *msg)
715 {
716   struct OperationContext *opc;
717   const char *emsg;
718   uint64_t op_id;
719   struct GNUNET_TESTBED_EventInformation event;
720
721   op_id = GNUNET_ntohll (msg->operation_id);
722   if (NULL == (opc = find_opc (c, op_id)))
723   {
724     LOG_DEBUG ("Operation not found\n");
725     return GNUNET_YES;
726   }
727   if (OP_FORWARDED == opc->type)
728   {
729     handle_forwarded_operation_msg (c, opc,
730                                     (const struct GNUNET_MessageHeader *) msg);
731     return GNUNET_YES;
732   }
733   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
734   opc->state = OPC_STATE_FINISHED;
735   emsg = GNUNET_TESTBED_parse_error_string_ (msg);
736   if (NULL == emsg)
737     emsg = "Unknown error";
738   if (OP_PEER_INFO == opc->type)
739   {
740     struct PeerInfoData *data;
741
742     data = opc->data;
743     if (NULL != data->cb)
744       data->cb (data->cb_cls, opc->op, NULL, emsg);
745     GNUNET_free (data);
746     return GNUNET_YES;          /* We do not call controller callback for peer info */
747   }
748   if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
749       (NULL != c->cc))
750   {
751     event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
752     event.details.operation_finished.operation = opc->op;
753     event.details.operation_finished.op_cls = opc->op_cls;
754     event.details.operation_finished.emsg = emsg;
755     event.details.operation_finished.generic = NULL;
756     c->cc (c->cc_cls, &event);
757     if (event.details.operation_finished.operation == last_finished_operation)
758       return GNUNET_YES;
759   }
760   switch (opc->type)
761   {
762   case OP_PEER_CREATE:
763   {
764     struct PeerCreateData *data;
765
766     data = opc->data;
767     GNUNET_free (data->peer);
768     if (NULL != data->cb)
769       data->cb (data->cls, NULL, emsg);
770     GNUNET_free (data);
771   }
772     break;
773   case OP_PEER_START:
774   case OP_PEER_STOP:
775   {
776     struct PeerEventData *data;
777
778     data = opc->data;
779     if (NULL != data->pcc)
780       data->pcc (data->pcc_cls, emsg);
781     GNUNET_free (data);
782   }
783     break;
784   case OP_PEER_DESTROY:
785     break;
786   case OP_PEER_INFO:
787     GNUNET_assert (0);
788   case OP_OVERLAY_CONNECT:
789   {
790     struct OverlayConnectData *data;
791
792     data = opc->data;
793     data->failed = GNUNET_YES;
794     if (NULL != data->cb)
795       data->cb (data->cb_cls, opc->op, emsg);
796   }
797     break;
798   case OP_FORWARDED:
799     GNUNET_assert (0);
800   case OP_LINK_CONTROLLERS:    /* No secondary callback */
801     break;
802   default:
803     GNUNET_break (0);
804   }
805   return GNUNET_YES;
806 }
807
808
809 /**
810  * Function to build GET_SLAVE_CONFIG message
811  *
812  * @param op_id the id this message should contain in its operation id field
813  * @param slave_id the id this message should contain in its slave id field
814  * @return newly allocated SlaveGetConfigurationMessage
815  */
816 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
817 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
818 {
819   struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
820   uint16_t msize;
821
822   msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
823   msg = GNUNET_malloc (msize);
824   msg->header.size = htons (msize);
825   msg->header.type =
826       htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
827   msg->operation_id = GNUNET_htonll (op_id);
828   msg->slave_id = htonl (slave_id);
829   return msg;
830 }
831
832
833 /**
834  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
835  * (testbed service)
836  *
837  * @param c the controller handler
838  * @param msg message received
839  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
840  *           not
841  */
842 static int
843 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
844                      const struct GNUNET_TESTBED_SlaveConfiguration *msg)
845 {
846   struct OperationContext *opc;
847   uint64_t op_id;
848   struct GNUNET_TESTBED_EventInformation event;
849
850   op_id = GNUNET_ntohll (msg->operation_id);
851   if (NULL == (opc = find_opc (c, op_id)))
852   {
853     LOG_DEBUG ("Operation not found\n");
854     return GNUNET_YES;
855   }
856   if (OP_GET_SLAVE_CONFIG != opc->type)
857   {
858     GNUNET_break (0);
859     return GNUNET_YES;
860   }
861   GNUNET_free (opc->data);
862   opc->data = NULL;
863   opc->state = OPC_STATE_FINISHED;
864   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
865   if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
866       (NULL != c->cc))
867   {
868     opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
869     event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
870     event.details.operation_finished.generic = opc->data;
871     event.details.operation_finished.operation = opc->op;
872     event.details.operation_finished.op_cls = opc->op_cls;
873     event.details.operation_finished.emsg = NULL;
874     c->cc (c->cc_cls, &event);
875   }
876   return GNUNET_YES;
877 }
878
879
880 /**
881  * Handler for messages from controller (testbed service)
882  *
883  * @param cls the controller handler
884  * @param msg message received, NULL on timeout or fatal error
885  */
886 static void
887 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
888 {
889   struct GNUNET_TESTBED_Controller *c = cls;
890   int status;
891   uint16_t msize;
892
893   c->in_receive = GNUNET_NO;
894   /* FIXME: Add checks for message integrity */
895   if (NULL == msg)
896   {
897     LOG_DEBUG ("Receive timed out or connection to service dropped\n");
898     return;
899   }
900   status = GNUNET_OK;
901   msize = ntohs (msg->size);
902   switch (ntohs (msg->type))
903   {
904   case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
905     GNUNET_assert (msize >=
906                    sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
907     status =
908         handle_addhostconfirm (c,
909                                (const struct GNUNET_TESTBED_HostConfirmedMessage
910                                 *) msg);
911     break;
912   case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
913     GNUNET_assert (msize ==
914                    sizeof (struct
915                            GNUNET_TESTBED_GenericOperationSuccessEventMessage));
916     status =
917         handle_opsuccess (c,
918                           (const struct
919                            GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
920                           msg);
921     break;
922   case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
923     GNUNET_assert (msize ==
924                    sizeof (struct
925                            GNUNET_TESTBED_PeerCreateSuccessEventMessage));
926     status =
927         handle_peer_create_success (c,
928                                     (const struct
929                                      GNUNET_TESTBED_PeerCreateSuccessEventMessage
930                                      *) msg);
931     break;
932   case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
933     GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
934     status =
935         handle_peer_event (c,
936                            (const struct GNUNET_TESTBED_PeerEventMessage *)
937                            msg);
938
939     break;
940   case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
941     GNUNET_assert (msize >=
942                    sizeof (struct
943                            GNUNET_TESTBED_PeerConfigurationInformationMessage));
944     status =
945         handle_peer_config (c,
946                             (const struct
947                              GNUNET_TESTBED_PeerConfigurationInformationMessage
948                              *) msg);
949     break;
950   case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
951     GNUNET_assert (msize ==
952                    sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
953     status =
954         handle_peer_conevent (c,
955                               (const struct
956                                GNUNET_TESTBED_ConnectionEventMessage *) msg);
957     break;
958   case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
959     GNUNET_assert (msize >=
960                    sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
961     status =
962         handle_op_fail_event (c,
963                               (const struct
964                                GNUNET_TESTBED_OperationFailureEventMessage *)
965                               msg);
966     break;
967   case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
968     GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
969     status =
970         handle_slave_config (c,
971                              (const struct GNUNET_TESTBED_SlaveConfiguration *)
972                              msg);
973     break;
974   default:
975     GNUNET_assert (0);
976   }
977   if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
978   {
979     c->in_receive = GNUNET_YES;
980     GNUNET_CLIENT_receive (c->client, &message_handler, c,
981                            GNUNET_TIME_UNIT_FOREVER_REL);
982   }
983 }
984
985
986 /**
987  * Function called to notify a client about the connection begin ready to queue
988  * more data.  "buf" will be NULL and "size" zero if the connection was closed
989  * for writing in the meantime.
990  *
991  * @param cls closure
992  * @param size number of bytes available in buf
993  * @param buf where the callee should write the message
994  * @return number of bytes written to buf
995  */
996 static size_t
997 transmit_ready_notify (void *cls, size_t size, void *buf)
998 {
999   struct GNUNET_TESTBED_Controller *c = cls;
1000   struct MessageQueue *mq_entry;
1001
1002   c->th = NULL;
1003   mq_entry = c->mq_head;
1004   GNUNET_assert (NULL != mq_entry);
1005   if ((0 == size) && (NULL == buf))     /* Timeout */
1006   {
1007     LOG_DEBUG ("Message sending timed out -- retrying\n");
1008     c->th =
1009         GNUNET_CLIENT_notify_transmit_ready (c->client,
1010                                              ntohs (mq_entry->msg->size),
1011                                              TIMEOUT_REL, GNUNET_YES,
1012                                              &transmit_ready_notify, c);
1013     return 0;
1014   }
1015   GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1016   size = ntohs (mq_entry->msg->size);
1017   memcpy (buf, mq_entry->msg, size);
1018   LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1019              ntohs (mq_entry->msg->type), size);
1020   GNUNET_free (mq_entry->msg);
1021   GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1022   GNUNET_free (mq_entry);
1023   mq_entry = c->mq_head;
1024   if (NULL != mq_entry)
1025     c->th =
1026         GNUNET_CLIENT_notify_transmit_ready (c->client,
1027                                              ntohs (mq_entry->msg->size),
1028                                              TIMEOUT_REL, GNUNET_YES,
1029                                              &transmit_ready_notify, c);
1030   if (GNUNET_NO == c->in_receive)
1031   {
1032     c->in_receive = GNUNET_YES;
1033     GNUNET_CLIENT_receive (c->client, &message_handler, c,
1034                            GNUNET_TIME_UNIT_FOREVER_REL);
1035   }
1036   return size;
1037 }
1038
1039
1040 /**
1041  * Queues a message in send queue for sending to the service
1042  *
1043  * @param controller the handle to the controller
1044  * @param msg the message to queue
1045  */
1046 void
1047 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1048                                struct GNUNET_MessageHeader *msg)
1049 {
1050   struct MessageQueue *mq_entry;
1051   uint16_t type;
1052   uint16_t size;
1053
1054   type = ntohs (msg->type);
1055   size = ntohs (msg->size);
1056   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1057                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1058   mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
1059   mq_entry->msg = msg;
1060   LOG (GNUNET_ERROR_TYPE_DEBUG,
1061        "Queueing message of type %u, size %u for sending\n", type,
1062        ntohs (msg->size));
1063   GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1064                                     mq_entry);
1065   if (NULL == controller->th)
1066     controller->th =
1067         GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1068                                              TIMEOUT_REL, GNUNET_YES,
1069                                              &transmit_ready_notify,
1070                                              controller);
1071 }
1072
1073
1074 /**
1075  * Sends the given message as an operation. The given callback is called when a
1076  * reply for the operation is available.  Call
1077  * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1078  * operation context if the cc hasn't been called
1079  *
1080  * @param controller the controller to which the message has to be sent
1081  * @param operation_id the operation id of the message
1082  * @param msg the message to send
1083  * @param cc the callback to call when reply is available
1084  * @param cc_cls the closure for the above callback
1085  * @return the operation context which can be used to cancel the forwarded
1086  *           operation
1087  */
1088 struct OperationContext *
1089 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1090                                        *controller, uint64_t operation_id,
1091                                        const struct GNUNET_MessageHeader *msg,
1092                                        GNUNET_CLIENT_MessageHandler cc,
1093                                        void *cc_cls)
1094 {
1095   struct OperationContext *opc;
1096   struct ForwardedOperationData *data;
1097   struct GNUNET_MessageHeader *dup_msg;
1098   uint16_t msize;
1099
1100   data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
1101   data->cc = cc;
1102   data->cc_cls = cc_cls;
1103   opc = GNUNET_malloc (sizeof (struct OperationContext));
1104   opc->c = controller;
1105   opc->type = OP_FORWARDED;
1106   opc->data = data;
1107   opc->id = operation_id;
1108   msize = ntohs (msg->size);
1109   dup_msg = GNUNET_malloc (msize);
1110   (void) memcpy (dup_msg, msg, msize);
1111   GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1112   GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
1113                                     opc);
1114   return opc;
1115 }
1116
1117
1118 /**
1119  * Function to cancel an operation created by simply forwarding an operation
1120  * message.
1121  *
1122  * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1123  */
1124 void
1125 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1126 {
1127   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1128   GNUNET_free (opc->data);
1129   GNUNET_free (opc);
1130 }
1131
1132
1133 /**
1134  * Functions with this signature are called whenever a
1135  * complete message is received by the tokenizer.
1136  *
1137  * Do not call GNUNET_SERVER_mst_destroy in callback
1138  *
1139  * @param cls closure
1140  * @param client identification of the client
1141  * @param message the actual message
1142  *
1143  * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
1144  */
1145 static int
1146 helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message)
1147 {
1148   struct GNUNET_TESTBED_ControllerProc *cp = cls;
1149   const struct GNUNET_TESTBED_HelperReply *msg;
1150   const char *hostname;
1151   char *config;
1152   uLongf config_size;
1153   uLongf xconfig_size;
1154
1155   msg = (const struct GNUNET_TESTBED_HelperReply *) message;
1156   GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) <
1157                  ntohs (msg->header.size));
1158   GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY ==
1159                  ntohs (msg->header.type));
1160   config_size = (uLongf) ntohs (msg->config_size);
1161   xconfig_size =
1162       (uLongf) (ntohs (msg->header.size) -
1163                 sizeof (struct GNUNET_TESTBED_HelperReply));
1164   config = GNUNET_malloc (config_size);
1165   GNUNET_assert (Z_OK ==
1166                  uncompress ((Bytef *) config, &config_size,
1167                              (const Bytef *) &msg[1], xconfig_size));
1168   GNUNET_assert (NULL == cp->cfg);
1169   cp->cfg = GNUNET_CONFIGURATION_create ();
1170   GNUNET_assert (GNUNET_CONFIGURATION_deserialize
1171                  (cp->cfg, config, config_size, GNUNET_NO));
1172   GNUNET_free (config);
1173   if ((NULL == cp->host) ||
1174       (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))))
1175     hostname = "localhost";
1176   /* Change the hostname so that we can connect to it */
1177   GNUNET_CONFIGURATION_set_value_string (cp->cfg, "testbed", "hostname",
1178                                          hostname);
1179   cp->cb (cp->cls, cp->cfg, GNUNET_OK);
1180   return GNUNET_OK;
1181 }
1182
1183
1184 /**
1185  * Continuation function from GNUNET_HELPER_send()
1186  *
1187  * @param cls closure
1188  * @param result GNUNET_OK on success,
1189  *               GNUNET_NO if helper process died
1190  *               GNUNET_SYSERR during GNUNET_HELPER_stop
1191  */
1192 static void
1193 clear_msg (void *cls, int result)
1194 {
1195   struct GNUNET_TESTBED_ControllerProc *cp = cls;
1196
1197   GNUNET_assert (NULL != cp->shandle);
1198   cp->shandle = NULL;
1199   GNUNET_free (cp->msg);
1200 }
1201
1202
1203 /**
1204  * Callback that will be called when the helper process dies. This is not called
1205  * when the helper process is stoped using GNUNET_HELPER_stop()
1206  *
1207  * @param cls the closure from GNUNET_HELPER_start()
1208  */
1209 static void
1210 helper_exp_cb (void *cls)
1211 {
1212   struct GNUNET_TESTBED_ControllerProc *cp = cls;
1213   GNUNET_TESTBED_ControllerStatusCallback cb;
1214   void *cb_cls;
1215
1216   cb = cp->cb;
1217   cb_cls = cp->cls;
1218   cp->helper = NULL;
1219   GNUNET_TESTBED_controller_stop (cp);
1220   if (NULL != cb)
1221     cb (cb_cls, NULL, GNUNET_SYSERR);
1222 }
1223
1224
1225 /**
1226  * Function to call to start a link-controllers type operation once all queues
1227  * the operation is part of declare that the operation can be activated.
1228  *
1229  * @param cls the closure from GNUNET_TESTBED_operation_create_()
1230  */
1231 static void
1232 opstart_link_controllers (void *cls)
1233 {
1234   struct OperationContext *opc = cls;
1235   struct ControllerLinkData *data;
1236   struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1237
1238   GNUNET_assert (NULL != opc->data);
1239   data = opc->data;
1240   msg = data->msg;
1241   data->msg = NULL;
1242   opc->state = OPC_STATE_STARTED;
1243   GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1244   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1245 }
1246
1247
1248 /**
1249  * Callback which will be called when link-controllers type operation is released
1250  *
1251  * @param cls the closure from GNUNET_TESTBED_operation_create_()
1252  */
1253 static void
1254 oprelease_link_controllers (void *cls)
1255 {
1256   struct OperationContext *opc = cls;
1257   struct ControllerLinkData *data;
1258
1259   data = opc->data;
1260   switch (opc->state)
1261   {
1262   case OPC_STATE_INIT:
1263     GNUNET_free (data->msg);
1264     break;
1265   case OPC_STATE_STARTED:
1266     GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1267     break;
1268   case OPC_STATE_FINISHED:
1269     break;
1270   }
1271   GNUNET_free_non_null (data);
1272   GNUNET_free (opc);
1273 }
1274
1275
1276 /**
1277  * Function to be called when get slave config operation is ready
1278  *
1279  * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1280  */
1281 static void
1282 opstart_get_slave_config (void *cls)
1283 {
1284   struct OperationContext *opc = cls;
1285   struct GetSlaveConfigData *data;
1286   struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1287
1288   data = opc->data;
1289   msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1290   GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1291   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1292   opc->state = OPC_STATE_STARTED;
1293 }
1294
1295
1296 /**
1297  * Function to be called when get slave config operation is cancelled or finished
1298  *
1299  * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1300  */
1301 static void
1302 oprelease_get_slave_config (void *cls)
1303 {
1304   struct OperationContext *opc = cls;
1305
1306   switch (opc->state)
1307   {
1308   case OPC_STATE_INIT:
1309     GNUNET_free (opc->data);
1310     break;
1311   case OPC_STATE_STARTED:
1312     GNUNET_free (opc->data);
1313     GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1314     break;
1315   case OPC_STATE_FINISHED:
1316     if (NULL != opc->data)
1317       GNUNET_CONFIGURATION_destroy (opc->data);
1318     break;
1319   }
1320   GNUNET_free (opc);
1321 }
1322
1323
1324 /**
1325  * Function to copy NULL terminated list of arguments
1326  *
1327  * @param argv the NULL terminated list of arguments. Cannot be NULL.
1328  * @return the copied NULL terminated arguments
1329  */
1330 static char **
1331 copy_argv (const char *const *argv)
1332 {
1333   char **argv_dup;
1334   unsigned int argp;
1335
1336   GNUNET_assert (NULL != argv);
1337   for (argp = 0; NULL != argv[argp]; argp++) ;
1338   argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1));
1339   for (argp = 0; NULL != argv[argp]; argp++)
1340     argv_dup[argp] = strdup (argv[argp]);
1341   return argv_dup;
1342 }
1343
1344
1345 /**
1346  * Function to join NULL terminated list of arguments
1347  *
1348  * @param argv1 the NULL terminated list of arguments. Cannot be NULL.
1349  * @param argv2 the NULL terminated list of arguments. Cannot be NULL.
1350  * @return the joined NULL terminated arguments
1351  */
1352 static char **
1353 join_argv (const char *const *argv1, const char *const *argv2)
1354 {
1355   char **argvj;
1356   char *argv;
1357   unsigned int carg;
1358   unsigned int cnt;
1359
1360   carg = 0;
1361   argvj = NULL;
1362   for (cnt = 0; NULL != argv1[cnt]; cnt++)
1363   {
1364     argv = GNUNET_strdup (argv1[cnt]);
1365     GNUNET_array_append (argvj, carg, argv);
1366   }
1367   for (cnt = 0; NULL != argv2[cnt]; cnt++)
1368   {
1369     argv = GNUNET_strdup (argv2[cnt]);
1370     GNUNET_array_append (argvj, carg, argv);
1371   }
1372   GNUNET_array_append (argvj, carg, NULL);
1373   return argvj;
1374 }
1375
1376
1377 /**
1378  * Frees the given NULL terminated arguments
1379  *
1380  * @param argv the NULL terminated list of arguments
1381  */
1382 static void
1383 free_argv (char **argv)
1384 {
1385   unsigned int argp;
1386
1387   for (argp = 0; NULL != argv[argp]; argp++)
1388     GNUNET_free (argv[argp]);
1389   GNUNET_free (argv);
1390 }
1391
1392
1393 /**
1394  * Generates arguments for opening a remote shell. Builds up the arguments
1395  * from the environment variable GNUNET_TESTBED_RSH_CMD. The variable
1396  * should not mention `-p' (port) option and destination address as these will
1397  * be set locally in the function from its parameteres. If the environmental
1398  * variable is not found then it defaults to `ssh -o BatchMode=yes -o
1399  * NoHostAuthenticationForLocalhost=yes'
1400  *
1401  * @param port the destination port number
1402  * @param dst the destination address
1403  * @return NULL terminated list of arguments
1404  */
1405 static char **
1406 gen_rsh_args (const char *port, const char *dst)
1407 {
1408   static const char *default_ssh_args[] = {
1409     "ssh",
1410     "-o",
1411     "BatchMode=yes",
1412     "-o",
1413     "NoHostAuthenticationForLocalhost=yes",
1414     NULL
1415   };
1416   char **ssh_args;
1417   char *ssh_cmd;
1418   char *ssh_cmd_cp;
1419   char *arg;
1420   unsigned int cnt;
1421
1422   ssh_args = NULL;
1423   if (NULL != (ssh_cmd = getenv ("GNUNET_TESTBED_RSH_CMD")))
1424   {
1425     ssh_cmd = GNUNET_strdup (ssh_cmd);
1426     ssh_cmd_cp = ssh_cmd;
1427     for (cnt = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL)
1428       GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (arg));
1429     GNUNET_free (ssh_cmd_cp);
1430   }
1431   else
1432   {
1433     ssh_args = copy_argv (default_ssh_args);
1434     cnt = (sizeof (default_ssh_args)) / (sizeof (const char *));
1435     GNUNET_array_grow (ssh_args, cnt, cnt - 1);
1436   }
1437   GNUNET_array_append (ssh_args, cnt, GNUNET_strdup ("-p"));
1438   GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (port));
1439   GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (dst));
1440   GNUNET_array_append (ssh_args, cnt, NULL);
1441   return ssh_args;
1442 }
1443
1444
1445 /**
1446  * Generates the arguments needed for executing the given binary in a remote
1447  * shell. Builds the arguments from the environmental variable
1448  * GNUNET_TETSBED_RSH_CMD_SUFFIX. If the environmental variable is not found,
1449  * only the given binary name will be present in the returned arguments
1450  *
1451  * @param helper_binary_path the path of the binary to execute
1452  * @return NULL-terminated args
1453  */
1454 static char **
1455 gen_rsh_suffix_args (const char *helper_binary_path)
1456 {
1457   char **rshell_args;
1458   char *rshell_cmd;
1459   char *rshell_cmd_cp;
1460   char *arg;
1461   unsigned int cnt;
1462
1463   rshell_args = NULL;
1464   cnt = 0;
1465   if (NULL != (rshell_cmd = getenv ("GNUNET_TESTBED_RSH_CMD_SUFFIX")))
1466   {
1467     rshell_cmd = GNUNET_strdup (rshell_cmd);
1468     rshell_cmd_cp = rshell_cmd;
1469     for (; NULL != (arg = strtok (rshell_cmd, " ")); rshell_cmd = NULL)
1470       GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (arg));
1471     GNUNET_free (rshell_cmd_cp);
1472   }
1473   GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (helper_binary_path));
1474   GNUNET_array_append (rshell_args, cnt, NULL);
1475   return rshell_args;
1476 }
1477
1478
1479 /**
1480  * Starts a controller process at the given host
1481  *
1482  * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1483  *          HOST(all connections form this ip are permitted by the testbed) when
1484  *          starting testbed controller at host. This can either be a single ip
1485  *          address or a network address in CIDR notation.
1486  * @param host the host where the controller has to be started; NULL for
1487  *          localhost
1488  * @param cfg template configuration to use for the remote controller; the
1489  *          remote controller will be started with a slightly modified
1490  *          configuration (port numbers, unix domain sockets and service home
1491  *          values are changed as per TESTING library on the remote host)
1492  * @param cb function called when the controller is successfully started or
1493  *          dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
1494  *          called if cb is called with GNUNET_SYSERR as status. Will never be
1495  *          called in the same task as 'GNUNET_TESTBED_controller_start'
1496  *          (synchronous errors will be signalled by returning NULL). This
1497  *          parameter cannot be NULL.
1498  * @param cls closure for above callbacks
1499  * @return the controller process handle, NULL on errors
1500  */
1501 struct GNUNET_TESTBED_ControllerProc *
1502 GNUNET_TESTBED_controller_start (const char *trusted_ip,
1503                                  struct GNUNET_TESTBED_Host *host,
1504                                  const struct GNUNET_CONFIGURATION_Handle *cfg,
1505                                  GNUNET_TESTBED_ControllerStatusCallback cb,
1506                                  void *cls)
1507 {
1508   struct GNUNET_TESTBED_ControllerProc *cp;
1509   struct GNUNET_TESTBED_HelperInit *msg;
1510   const char *hostname;
1511
1512   static char *const binary_argv[] = {
1513     HELPER_TESTBED_BINARY, NULL
1514   };
1515
1516   hostname = NULL;
1517   cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
1518   if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
1519   {
1520     cp->helper =
1521         GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
1522                              &helper_mst, &helper_exp_cb, cp);
1523   }
1524   else
1525   {
1526     char *helper_binary_path;
1527     char **ssh_args;
1528     char **rshell_args;
1529     const char *username;
1530     char *port;
1531     char *dst;
1532
1533     username = GNUNET_TESTBED_host_get_username_ (host);
1534     hostname = GNUNET_TESTBED_host_get_hostname (host);
1535     GNUNET_asprintf (&port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
1536     if (NULL == username)
1537       GNUNET_asprintf (&dst, "%s", hostname);
1538     else
1539       GNUNET_asprintf (&dst, "%s@%s", username, hostname);
1540     LOG_DEBUG ("Starting SSH to destination %s\n", dst);
1541
1542     if (GNUNET_OK !=
1543         GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
1544                                                "HELPER_BINARY_PATH",
1545                                                &helper_binary_path))
1546       helper_binary_path =
1547           GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
1548     ssh_args = gen_rsh_args (port, dst);
1549     rshell_args = gen_rsh_suffix_args (helper_binary_path);
1550     cp->helper_argv =
1551         join_argv ((const char **) ssh_args, (const char **) rshell_args);
1552     free_argv (ssh_args);
1553     free_argv (rshell_args);
1554     GNUNET_free (port);
1555     GNUNET_free (dst);
1556     cp->helper =
1557         GNUNET_HELPER_start (GNUNET_NO, "ssh", cp->helper_argv, &helper_mst,
1558                              &helper_exp_cb, cp);
1559     GNUNET_free (helper_binary_path);
1560   }
1561   if (NULL == cp->helper)
1562   {
1563     if (NULL != cp->helper_argv)
1564       free_argv (cp->helper_argv);
1565     GNUNET_free (cp);
1566     return NULL;
1567   }
1568   cp->host = host;
1569   cp->cb = cb;
1570   cp->cls = cls;
1571   msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg);
1572   cp->msg = &msg->header;
1573   cp->shandle =
1574       GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp);
1575   if (NULL == cp->shandle)
1576   {
1577     GNUNET_free (msg);
1578     GNUNET_TESTBED_controller_stop (cp);
1579     return NULL;
1580   }
1581   return cp;
1582 }
1583
1584
1585 /**
1586  * Stop the controller process (also will terminate all peers and controllers
1587  * dependent on this controller).  This function blocks until the testbed has
1588  * been fully terminated (!). The controller status cb from
1589  * GNUNET_TESTBED_controller_start() will not be called.
1590  *
1591  * @param cproc the controller process handle
1592  */
1593 void
1594 GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
1595 {
1596   if (NULL != cproc->shandle)
1597     GNUNET_HELPER_send_cancel (cproc->shandle);
1598   if (NULL != cproc->helper)
1599     GNUNET_HELPER_soft_stop (cproc->helper);
1600   if (NULL != cproc->cfg)
1601     GNUNET_CONFIGURATION_destroy (cproc->cfg);
1602   if (NULL != cproc->helper_argv)
1603     free_argv (cproc->helper_argv);
1604   GNUNET_free (cproc);
1605 }
1606
1607
1608 /**
1609  * Start a controller process using the given configuration at the
1610  * given host.
1611  *
1612  * @param cfg configuration to use
1613  * @param host host to run the controller on; This should be the same host if
1614  *          the controller was previously started with
1615  *          GNUNET_TESTBED_controller_start; NULL for localhost
1616  * @param event_mask bit mask with set of events to call 'cc' for;
1617  *                   or-ed values of "1LL" shifted by the
1618  *                   respective 'enum GNUNET_TESTBED_EventType'
1619  *                   (i.e.  "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1620  * @param cc controller callback to invoke on events
1621  * @param cc_cls closure for cc
1622  * @return handle to the controller
1623  */
1624 struct GNUNET_TESTBED_Controller *
1625 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1626                                    *cfg, struct GNUNET_TESTBED_Host *host,
1627                                    uint64_t event_mask,
1628                                    GNUNET_TESTBED_ControllerCallback cc,
1629                                    void *cc_cls)
1630 {
1631   struct GNUNET_TESTBED_Controller *controller;
1632   struct GNUNET_TESTBED_InitMessage *msg;
1633   const char *controller_hostname;
1634   unsigned long long max_parallel_operations;
1635   unsigned long long max_parallel_service_connections;
1636   unsigned long long max_parallel_topology_config_operations;
1637
1638   if (GNUNET_OK !=
1639       GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1640                                              "MAX_PARALLEL_OPERATIONS",
1641                                              &max_parallel_operations))
1642   {
1643     GNUNET_break (0);
1644     return NULL;
1645   }
1646   if (GNUNET_OK !=
1647       GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1648                                              "MAX_PARALLEL_SERVICE_CONNECTIONS",
1649                                              &max_parallel_service_connections))
1650   {
1651     GNUNET_break (0);
1652     return NULL;
1653   }
1654   if (GNUNET_OK !=
1655       GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1656                                              "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1657                                              &max_parallel_topology_config_operations))
1658   {
1659     GNUNET_break (0);
1660     return NULL;
1661   }
1662   controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1663   controller->cc = cc;
1664   controller->cc_cls = cc_cls;
1665   controller->event_mask = event_mask;
1666   controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1667   controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1668   if (NULL == controller->client)
1669   {
1670     GNUNET_TESTBED_controller_disconnect (controller);
1671     return NULL;
1672   }
1673   if (NULL == host)
1674   {
1675     host = GNUNET_TESTBED_host_create_by_id_ (0);
1676     if (NULL == host)           /* If the above host create fails */
1677     {
1678       LOG (GNUNET_ERROR_TYPE_WARNING,
1679            "Treating NULL host as localhost. Multiple references to localhost "
1680            "may break when localhost freed before calling disconnect \n");
1681       host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1682     }
1683     else
1684     {
1685       controller->aux_host = GNUNET_YES;
1686     }
1687   }
1688   GNUNET_assert (NULL != host);
1689   GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1690   controller->host = host;
1691   controller->opq_parallel_operations =
1692       GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1693                                               max_parallel_operations);
1694   controller->opq_parallel_service_connections =
1695       GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1696                                               max_parallel_service_connections);
1697   controller->opq_parallel_topology_config_operations =
1698       GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1699                                               max_parallel_topology_config_operations);
1700   controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1701   if (NULL == controller_hostname)
1702     controller_hostname = "127.0.0.1";
1703   msg =
1704       GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1705                      strlen (controller_hostname) + 1);
1706   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1707   msg->header.size =
1708       htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1709              strlen (controller_hostname) + 1);
1710   msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1711   msg->event_mask = GNUNET_htonll (controller->event_mask);
1712   strcpy ((char *) &msg[1], controller_hostname);
1713   GNUNET_TESTBED_queue_message_ (controller,
1714                                  (struct GNUNET_MessageHeader *) msg);
1715   return controller;
1716 }
1717
1718
1719 /**
1720  * Configure shared services at a controller.  Using this function,
1721  * you can specify that certain services (such as "resolver")
1722  * should not be run for each peer but instead be shared
1723  * across N peers on the specified host.  This function
1724  * must be called before any peers are created at the host.
1725  *
1726  * @param controller controller to configure
1727  * @param service_name name of the service to share
1728  * @param num_peers number of peers that should share one instance
1729  *        of the specified service (1 for no sharing is the default),
1730  *        use 0 to disable the service
1731  */
1732 void
1733 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1734                                              *controller,
1735                                              const char *service_name,
1736                                              uint32_t num_peers)
1737 {
1738   struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1739   uint16_t service_name_size;
1740   uint16_t msg_size;
1741
1742   service_name_size = strlen (service_name) + 1;
1743   msg_size =
1744       sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1745       service_name_size;
1746   msg = GNUNET_malloc (msg_size);
1747   msg->header.size = htons (msg_size);
1748   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE);
1749   msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1750   msg->num_peers = htonl (num_peers);
1751   memcpy (&msg[1], service_name, service_name_size);
1752   GNUNET_TESTBED_queue_message_ (controller,
1753                                  (struct GNUNET_MessageHeader *) msg);
1754   GNUNET_break (0);             /* This function is not yet implemented on the
1755                                  * testbed service */
1756 }
1757
1758
1759 /**
1760  * disconnects from the controller.
1761  *
1762  * @param controller handle to controller to stop
1763  */
1764 void
1765 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1766                                       *controller)
1767 {
1768   struct MessageQueue *mq_entry;
1769
1770   if (NULL != controller->th)
1771     GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1772   /* Clear the message queue */
1773   while (NULL != (mq_entry = controller->mq_head))
1774   {
1775     GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1776                                  mq_entry);
1777     GNUNET_free (mq_entry->msg);
1778     GNUNET_free (mq_entry);
1779   }
1780   if (NULL != controller->client)
1781     GNUNET_CLIENT_disconnect (controller->client);
1782   GNUNET_CONFIGURATION_destroy (controller->cfg);
1783   if (GNUNET_YES == controller->aux_host)
1784     GNUNET_TESTBED_host_destroy (controller->host);
1785   GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1786   GNUNET_TESTBED_operation_queue_destroy_
1787       (controller->opq_parallel_service_connections);
1788   GNUNET_TESTBED_operation_queue_destroy_
1789       (controller->opq_parallel_topology_config_operations);
1790   GNUNET_free (controller);
1791 }
1792
1793
1794 /**
1795  * Register a host with the controller
1796  *
1797  * @param controller the controller handle
1798  * @param host the host to register
1799  * @param cc the completion callback to call to inform the status of
1800  *          registration. After calling this callback the registration handle
1801  *          will be invalid. Cannot be NULL.
1802  * @param cc_cls the closure for the cc
1803  * @return handle to the host registration which can be used to cancel the
1804  *           registration
1805  */
1806 struct GNUNET_TESTBED_HostRegistrationHandle *
1807 GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller,
1808                               struct GNUNET_TESTBED_Host *host,
1809                               GNUNET_TESTBED_HostRegistrationCompletion cc,
1810                               void *cc_cls)
1811 {
1812   struct GNUNET_TESTBED_HostRegistrationHandle *rh;
1813   struct GNUNET_TESTBED_AddHostMessage *msg;
1814   const char *username;
1815   const char *hostname;
1816   uint16_t msg_size;
1817   uint16_t user_name_length;
1818
1819   if (NULL != controller->rh)
1820     return NULL;
1821   hostname = GNUNET_TESTBED_host_get_hostname (host);
1822   if (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (host, controller))
1823   {
1824     LOG (GNUNET_ERROR_TYPE_WARNING, "Host hostname: %s already registered\n",
1825          (NULL == hostname) ? "localhost" : hostname);
1826     return NULL;
1827   }
1828   rh = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostRegistrationHandle));
1829   rh->host = host;
1830   rh->c = controller;
1831   GNUNET_assert (NULL != cc);
1832   rh->cc = cc;
1833   rh->cc_cls = cc_cls;
1834   controller->rh = rh;
1835   username = GNUNET_TESTBED_host_get_username_ (host);
1836   msg_size = (sizeof (struct GNUNET_TESTBED_AddHostMessage));
1837   user_name_length = 0;
1838   if (NULL != username)
1839   {
1840     user_name_length = strlen (username) + 1;
1841     msg_size += user_name_length;
1842   }
1843   /* FIXME: what happens when hostname is NULL? localhost */
1844   GNUNET_assert (NULL != hostname);
1845   msg_size += strlen (hostname) + 1;
1846   msg = GNUNET_malloc (msg_size);
1847   msg->header.size = htons (msg_size);
1848   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST);
1849   msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1850   msg->ssh_port = htons (GNUNET_TESTBED_host_get_ssh_port_ (host));
1851   if (NULL != username)
1852   {
1853     msg->user_name_length = htons (user_name_length - 1);
1854     memcpy (&msg[1], username, user_name_length);
1855   }
1856   else
1857     msg->user_name_length = htons (user_name_length);
1858   strcpy (((void *) &msg[1]) + user_name_length, hostname);
1859   GNUNET_TESTBED_queue_message_ (controller,
1860                                  (struct GNUNET_MessageHeader *) msg);
1861   return rh;
1862 }
1863
1864
1865 /**
1866  * Cancel the pending registration. Note that if the registration message is
1867  * already sent to the service the cancellation has only the effect that the
1868  * registration completion callback for the registration is never called.
1869  *
1870  * @param handle the registration handle to cancel
1871  */
1872 void
1873 GNUNET_TESTBED_cancel_registration (struct GNUNET_TESTBED_HostRegistrationHandle
1874                                     *handle)
1875 {
1876   if (handle != handle->c->rh)
1877   {
1878     GNUNET_break (0);
1879     return;
1880   }
1881   handle->c->rh = NULL;
1882   GNUNET_free (handle);
1883 }
1884
1885
1886 /**
1887  * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1888  * and slave host
1889  *
1890  * @param op_cls the operation closure for the event which is generated to
1891  *          signal success or failure of this operation
1892  * @param master handle to the master controller who creates the association
1893  * @param delegated_host_id id of the host to which requests should be delegated
1894  * @param slave_host_id id of the host which is used to run the slave controller
1895  * @param sxcfg serialized and compressed configuration
1896  * @param sxcfg_size the size sxcfg
1897  * @param scfg_size the size of uncompressed serialized configuration
1898  * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1899  *          be started by the slave controller; GNUNET_NO if the slave
1900  *          controller has to connect to the already started delegated
1901  *          controller via TCP/IP
1902  * @return the operation handle
1903  */
1904 struct GNUNET_TESTBED_Operation *
1905 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1906                                    struct GNUNET_TESTBED_Controller *master,
1907                                    uint32_t delegated_host_id,
1908                                    uint32_t slave_host_id, const char *sxcfg,
1909                                    size_t sxcfg_size, size_t scfg_size,
1910                                    int is_subordinate)
1911 {
1912   struct OperationContext *opc;
1913   struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1914   struct ControllerLinkData *data;
1915   uint16_t msg_size;
1916
1917   msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1918   msg = GNUNET_malloc (msg_size);
1919   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1920   msg->header.size = htons (msg_size);
1921   msg->delegated_host_id = htonl (delegated_host_id);
1922   msg->slave_host_id = htonl (slave_host_id);
1923   msg->config_size = htons ((uint16_t) scfg_size);
1924   msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1925   memcpy (&msg[1], sxcfg, sxcfg_size);
1926   data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1927   data->msg = msg;
1928   opc = GNUNET_malloc (sizeof (struct OperationContext));
1929   opc->c = master;
1930   opc->data = data;
1931   opc->type = OP_LINK_CONTROLLERS;
1932   opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1933   opc->state = OPC_STATE_INIT;
1934   opc->op_cls = op_cls;
1935   msg->operation_id = GNUNET_htonll (opc->id);
1936   opc->op =
1937       GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1938                                         &oprelease_link_controllers);
1939   GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1940                                           opc->op);
1941   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1942   return opc->op;
1943 }
1944
1945
1946 /**
1947  * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1948  * serialized and compressed
1949  *
1950  * @param op_cls the operation closure for the event which is generated to
1951  *          signal success or failure of this operation
1952  * @param master handle to the master controller who creates the association
1953  * @param delegated_host requests to which host should be delegated; cannot be NULL
1954  * @param slave_host which host is used to run the slave controller; use NULL to
1955  *          make the master controller connect to the delegated host
1956  * @param sxcfg serialized and compressed configuration
1957  * @param sxcfg_size the size sxcfg
1958  * @param scfg_size the size of uncompressed serialized configuration
1959  * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1960  *          be started by the slave controller; GNUNET_NO if the slave
1961  *          controller has to connect to the already started delegated
1962  *          controller via TCP/IP
1963  * @return the operation handle
1964  */
1965 struct GNUNET_TESTBED_Operation *
1966 GNUNET_TESTBED_controller_link_2 (void *op_cls,
1967                                   struct GNUNET_TESTBED_Controller *master,
1968                                   struct GNUNET_TESTBED_Host *delegated_host,
1969                                   struct GNUNET_TESTBED_Host *slave_host,
1970                                   const char *sxcfg, size_t sxcfg_size,
1971                                   size_t scfg_size, int is_subordinate)
1972 {
1973   uint32_t delegated_host_id;
1974   uint32_t slave_host_id;
1975
1976   GNUNET_assert (GNUNET_YES ==
1977                  GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1978   delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1979   slave_host_id =
1980       GNUNET_TESTBED_host_get_id_ ((NULL !=
1981                                     slave_host) ? slave_host : master->host);
1982   if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1983     GNUNET_assert (GNUNET_YES ==
1984                    GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1985
1986   return GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1987                                             slave_host_id, sxcfg, sxcfg_size,
1988                                             scfg_size, is_subordinate);
1989 }
1990
1991
1992 /**
1993  * Compresses given configuration using zlib compress
1994  *
1995  * @param config the serialized configuration
1996  * @param size the size of config
1997  * @param xconfig will be set to the compressed configuration (memory is fresly
1998  *          allocated)
1999  * @return the size of the xconfig
2000  */
2001 size_t
2002 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
2003                                  char **xconfig)
2004 {
2005   size_t xsize;
2006
2007   xsize = compressBound ((uLong) size);
2008   *xconfig = GNUNET_malloc (xsize);
2009   GNUNET_assert (Z_OK ==
2010                  compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
2011                             (const Bytef *) config, (uLongf) size,
2012                             Z_BEST_SPEED));
2013   return xsize;
2014 }
2015
2016
2017 /**
2018  * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
2019  * and slave host
2020  *
2021  * @param op_cls the operation closure for the event which is generated to
2022  *          signal success or failure of this operation
2023  * @param master handle to the master controller who creates the association
2024  * @param delegated_host_id id of the host to which requests should be
2025  *          delegated; cannot be NULL
2026  * @param slave_host_id id of the host which should connect to controller
2027  *          running on delegated host ; use NULL to make the master controller
2028  *          connect to the delegated host
2029  * @param slave_cfg configuration to use for the slave controller
2030  * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2031  *          be started by the slave controller; GNUNET_NO if the slave
2032  *          controller has to connect to the already started delegated
2033  *          controller via TCP/IP
2034  * @return the operation handle
2035  */
2036 struct GNUNET_TESTBED_Operation *
2037 GNUNET_TESTBED_controller_link_ (void *op_cls,
2038                                  struct GNUNET_TESTBED_Controller *master,
2039                                  uint32_t delegated_host_id,
2040                                  uint32_t slave_host_id,
2041                                  const struct GNUNET_CONFIGURATION_Handle
2042                                  *slave_cfg, int is_subordinate)
2043 {
2044   struct GNUNET_TESTBED_Operation *op;
2045   char *config;
2046   char *cconfig;
2047   size_t cc_size;
2048   size_t config_size;
2049
2050   config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
2051   cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
2052   GNUNET_free (config);
2053   /* Configuration doesn't fit in 1 message */
2054   GNUNET_assert ((UINT16_MAX -
2055                   sizeof (struct GNUNET_TESTBED_ControllerLinkMessage)) >=
2056                  cc_size);
2057   op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
2058                                           slave_host_id, (const char *) cconfig,
2059                                           cc_size, config_size, is_subordinate);
2060   GNUNET_free (cconfig);
2061   return op;
2062 }
2063
2064
2065 /**
2066  * Create a link from slave controller to delegated controller. Whenever the
2067  * master controller is asked to start a peer at the delegated controller the
2068  * request will be routed towards slave controller (if a route exists). The
2069  * slave controller will then route it to the delegated controller. The
2070  * configuration of the delegated controller is given and is used to either
2071  * create the delegated controller or to connect to an existing controller. Note
2072  * that while starting the delegated controller the configuration will be
2073  * modified to accommodate available free ports.  the 'is_subordinate' specifies
2074  * if the given delegated controller should be started and managed by the slave
2075  * controller, or if the delegated controller already has a master and the slave
2076  * controller connects to it as a non master controller. The success or failure
2077  * of this operation will be signalled through the
2078  * GNUNET_TESTBED_ControllerCallback() with an event of type
2079  * GNUNET_TESTBED_ET_OPERATION_FINISHED
2080  *
2081  * @param op_cls the operation closure for the event which is generated to
2082  *          signal success or failure of this operation
2083  * @param master handle to the master controller who creates the association
2084  * @param delegated_host requests to which host should be delegated; cannot be NULL
2085  * @param slave_host which host is used to run the slave controller; use NULL to
2086  *          make the master controller connect to the delegated host
2087  * @param slave_cfg configuration to use for the slave controller
2088  * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2089  *          be started by the slave controller; GNUNET_NO if the slave
2090  *          controller has to connect to the already started delegated
2091  *          controller via TCP/IP
2092  * @return the operation handle
2093  */
2094 struct GNUNET_TESTBED_Operation *
2095 GNUNET_TESTBED_controller_link (void *op_cls,
2096                                 struct GNUNET_TESTBED_Controller *master,
2097                                 struct GNUNET_TESTBED_Host *delegated_host,
2098                                 struct GNUNET_TESTBED_Host *slave_host,
2099                                 const struct GNUNET_CONFIGURATION_Handle
2100                                 *slave_cfg, int is_subordinate)
2101 {
2102   uint32_t slave_host_id;
2103   uint32_t delegated_host_id;
2104
2105   GNUNET_assert (GNUNET_YES ==
2106                  GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
2107   slave_host_id =
2108       GNUNET_TESTBED_host_get_id_ ((NULL !=
2109                                     slave_host) ? slave_host : master->host);
2110   delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
2111   if ((NULL != slave_host) && (0 != slave_host_id))
2112     GNUNET_assert (GNUNET_YES ==
2113                    GNUNET_TESTBED_is_host_registered_ (slave_host, master));
2114   return GNUNET_TESTBED_controller_link_ (op_cls, master, delegated_host_id,
2115                                           slave_host_id, slave_cfg,
2116                                           is_subordinate);
2117
2118 }
2119
2120
2121 /**
2122  * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
2123  * check. Another difference is that this function takes the id of the slave
2124  * host.
2125  *
2126  * @param op_cls the closure for the operation
2127  * @param master the handle to master controller
2128  * @param slave_host_id id of the host where the slave controller is running to
2129  *          the slave_host should remain valid until this operation is cancelled
2130  *          or marked as finished
2131  * @return the operation handle;
2132  */
2133 struct GNUNET_TESTBED_Operation *
2134 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
2135                                   struct GNUNET_TESTBED_Controller *master,
2136                                   uint32_t slave_host_id)
2137 {
2138   struct OperationContext *opc;
2139   struct GetSlaveConfigData *data;
2140
2141   data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
2142   data->slave_id = slave_host_id;
2143   opc = GNUNET_malloc (sizeof (struct OperationContext));
2144   opc->state = OPC_STATE_INIT;
2145   opc->c = master;
2146   opc->id = GNUNET_TESTBED_get_next_op_id (master);
2147   opc->type = OP_GET_SLAVE_CONFIG;
2148   opc->data = data;
2149   opc->op_cls = op_cls;
2150   opc->op =
2151       GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
2152                                         &oprelease_get_slave_config);
2153   GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
2154                                           opc->op);
2155   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2156   return opc->op;
2157 }
2158
2159
2160 /**
2161  * Function to acquire the configuration of a running slave controller. The
2162  * completion of the operation is signalled through the controller_cb from
2163  * GNUNET_TESTBED_controller_connect(). If the operation is successful the
2164  * handle to the configuration is available in the generic pointer of
2165  * operation_finished field of struct GNUNET_TESTBED_EventInformation.
2166  *
2167  * @param op_cls the closure for the operation
2168  * @param master the handle to master controller
2169  * @param slave_host the host where the slave controller is running; the handle
2170  *          to the slave_host should remain valid until this operation is
2171  *          cancelled or marked as finished
2172  * @return the operation handle; NULL if the slave_host is not registered at
2173  *           master
2174  */
2175 struct GNUNET_TESTBED_Operation *
2176 GNUNET_TESTBED_get_slave_config (void *op_cls,
2177                                  struct GNUNET_TESTBED_Controller *master,
2178                                  struct GNUNET_TESTBED_Host *slave_host)
2179 {
2180   if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
2181     return NULL;
2182   return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
2183                                            GNUNET_TESTBED_host_get_id_
2184                                            (slave_host));
2185 }
2186
2187
2188 /**
2189  * Ask the testbed controller to write the current overlay topology to
2190  * a file.  Naturally, the file will only contain a snapshot as the
2191  * topology may evolve all the time.
2192  *
2193  * @param controller overlay controller to inspect
2194  * @param filename name of the file the topology should
2195  *        be written to.
2196  */
2197 void
2198 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
2199                                                *controller,
2200                                                const char *filename)
2201 {
2202   GNUNET_break (0);
2203 }
2204
2205
2206 /**
2207  * Creates a helper initialization message. This function is here because we
2208  * want to use this in testing
2209  *
2210  * @param trusted_ip the ip address of the controller which will be set as TRUSTED
2211  *          HOST(all connections form this ip are permitted by the testbed) when
2212  *          starting testbed controller at host. This can either be a single ip
2213  *          address or a network address in CIDR notation.
2214  * @param hostname the hostname of the destination this message is intended for
2215  * @param cfg the configuration that has to used to start the testbed service
2216  *          thru helper
2217  * @return the initialization message
2218  */
2219 struct GNUNET_TESTBED_HelperInit *
2220 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
2221                                         const char *hostname,
2222                                         const struct GNUNET_CONFIGURATION_Handle
2223                                         *cfg)
2224 {
2225   struct GNUNET_TESTBED_HelperInit *msg;
2226   char *config;
2227   char *xconfig;
2228   size_t config_size;
2229   size_t xconfig_size;
2230   uint16_t trusted_ip_len;
2231   uint16_t hostname_len;
2232   uint16_t msg_size;
2233
2234   config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
2235   GNUNET_assert (NULL != config);
2236   xconfig_size =
2237       GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
2238   GNUNET_free (config);
2239   trusted_ip_len = strlen (trusted_ip);
2240   hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
2241   msg_size =
2242       xconfig_size + trusted_ip_len + 1 +
2243       sizeof (struct GNUNET_TESTBED_HelperInit);
2244   msg_size += hostname_len;
2245   msg = GNUNET_realloc (xconfig, msg_size);
2246   (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
2247                   xconfig_size);
2248   msg->header.size = htons (msg_size);
2249   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
2250   msg->trusted_ip_size = htons (trusted_ip_len);
2251   msg->hostname_size = htons (hostname_len);
2252   msg->config_size = htons (config_size);
2253   (void) strcpy ((char *) &msg[1], trusted_ip);
2254   if (0 != hostname_len)
2255     (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
2256                     hostname_len);
2257   return msg;
2258 }
2259
2260
2261 /**
2262  * Cancel a pending operation.  Releases all resources
2263  * of the operation and will ensure that no event
2264  * is generated for the operation.  Does NOT guarantee
2265  * that the operation will be fully undone (or that
2266  * nothing ever happened).
2267  *
2268  * @param operation operation to cancel
2269  */
2270 void
2271 GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
2272 {
2273   GNUNET_TESTBED_operation_done (operation);
2274 }
2275
2276
2277 /**
2278  * Signal that the information from an operation has been fully
2279  * processed.  This function MUST be called for each event
2280  * of type 'operation_finished' to fully remove the operation
2281  * from the operation queue.  After calling this function, the
2282  * 'op_result' becomes invalid (!).
2283  *
2284  * @param operation operation to signal completion for
2285  */
2286 void
2287 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
2288 {
2289   last_finished_operation = operation;
2290   GNUNET_TESTBED_operation_release_ (operation);
2291 }
2292
2293
2294 /**
2295  * Generates configuration by uncompressing configuration in given message. The
2296  * given message should be of the following types:
2297  * GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG,
2298  * GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG
2299  *
2300  * @param msg the message containing compressed configuration
2301  * @return handle to the parsed configuration
2302  */
2303 struct GNUNET_CONFIGURATION_Handle *
2304 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
2305 {
2306   struct GNUNET_CONFIGURATION_Handle *cfg;
2307   Bytef *data;
2308   const Bytef *xdata;
2309   uLong data_len;
2310   uLong xdata_len;
2311   int ret;
2312
2313   switch (ntohs (msg->type))
2314   {
2315   case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
2316   {
2317     const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
2318
2319     imsg =
2320         (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
2321     data_len = (uLong) ntohs (imsg->config_size);
2322     xdata_len =
2323         ntohs (imsg->header.size) -
2324         sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2325     xdata = (const Bytef *) &imsg[1];
2326   }
2327     break;
2328   case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
2329   {
2330     const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
2331
2332     imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
2333     data_len = (uLong) ntohs (imsg->config_size);
2334     xdata_len =
2335         ntohs (imsg->header.size) -
2336         sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
2337     xdata = (const Bytef *) &imsg[1];
2338   }
2339     break;
2340   default:
2341     GNUNET_assert (0);
2342   }
2343   data = GNUNET_malloc (data_len);
2344   if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
2345     GNUNET_assert (0);
2346   cfg = GNUNET_CONFIGURATION_create ();
2347   GNUNET_assert (GNUNET_OK ==
2348                  GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
2349                                                    (size_t) data_len,
2350                                                    GNUNET_NO));
2351   GNUNET_free (data);
2352   return cfg;
2353 }
2354
2355
2356 /**
2357  * Checks the integrity of the OperationFailureEventMessage and if good returns
2358  * the error message it contains.
2359  *
2360  * @param msg the OperationFailureEventMessage
2361  * @return the error message
2362  */
2363 const char *
2364 GNUNET_TESTBED_parse_error_string_ (const struct
2365                                     GNUNET_TESTBED_OperationFailureEventMessage
2366                                     *msg)
2367 {
2368   uint16_t msize;
2369   const char *emsg;
2370
2371   msize = ntohs (msg->header.size);
2372   if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2373     return NULL;
2374   msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2375   emsg = (const char *) &msg[1];
2376   if ('\0' != emsg[msize - 1])
2377   {
2378     GNUNET_break (0);
2379     return NULL;
2380   }
2381   return emsg;
2382 }
2383
2384
2385 /**
2386  * Function to return the operation id for a controller. The operation id is
2387  * created from the controllers host id and its internal operation counter.
2388  *
2389  * @param controller the handle to the controller whose operation id has to be incremented
2390  * @return the incremented operation id.
2391  */
2392 uint64_t
2393 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
2394 {
2395   uint64_t op_id;
2396
2397   op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2398   op_id = op_id << 32;
2399   op_id |= (uint64_t) controller->operation_counter++;
2400   return op_id;
2401 }
2402
2403
2404 /* end of testbed_api.c */