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