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