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