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