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