-remove debug message
[oweals/gnunet.git] / testbed / testbed_api.c
1 /*
2       This file is part of GNUnet
3       (C) 2008--2013 Christian Grothoff (and other contributing authors)
4
5       GNUnet is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published
7       by the Free Software Foundation; either version 3, or (at your
8       option) any later version.
9
10       GNUnet is distributed in the hope that it will be useful, but
11       WITHOUT ANY WARRANTY; without even the implied warranty of
12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13       General Public License for more details.
14
15       You should have received a copy of the GNU General Public License
16       along with GNUnet; see the file COPYING.  If not, write to the
17       Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18       Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file testbed/testbed_api.c
23  * @brief API for accessing the GNUnet testing service.
24  *        This library is supposed to make it easier to write
25  *        testcases and script large-scale benchmarks.
26  * @author Christian Grothoff
27  * @author Sree Harsha Totakura
28  */
29
30
31 #include "platform.h"
32 #include "gnunet_testbed_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_transport_service.h"
36 #include "gnunet_hello_lib.h"
37 #include <zlib.h>
38
39 #include "testbed.h"
40 #include "testbed_api.h"
41 #include "testbed_api_hosts.h"
42 #include "testbed_api_peers.h"
43 #include "testbed_api_operations.h"
44 #include "testbed_api_sd.h"
45
46 /**
47  * Generic logging shorthand
48  */
49 #define LOG(kind, ...)                          \
50   GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
51
52 /**
53  * Debug logging
54  */
55 #define LOG_DEBUG(...)                          \
56   LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__);
57
58 /**
59  * Relative time seconds shorthand
60  */
61 #define TIME_REL_SECS(sec) \
62   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
63
64
65 /**
66  * Default server message sending retry timeout
67  */
68 #define TIMEOUT_REL TIME_REL_SECS(1)
69
70
71 /**
72  * The message queue for sending messages to the controller service
73  */
74 struct MessageQueue
75 {
76   /**
77    * The message to be sent
78    */
79   struct GNUNET_MessageHeader *msg;
80
81   /**
82    * next pointer for DLL
83    */
84   struct MessageQueue *next;
85
86   /**
87    * prev pointer for DLL
88    */
89   struct MessageQueue *prev;
90 };
91
92
93 /**
94  * Structure for a controller link
95  */
96 struct ControllerLink
97 {
98   /**
99    * The next ptr for DLL
100    */
101   struct ControllerLink *next;
102
103   /**
104    * The prev ptr for DLL
105    */
106   struct ControllerLink *prev;
107
108   /**
109    * The host which will be referred in the peer start request. This is the
110    * host where the peer should be started
111    */
112   struct GNUNET_TESTBED_Host *delegated_host;
113
114   /**
115    * The host which will contacted to delegate the peer start request
116    */
117   struct GNUNET_TESTBED_Host *slave_host;
118
119   /**
120    * The configuration to be used to connect to slave host
121    */
122   const struct GNUNET_CONFIGURATION_Handle *slave_cfg;
123
124   /**
125    * GNUNET_YES if the slave should be started (and stopped) by us; GNUNET_NO
126    * if we are just allowed to use the slave via TCP/IP
127    */
128   int is_subordinate;
129 };
130
131
132 /**
133  * Context data for forwarded Operation
134  */
135 struct ForwardedOperationData
136 {
137
138   /**
139    * The callback to call when reply is available
140    */
141   GNUNET_CLIENT_MessageHandler cc;
142
143   /**
144    * The closure for the above callback
145    */
146   void *cc_cls;
147
148 };
149
150
151 /**
152  * Context data for get slave config operations
153  */
154 struct GetSlaveConfigData
155 {
156   /**
157    * The id of the slave controller
158    */
159   uint32_t slave_id;
160
161 };
162
163
164 /**
165  * Context data for controller link operations
166  */
167 struct ControllerLinkData
168 {
169   /**
170    * The controller link message
171    */
172   struct GNUNET_TESTBED_ControllerLinkMessage *msg;
173
174 };
175
176
177 /**
178  * This variable is set to the operation that has been last marked as done. It
179  * is used to verify whether the state associated with an operation is valid
180  * after the first notify callback is called. Such checks are necessary for
181  * certain operations where we have 2 notify callbacks. Examples are
182  * OP_PEER_CREATE, OP_PEER_START/STOP, OP_OVERLAY_CONNECT.
183  *
184  * This variable should ONLY be used to compare; it is a dangling pointer!!
185  */
186 static const struct GNUNET_TESTBED_Operation *last_finished_operation;
187
188
189 /**
190  * Returns the operation context with the given id if found in the Operation
191  * context queues of the controller
192  *
193  * @param c the controller whose queues are searched
194  * @param id the id which has to be checked
195  * @return the matching operation context; NULL if no match found
196  */
197 static struct OperationContext *
198 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
199 {
200   struct OperationContext *opc;
201
202   for (opc = c->ocq_head; NULL != opc; opc = opc->next)
203   {
204     if (id == opc->id)
205       return opc;
206   }
207   return NULL;
208 }
209
210
211 /**
212  * Handler for forwarded operations
213  *
214  * @param c the controller handle
215  * @param opc the opearation context
216  * @param msg the message
217  */
218 static void
219 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
220                                 struct OperationContext *opc,
221                                 const struct GNUNET_MessageHeader *msg)
222 {
223   struct ForwardedOperationData *fo_data;
224
225   fo_data = opc->data;
226   if (NULL != fo_data->cc)
227     fo_data->cc (fo_data->cc_cls, msg);
228   GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
229   GNUNET_free (fo_data);
230   GNUNET_free (opc);
231 }
232
233
234 /**
235  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
236  * controller (testbed service)
237  *
238  * @param c the controller handler
239  * @param msg message received
240  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
241  *           not
242  */
243 static int
244 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
245                   const struct
246                   GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
247 {
248   struct OperationContext *opc;
249   struct GNUNET_TESTBED_EventInformation event;
250   uint64_t op_id;
251
252   op_id = GNUNET_ntohll (msg->operation_id);
253   LOG_DEBUG ("Operation %lu successful\n", op_id);
254   if (NULL == (opc = find_opc (c, op_id)))
255   {
256     LOG_DEBUG ("Operation not found\n");
257     return GNUNET_YES;
258   }
259   event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
260   event.details.operation_finished.operation = opc->op;
261   event.details.operation_finished.op_cls = opc->op_cls;
262   event.details.operation_finished.emsg = NULL;
263   event.details.operation_finished.generic = NULL;
264   switch (opc->type)
265   {
266   case OP_FORWARDED:
267   {
268     handle_forwarded_operation_msg (c, opc,
269                                     (const struct GNUNET_MessageHeader *) msg);
270     return GNUNET_YES;
271   }
272     break;
273   case OP_PEER_DESTROY:
274   {
275     struct GNUNET_TESTBED_Peer *peer;
276
277     peer = opc->data;
278     GNUNET_free (peer);
279     opc->data = NULL;
280     //PEERDESTROYDATA
281   }
282     break;
283   case OP_LINK_CONTROLLERS:
284   {
285     struct ControllerLinkData *data;
286
287     data = opc->data;
288     GNUNET_assert (NULL != data);
289     GNUNET_free (data);
290     opc->data = NULL;
291   }
292     break;
293   default:
294     GNUNET_assert (0);
295   }
296   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
297   opc->state = OPC_STATE_FINISHED;
298   if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
299   {
300     if (NULL != c->cc)
301       c->cc (c->cc_cls, &event);
302   }
303   else
304     LOG_DEBUG ("Not calling callback\n");
305   return GNUNET_YES;
306 }
307
308
309 /**
310  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
311  * controller (testbed service)
312  *
313  * @param c the controller handle
314  * @param msg message received
315  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
316  *           not
317  */
318 static int
319 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
320                             const struct
321                             GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
322 {
323   struct OperationContext *opc;
324   struct PeerCreateData *data;
325   struct GNUNET_TESTBED_Peer *peer;
326   GNUNET_TESTBED_PeerCreateCallback cb;
327   void *cls;
328   uint64_t op_id;
329
330   GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
331                  ntohs (msg->header.size));
332   op_id = GNUNET_ntohll (msg->operation_id);
333   if (NULL == (opc = find_opc (c, op_id)))
334   {
335     LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
336     return GNUNET_YES;
337   }
338   if (OP_FORWARDED == opc->type)
339   {
340     handle_forwarded_operation_msg (c, opc,
341                                     (const struct GNUNET_MessageHeader *) msg);
342     return GNUNET_YES;
343   }
344   GNUNET_assert (OP_PEER_CREATE == opc->type);
345   GNUNET_assert (NULL != opc->data);
346   data = opc->data;
347   GNUNET_assert (NULL != data->peer);
348   peer = data->peer;
349   GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
350   peer->state = PS_CREATED;
351   cb = data->cb;
352   cls = data->cls;
353   GNUNET_free (opc->data);
354   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
355   opc->state = OPC_STATE_FINISHED;
356   if (NULL != cb)
357     cb (cls, peer, NULL);
358   return GNUNET_YES;
359 }
360
361
362 /**
363  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
364  * controller (testbed service)
365  *
366  * @param c the controller handler
367  * @param msg message received
368  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
369  *           not
370  */
371 static int
372 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
373                    const struct GNUNET_TESTBED_PeerEventMessage *msg)
374 {
375   struct OperationContext *opc;
376   struct GNUNET_TESTBED_Peer *peer;
377   struct PeerEventData *data;
378   GNUNET_TESTBED_PeerChurnCallback pcc;
379   void *pcc_cls;
380   struct GNUNET_TESTBED_EventInformation event;
381   uint64_t op_id;
382
383   GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
384                  ntohs (msg->header.size));
385   op_id = GNUNET_ntohll (msg->operation_id);
386   if (NULL == (opc = find_opc (c, op_id)))
387   {
388     LOG_DEBUG ("Operation not found\n");
389     return GNUNET_YES;
390   }
391   if (OP_FORWARDED == opc->type)
392   {
393     handle_forwarded_operation_msg (c, opc,
394                                     (const struct GNUNET_MessageHeader *) msg);
395     return GNUNET_YES;
396   }
397   GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
398   data = opc->data;
399   GNUNET_assert (NULL != data);
400   peer = data->peer;
401   GNUNET_assert (NULL != peer);
402   event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
403   switch (event.type)
404   {
405   case GNUNET_TESTBED_ET_PEER_START:
406     peer->state = PS_STARTED;
407     event.details.peer_start.host = peer->host;
408     event.details.peer_start.peer = peer;
409     break;
410   case GNUNET_TESTBED_ET_PEER_STOP:
411     peer->state = PS_STOPPED;
412     event.details.peer_stop.peer = peer;
413     break;
414   default:
415     GNUNET_assert (0);          /* We should never reach this state */
416   }
417   pcc = data->pcc;
418   pcc_cls = data->pcc_cls;
419   GNUNET_free (data);
420   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
421   opc->state = OPC_STATE_FINISHED;
422   if (0 !=
423       ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
424        c->event_mask))
425   {
426     if (NULL != c->cc)
427       c->cc (c->cc_cls, &event);
428   }
429   if (NULL != pcc)
430     pcc (pcc_cls, NULL);
431   return GNUNET_YES;
432 }
433
434
435 /**
436  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
437  * controller (testbed service)
438  *
439  * @param c the controller handler
440  * @param msg message received
441  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
442  *           not
443  */
444 static int
445 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
446                       const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
447 {
448   struct OperationContext *opc;
449   struct OverlayConnectData *data;
450   GNUNET_TESTBED_OperationCompletionCallback cb;
451   void *cb_cls;
452   struct GNUNET_TESTBED_EventInformation event;
453   uint64_t op_id;
454
455   op_id = GNUNET_ntohll (msg->operation_id);
456   if (NULL == (opc = find_opc (c, op_id)))
457   {
458     LOG_DEBUG ("Operation not found\n");
459     return GNUNET_YES;
460   }
461   if (OP_FORWARDED == opc->type)
462   {
463     handle_forwarded_operation_msg (c, opc,
464                                     (const struct GNUNET_MessageHeader *) msg);
465     return GNUNET_YES;
466   }
467   GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
468   data = opc->data;
469   GNUNET_assert (NULL != data);
470   GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
471                  (ntohl (msg->peer2) == data->p2->unique_id));
472   event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
473   switch (event.type)
474   {
475   case GNUNET_TESTBED_ET_CONNECT:
476     event.details.peer_connect.peer1 = data->p1;
477     event.details.peer_connect.peer2 = data->p2;
478     break;
479   case GNUNET_TESTBED_ET_DISCONNECT:
480     GNUNET_assert (0);          /* FIXME: implement */
481     break;
482   default:
483     GNUNET_assert (0);          /* Should never reach here */
484     break;
485   }
486   cb = data->cb;
487   cb_cls = data->cb_cls;
488   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
489   opc->state = OPC_STATE_FINISHED;
490   if (NULL != cb)
491     cb (cb_cls, opc->op, NULL);
492   if (0 !=
493       ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
494        c->event_mask))
495   {
496     if (NULL != c->cc)
497       c->cc (c->cc_cls, &event);
498   }
499   return GNUNET_YES;
500 }
501
502
503 /**
504  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
505  * controller (testbed service)
506  *
507  * @param c the controller handler
508  * @param msg message received
509  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
510  *           not
511  */
512 static int
513 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
514                     const struct
515                     GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
516 {
517   struct OperationContext *opc;
518   struct GNUNET_TESTBED_Peer *peer;
519   struct PeerInfoData *data;
520   struct GNUNET_TESTBED_PeerInformation *pinfo;
521   GNUNET_TESTBED_PeerInfoCallback cb;
522   void *cb_cls;
523   uint64_t op_id;
524
525   op_id = GNUNET_ntohll (msg->operation_id);
526   if (NULL == (opc = find_opc (c, op_id)))
527   {
528     LOG_DEBUG ("Operation not found\n");
529     return GNUNET_YES;
530   }
531   if (OP_FORWARDED == opc->type)
532   {
533     handle_forwarded_operation_msg (c, opc,
534                                     (const struct GNUNET_MessageHeader *) msg);
535     return GNUNET_YES;
536   }
537   data = opc->data;
538   GNUNET_assert (NULL != data);
539   peer = data->peer;
540   GNUNET_assert (NULL != peer);
541   GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
542   pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
543   pinfo->pit = data->pit;
544   cb = data->cb;
545   cb_cls = data->cb_cls;
546   GNUNET_free (data);
547   opc->data = NULL;
548   switch (pinfo->pit)
549   {
550   case GNUNET_TESTBED_PIT_IDENTITY:
551     pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
552     (void) memcpy (pinfo->result.id, &msg->peer_identity,
553                    sizeof (struct GNUNET_PeerIdentity));
554     break;
555   case GNUNET_TESTBED_PIT_CONFIGURATION:
556     pinfo->result.cfg =         /* Freed in oprelease_peer_getinfo */
557         GNUNET_TESTBED_extract_config_ (&msg->header);
558     break;
559   case GNUNET_TESTBED_PIT_GENERIC:
560     GNUNET_assert (0);          /* never reach here */
561     break;
562   }
563   opc->data = pinfo;
564   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
565   opc->state = OPC_STATE_FINISHED;
566   if (NULL != cb)
567     cb (cb_cls, opc->op, pinfo, NULL);
568   return GNUNET_YES;
569 }
570
571
572 /**
573  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
574  * controller (testbed service)
575  *
576  * @param c the controller handler
577  * @param msg message received
578  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
579  *           not
580  */
581 static int
582 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
583                       const struct GNUNET_TESTBED_OperationFailureEventMessage
584                       *msg)
585 {
586   struct OperationContext *opc;
587   const char *emsg;
588   uint64_t op_id;
589   struct GNUNET_TESTBED_EventInformation event;
590
591   op_id = GNUNET_ntohll (msg->operation_id);
592   if (NULL == (opc = find_opc (c, op_id)))
593   {
594     LOG_DEBUG ("Operation not found\n");
595     return GNUNET_YES;
596   }
597   if (OP_FORWARDED == opc->type)
598   {
599     handle_forwarded_operation_msg (c, opc,
600                                     (const struct GNUNET_MessageHeader *) msg);
601     return GNUNET_YES;
602   }
603   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
604   opc->state = OPC_STATE_FINISHED;
605   emsg = GNUNET_TESTBED_parse_error_string_ (msg);
606   if (NULL == emsg)
607     emsg = "Unknown error";
608   if (OP_PEER_INFO == opc->type)
609   {
610     struct PeerInfoData *data;
611
612     data = opc->data;
613     if (NULL != data->cb)
614       data->cb (data->cb_cls, opc->op, NULL, emsg);
615     GNUNET_free (data);
616     return GNUNET_YES;          /* We do not call controller callback for peer info */
617   }
618   if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
619       (NULL != c->cc))
620   {
621     event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
622     event.details.operation_finished.operation = opc->op;
623     event.details.operation_finished.op_cls = opc->op_cls;
624     event.details.operation_finished.emsg = emsg;
625     event.details.operation_finished.generic = NULL;
626     c->cc (c->cc_cls, &event);
627     if (event.details.operation_finished.operation == last_finished_operation)
628       return GNUNET_YES;
629   }
630   switch (opc->type)
631   {
632   case OP_PEER_CREATE:
633   {
634     struct PeerCreateData *data;
635
636     data = opc->data;
637     GNUNET_free (data->peer);
638     if (NULL != data->cb)
639       data->cb (data->cls, NULL, emsg);
640     GNUNET_free (data);
641   }
642     break;
643   case OP_PEER_START:
644   case OP_PEER_STOP:
645   {
646     struct PeerEventData *data;
647
648     data = opc->data;
649     if (NULL != data->pcc)
650       data->pcc (data->pcc_cls, emsg);
651     GNUNET_free (data);
652   }
653     break;
654   case OP_PEER_DESTROY:
655     break;
656   case OP_PEER_INFO:
657     GNUNET_assert (0);
658   case OP_OVERLAY_CONNECT:
659   {
660     struct OverlayConnectData *data;
661
662     data = opc->data;
663     data->failed = GNUNET_YES;
664     if (NULL != data->cb)
665       data->cb (data->cb_cls, opc->op, emsg);
666   }
667     break;
668   case OP_FORWARDED:
669     GNUNET_assert (0);
670   case OP_LINK_CONTROLLERS:    /* No secondary callback */
671     break;
672   default:
673     GNUNET_break (0);
674   }
675   return GNUNET_YES;
676 }
677
678
679 /**
680  * Function to build GET_SLAVE_CONFIG message
681  *
682  * @param op_id the id this message should contain in its operation id field
683  * @param slave_id the id this message should contain in its slave id field
684  * @return newly allocated SlaveGetConfigurationMessage
685  */
686 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
687 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
688 {
689   struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
690   uint16_t msize;
691
692   msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
693   msg = GNUNET_malloc (msize);
694   msg->header.size = htons (msize);
695   msg->header.type =
696       htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
697   msg->operation_id = GNUNET_htonll (op_id);
698   msg->slave_id = htonl (slave_id);
699   return msg;
700 }
701
702
703 /**
704  * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
705  * (testbed service)
706  *
707  * @param c the controller handler
708  * @param msg message received
709  * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
710  *           not
711  */
712 static int
713 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
714                      const struct GNUNET_TESTBED_SlaveConfiguration *msg)
715 {
716   struct OperationContext *opc;
717   uint64_t op_id;
718   struct GNUNET_TESTBED_EventInformation event;
719
720   op_id = GNUNET_ntohll (msg->operation_id);
721   if (NULL == (opc = find_opc (c, op_id)))
722   {
723     LOG_DEBUG ("Operation not found\n");
724     return GNUNET_YES;
725   }
726   if (OP_GET_SLAVE_CONFIG != opc->type)
727   {
728     GNUNET_break (0);
729     return GNUNET_YES;
730   }
731   GNUNET_free (opc->data);
732   opc->data = NULL;
733   opc->state = OPC_STATE_FINISHED;
734   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
735   if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
736       (NULL != c->cc))
737   {
738     opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
739     event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
740     event.details.operation_finished.generic = opc->data;
741     event.details.operation_finished.operation = opc->op;
742     event.details.operation_finished.op_cls = opc->op_cls;
743     event.details.operation_finished.emsg = NULL;
744     c->cc (c->cc_cls, &event);
745   }
746   return GNUNET_YES;
747 }
748
749
750 /**
751  * Handler for messages from controller (testbed service)
752  *
753  * @param cls the controller handler
754  * @param msg message received, NULL on timeout or fatal error
755  */
756 static void
757 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
758 {
759   struct GNUNET_TESTBED_Controller *c = cls;
760   int status;
761   uint16_t msize;
762
763   c->in_receive = GNUNET_NO;
764   /* FIXME: Add checks for message integrity */
765   if (NULL == msg)
766   {
767     LOG_DEBUG ("Receive timed out or connection to service dropped\n");
768     return;
769   }
770   status = GNUNET_OK;
771   msize = ntohs (msg->size);
772   switch (ntohs (msg->type))
773   {
774   case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
775     GNUNET_assert (msize >=
776                    sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
777     status =
778         GNUNET_TESTBED_host_handle_addhostconfirm_
779         (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg);
780     break;
781   case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
782     GNUNET_assert (msize ==
783                    sizeof (struct
784                            GNUNET_TESTBED_GenericOperationSuccessEventMessage));
785     status =
786         handle_opsuccess (c,
787                           (const struct
788                            GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
789                           msg);
790     break;
791   case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
792     GNUNET_assert (msize ==
793                    sizeof (struct
794                            GNUNET_TESTBED_PeerCreateSuccessEventMessage));
795     status =
796         handle_peer_create_success (c,
797                                     (const struct
798                                      GNUNET_TESTBED_PeerCreateSuccessEventMessage
799                                      *) msg);
800     break;
801   case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
802     GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
803     status =
804         handle_peer_event (c,
805                            (const struct GNUNET_TESTBED_PeerEventMessage *)
806                            msg);
807
808     break;
809   case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
810     GNUNET_assert (msize >=
811                    sizeof (struct
812                            GNUNET_TESTBED_PeerConfigurationInformationMessage));
813     status =
814         handle_peer_config (c,
815                             (const struct
816                              GNUNET_TESTBED_PeerConfigurationInformationMessage
817                              *) msg);
818     break;
819   case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
820     GNUNET_assert (msize ==
821                    sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
822     status =
823         handle_peer_conevent (c,
824                               (const struct
825                                GNUNET_TESTBED_ConnectionEventMessage *) msg);
826     break;
827   case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
828     GNUNET_assert (msize >=
829                    sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
830     status =
831         handle_op_fail_event (c,
832                               (const struct
833                                GNUNET_TESTBED_OperationFailureEventMessage *)
834                               msg);
835     break;
836   case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
837     GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
838     status =
839         handle_slave_config (c,
840                              (const struct GNUNET_TESTBED_SlaveConfiguration *)
841                              msg);
842     break;
843   default:
844     GNUNET_assert (0);
845   }
846   if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
847   {
848     c->in_receive = GNUNET_YES;
849     GNUNET_CLIENT_receive (c->client, &message_handler, c,
850                            GNUNET_TIME_UNIT_FOREVER_REL);
851   }
852 }
853
854
855 /**
856  * Function called to notify a client about the connection begin ready to queue
857  * more data.  "buf" will be NULL and "size" zero if the connection was closed
858  * for writing in the meantime.
859  *
860  * @param cls closure
861  * @param size number of bytes available in buf
862  * @param buf where the callee should write the message
863  * @return number of bytes written to buf
864  */
865 static size_t
866 transmit_ready_notify (void *cls, size_t size, void *buf)
867 {
868   struct GNUNET_TESTBED_Controller *c = cls;
869   struct MessageQueue *mq_entry;
870
871   c->th = NULL;
872   mq_entry = c->mq_head;
873   GNUNET_assert (NULL != mq_entry);
874   if ((0 == size) && (NULL == buf))     /* Timeout */
875   {
876     LOG_DEBUG ("Message sending timed out -- retrying\n");
877     c->th =
878         GNUNET_CLIENT_notify_transmit_ready (c->client,
879                                              ntohs (mq_entry->msg->size),
880                                              TIMEOUT_REL, GNUNET_YES,
881                                              &transmit_ready_notify, c);
882     return 0;
883   }
884   GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
885   size = ntohs (mq_entry->msg->size);
886   memcpy (buf, mq_entry->msg, size);
887   LOG_DEBUG ("Message of type: %u and size: %u sent\n",
888              ntohs (mq_entry->msg->type), size);
889   GNUNET_free (mq_entry->msg);
890   GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
891   GNUNET_free (mq_entry);
892   mq_entry = c->mq_head;
893   if (NULL != mq_entry)
894     c->th =
895         GNUNET_CLIENT_notify_transmit_ready (c->client,
896                                              ntohs (mq_entry->msg->size),
897                                              TIMEOUT_REL, GNUNET_YES,
898                                              &transmit_ready_notify, c);
899   if (GNUNET_NO == c->in_receive)
900   {
901     c->in_receive = GNUNET_YES;
902     GNUNET_CLIENT_receive (c->client, &message_handler, c,
903                            GNUNET_TIME_UNIT_FOREVER_REL);
904   }
905   return size;
906 }
907
908
909 /**
910  * Queues a message in send queue for sending to the service
911  *
912  * @param controller the handle to the controller
913  * @param msg the message to queue
914  */
915 void
916 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
917                                struct GNUNET_MessageHeader *msg)
918 {
919   struct MessageQueue *mq_entry;
920   uint16_t type;
921   uint16_t size;
922
923   type = ntohs (msg->type);
924   size = ntohs (msg->size);
925   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
926                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
927   mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
928   mq_entry->msg = msg;
929   LOG (GNUNET_ERROR_TYPE_DEBUG,
930        "Queueing message of type %u, size %u for sending\n", type,
931        ntohs (msg->size));
932   GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
933                                     mq_entry);
934   if (NULL == controller->th)
935     controller->th =
936         GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
937                                              TIMEOUT_REL, GNUNET_YES,
938                                              &transmit_ready_notify,
939                                              controller);
940 }
941
942
943 /**
944  * Sends the given message as an operation. The given callback is called when a
945  * reply for the operation is available.  Call
946  * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
947  * operation context if the cc hasn't been called
948  *
949  * @param controller the controller to which the message has to be sent
950  * @param operation_id the operation id of the message
951  * @param msg the message to send
952  * @param cc the callback to call when reply is available
953  * @param cc_cls the closure for the above callback
954  * @return the operation context which can be used to cancel the forwarded
955  *           operation
956  */
957 struct OperationContext *
958 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
959                                        *controller, uint64_t operation_id,
960                                        const struct GNUNET_MessageHeader *msg,
961                                        GNUNET_CLIENT_MessageHandler cc,
962                                        void *cc_cls)
963 {
964   struct OperationContext *opc;
965   struct ForwardedOperationData *data;
966   struct GNUNET_MessageHeader *dup_msg;
967   uint16_t msize;
968
969   data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
970   data->cc = cc;
971   data->cc_cls = cc_cls;
972   opc = GNUNET_malloc (sizeof (struct OperationContext));
973   opc->c = controller;
974   opc->type = OP_FORWARDED;
975   opc->data = data;
976   opc->id = operation_id;
977   msize = ntohs (msg->size);
978   dup_msg = GNUNET_malloc (msize);
979   (void) memcpy (dup_msg, msg, msize);
980   GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
981   GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
982                                     opc);
983   return opc;
984 }
985
986
987 /**
988  * Function to cancel an operation created by simply forwarding an operation
989  * message.
990  *
991  * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
992  */
993 void
994 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
995 {
996   GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
997   GNUNET_free (opc->data);
998   GNUNET_free (opc);
999 }
1000
1001
1002 /**
1003  * Function to call to start a link-controllers type operation once all queues
1004  * the operation is part of declare that the operation can be activated.
1005  *
1006  * @param cls the closure from GNUNET_TESTBED_operation_create_()
1007  */
1008 static void
1009 opstart_link_controllers (void *cls)
1010 {
1011   struct OperationContext *opc = cls;
1012   struct ControllerLinkData *data;
1013   struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1014
1015   GNUNET_assert (NULL != opc->data);
1016   data = opc->data;
1017   msg = data->msg;
1018   data->msg = NULL;
1019   opc->state = OPC_STATE_STARTED;
1020   GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1021   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1022 }
1023
1024
1025 /**
1026  * Callback which will be called when link-controllers type operation is released
1027  *
1028  * @param cls the closure from GNUNET_TESTBED_operation_create_()
1029  */
1030 static void
1031 oprelease_link_controllers (void *cls)
1032 {
1033   struct OperationContext *opc = cls;
1034   struct ControllerLinkData *data;
1035
1036   data = opc->data;
1037   switch (opc->state)
1038   {
1039   case OPC_STATE_INIT:
1040     GNUNET_free (data->msg);
1041     break;
1042   case OPC_STATE_STARTED:
1043     GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1044     break;
1045   case OPC_STATE_FINISHED:
1046     break;
1047   }
1048   GNUNET_free_non_null (data);
1049   GNUNET_free (opc);
1050 }
1051
1052
1053 /**
1054  * Function to be called when get slave config operation is ready
1055  *
1056  * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1057  */
1058 static void
1059 opstart_get_slave_config (void *cls)
1060 {
1061   struct OperationContext *opc = cls;
1062   struct GetSlaveConfigData *data;
1063   struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1064
1065   data = opc->data;
1066   msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1067   GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1068   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1069   opc->state = OPC_STATE_STARTED;
1070 }
1071
1072
1073 /**
1074  * Function to be called when get slave config operation is cancelled or finished
1075  *
1076  * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1077  */
1078 static void
1079 oprelease_get_slave_config (void *cls)
1080 {
1081   struct OperationContext *opc = cls;
1082
1083   switch (opc->state)
1084   {
1085   case OPC_STATE_INIT:
1086     GNUNET_free (opc->data);
1087     break;
1088   case OPC_STATE_STARTED:
1089     GNUNET_free (opc->data);
1090     GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1091     break;
1092   case OPC_STATE_FINISHED:
1093     if (NULL != opc->data)
1094       GNUNET_CONFIGURATION_destroy (opc->data);
1095     break;
1096   }
1097   GNUNET_free (opc);
1098 }
1099
1100
1101 /**
1102  * Start a controller process using the given configuration at the
1103  * given host.
1104  *
1105  * @param cfg configuration to use
1106  * @param host host to run the controller on; This should be the same host if
1107  *          the controller was previously started with
1108  *          GNUNET_TESTBED_controller_start; NULL for localhost
1109  * @param event_mask bit mask with set of events to call 'cc' for;
1110  *                   or-ed values of "1LL" shifted by the
1111  *                   respective 'enum GNUNET_TESTBED_EventType'
1112  *                   (i.e.  "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1113  * @param cc controller callback to invoke on events
1114  * @param cc_cls closure for cc
1115  * @return handle to the controller
1116  */
1117 struct GNUNET_TESTBED_Controller *
1118 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1119                                    *cfg, struct GNUNET_TESTBED_Host *host,
1120                                    uint64_t event_mask,
1121                                    GNUNET_TESTBED_ControllerCallback cc,
1122                                    void *cc_cls)
1123 {
1124   struct GNUNET_TESTBED_Controller *controller;
1125   struct GNUNET_TESTBED_InitMessage *msg;
1126   const char *controller_hostname;
1127   unsigned long long max_parallel_operations;
1128   unsigned long long max_parallel_service_connections;
1129   unsigned long long max_parallel_topology_config_operations;
1130
1131   if (GNUNET_OK !=
1132       GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1133                                              "MAX_PARALLEL_OPERATIONS",
1134                                              &max_parallel_operations))
1135   {
1136     GNUNET_break (0);
1137     return NULL;
1138   }
1139   if (GNUNET_OK !=
1140       GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1141                                              "MAX_PARALLEL_SERVICE_CONNECTIONS",
1142                                              &max_parallel_service_connections))
1143   {
1144     GNUNET_break (0);
1145     return NULL;
1146   }
1147   if (GNUNET_OK !=
1148       GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1149                                              "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1150                                              &max_parallel_topology_config_operations))
1151   {
1152     GNUNET_break (0);
1153     return NULL;
1154   }
1155   controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1156   controller->cc = cc;
1157   controller->cc_cls = cc_cls;
1158   controller->event_mask = event_mask;
1159   controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1160   controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1161   if (NULL == controller->client)
1162   {
1163     GNUNET_TESTBED_controller_disconnect (controller);
1164     return NULL;
1165   }
1166   if (NULL == host)
1167   {
1168     host = GNUNET_TESTBED_host_create_by_id_ (0, controller->cfg);
1169     if (NULL == host)           /* If the above host create fails */
1170     {
1171       LOG (GNUNET_ERROR_TYPE_WARNING,
1172            "Treating NULL host as localhost. Multiple references to localhost "
1173            "may break when localhost freed before calling disconnect \n");
1174       host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1175     }
1176     else
1177     {
1178       controller->aux_host = GNUNET_YES;
1179     }
1180   }
1181   GNUNET_assert (NULL != host);
1182   GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1183   controller->host = host;
1184   controller->opq_parallel_operations =
1185       GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1186                                               max_parallel_operations);
1187   controller->opq_parallel_service_connections =
1188       GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1189                                               max_parallel_service_connections);
1190   controller->opq_parallel_topology_config_operations =
1191       GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1192                                               max_parallel_topology_config_operations);
1193   controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1194   if (NULL == controller_hostname)
1195     controller_hostname = "127.0.0.1";
1196   msg =
1197       GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1198                      strlen (controller_hostname) + 1);
1199   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1200   msg->header.size =
1201       htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1202              strlen (controller_hostname) + 1);
1203   msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1204   msg->event_mask = GNUNET_htonll (controller->event_mask);
1205   strcpy ((char *) &msg[1], controller_hostname);
1206   GNUNET_TESTBED_queue_message_ (controller,
1207                                  (struct GNUNET_MessageHeader *) msg);
1208   return controller;
1209 }
1210
1211
1212 /**
1213  * Configure shared services at a controller.  Using this function,
1214  * you can specify that certain services (such as "resolver")
1215  * should not be run for each peer but instead be shared
1216  * across N peers on the specified host.  This function
1217  * must be called before any peers are created at the host.
1218  *
1219  * @param controller controller to configure
1220  * @param service_name name of the service to share
1221  * @param num_peers number of peers that should share one instance
1222  *        of the specified service (1 for no sharing is the default),
1223  *        use 0 to disable the service
1224  */
1225 void
1226 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1227                                              *controller,
1228                                              const char *service_name,
1229                                              uint32_t num_peers)
1230 {
1231   struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1232   uint16_t service_name_size;
1233   uint16_t msg_size;
1234
1235   service_name_size = strlen (service_name) + 1;
1236   msg_size =
1237       sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1238       service_name_size;
1239   msg = GNUNET_malloc (msg_size);
1240   msg->header.size = htons (msg_size);
1241   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE);
1242   msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1243   msg->num_peers = htonl (num_peers);
1244   memcpy (&msg[1], service_name, service_name_size);
1245   GNUNET_TESTBED_queue_message_ (controller,
1246                                  (struct GNUNET_MessageHeader *) msg);
1247   GNUNET_break (0);             /* This function is not yet implemented on the
1248                                  * testbed service */
1249 }
1250
1251
1252 /**
1253  * disconnects from the controller.
1254  *
1255  * @param controller handle to controller to stop
1256  */
1257 void
1258 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1259                                       *controller)
1260 {
1261   struct MessageQueue *mq_entry;
1262
1263   if (NULL != controller->th)
1264     GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1265   /* Clear the message queue */
1266   while (NULL != (mq_entry = controller->mq_head))
1267   {
1268     GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1269                                  mq_entry);
1270     GNUNET_free (mq_entry->msg);
1271     GNUNET_free (mq_entry);
1272   }
1273   if (NULL != controller->client)
1274     GNUNET_CLIENT_disconnect (controller->client);
1275   GNUNET_CONFIGURATION_destroy (controller->cfg);
1276   if (GNUNET_YES == controller->aux_host)
1277     GNUNET_TESTBED_host_destroy (controller->host);
1278   GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1279   GNUNET_TESTBED_operation_queue_destroy_
1280       (controller->opq_parallel_service_connections);
1281   GNUNET_TESTBED_operation_queue_destroy_
1282       (controller->opq_parallel_topology_config_operations);
1283   GNUNET_free (controller);
1284 }
1285
1286
1287 /**
1288  * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1289  * and slave host
1290  *
1291  * @param op_cls the operation closure for the event which is generated to
1292  *          signal success or failure of this operation
1293  * @param master handle to the master controller who creates the association
1294  * @param delegated_host_id id of the host to which requests should be delegated
1295  * @param slave_host_id id of the host which is used to run the slave controller
1296  * @param sxcfg serialized and compressed configuration
1297  * @param sxcfg_size the size sxcfg
1298  * @param scfg_size the size of uncompressed serialized configuration
1299  * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1300  *          be started by the slave controller; GNUNET_NO if the slave
1301  *          controller has to connect to the already started delegated
1302  *          controller via TCP/IP
1303  * @return the operation handle
1304  */
1305 struct GNUNET_TESTBED_Operation *
1306 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1307                                    struct GNUNET_TESTBED_Controller *master,
1308                                    uint32_t delegated_host_id,
1309                                    uint32_t slave_host_id, const char *sxcfg,
1310                                    size_t sxcfg_size, size_t scfg_size,
1311                                    int is_subordinate)
1312 {
1313   struct OperationContext *opc;
1314   struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1315   struct ControllerLinkData *data;
1316   uint16_t msg_size;
1317
1318   msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1319   msg = GNUNET_malloc (msg_size);
1320   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1321   msg->header.size = htons (msg_size);
1322   msg->delegated_host_id = htonl (delegated_host_id);
1323   msg->slave_host_id = htonl (slave_host_id);
1324   msg->config_size = htons ((uint16_t) scfg_size);
1325   msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1326   memcpy (&msg[1], sxcfg, sxcfg_size);
1327   data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1328   data->msg = msg;
1329   opc = GNUNET_malloc (sizeof (struct OperationContext));
1330   opc->c = master;
1331   opc->data = data;
1332   opc->type = OP_LINK_CONTROLLERS;
1333   opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1334   opc->state = OPC_STATE_INIT;
1335   opc->op_cls = op_cls;
1336   msg->operation_id = GNUNET_htonll (opc->id);
1337   opc->op =
1338       GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1339                                         &oprelease_link_controllers);
1340   GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1341                                           opc->op);
1342   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1343   return opc->op;
1344 }
1345
1346
1347 /**
1348  * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1349  * serialized and compressed
1350  *
1351  * @param op_cls the operation closure for the event which is generated to
1352  *          signal success or failure of this operation
1353  * @param master handle to the master controller who creates the association
1354  * @param delegated_host requests to which host should be delegated; cannot be NULL
1355  * @param slave_host which host is used to run the slave controller; use NULL to
1356  *          make the master controller connect to the delegated host
1357  * @param sxcfg serialized and compressed configuration
1358  * @param sxcfg_size the size sxcfg
1359  * @param scfg_size the size of uncompressed serialized configuration
1360  * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1361  *          be started by the slave controller; GNUNET_NO if the slave
1362  *          controller has to connect to the already started delegated
1363  *          controller via TCP/IP
1364  * @return the operation handle
1365  */
1366 struct GNUNET_TESTBED_Operation *
1367 GNUNET_TESTBED_controller_link_2 (void *op_cls,
1368                                   struct GNUNET_TESTBED_Controller *master,
1369                                   struct GNUNET_TESTBED_Host *delegated_host,
1370                                   struct GNUNET_TESTBED_Host *slave_host,
1371                                   const char *sxcfg, size_t sxcfg_size,
1372                                   size_t scfg_size, int is_subordinate)
1373 {
1374   uint32_t delegated_host_id;
1375   uint32_t slave_host_id;
1376
1377   GNUNET_assert (GNUNET_YES ==
1378                  GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1379   delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1380   slave_host_id =
1381       GNUNET_TESTBED_host_get_id_ ((NULL !=
1382                                     slave_host) ? slave_host : master->host);
1383   if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1384     GNUNET_assert (GNUNET_YES ==
1385                    GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1386
1387   return GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1388                                             slave_host_id, sxcfg, sxcfg_size,
1389                                             scfg_size, is_subordinate);
1390 }
1391
1392
1393 /**
1394  * Compresses given configuration using zlib compress
1395  *
1396  * @param config the serialized configuration
1397  * @param size the size of config
1398  * @param xconfig will be set to the compressed configuration (memory is fresly
1399  *          allocated)
1400  * @return the size of the xconfig
1401  */
1402 size_t
1403 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1404                                  char **xconfig)
1405 {
1406   size_t xsize;
1407
1408   xsize = compressBound ((uLong) size);
1409   *xconfig = GNUNET_malloc (xsize);
1410   GNUNET_assert (Z_OK ==
1411                  compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1412                             (const Bytef *) config, (uLongf) size,
1413                             Z_BEST_SPEED));
1414   return xsize;
1415 }
1416
1417
1418 /**
1419  * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
1420  * and slave host
1421  *
1422  * @param op_cls the operation closure for the event which is generated to
1423  *          signal success or failure of this operation
1424  * @param master handle to the master controller who creates the association
1425  * @param delegated_host_id id of the host to which requests should be
1426  *          delegated; cannot be NULL
1427  * @param slave_host_id id of the host which should connect to controller
1428  *          running on delegated host ; use NULL to make the master controller
1429  *          connect to the delegated host
1430  * @param slave_cfg configuration to use for the slave controller
1431  * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1432  *          be started by the slave controller; GNUNET_NO if the slave
1433  *          controller has to connect to the already started delegated
1434  *          controller via TCP/IP
1435  * @return the operation handle
1436  */
1437 struct GNUNET_TESTBED_Operation *
1438 GNUNET_TESTBED_controller_link_ (void *op_cls,
1439                                  struct GNUNET_TESTBED_Controller *master,
1440                                  uint32_t delegated_host_id,
1441                                  uint32_t slave_host_id,
1442                                  const struct GNUNET_CONFIGURATION_Handle
1443                                  *slave_cfg, int is_subordinate)
1444 {
1445   struct GNUNET_TESTBED_Operation *op;
1446   char *config;
1447   char *cconfig;
1448   size_t cc_size;
1449   size_t config_size;
1450
1451   config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
1452   cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
1453   GNUNET_free (config);
1454   /* Configuration doesn't fit in 1 message */
1455   GNUNET_assert ((UINT16_MAX -
1456                   sizeof (struct GNUNET_TESTBED_ControllerLinkMessage)) >=
1457                  cc_size);
1458   op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1459                                           slave_host_id, (const char *) cconfig,
1460                                           cc_size, config_size, is_subordinate);
1461   GNUNET_free (cconfig);
1462   return op;
1463 }
1464
1465
1466 /**
1467  * Create a link from slave controller to delegated controller. Whenever the
1468  * master controller is asked to start a peer at the delegated controller the
1469  * request will be routed towards slave controller (if a route exists). The
1470  * slave controller will then route it to the delegated controller. The
1471  * configuration of the delegated controller is given and is used to either
1472  * create the delegated controller or to connect to an existing controller. Note
1473  * that while starting the delegated controller the configuration will be
1474  * modified to accommodate available free ports.  the 'is_subordinate' specifies
1475  * if the given delegated controller should be started and managed by the slave
1476  * controller, or if the delegated controller already has a master and the slave
1477  * controller connects to it as a non master controller. The success or failure
1478  * of this operation will be signalled through the
1479  * GNUNET_TESTBED_ControllerCallback() with an event of type
1480  * GNUNET_TESTBED_ET_OPERATION_FINISHED
1481  *
1482  * @param op_cls the operation closure for the event which is generated to
1483  *          signal success or failure of this operation
1484  * @param master handle to the master controller who creates the association
1485  * @param delegated_host requests to which host should be delegated; cannot be NULL
1486  * @param slave_host which host is used to run the slave controller; use NULL to
1487  *          make the master controller connect to the delegated host
1488  * @param slave_cfg configuration to use for the slave controller
1489  * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1490  *          be started by the slave controller; GNUNET_NO if the slave
1491  *          controller has to connect to the already started delegated
1492  *          controller via TCP/IP
1493  * @return the operation handle
1494  */
1495 struct GNUNET_TESTBED_Operation *
1496 GNUNET_TESTBED_controller_link (void *op_cls,
1497                                 struct GNUNET_TESTBED_Controller *master,
1498                                 struct GNUNET_TESTBED_Host *delegated_host,
1499                                 struct GNUNET_TESTBED_Host *slave_host,
1500                                 const struct GNUNET_CONFIGURATION_Handle
1501                                 *slave_cfg, int is_subordinate)
1502 {
1503   uint32_t slave_host_id;
1504   uint32_t delegated_host_id;
1505
1506   GNUNET_assert (GNUNET_YES ==
1507                  GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1508   slave_host_id =
1509       GNUNET_TESTBED_host_get_id_ ((NULL !=
1510                                     slave_host) ? slave_host : master->host);
1511   delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1512   if ((NULL != slave_host) && (0 != slave_host_id))
1513     GNUNET_assert (GNUNET_YES ==
1514                    GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1515   return GNUNET_TESTBED_controller_link_ (op_cls, master, delegated_host_id,
1516                                           slave_host_id, slave_cfg,
1517                                           is_subordinate);
1518
1519 }
1520
1521
1522 /**
1523  * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1524  * check. Another difference is that this function takes the id of the slave
1525  * host.
1526  *
1527  * @param op_cls the closure for the operation
1528  * @param master the handle to master controller
1529  * @param slave_host_id id of the host where the slave controller is running to
1530  *          the slave_host should remain valid until this operation is cancelled
1531  *          or marked as finished
1532  * @return the operation handle;
1533  */
1534 struct GNUNET_TESTBED_Operation *
1535 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1536                                   struct GNUNET_TESTBED_Controller *master,
1537                                   uint32_t slave_host_id)
1538 {
1539   struct OperationContext *opc;
1540   struct GetSlaveConfigData *data;
1541
1542   data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
1543   data->slave_id = slave_host_id;
1544   opc = GNUNET_malloc (sizeof (struct OperationContext));
1545   opc->state = OPC_STATE_INIT;
1546   opc->c = master;
1547   opc->id = GNUNET_TESTBED_get_next_op_id (master);
1548   opc->type = OP_GET_SLAVE_CONFIG;
1549   opc->data = data;
1550   opc->op_cls = op_cls;
1551   opc->op =
1552       GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1553                                         &oprelease_get_slave_config);
1554   GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1555                                           opc->op);
1556   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1557   return opc->op;
1558 }
1559
1560
1561 /**
1562  * Function to acquire the configuration of a running slave controller. The
1563  * completion of the operation is signalled through the controller_cb from
1564  * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1565  * handle to the configuration is available in the generic pointer of
1566  * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1567  *
1568  * @param op_cls the closure for the operation
1569  * @param master the handle to master controller
1570  * @param slave_host the host where the slave controller is running; the handle
1571  *          to the slave_host should remain valid until this operation is
1572  *          cancelled or marked as finished
1573  * @return the operation handle; NULL if the slave_host is not registered at
1574  *           master
1575  */
1576 struct GNUNET_TESTBED_Operation *
1577 GNUNET_TESTBED_get_slave_config (void *op_cls,
1578                                  struct GNUNET_TESTBED_Controller *master,
1579                                  struct GNUNET_TESTBED_Host *slave_host)
1580 {
1581   if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1582     return NULL;
1583   return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1584                                            GNUNET_TESTBED_host_get_id_
1585                                            (slave_host));
1586 }
1587
1588
1589 /**
1590  * Ask the testbed controller to write the current overlay topology to
1591  * a file.  Naturally, the file will only contain a snapshot as the
1592  * topology may evolve all the time.
1593  *
1594  * @param controller overlay controller to inspect
1595  * @param filename name of the file the topology should
1596  *        be written to.
1597  */
1598 void
1599 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1600                                                *controller,
1601                                                const char *filename)
1602 {
1603   GNUNET_break (0);
1604 }
1605
1606
1607 /**
1608  * Creates a helper initialization message. This function is here because we
1609  * want to use this in testing
1610  *
1611  * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1612  *          HOST(all connections form this ip are permitted by the testbed) when
1613  *          starting testbed controller at host. This can either be a single ip
1614  *          address or a network address in CIDR notation.
1615  * @param hostname the hostname of the destination this message is intended for
1616  * @param cfg the configuration that has to used to start the testbed service
1617  *          thru helper
1618  * @return the initialization message
1619  */
1620 struct GNUNET_TESTBED_HelperInit *
1621 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1622                                         const char *hostname,
1623                                         const struct GNUNET_CONFIGURATION_Handle
1624                                         *cfg)
1625 {
1626   struct GNUNET_TESTBED_HelperInit *msg;
1627   char *config;
1628   char *xconfig;
1629   size_t config_size;
1630   size_t xconfig_size;
1631   uint16_t trusted_ip_len;
1632   uint16_t hostname_len;
1633   uint16_t msg_size;
1634
1635   config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1636   GNUNET_assert (NULL != config);
1637   xconfig_size =
1638       GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1639   GNUNET_free (config);
1640   trusted_ip_len = strlen (trusted_ip);
1641   hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
1642   msg_size =
1643       xconfig_size + trusted_ip_len + 1 +
1644       sizeof (struct GNUNET_TESTBED_HelperInit);
1645   msg_size += hostname_len;
1646   msg = GNUNET_realloc (xconfig, msg_size);
1647   (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
1648                   xconfig_size);
1649   msg->header.size = htons (msg_size);
1650   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
1651   msg->trusted_ip_size = htons (trusted_ip_len);
1652   msg->hostname_size = htons (hostname_len);
1653   msg->config_size = htons (config_size);
1654   (void) strcpy ((char *) &msg[1], trusted_ip);
1655   if (0 != hostname_len)
1656     (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
1657                     hostname_len);
1658   return msg;
1659 }
1660
1661
1662 /**
1663  * Cancel a pending operation.  Releases all resources
1664  * of the operation and will ensure that no event
1665  * is generated for the operation.  Does NOT guarantee
1666  * that the operation will be fully undone (or that
1667  * nothing ever happened).
1668  *
1669  * @param operation operation to cancel
1670  */
1671 void
1672 GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
1673 {
1674   GNUNET_TESTBED_operation_done (operation);
1675 }
1676
1677
1678 /**
1679  * Signal that the information from an operation has been fully
1680  * processed.  This function MUST be called for each event
1681  * of type 'operation_finished' to fully remove the operation
1682  * from the operation queue.  After calling this function, the
1683  * 'op_result' becomes invalid (!).
1684  *
1685  * @param operation operation to signal completion for
1686  */
1687 void
1688 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1689 {
1690   last_finished_operation = operation;
1691   GNUNET_TESTBED_operation_release_ (operation);
1692 }
1693
1694
1695 /**
1696  * Generates configuration by uncompressing configuration in given message. The
1697  * given message should be of the following types:
1698  * GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION,
1699  * GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1700  * GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST
1701  *
1702  * @param msg the message containing compressed configuration
1703  * @return handle to the parsed configuration; NULL upon error while parsing the message
1704  */
1705 struct GNUNET_CONFIGURATION_Handle *
1706 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1707 {
1708   struct GNUNET_CONFIGURATION_Handle *cfg;
1709   Bytef *data;
1710   const Bytef *xdata;
1711   uLong data_len;
1712   uLong xdata_len;
1713   int ret;
1714
1715   switch (ntohs (msg->type))
1716   {
1717   case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
1718   {
1719     const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
1720
1721     imsg =
1722         (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1723     data_len = (uLong) ntohs (imsg->config_size);
1724     xdata_len =
1725         ntohs (imsg->header.size) -
1726         sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1727     xdata = (const Bytef *) &imsg[1];
1728   }
1729     break;
1730   case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1731   {
1732     const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
1733
1734     imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
1735     data_len = (uLong) ntohs (imsg->config_size);
1736     xdata_len =
1737         ntohs (imsg->header.size) -
1738         sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
1739     xdata = (const Bytef *) &imsg[1];
1740   }
1741   break;
1742   case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
1743     {
1744       const struct GNUNET_TESTBED_AddHostMessage *imsg;
1745       uint16_t osize;
1746       
1747       imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
1748       data_len = (uLong) ntohs (imsg->config_size);
1749       osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1750           ntohs (imsg->username_length) + ntohs (imsg->hostname_length); 
1751       xdata_len = ntohs (imsg->header.size) - osize;
1752       xdata = (const Bytef *) ((const void *) imsg + osize);
1753     }
1754     break;
1755   default:
1756     GNUNET_assert (0);
1757   }
1758   data = GNUNET_malloc (data_len);
1759   if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
1760   {
1761     GNUNET_free (data);
1762     return NULL;
1763   }
1764   cfg = GNUNET_CONFIGURATION_create ();
1765   GNUNET_assert (GNUNET_OK ==
1766                  GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
1767                                                    (size_t) data_len,
1768                                                    GNUNET_NO));
1769   GNUNET_free (data);
1770   return cfg;
1771 }
1772
1773
1774 /**
1775  * Checks the integrity of the OperationFailureEventMessage and if good returns
1776  * the error message it contains.
1777  *
1778  * @param msg the OperationFailureEventMessage
1779  * @return the error message
1780  */
1781 const char *
1782 GNUNET_TESTBED_parse_error_string_ (const struct
1783                                     GNUNET_TESTBED_OperationFailureEventMessage
1784                                     *msg)
1785 {
1786   uint16_t msize;
1787   const char *emsg;
1788
1789   msize = ntohs (msg->header.size);
1790   if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
1791     return NULL;
1792   msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
1793   emsg = (const char *) &msg[1];
1794   if ('\0' != emsg[msize - 1])
1795   {
1796     GNUNET_break (0);
1797     return NULL;
1798   }
1799   return emsg;
1800 }
1801
1802
1803 /**
1804  * Function to return the operation id for a controller. The operation id is
1805  * created from the controllers host id and its internal operation counter.
1806  *
1807  * @param controller the handle to the controller whose operation id has to be incremented
1808  * @return the incremented operation id.
1809  */
1810 uint64_t
1811 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
1812 {
1813   uint64_t op_id;
1814
1815   op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
1816   op_id = op_id << 32;
1817   op_id |= (uint64_t) controller->operation_counter++;
1818   return op_id;
1819 }
1820
1821
1822 /* end of testbed_api.c */