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