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