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