yapf format.
[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 it
6       under the terms of the GNU Affero General Public License as published
7       by the Free Software Foundation, either version 3 of the License,
8       or (at your 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       Affero General Public License for more details.
14
15       You should have received a copy of the GNU Affero General Public License
16       along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
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, ...) GNUNET_log_from (kind, "testbed-api", __VA_ARGS__)
48
49 /**
50  * Debug logging
51  */
52 #define LOG_DEBUG(...) LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
53
54 /**
55  * Relative time seconds shorthand
56  */
57 #define TIME_REL_SECS(sec) \
58   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
59
60
61 /**
62  * Default server message sending retry timeout
63  */
64 #define TIMEOUT_REL TIME_REL_SECS (1)
65
66
67 /**
68  * Context data for forwarded Operation
69  */
70 struct ForwardedOperationData
71 {
72   /**
73    * The callback to call when reply is available
74    */
75   GNUNET_MQ_MessageCallback cc;
76
77   /**
78    * The closure for the above callback
79    */
80   void *cc_cls;
81 };
82
83
84 /**
85  * Context data for get slave config operations
86  */
87 struct GetSlaveConfigData
88 {
89   /**
90    * The id of the slave controller
91    */
92   uint32_t slave_id;
93 };
94
95
96 /**
97  * Context data for controller link operations
98  */
99 struct ControllerLinkData
100 {
101   /**
102    * The controller link message
103    */
104   struct GNUNET_TESTBED_ControllerLinkRequest *msg;
105
106   /**
107    * The id of the host which is hosting the controller to be linked
108    */
109   uint32_t host_id;
110 };
111
112
113 /**
114  * Date context for OP_SHUTDOWN_PEERS operations
115  */
116 struct ShutdownPeersData
117 {
118   /**
119    * The operation completion callback to call
120    */
121   GNUNET_TESTBED_OperationCompletionCallback cb;
122
123   /**
124    * The closure for the above callback
125    */
126   void *cb_cls;
127 };
128
129
130 /**
131  * An entry in the stack for keeping operations which are about to expire
132  */
133 struct ExpireOperationEntry
134 {
135   /**
136    * DLL head; new entries are to be inserted here
137    */
138   struct ExpireOperationEntry *next;
139
140   /**
141    * DLL tail; entries are deleted from here
142    */
143   struct ExpireOperationEntry *prev;
144
145   /**
146    * The operation.  This will be a dangling pointer when the operation is freed
147    */
148   const struct GNUNET_TESTBED_Operation *op;
149 };
150
151
152 /**
153  * DLL head for list of operations marked for expiry
154  */
155 static struct ExpireOperationEntry *exop_head;
156
157 /**
158  * DLL tail for list of operation marked for expiry
159  */
160 static struct ExpireOperationEntry *exop_tail;
161
162
163 /**
164  * Inserts an operation into the list of operations marked for expiry
165  *
166  * @param op the operation to insert
167  */
168 static void
169 exop_insert (struct GNUNET_TESTBED_Operation *op)
170 {
171   struct ExpireOperationEntry *entry;
172
173   entry = GNUNET_new (struct ExpireOperationEntry);
174   entry->op = op;
175   GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry);
176 }
177
178
179 /**
180  * Checks if an operation is present in the list of operations marked for
181  * expiry.  If the operation is found, it and the tail of operations after it
182  * are removed from the list.
183  *
184  * @param op the operation to check
185  * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if
186  *           the operation is found in the list (the operation is then removed
187  *           from the list -- calling this function again with the same
188  *           paramenter will return GNUNET_NO)
189  */
190 static int
191 exop_check (const struct GNUNET_TESTBED_Operation *const op)
192 {
193   struct ExpireOperationEntry *entry;
194   struct ExpireOperationEntry *entry2;
195   int found;
196
197   found = GNUNET_NO;
198   entry = exop_head;
199   while (NULL != entry)
200   {
201     if (op == entry->op)
202     {
203       found = GNUNET_YES;
204       break;
205     }
206     entry = entry->next;
207   }
208   if (GNUNET_NO == found)
209     return GNUNET_NO;
210   /* Truncate the tail */
211   while (NULL != entry)
212   {
213     entry2 = entry->next;
214     GNUNET_CONTAINER_DLL_remove (exop_head, exop_tail, entry);
215     GNUNET_free (entry);
216     entry = entry2;
217   }
218   return GNUNET_YES;
219 }
220
221
222 /**
223  * Context information to be used while searching for operation contexts
224  */
225 struct SearchContext
226 {
227   /**
228    * The result of the search
229    */
230   struct OperationContext *opc;
231
232   /**
233    * The id of the operation context we are searching for
234    */
235   uint64_t id;
236 };
237
238
239 /**
240  * Search iterator for searching an operation context
241  *
242  * @param cls the serach context
243  * @param key current key code
244  * @param value value in the hash map
245  * @return #GNUNET_YES if we should continue to iterate,
246  *         #GNUNET_NO if not.
247  */
248 static int
249 opc_search_iterator (void *cls, uint32_t key, void *value)
250 {
251   struct SearchContext *sc = cls;
252   struct OperationContext *opc = value;
253
254   GNUNET_assert (NULL != opc);
255   GNUNET_assert (NULL == sc->opc);
256   if (opc->id != sc->id)
257     return GNUNET_YES;
258   sc->opc = opc;
259   return GNUNET_NO;
260 }
261
262
263 /**
264  * Returns the operation context with the given id if found in the Operation
265  * context queues of the controller
266  *
267  * @param c the controller whose operation context map is searched
268  * @param id the id which has to be checked
269  * @return the matching operation context; NULL if no match found
270  */
271 static struct OperationContext *
272 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
273 {
274   struct SearchContext sc;
275
276   sc.id = id;
277   sc.opc = NULL;
278   GNUNET_assert (NULL != c->opc_map);
279   if (GNUNET_SYSERR !=
280       GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map,
281                                                     (uint32_t) id,
282                                                     &opc_search_iterator,
283                                                     &sc))
284     return NULL;
285   return sc.opc;
286 }
287
288
289 /**
290  * Inserts the given operation context into the operation context map of the
291  * given controller.  Creates the operation context map if one does not exist
292  * for the controller
293  *
294  * @param c the controller
295  * @param opc the operation context to be inserted
296  */
297 void
298 GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c,
299                             struct OperationContext *opc)
300 {
301   if (NULL == c->opc_map)
302     c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256);
303   GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap32_put (
304                    c->opc_map,
305                    (uint32_t) opc->id,
306                    opc,
307                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
308 }
309
310
311 /**
312  * Removes the given operation context from the operation context map of the
313  * given controller
314  *
315  * @param c the controller
316  * @param opc the operation context to remove
317  */
318 void
319 GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c,
320                             struct OperationContext *opc)
321 {
322   GNUNET_assert (NULL != c->opc_map);
323   GNUNET_assert (GNUNET_YES ==
324                  GNUNET_CONTAINER_multihashmap32_remove (c->opc_map,
325                                                          (uint32_t) opc->id,
326                                                          opc));
327   if ((0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map)) &&
328       (NULL != c->opcq_empty_cb))
329     c->opcq_empty_cb (c->opcq_empty_cls);
330 }
331
332
333 /**
334  * Check #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message is well-formed.
335  *
336  * @param cls the controller handler
337  * @param msg message received
338  * @return #GNUNET_OK if message is well-formed
339  */
340 static int
341 check_add_host_confirm (void *cls,
342                         const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
343 {
344   const char *emsg;
345   uint16_t msg_size;
346
347   msg_size = ntohs (msg->header.size) - sizeof(*msg);
348   if (0 == msg_size)
349     return GNUNET_OK;
350   /* We have an error message */
351   emsg = (const char *) &msg[1];
352   if ('\0' != emsg[msg_size - 1])
353   {
354     GNUNET_break (0);
355     return GNUNET_SYSERR;
356   }
357   return GNUNET_OK;
358 }
359
360
361 /**
362  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
363  * controller (testbed service)
364  *
365  * @param cls the controller handler
366  * @param msg message received
367  */
368 static void
369 handle_add_host_confirm (void *cls,
370                          const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
371 {
372   struct GNUNET_TESTBED_Controller *c = cls;
373   struct GNUNET_TESTBED_HostRegistrationHandle *rh = c->rh;
374   const char *emsg;
375   uint16_t msg_size;
376
377   if (NULL == rh)
378     return;
379   if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
380   {
381     LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
382                GNUNET_TESTBED_host_get_id_ (rh->host),
383                ntohl (msg->host_id));
384     return;
385   }
386   c->rh = NULL;
387   msg_size = ntohs (msg->header.size) - sizeof(*msg);
388   if (0 == msg_size)
389   {
390     LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id));
391     GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c);
392     rh->cc (rh->cc_cls, NULL);
393     GNUNET_free (rh);
394     return;
395   }
396   /* We have an error message */
397   emsg = (const char *) &msg[1];
398   LOG (GNUNET_ERROR_TYPE_ERROR,
399        _ ("Adding host %u failed with error: %s\n"),
400        ntohl (msg->host_id),
401        emsg);
402   rh->cc (rh->cc_cls, emsg);
403   GNUNET_free (rh);
404 }
405
406
407 /**
408  * Handler for forwarded operations
409  *
410  * @param c the controller handle
411  * @param opc the opearation context
412  * @param msg the message
413  */
414 static void
415 handle_forwarded_operation_msg (void *cls,
416                                 struct OperationContext *opc,
417                                 const struct GNUNET_MessageHeader *msg)
418 {
419   struct GNUNET_TESTBED_Controller *c = cls;
420   struct ForwardedOperationData *fo_data;
421
422   fo_data = opc->data;
423   if (NULL != fo_data->cc)
424     fo_data->cc (fo_data->cc_cls, msg);
425   GNUNET_TESTBED_remove_opc_ (c, opc);
426   GNUNET_free (fo_data);
427   GNUNET_free (opc);
428 }
429
430
431 /**
432  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS message from
433  * controller (testbed service)
434  *
435  * @param c the controller handler
436  * @param msg message received
437  */
438 static void
439 handle_opsuccess (
440   void *cls,
441   const struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
442 {
443   struct GNUNET_TESTBED_Controller *c = cls;
444   struct OperationContext *opc;
445   GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
446   void *op_comp_cb_cls;
447   struct GNUNET_TESTBED_EventInformation event;
448   uint64_t op_id;
449
450   op_id = GNUNET_ntohll (msg->operation_id);
451   LOG_DEBUG ("Operation %lu successful\n", op_id);
452   if (NULL == (opc = find_opc (c, op_id)))
453   {
454     LOG_DEBUG ("Operation not found\n");
455     return;
456   }
457   event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
458   event.op = opc->op;
459   event.op_cls = opc->op_cls;
460   event.details.operation_finished.emsg = NULL;
461   event.details.operation_finished.generic = NULL;
462   op_comp_cb = NULL;
463   op_comp_cb_cls = NULL;
464   switch (opc->type)
465   {
466   case OP_FORWARDED: {
467       handle_forwarded_operation_msg (c,
468                                       opc,
469                                       (const struct
470                                        GNUNET_MessageHeader *) msg);
471       return;
472     }
473     break;
474
475   case OP_PEER_DESTROY: {
476       struct GNUNET_TESTBED_Peer *peer;
477
478       peer = opc->data;
479       GNUNET_TESTBED_peer_deregister_ (peer);
480       GNUNET_free (peer);
481       opc->data = NULL;
482       // PEERDESTROYDATA
483     }
484     break;
485
486   case OP_SHUTDOWN_PEERS: {
487       struct ShutdownPeersData *data;
488
489       data = opc->data;
490       op_comp_cb = data->cb;
491       op_comp_cb_cls = data->cb_cls;
492       GNUNET_free (data);
493       opc->data = NULL;
494       GNUNET_TESTBED_cleanup_peers_ ();
495     }
496     break;
497
498   case OP_MANAGE_SERVICE: {
499       struct ManageServiceData *data;
500
501       GNUNET_assert (NULL != (data = opc->data));
502       op_comp_cb = data->cb;
503       op_comp_cb_cls = data->cb_cls;
504       GNUNET_free (data);
505       opc->data = NULL;
506     }
507     break;
508
509   case OP_PEER_RECONFIGURE:
510     break;
511
512   default:
513     GNUNET_assert (0);
514   }
515   GNUNET_TESTBED_remove_opc_ (opc->c, opc);
516   opc->state = OPC_STATE_FINISHED;
517   exop_insert (event.op);
518   if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
519   {
520     if (NULL != c->cc)
521       c->cc (c->cc_cls, &event);
522     if (GNUNET_NO == exop_check (event.op))
523       return;
524   }
525   else
526     LOG_DEBUG ("Not calling callback\n");
527   if (NULL != op_comp_cb)
528     op_comp_cb (op_comp_cb_cls, event.op, NULL);
529   /* You could have marked the operation as done by now */
530   GNUNET_break (GNUNET_NO == exop_check (event.op));
531 }
532
533
534 /**
535  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS message from
536  * controller (testbed service)
537  *
538  * @param c the controller handle
539  * @param msg message received
540  */
541 static void
542 handle_peer_create_success (
543   void *cls,
544   const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
545 {
546   struct GNUNET_TESTBED_Controller *c = cls;
547   struct OperationContext *opc;
548   struct PeerCreateData *data;
549   struct GNUNET_TESTBED_Peer *peer;
550   struct GNUNET_TESTBED_Operation *op;
551   GNUNET_TESTBED_PeerCreateCallback cb;
552   void *cb_cls;
553   uint64_t op_id;
554
555   GNUNET_assert (sizeof(struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
556                  ntohs (msg->header.size));
557   op_id = GNUNET_ntohll (msg->operation_id);
558   if (NULL == (opc = find_opc (c, op_id)))
559   {
560     LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
561     return;
562   }
563   if (OP_FORWARDED == opc->type)
564   {
565     handle_forwarded_operation_msg (c,
566                                     opc,
567                                     (const struct GNUNET_MessageHeader *) msg);
568     return;
569   }
570   GNUNET_assert (OP_PEER_CREATE == opc->type);
571   GNUNET_assert (NULL != opc->data);
572   data = opc->data;
573   GNUNET_assert (NULL != data->peer);
574   peer = data->peer;
575   GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
576   peer->state = TESTBED_PS_CREATED;
577   GNUNET_TESTBED_peer_register_ (peer);
578   cb = data->cb;
579   cb_cls = data->cls;
580   op = opc->op;
581   GNUNET_free (opc->data);
582   GNUNET_TESTBED_remove_opc_ (opc->c, opc);
583   opc->state = OPC_STATE_FINISHED;
584   exop_insert (op);
585   if (NULL != cb)
586     cb (cb_cls, peer, NULL);
587   /* You could have marked the operation as done by now */
588   GNUNET_break (GNUNET_NO == exop_check (op));
589 }
590
591
592 /**
593  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT message from
594  * controller (testbed service)
595  *
596  * @param c the controller handler
597  * @param msg message received
598  */
599 static void
600 handle_peer_event (void *cls, const struct GNUNET_TESTBED_PeerEventMessage *msg)
601 {
602   struct GNUNET_TESTBED_Controller *c = cls;
603   struct OperationContext *opc;
604   struct GNUNET_TESTBED_Peer *peer;
605   struct PeerEventData *data;
606   GNUNET_TESTBED_PeerChurnCallback pcc;
607   void *pcc_cls;
608   struct GNUNET_TESTBED_EventInformation event;
609   uint64_t op_id;
610   uint64_t mask;
611
612   GNUNET_assert (sizeof(struct GNUNET_TESTBED_PeerEventMessage) ==
613                  ntohs (msg->header.size));
614   op_id = GNUNET_ntohll (msg->operation_id);
615   if (NULL == (opc = find_opc (c, op_id)))
616   {
617     LOG_DEBUG ("Operation not found\n");
618     return;
619   }
620   if (OP_FORWARDED == opc->type)
621   {
622     handle_forwarded_operation_msg (c,
623                                     opc,
624                                     (const struct GNUNET_MessageHeader *) msg);
625     return;
626   }
627   GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
628   data = opc->data;
629   GNUNET_assert (NULL != data);
630   peer = data->peer;
631   GNUNET_assert (NULL != peer);
632   event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
633   event.op = opc->op;
634   event.op_cls = opc->op_cls;
635   switch (event.type)
636   {
637   case GNUNET_TESTBED_ET_PEER_START:
638     peer->state = TESTBED_PS_STARTED;
639     event.details.peer_start.host = peer->host;
640     event.details.peer_start.peer = peer;
641     break;
642
643   case GNUNET_TESTBED_ET_PEER_STOP:
644     peer->state = TESTBED_PS_STOPPED;
645     event.details.peer_stop.peer = peer;
646     break;
647
648   default:
649     GNUNET_assert (0);  /* We should never reach this state */
650   }
651   pcc = data->pcc;
652   pcc_cls = data->pcc_cls;
653   GNUNET_free (data);
654   GNUNET_TESTBED_remove_opc_ (opc->c, opc);
655   opc->state = OPC_STATE_FINISHED;
656   exop_insert (event.op);
657   mask = 1LL << GNUNET_TESTBED_ET_PEER_START;
658   mask |= 1LL << GNUNET_TESTBED_ET_PEER_STOP;
659   if (0 != (mask & c->event_mask))
660   {
661     if (NULL != c->cc)
662       c->cc (c->cc_cls, &event);
663     if (GNUNET_NO == exop_check (event.op))
664       return;
665   }
666   if (NULL != pcc)
667     pcc (pcc_cls, NULL);
668   /* You could have marked the operation as done by now */
669   GNUNET_break (GNUNET_NO == exop_check (event.op));
670 }
671
672
673 /**
674  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT message from
675  * controller (testbed service)
676  *
677  * @param c the controller handler
678  * @param msg message received
679  */
680 static void
681 handle_peer_conevent (void *cls,
682                       const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
683 {
684   struct GNUNET_TESTBED_Controller *c = cls;
685   struct OperationContext *opc;
686   struct OverlayConnectData *data;
687   GNUNET_TESTBED_OperationCompletionCallback cb;
688   void *cb_cls;
689   struct GNUNET_TESTBED_EventInformation event;
690   uint64_t op_id;
691   uint64_t mask;
692
693   op_id = GNUNET_ntohll (msg->operation_id);
694   if (NULL == (opc = find_opc (c, op_id)))
695   {
696     LOG_DEBUG ("Operation not found\n");
697     return;
698   }
699   if (OP_FORWARDED == opc->type)
700   {
701     handle_forwarded_operation_msg (c,
702                                     opc,
703                                     (const struct GNUNET_MessageHeader *) msg);
704     return;
705   }
706   GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
707   GNUNET_assert (NULL != (data = opc->data));
708   GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
709                  (ntohl (msg->peer2) == data->p2->unique_id));
710   event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
711   event.op = opc->op;
712   event.op_cls = opc->op_cls;
713   switch (event.type)
714   {
715   case GNUNET_TESTBED_ET_CONNECT:
716     event.details.peer_connect.peer1 = data->p1;
717     event.details.peer_connect.peer2 = data->p2;
718     break;
719
720   case GNUNET_TESTBED_ET_DISCONNECT:
721     GNUNET_assert (0);  /* FIXME: implement */
722     break;
723
724   default:
725     GNUNET_assert (0);  /* Should never reach here */
726     break;
727   }
728   cb = data->cb;
729   cb_cls = data->cb_cls;
730   GNUNET_TESTBED_remove_opc_ (opc->c, opc);
731   opc->state = OPC_STATE_FINISHED;
732   exop_insert (event.op);
733   mask = 1LL << GNUNET_TESTBED_ET_CONNECT;
734   mask |= 1LL << GNUNET_TESTBED_ET_DISCONNECT;
735   if (0 != (mask & c->event_mask))
736   {
737     if (NULL != c->cc)
738       c->cc (c->cc_cls, &event);
739     if (GNUNET_NO == exop_check (event.op))
740       return;
741   }
742   if (NULL != cb)
743     cb (cb_cls, opc->op, NULL);
744   /* You could have marked the operation as done by now */
745   GNUNET_break (GNUNET_NO == exop_check (event.op));
746 }
747
748
749 /**
750  * Validate #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from
751  * controller (testbed service)
752  *
753  * @param c the controller handler
754  * @param msg message received
755  */
756 static int
757 check_peer_config (
758   void *cls,
759   const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
760 {
761   /* anything goes? */
762   return GNUNET_OK;
763 }
764
765
766 /**
767  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from
768  * controller (testbed service)
769  *
770  * @param c the controller handler
771  * @param msg message received
772  */
773 static void
774 handle_peer_config (
775   void *cls,
776   const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
777 {
778   struct GNUNET_TESTBED_Controller *c = cls;
779   struct OperationContext *opc;
780   struct GNUNET_TESTBED_Peer *peer;
781   struct PeerInfoData *data;
782   struct GNUNET_TESTBED_PeerInformation *pinfo;
783   GNUNET_TESTBED_PeerInfoCallback cb;
784   void *cb_cls;
785   uint64_t op_id;
786
787   op_id = GNUNET_ntohll (msg->operation_id);
788   if (NULL == (opc = find_opc (c, op_id)))
789   {
790     LOG_DEBUG ("Operation not found\n");
791     return;
792   }
793   if (OP_FORWARDED == opc->type)
794   {
795     handle_forwarded_operation_msg (c, opc, &msg->header);
796     return;
797   }
798   data = opc->data;
799   GNUNET_assert (NULL != data);
800   peer = data->peer;
801   GNUNET_assert (NULL != peer);
802   GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
803   pinfo = GNUNET_new (struct GNUNET_TESTBED_PeerInformation);
804   pinfo->pit = data->pit;
805   cb = data->cb;
806   cb_cls = data->cb_cls;
807   GNUNET_assert (NULL != cb);
808   GNUNET_free (data);
809   opc->data = NULL;
810   switch (pinfo->pit)
811   {
812   case GNUNET_TESTBED_PIT_IDENTITY:
813     pinfo->result.id = GNUNET_new (struct GNUNET_PeerIdentity);
814     GNUNET_memcpy (pinfo->result.id,
815                    &msg->peer_identity,
816                    sizeof(struct GNUNET_PeerIdentity));
817     break;
818
819   case GNUNET_TESTBED_PIT_CONFIGURATION:
820     pinfo->result.cfg =   /* Freed in oprelease_peer_getinfo */
821                         GNUNET_TESTBED_extract_config_ (&msg->header);
822     break;
823
824   case GNUNET_TESTBED_PIT_GENERIC:
825     GNUNET_assert (0);  /* never reach here */
826     break;
827   }
828   opc->data = pinfo;
829   GNUNET_TESTBED_remove_opc_ (opc->c, opc);
830   opc->state = OPC_STATE_FINISHED;
831   cb (cb_cls, opc->op, pinfo, NULL);
832   /* We dont check whether the operation is marked as done here as the
833      operation contains data (cfg/identify) which will be freed at a later point
834    */
835 }
836
837
838 /**
839  * Validate #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from
840  * controller (testbed service)
841  *
842  * @param c the controller handler
843  * @param msg message received
844  * @return #GNUNET_OK if message is well-formed
845  */
846 static int
847 check_op_fail_event (
848   void *cls,
849   const struct GNUNET_TESTBED_OperationFailureEventMessage *msg)
850 {
851   /* we accept anything as a valid error message */
852   return GNUNET_OK;
853 }
854
855
856 /**
857  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from
858  * controller (testbed service)
859  *
860  * @param c the controller handler
861  * @param msg message received
862  */
863 static void
864 handle_op_fail_event (
865   void *cls,
866   const struct GNUNET_TESTBED_OperationFailureEventMessage *msg)
867 {
868   struct GNUNET_TESTBED_Controller *c = cls;
869   struct OperationContext *opc;
870   const char *emsg;
871   uint64_t op_id;
872   uint64_t mask;
873   struct GNUNET_TESTBED_EventInformation event;
874
875   op_id = GNUNET_ntohll (msg->operation_id);
876   if (NULL == (opc = find_opc (c, op_id)))
877   {
878     LOG_DEBUG ("Operation not found\n");
879     return;
880   }
881   if (OP_FORWARDED == opc->type)
882   {
883     handle_forwarded_operation_msg (c,
884                                     opc,
885                                     (const struct GNUNET_MessageHeader *) msg);
886     return;
887   }
888   GNUNET_TESTBED_remove_opc_ (opc->c, opc);
889   opc->state = OPC_STATE_FINISHED;
890   emsg = GNUNET_TESTBED_parse_error_string_ (msg);
891   if (NULL == emsg)
892     emsg = "Unknown error";
893   if (OP_PEER_INFO == opc->type)
894   {
895     struct PeerInfoData *data;
896
897     data = opc->data;
898     if (NULL != data->cb)
899       data->cb (data->cb_cls, opc->op, NULL, emsg);
900     GNUNET_free (data);
901     return;   /* We do not call controller callback for peer info */
902   }
903   event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
904   event.op = opc->op;
905   event.op_cls = opc->op_cls;
906   event.details.operation_finished.emsg = emsg;
907   event.details.operation_finished.generic = NULL;
908   mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
909   if ((0 != (mask & c->event_mask)) && (NULL != c->cc))
910   {
911     exop_insert (event.op);
912     c->cc (c->cc_cls, &event);
913     if (GNUNET_NO == exop_check (event.op))
914       return;
915   }
916   switch (opc->type)
917   {
918   case OP_PEER_CREATE: {
919       struct PeerCreateData *data;
920
921       data = opc->data;
922       GNUNET_free (data->peer);
923       if (NULL != data->cb)
924         data->cb (data->cls, NULL, emsg);
925       GNUNET_free (data);
926     }
927     break;
928
929   case OP_PEER_START:
930   case OP_PEER_STOP: {
931       struct PeerEventData *data;
932
933       data = opc->data;
934       if (NULL != data->pcc)
935         data->pcc (data->pcc_cls, emsg);
936       GNUNET_free (data);
937     }
938     break;
939
940   case OP_PEER_DESTROY:
941     break;
942
943   case OP_PEER_INFO:
944     GNUNET_assert (0);
945
946   case OP_OVERLAY_CONNECT: {
947       struct OverlayConnectData *data;
948
949       data = opc->data;
950       GNUNET_TESTBED_operation_mark_failed (opc->op);
951       if (NULL != data->cb)
952         data->cb (data->cb_cls, opc->op, emsg);
953     }
954     break;
955
956   case OP_FORWARDED:
957     GNUNET_assert (0);
958
959   case OP_LINK_CONTROLLERS:   /* No secondary callback */
960     break;
961
962   case OP_SHUTDOWN_PEERS: {
963       struct ShutdownPeersData *data;
964
965       data = opc->data;
966       GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */
967       opc->data = NULL;
968     }
969     break;
970
971   case OP_MANAGE_SERVICE: {
972       struct ManageServiceData *data = opc->data;
973       GNUNET_TESTBED_OperationCompletionCallback cb;
974       void *cb_cls;
975
976       GNUNET_assert (NULL != data);
977       cb = data->cb;
978       cb_cls = data->cb_cls;
979       GNUNET_free (data);
980       opc->data = NULL;
981       exop_insert (event.op);
982       if (NULL != cb)
983         cb (cb_cls, opc->op, emsg);
984       /* You could have marked the operation as done by now */
985       GNUNET_break (GNUNET_NO == exop_check (event.op));
986     }
987     break;
988
989   default:
990     GNUNET_break (0);
991   }
992 }
993
994
995 /**
996  * Function to build GET_SLAVE_CONFIG message
997  *
998  * @param op_id the id this message should contain in its operation id field
999  * @param slave_id the id this message should contain in its slave id field
1000  * @return newly allocated SlaveGetConfigurationMessage
1001  */
1002 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
1003 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
1004 {
1005   struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1006   uint16_t msize;
1007
1008   msize = sizeof(struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
1009   msg = GNUNET_malloc (msize);
1010   msg->header.size = htons (msize);
1011   msg->header.type =
1012     htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
1013   msg->operation_id = GNUNET_htonll (op_id);
1014   msg->slave_id = htonl (slave_id);
1015   return msg;
1016 }
1017
1018
1019 /**
1020  * Validate #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_INFORMATION message from
1021  * controller (testbed service)
1022  *
1023  * @param c the controller handler
1024  * @param msg message received
1025  */
1026 static int
1027 check_slave_config (void *cls,
1028                     const struct GNUNET_TESTBED_SlaveConfiguration *msg)
1029 {
1030   /* anything goes? */
1031   return GNUNET_OK;
1032 }
1033
1034
1035 /**
1036  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION message from controller
1037  * (testbed service)
1038  *
1039  * @param c the controller handler
1040  * @param msg message received
1041  */
1042 static void
1043 handle_slave_config (void *cls,
1044                      const struct GNUNET_TESTBED_SlaveConfiguration *msg)
1045 {
1046   struct GNUNET_TESTBED_Controller *c = cls;
1047   struct OperationContext *opc;
1048   uint64_t op_id;
1049   uint64_t mask;
1050   struct GNUNET_TESTBED_EventInformation event;
1051
1052   op_id = GNUNET_ntohll (msg->operation_id);
1053   if (NULL == (opc = find_opc (c, op_id)))
1054   {
1055     LOG_DEBUG ("Operation not found\n");
1056     return;
1057   }
1058   if (OP_GET_SLAVE_CONFIG != opc->type)
1059   {
1060     GNUNET_break (0);
1061     return;
1062   }
1063   opc->state = OPC_STATE_FINISHED;
1064   GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1065   mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
1066   if ((0 != (mask & c->event_mask)) && (NULL != c->cc))
1067   {
1068     opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
1069     event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1070     event.op = opc->op;
1071     event.op_cls = opc->op_cls;
1072     event.details.operation_finished.generic = opc->data;
1073     event.details.operation_finished.emsg = NULL;
1074     c->cc (c->cc_cls, &event);
1075   }
1076 }
1077
1078
1079 /**
1080  * Check #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller
1081  * (testbed service)
1082  *
1083  * @param c the controller handler
1084  * @param msg message received
1085  * @return #GNUNET_OK if @a msg is well-formed
1086  */
1087 static int
1088 check_link_controllers_result (
1089   void *cls,
1090   const struct GNUNET_TESTBED_ControllerLinkResponse *msg)
1091 {
1092   /* actual check to be implemented */
1093   return GNUNET_OK;
1094 }
1095
1096
1097 /**
1098  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller
1099  * (testbed service)
1100  *
1101  * @param c the controller handler
1102  * @param msg message received
1103  */
1104 static void
1105 handle_link_controllers_result (
1106   void *cls,
1107   const struct GNUNET_TESTBED_ControllerLinkResponse *msg)
1108 {
1109   struct GNUNET_TESTBED_Controller *c = cls;
1110   struct OperationContext *opc;
1111   struct ControllerLinkData *data;
1112   struct GNUNET_CONFIGURATION_Handle *cfg;
1113   struct GNUNET_TESTBED_Host *host;
1114   char *emsg;
1115   uint64_t op_id;
1116   struct GNUNET_TESTBED_EventInformation event;
1117
1118   op_id = GNUNET_ntohll (msg->operation_id);
1119   if (NULL == (opc = find_opc (c, op_id)))
1120   {
1121     LOG_DEBUG ("Operation not found\n");
1122     return;
1123   }
1124   if (OP_FORWARDED == opc->type)
1125   {
1126     handle_forwarded_operation_msg (c,
1127                                     opc,
1128                                     (const struct GNUNET_MessageHeader *) msg);
1129     return;
1130   }
1131   if (OP_LINK_CONTROLLERS != opc->type)
1132   {
1133     GNUNET_break (0);
1134     return;
1135   }
1136   GNUNET_assert (NULL != (data = opc->data));
1137   host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
1138   GNUNET_assert (NULL != host);
1139   GNUNET_free (data);
1140   opc->data = NULL;
1141   opc->state = OPC_STATE_FINISHED;
1142   GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1143   event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1144   event.op = opc->op;
1145   event.op_cls = opc->op_cls;
1146   event.details.operation_finished.emsg = NULL;
1147   event.details.operation_finished.generic = NULL;
1148   emsg = NULL;
1149   cfg = NULL;
1150   if (GNUNET_NO == ntohs (msg->success))
1151   {
1152     emsg =
1153       GNUNET_malloc (ntohs (msg->header.size)
1154                      - sizeof(struct GNUNET_TESTBED_ControllerLinkResponse)
1155                      + 1);
1156     GNUNET_memcpy (emsg,
1157                    &msg[1],
1158                    ntohs (msg->header.size)
1159                    - sizeof(struct GNUNET_TESTBED_ControllerLinkResponse));
1160     event.details.operation_finished.emsg = emsg;
1161   }
1162   else
1163   {
1164     if (0 != ntohs (msg->config_size))
1165     {
1166       cfg = GNUNET_TESTBED_extract_config_ (
1167         (const struct GNUNET_MessageHeader *) msg);
1168       GNUNET_assert (NULL != cfg);
1169       GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
1170     }
1171   }
1172   if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
1173   {
1174     if (NULL != c->cc)
1175       c->cc (c->cc_cls, &event);
1176   }
1177   else
1178     LOG_DEBUG ("Not calling callback\n");
1179   if (NULL != cfg)
1180     GNUNET_CONFIGURATION_destroy (cfg);
1181   GNUNET_free_non_null (emsg);
1182 }
1183
1184
1185 /**
1186  * Validate #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS message.
1187  *
1188  * @param cls the controller handle to determine the connection this message
1189  *   belongs to
1190  * @param msg the barrier status message
1191  * @return #GNUNET_OK if the message is valid; #GNUNET_SYSERR to tear it
1192  *   down signalling an error (message malformed)
1193  */
1194 static int
1195 check_barrier_status (void *cls,
1196                       const struct GNUNET_TESTBED_BarrierStatusMsg *msg)
1197 {
1198   uint16_t msize;
1199   uint16_t name_len;
1200   int status;
1201   const char *name;
1202   size_t emsg_len;
1203
1204   msize = ntohs (msg->header.size);
1205   name = msg->data;
1206   name_len = ntohs (msg->name_len);
1207
1208   if (sizeof(struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1 > msize)
1209   {
1210     GNUNET_break_op (0);
1211     return GNUNET_SYSERR;
1212   }
1213   if ('\0' != name[name_len])
1214   {
1215     GNUNET_break_op (0);
1216     return GNUNET_SYSERR;
1217   }
1218   status = ntohs (msg->status);
1219   if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)
1220   {
1221     emsg_len = msize - (sizeof(struct GNUNET_TESTBED_BarrierStatusMsg)
1222                         + name_len + 1); /* +1!? */
1223     if (0 == emsg_len)
1224     {
1225       GNUNET_break_op (0);
1226       return GNUNET_SYSERR;
1227     }
1228   }
1229   return GNUNET_OK;
1230 }
1231
1232
1233 /**
1234  * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages
1235  *
1236  * @param cls the controller handle to determine the connection this message
1237  *   belongs to
1238  * @param msg the barrier status message
1239  */
1240 static void
1241 handle_barrier_status (void *cls,
1242                        const struct GNUNET_TESTBED_BarrierStatusMsg *msg)
1243 {
1244   struct GNUNET_TESTBED_Controller *c = cls;
1245   struct GNUNET_TESTBED_Barrier *barrier;
1246   char *emsg;
1247   const char *name;
1248   struct GNUNET_HashCode key;
1249   size_t emsg_len;
1250   int status;
1251   uint16_t msize;
1252   uint16_t name_len;
1253
1254   emsg = NULL;
1255   barrier = NULL;
1256   msize = ntohs (msg->header.size);
1257   if (msize <= sizeof(struct GNUNET_TESTBED_BarrierStatusMsg))
1258   {
1259     GNUNET_break_op (0);
1260     goto cleanup;
1261   }
1262   name = msg->data;
1263   name_len = ntohs (msg->name_len);
1264   if (name_len >= // name_len is strlen(barrier_name)
1265       (msize - ((sizeof msg->header) + sizeof(msg->status))))
1266   {
1267     GNUNET_break_op (0);
1268     goto cleanup;
1269   }
1270   if ('\0' != name[name_len])
1271   {
1272     GNUNET_break_op (0);
1273     goto cleanup;
1274   }
1275   LOG_DEBUG ("Received BARRIER_STATUS msg\n");
1276   status = ntohs (msg->status);
1277   if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)
1278   {
1279     status = -1;
1280     // unlike name_len, emsg_len includes the trailing zero
1281     emsg_len = msize - (sizeof(struct GNUNET_TESTBED_BarrierStatusMsg)
1282                         + (name_len + 1));
1283     if (0 == emsg_len)
1284     {
1285       GNUNET_break_op (0);
1286       goto cleanup;
1287     }
1288     if ('\0' != (msg->data[(name_len + 1) + (emsg_len - 1)]))
1289     {
1290       GNUNET_break_op (0);
1291       goto cleanup;
1292     }
1293     emsg = GNUNET_malloc (emsg_len);
1294     GNUNET_memcpy (emsg, msg->data + name_len + 1, emsg_len);
1295   }
1296   if (NULL == c->barrier_map)
1297   {
1298     GNUNET_break_op (0);
1299     goto cleanup;
1300   }
1301   GNUNET_CRYPTO_hash (name, name_len, &key);
1302   barrier = GNUNET_CONTAINER_multihashmap_get (c->barrier_map, &key);
1303   if (NULL == barrier)
1304   {
1305     GNUNET_break_op (0);
1306     goto cleanup;
1307   }
1308   GNUNET_assert (NULL != barrier->cb);
1309   if ((GNUNET_YES == barrier->echo) &&
1310       (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status))
1311     GNUNET_TESTBED_queue_message_ (c, GNUNET_copy_message (&msg->header));
1312   barrier->cb (barrier->cls, name, barrier, status, emsg);
1313   if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED == status)
1314     return; /* just initialised; skip cleanup */
1315
1316 cleanup:
1317   GNUNET_free_non_null (emsg);
1318   /**
1319    * Do not remove the barrier if we did not echo the status back; this is
1320    * required at the chained testbed controller setup to ensure the only the
1321    * test-driver echos the status and the controller hierarchy properly
1322    * propagates the status.
1323    */
1324   if ((NULL != barrier) && (GNUNET_YES == barrier->echo))
1325     GNUNET_TESTBED_barrier_remove_ (barrier);
1326 }
1327
1328
1329 /**
1330  * Queues a message in send queue for sending to the service
1331  *
1332  * @param controller the handle to the controller
1333  * @param msg the message to queue
1334  */
1335 void
1336 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1337                                struct GNUNET_MessageHeader *msg)
1338 {
1339   struct GNUNET_MQ_Envelope *env;
1340   struct GNUNET_MessageHeader *m2;
1341   uint16_t type;
1342   uint16_t size;
1343
1344   type = ntohs (msg->type);
1345   size = ntohs (msg->size);
1346   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1347                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1348   env = GNUNET_MQ_msg_extra (m2, size - sizeof(*m2), type);
1349   GNUNET_memcpy (m2, msg, size);
1350   GNUNET_free (msg);
1351   GNUNET_MQ_send (controller->mq, env);
1352 }
1353
1354
1355 /**
1356  * Sends the given message as an operation. The given callback is called when a
1357  * reply for the operation is available.  Call
1358  * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1359  * operation context if the cc hasn't been called
1360  *
1361  * @param controller the controller to which the message has to be sent
1362  * @param operation_id the operation id of the message
1363  * @param msg the message to send
1364  * @param cc the callback to call when reply is available
1365  * @param cc_cls the closure for the above callback
1366  * @return the operation context which can be used to cancel the forwarded
1367  *           operation
1368  */
1369 struct OperationContext *
1370 GNUNET_TESTBED_forward_operation_msg_ (
1371   struct GNUNET_TESTBED_Controller *controller,
1372   uint64_t operation_id,
1373   const struct GNUNET_MessageHeader *msg,
1374   GNUNET_MQ_MessageCallback cc,
1375   void *cc_cls)
1376 {
1377   struct OperationContext *opc;
1378   struct ForwardedOperationData *data;
1379   struct GNUNET_MQ_Envelope *env;
1380   struct GNUNET_MessageHeader *m2;
1381   uint16_t type = ntohs (msg->type);
1382   uint16_t size = ntohs (msg->size);
1383
1384   env = GNUNET_MQ_msg_extra (m2, size - sizeof(*m2), type);
1385   GNUNET_memcpy (m2, msg, size);
1386   GNUNET_MQ_send (controller->mq, env);
1387   data = GNUNET_new (struct ForwardedOperationData);
1388   data->cc = cc;
1389   data->cc_cls = cc_cls;
1390   opc = GNUNET_new (struct OperationContext);
1391   opc->c = controller;
1392   opc->type = OP_FORWARDED;
1393   opc->data = data;
1394   opc->id = operation_id;
1395   GNUNET_TESTBED_insert_opc_ (controller, opc);
1396   return opc;
1397 }
1398
1399
1400 /**
1401  * Function to cancel an operation created by simply forwarding an operation
1402  * message.
1403  *
1404  * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1405  */
1406 void
1407 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1408 {
1409   GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1410   GNUNET_free (opc->data);
1411   GNUNET_free (opc);
1412 }
1413
1414
1415 /**
1416  * Function to call to start a link-controllers type operation once all queues
1417  * the operation is part of declare that the operation can be activated.
1418  *
1419  * @param cls the closure from GNUNET_TESTBED_operation_create_()
1420  */
1421 static void
1422 opstart_link_controllers (void *cls)
1423 {
1424   struct OperationContext *opc = cls;
1425   struct ControllerLinkData *data;
1426   struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1427
1428   GNUNET_assert (NULL != opc->data);
1429   data = opc->data;
1430   msg = data->msg;
1431   data->msg = NULL;
1432   opc->state = OPC_STATE_STARTED;
1433   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1434   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1435 }
1436
1437
1438 /**
1439  * Callback which will be called when link-controllers type operation is released
1440  *
1441  * @param cls the closure from GNUNET_TESTBED_operation_create_()
1442  */
1443 static void
1444 oprelease_link_controllers (void *cls)
1445 {
1446   struct OperationContext *opc = cls;
1447   struct ControllerLinkData *data;
1448
1449   data = opc->data;
1450   switch (opc->state)
1451   {
1452   case OPC_STATE_INIT:
1453     GNUNET_free (data->msg);
1454     break;
1455
1456   case OPC_STATE_STARTED:
1457     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1458     break;
1459
1460   case OPC_STATE_FINISHED:
1461     break;
1462   }
1463   GNUNET_free_non_null (data);
1464   GNUNET_free (opc);
1465 }
1466
1467
1468 /**
1469  * Function to be called when get slave config operation is ready
1470  *
1471  * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1472  */
1473 static void
1474 opstart_get_slave_config (void *cls)
1475 {
1476   struct OperationContext *opc = cls;
1477   struct GetSlaveConfigData *data = opc->data;
1478   struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1479
1480   GNUNET_assert (NULL != data);
1481   msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1482   GNUNET_free (opc->data);
1483   data = NULL;
1484   opc->data = NULL;
1485   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1486   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1487   opc->state = OPC_STATE_STARTED;
1488 }
1489
1490
1491 /**
1492  * Function to be called when get slave config operation is cancelled or finished
1493  *
1494  * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1495  */
1496 static void
1497 oprelease_get_slave_config (void *cls)
1498 {
1499   struct OperationContext *opc = cls;
1500
1501   switch (opc->state)
1502   {
1503   case OPC_STATE_INIT:
1504     GNUNET_free (opc->data);
1505     break;
1506
1507   case OPC_STATE_STARTED:
1508     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1509     break;
1510
1511   case OPC_STATE_FINISHED:
1512     if (NULL != opc->data)
1513       GNUNET_CONFIGURATION_destroy (opc->data);
1514     break;
1515   }
1516   GNUNET_free (opc);
1517 }
1518
1519
1520 /**
1521  * Generic error handler, called with the appropriate error code and
1522  * the same closure specified at the creation of the message queue.
1523  * Not every message queue implementation supports an error handler.
1524  *
1525  * @param cls closure, a `struct GNUNET_TESTBED_Controller *`
1526  * @param error error code
1527  */
1528 static void
1529 mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
1530 {
1531   /* struct GNUNET_TESTBED_Controller *c = cls; */
1532
1533   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encountered MQ error: %d\n", error);
1534   /* now what? */
1535   GNUNET_SCHEDULER_shutdown ();  /* seems most reasonable */
1536 }
1537
1538
1539 /**
1540  * Start a controller process using the given configuration at the
1541  * given host.
1542  *
1543  * @param host host to run the controller on; This should be the same host if
1544  *          the controller was previously started with
1545  *          GNUNET_TESTBED_controller_start()
1546  * @param event_mask bit mask with set of events to call 'cc' for;
1547  *                   or-ed values of "1LL" shifted by the
1548  *                   respective 'enum GNUNET_TESTBED_EventType'
1549  *                   (i.e.  "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1550  * @param cc controller callback to invoke on events
1551  * @param cc_cls closure for cc
1552  * @return handle to the controller
1553  */
1554 struct GNUNET_TESTBED_Controller *
1555 GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host,
1556                                    uint64_t event_mask,
1557                                    GNUNET_TESTBED_ControllerCallback cc,
1558                                    void *cc_cls)
1559 {
1560   struct GNUNET_TESTBED_Controller *controller =
1561     GNUNET_new (struct GNUNET_TESTBED_Controller);
1562   struct GNUNET_MQ_MessageHandler handlers[] =
1563   { GNUNET_MQ_hd_var_size (add_host_confirm,
1564                            GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS,
1565                            struct GNUNET_TESTBED_HostConfirmedMessage,
1566                            controller),
1567     GNUNET_MQ_hd_fixed_size (peer_conevent,
1568                              GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT,
1569                              struct GNUNET_TESTBED_ConnectionEventMessage,
1570                              controller),
1571     GNUNET_MQ_hd_fixed_size (opsuccess,
1572                              GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS,
1573                              struct
1574                              GNUNET_TESTBED_GenericOperationSuccessEventMessage,
1575                              controller),
1576     GNUNET_MQ_hd_var_size (op_fail_event,
1577                            GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT,
1578                            struct GNUNET_TESTBED_OperationFailureEventMessage,
1579                            controller),
1580     GNUNET_MQ_hd_fixed_size (peer_create_success,
1581                              GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS,
1582                              struct
1583                              GNUNET_TESTBED_PeerCreateSuccessEventMessage,
1584                              controller),
1585     GNUNET_MQ_hd_fixed_size (peer_event,
1586                              GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT,
1587                              struct GNUNET_TESTBED_PeerEventMessage,
1588                              controller),
1589     GNUNET_MQ_hd_var_size (peer_config,
1590                            GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION,
1591                            struct
1592                            GNUNET_TESTBED_PeerConfigurationInformationMessage,
1593                            controller),
1594     GNUNET_MQ_hd_var_size (slave_config,
1595                            GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1596                            struct GNUNET_TESTBED_SlaveConfiguration,
1597                            controller),
1598     GNUNET_MQ_hd_var_size (link_controllers_result,
1599                            GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
1600                            struct GNUNET_TESTBED_ControllerLinkResponse,
1601                            controller),
1602     GNUNET_MQ_hd_var_size (barrier_status,
1603                            GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS,
1604                            struct GNUNET_TESTBED_BarrierStatusMsg,
1605                            controller),
1606     GNUNET_MQ_handler_end () };
1607   struct GNUNET_TESTBED_InitMessage *msg;
1608   struct GNUNET_MQ_Envelope *env;
1609   const struct GNUNET_CONFIGURATION_Handle *cfg;
1610   const char *controller_hostname;
1611   unsigned long long max_parallel_operations;
1612   unsigned long long max_parallel_service_connections;
1613   unsigned long long max_parallel_topology_config_operations;
1614   size_t slen;
1615
1616   GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host)));
1617   if (GNUNET_OK !=
1618       GNUNET_CONFIGURATION_get_value_number (cfg,
1619                                              "testbed",
1620                                              "MAX_PARALLEL_OPERATIONS",
1621                                              &max_parallel_operations))
1622   {
1623     GNUNET_break (0);
1624     GNUNET_free (controller);
1625     return NULL;
1626   }
1627   if (GNUNET_OK !=
1628       GNUNET_CONFIGURATION_get_value_number (cfg,
1629                                              "testbed",
1630                                              "MAX_PARALLEL_SERVICE_CONNECTIONS",
1631                                              &max_parallel_service_connections))
1632   {
1633     GNUNET_break (0);
1634     GNUNET_free (controller);
1635     return NULL;
1636   }
1637   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (
1638         cfg,
1639         "testbed",
1640         "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1641         &max_parallel_topology_config_operations))
1642   {
1643     GNUNET_break (0);
1644     GNUNET_free (controller);
1645     return NULL;
1646   }
1647   controller->cc = cc;
1648   controller->cc_cls = cc_cls;
1649   controller->event_mask = event_mask;
1650   controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1651   controller->mq = GNUNET_CLIENT_connect (controller->cfg,
1652                                           "testbed",
1653                                           handlers,
1654                                           &mq_error_handler,
1655                                           controller);
1656   if (NULL == controller->mq)
1657   {
1658     GNUNET_break (0);
1659     GNUNET_TESTBED_controller_disconnect (controller);
1660     return NULL;
1661   }
1662   GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1663   controller->host = host;
1664   controller->opq_parallel_operations =
1665     GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1666                                             (unsigned int)
1667                                             max_parallel_operations);
1668   controller->opq_parallel_service_connections =
1669     GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1670                                             (unsigned int)
1671                                             max_parallel_service_connections);
1672   controller->opq_parallel_topology_config_operations =
1673     GNUNET_TESTBED_operation_queue_create_ (
1674       OPERATION_QUEUE_TYPE_FIXED,
1675       (unsigned int) max_parallel_topology_config_operations);
1676   controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1677   if (NULL == controller_hostname)
1678     controller_hostname = "127.0.0.1";
1679   slen = strlen (controller_hostname) + 1;
1680   env = GNUNET_MQ_msg_extra (msg, slen, GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1681   msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1682   msg->event_mask = GNUNET_htonll (controller->event_mask);
1683   GNUNET_memcpy (&msg[1], controller_hostname, slen);
1684   GNUNET_MQ_send (controller->mq, env);
1685   return controller;
1686 }
1687
1688
1689 /**
1690  * Iterator to free opc map entries
1691  *
1692  * @param cls closure
1693  * @param key current key code
1694  * @param value value in the hash map
1695  * @return #GNUNET_YES if we should continue to iterate,
1696  *         #GNUNET_NO if not.
1697  */
1698 static int
1699 opc_free_iterator (void *cls, uint32_t key, void *value)
1700 {
1701   struct GNUNET_CONTAINER_MultiHashMap32 *map = cls;
1702   struct OperationContext *opc = value;
1703
1704   GNUNET_assert (NULL != opc);
1705   GNUNET_break (0);
1706   GNUNET_assert (GNUNET_YES ==
1707                  GNUNET_CONTAINER_multihashmap32_remove (map, key, value));
1708   GNUNET_free (opc);
1709   return GNUNET_YES;
1710 }
1711
1712
1713 /**
1714  * Stop the given controller (also will terminate all peers and
1715  * controllers dependent on this controller).  This function
1716  * blocks until the testbed has been fully terminated (!).
1717  *
1718  * @param c handle to controller to stop
1719  */
1720 void
1721 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *c)
1722 {
1723   if (NULL != c->mq)
1724   {
1725     GNUNET_MQ_destroy (c->mq);
1726     c->mq = NULL;
1727   }
1728   if (NULL != c->host)
1729     GNUNET_TESTBED_deregister_host_at_ (c->host, c);
1730   GNUNET_CONFIGURATION_destroy (c->cfg);
1731   GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations);
1732   GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_service_connections);
1733   GNUNET_TESTBED_operation_queue_destroy_ (
1734     c->opq_parallel_topology_config_operations);
1735   if (NULL != c->opc_map)
1736   {
1737     GNUNET_assert (GNUNET_SYSERR !=
1738                    GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map,
1739                                                             &opc_free_iterator,
1740                                                             c->opc_map));
1741     GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map));
1742     GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map);
1743   }
1744   GNUNET_free (c);
1745 }
1746
1747
1748 /**
1749  * Compresses given configuration using zlib compress
1750  *
1751  * @param config the serialized configuration
1752  * @param size the size of config
1753  * @param xconfig will be set to the compressed configuration (memory is fresly
1754  *          allocated)
1755  * @return the size of the xconfig
1756  */
1757 size_t
1758 GNUNET_TESTBED_compress_config_ (const char *config,
1759                                  size_t size,
1760                                  char **xconfig)
1761 {
1762   size_t xsize;
1763
1764   xsize = compressBound ((uLong) size);
1765   *xconfig = GNUNET_malloc (xsize);
1766   GNUNET_assert (Z_OK == compress2 ((Bytef *) *xconfig,
1767                                     (uLongf *) &xsize,
1768                                     (const Bytef *) config,
1769                                     (uLongf) size,
1770                                     Z_BEST_SPEED));
1771   return xsize;
1772 }
1773
1774
1775 /**
1776  * Function to serialize and compress using zlib a configuration through a
1777  * configuration handle
1778  *
1779  * @param cfg the configuration
1780  * @param size the size of configuration when serialize.  Will be set on success.
1781  * @param xsize the sizeo of the compressed configuration.  Will be set on success.
1782  * @return the serialized and compressed configuration
1783  */
1784 char *
1785 GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
1786                               size_t *size,
1787                               size_t *xsize)
1788 {
1789   char *config;
1790   char *xconfig;
1791   size_t size_;
1792   size_t xsize_;
1793
1794   config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
1795   xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
1796   GNUNET_free (config);
1797   *size = size_;
1798   *xsize = xsize_;
1799   return xconfig;
1800 }
1801
1802
1803 /**
1804  * Create a link from slave controller to delegated controller. Whenever the
1805  * master controller is asked to start a peer at the delegated controller the
1806  * request will be routed towards slave controller (if a route exists). The
1807  * slave controller will then route it to the delegated controller. The
1808  * configuration of the delegated controller is given and is used to either
1809  * create the delegated controller or to connect to an existing controller. Note
1810  * that while starting the delegated controller the configuration will be
1811  * modified to accommodate available free ports.  the 'is_subordinate' specifies
1812  * if the given delegated controller should be started and managed by the slave
1813  * controller, or if the delegated controller already has a master and the slave
1814  * controller connects to it as a non master controller. The success or failure
1815  * of this operation will be signalled through the
1816  * GNUNET_TESTBED_ControllerCallback() with an event of type
1817  * GNUNET_TESTBED_ET_OPERATION_FINISHED
1818  *
1819  * @param op_cls the operation closure for the event which is generated to
1820  *          signal success or failure of this operation
1821  * @param master handle to the master controller who creates the association
1822  * @param delegated_host requests to which host should be delegated; cannot be NULL
1823  * @param slave_host which host is used to run the slave controller; use NULL to
1824  *          make the master controller connect to the delegated host
1825  * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1826  *          be started by the slave controller; GNUNET_NO if the slave
1827  *          controller has to connect to the already started delegated
1828  *          controller via TCP/IP
1829  * @return the operation handle
1830  */
1831 struct GNUNET_TESTBED_Operation *
1832 GNUNET_TESTBED_controller_link (void *op_cls,
1833                                 struct GNUNET_TESTBED_Controller *master,
1834                                 struct GNUNET_TESTBED_Host *delegated_host,
1835                                 struct GNUNET_TESTBED_Host *slave_host,
1836                                 int is_subordinate)
1837 {
1838   struct OperationContext *opc;
1839   struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1840   struct ControllerLinkData *data;
1841   uint32_t slave_host_id;
1842   uint32_t delegated_host_id;
1843   uint16_t msg_size;
1844
1845   GNUNET_assert (GNUNET_YES ==
1846                  GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1847   slave_host_id = GNUNET_TESTBED_host_get_id_ (
1848     (NULL != slave_host) ? slave_host : master->host);
1849   delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1850   if ((NULL != slave_host) && (0 != slave_host_id))
1851     GNUNET_assert (GNUNET_YES ==
1852                    GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1853   msg_size = sizeof(struct GNUNET_TESTBED_ControllerLinkRequest);
1854   msg = GNUNET_malloc (msg_size);
1855   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1856   msg->header.size = htons (msg_size);
1857   msg->delegated_host_id = htonl (delegated_host_id);
1858   msg->slave_host_id = htonl (slave_host_id);
1859   msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1860   data = GNUNET_new (struct ControllerLinkData);
1861   data->msg = msg;
1862   data->host_id = delegated_host_id;
1863   opc = GNUNET_new (struct OperationContext);
1864   opc->c = master;
1865   opc->data = data;
1866   opc->type = OP_LINK_CONTROLLERS;
1867   opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1868   opc->state = OPC_STATE_INIT;
1869   opc->op_cls = op_cls;
1870   msg->operation_id = GNUNET_htonll (opc->id);
1871   opc->op = GNUNET_TESTBED_operation_create_ (opc,
1872                                               &opstart_link_controllers,
1873                                               &oprelease_link_controllers);
1874   GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1875                                           opc->op);
1876   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1877   return opc->op;
1878 }
1879
1880
1881 /**
1882  * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1883  * check. Another difference is that this function takes the id of the slave
1884  * host.
1885  *
1886  * @param op_cls the closure for the operation
1887  * @param master the handle to master controller
1888  * @param slave_host_id id of the host where the slave controller is running to
1889  *          the slave_host should remain valid until this operation is cancelled
1890  *          or marked as finished
1891  * @return the operation handle;
1892  */
1893 struct GNUNET_TESTBED_Operation *
1894 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1895                                   struct GNUNET_TESTBED_Controller *master,
1896                                   uint32_t slave_host_id)
1897 {
1898   struct OperationContext *opc;
1899   struct GetSlaveConfigData *data;
1900
1901   data = GNUNET_new (struct GetSlaveConfigData);
1902   data->slave_id = slave_host_id;
1903   opc = GNUNET_new (struct OperationContext);
1904   opc->state = OPC_STATE_INIT;
1905   opc->c = master;
1906   opc->id = GNUNET_TESTBED_get_next_op_id (master);
1907   opc->type = OP_GET_SLAVE_CONFIG;
1908   opc->data = data;
1909   opc->op_cls = op_cls;
1910   opc->op = GNUNET_TESTBED_operation_create_ (opc,
1911                                               &opstart_get_slave_config,
1912                                               &oprelease_get_slave_config);
1913   GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1914                                           opc->op);
1915   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1916   return opc->op;
1917 }
1918
1919
1920 /**
1921  * Function to acquire the configuration of a running slave controller. The
1922  * completion of the operation is signalled through the controller_cb from
1923  * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1924  * handle to the configuration is available in the generic pointer of
1925  * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1926  *
1927  * @param op_cls the closure for the operation
1928  * @param master the handle to master controller
1929  * @param slave_host the host where the slave controller is running; the handle
1930  *          to the slave_host should remain valid until this operation is
1931  *          cancelled or marked as finished
1932  * @return the operation handle; NULL if the slave_host is not registered at
1933  *           master
1934  */
1935 struct GNUNET_TESTBED_Operation *
1936 GNUNET_TESTBED_get_slave_config (void *op_cls,
1937                                  struct GNUNET_TESTBED_Controller *master,
1938                                  struct GNUNET_TESTBED_Host *slave_host)
1939 {
1940   if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1941     return NULL;
1942   return GNUNET_TESTBED_get_slave_config_ (op_cls,
1943                                            master,
1944                                            GNUNET_TESTBED_host_get_id_ (
1945                                              slave_host));
1946 }
1947
1948
1949 /**
1950  * Ask the testbed controller to write the current overlay topology to
1951  * a file.  Naturally, the file will only contain a snapshot as the
1952  * topology may evolve all the time.
1953  *
1954  * @param controller overlay controller to inspect
1955  * @param filename name of the file the topology should
1956  *        be written to.
1957  */
1958 void
1959 GNUNET_TESTBED_overlay_write_topology_to_file (
1960   struct GNUNET_TESTBED_Controller *controller,
1961   const char *filename)
1962 {
1963   GNUNET_break (0);
1964 }
1965
1966
1967 /**
1968  * Creates a helper initialization message. This function is here because we
1969  * want to use this in testing
1970  *
1971  * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1972  *          HOST(all connections form this ip are permitted by the testbed) when
1973  *          starting testbed controller at host. This can either be a single ip
1974  *          address or a network address in CIDR notation.
1975  * @param hostname the hostname of the destination this message is intended for
1976  * @param cfg the configuration that has to used to start the testbed service
1977  *          thru helper
1978  * @return the initialization message
1979  */
1980 struct GNUNET_TESTBED_HelperInit *
1981 GNUNET_TESTBED_create_helper_init_msg_ (
1982   const char *trusted_ip,
1983   const char *hostname,
1984   const struct GNUNET_CONFIGURATION_Handle *cfg)
1985 {
1986   struct GNUNET_TESTBED_HelperInit *msg;
1987   char *config;
1988   char *xconfig;
1989   size_t config_size;
1990   size_t xconfig_size;
1991   uint16_t trusted_ip_len;
1992   uint16_t hostname_len;
1993   uint16_t msg_size;
1994
1995   config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1996   GNUNET_assert (NULL != config);
1997   xconfig_size =
1998     GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1999   GNUNET_free (config);
2000   trusted_ip_len = strlen (trusted_ip);
2001   hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
2002   msg_size = xconfig_size + trusted_ip_len + 1
2003              + sizeof(struct GNUNET_TESTBED_HelperInit);
2004   msg_size += hostname_len;
2005   msg = GNUNET_realloc (xconfig, msg_size);
2006   (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len,
2007                   msg,
2008                   xconfig_size);
2009   msg->header.size = htons (msg_size);
2010   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
2011   msg->trusted_ip_size = htons (trusted_ip_len);
2012   msg->hostname_size = htons (hostname_len);
2013   msg->config_size = htons (config_size);
2014   (void) strcpy ((char *) &msg[1], trusted_ip);
2015   if (0 != hostname_len)
2016     GNUNET_memcpy ((char *) &msg[1] + trusted_ip_len + 1,
2017                    hostname,
2018                    hostname_len);
2019   return msg;
2020 }
2021
2022
2023 /**
2024  * This function is used to signal that the event information (struct
2025  * GNUNET_TESTBED_EventInformation) from an operation has been fully processed
2026  * i.e. if the event callback is ever called for this operation. If the event
2027  * callback for this operation has not yet been called, calling this function
2028  * cancels the operation, frees its resources and ensures the no event is
2029  * generated with respect to this operation. Note that however cancelling an
2030  * operation does NOT guarantee that the operation will be fully undone (or that
2031  * nothing ever happened).
2032  *
2033  * This function MUST be called for every operation to fully remove the
2034  * operation from the operation queue.  After calling this function, if
2035  * operation is completed and its event information is of type
2036  * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!).
2037
2038  * If the operation is generated from GNUNET_TESTBED_service_connect() then
2039  * calling this function on such as operation calls the disconnect adapter if
2040  * the connect adapter was ever called.
2041  *
2042  * @param operation operation to signal completion or cancellation
2043  */
2044 void
2045 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
2046 {
2047   (void) exop_check (operation);
2048   GNUNET_TESTBED_operation_release_ (operation);
2049 }
2050
2051
2052 /**
2053  * Generates configuration by uncompressing configuration in given message. The
2054  * given message should be of the following types:
2055  * #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION,
2056  * #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
2057  * #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
2058  * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
2059  * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
2060  *
2061  * FIXME: This API is incredibly ugly.
2062  *
2063  * @param msg the message containing compressed configuration
2064  * @return handle to the parsed configuration; NULL upon error while parsing the message
2065  */
2066 struct GNUNET_CONFIGURATION_Handle *
2067 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
2068 {
2069   struct GNUNET_CONFIGURATION_Handle *cfg;
2070   Bytef *data;
2071   const Bytef *xdata;
2072   uLong data_len;
2073   uLong xdata_len;
2074   int ret;
2075
2076   switch (ntohs (msg->type))
2077   {
2078   case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION: {
2079       const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
2080
2081       imsg =
2082         (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
2083       data_len = (uLong) ntohs (imsg->config_size);
2084       xdata_len =
2085         ntohs (imsg->header.size)
2086         - sizeof(struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2087       xdata = (const Bytef *) &imsg[1];
2088     }
2089     break;
2090
2091   case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION: {
2092       const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
2093
2094       imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
2095       data_len = (uLong) ntohs (imsg->config_size);
2096       xdata_len = ntohs (imsg->header.size)
2097                   - sizeof(struct GNUNET_TESTBED_SlaveConfiguration);
2098       xdata = (const Bytef *) &imsg[1];
2099     }
2100     break;
2101
2102   case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST: {
2103       const struct GNUNET_TESTBED_AddHostMessage *imsg;
2104       uint16_t osize;
2105
2106       imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
2107       data_len = (uLong) ntohs (imsg->config_size);
2108       osize = sizeof(struct GNUNET_TESTBED_AddHostMessage)
2109               + ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
2110       xdata_len = ntohs (imsg->header.size) - osize;
2111       xdata = (const Bytef *) ((const void *) imsg + osize);
2112     }
2113     break;
2114
2115   case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT: {
2116       const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
2117
2118       imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
2119       data_len = ntohs (imsg->config_size);
2120       xdata_len = ntohs (imsg->header.size)
2121                   - sizeof(const struct GNUNET_TESTBED_ControllerLinkResponse);
2122       xdata = (const Bytef *) &imsg[1];
2123     }
2124     break;
2125
2126   case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER: {
2127       const struct GNUNET_TESTBED_PeerCreateMessage *imsg;
2128
2129       imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg;
2130       data_len = ntohs (imsg->config_size);
2131       xdata_len = ntohs (imsg->header.size)
2132                   - sizeof(struct GNUNET_TESTBED_PeerCreateMessage);
2133       xdata = (const Bytef *) &imsg[1];
2134     }
2135     break;
2136
2137   case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER: {
2138       const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg;
2139
2140       imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg;
2141       data_len = ntohs (imsg->config_size);
2142       xdata_len = ntohs (imsg->header.size)
2143                   - sizeof(struct GNUNET_TESTBED_PeerReconfigureMessage);
2144       xdata = (const Bytef *) &imsg[1];
2145     }
2146     break;
2147
2148   default:
2149     GNUNET_assert (0);
2150   }
2151   data = GNUNET_malloc (data_len);
2152   if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
2153   {
2154     GNUNET_free (data);
2155     GNUNET_break_op (0);  /* Un-compression failure */
2156     return NULL;
2157   }
2158   cfg = GNUNET_CONFIGURATION_create ();
2159   if (GNUNET_OK != GNUNET_CONFIGURATION_deserialize (cfg,
2160                                                      (const char *) data,
2161                                                      (size_t) data_len,
2162                                                      NULL))
2163   {
2164     GNUNET_free (data);
2165     GNUNET_break_op (0);  /* De-serialization failure */
2166     return NULL;
2167   }
2168   GNUNET_free (data);
2169   return cfg;
2170 }
2171
2172
2173 /**
2174  * Checks the integrity of the OperationFailureEventMessage and if good returns
2175  * the error message it contains.
2176  *
2177  * @param msg the OperationFailureEventMessage
2178  * @return the error message
2179  */
2180 const char *
2181 GNUNET_TESTBED_parse_error_string_ (
2182   const struct GNUNET_TESTBED_OperationFailureEventMessage *msg)
2183 {
2184   uint16_t msize;
2185   const char *emsg;
2186
2187   msize = ntohs (msg->header.size);
2188   if (sizeof(struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2189     return NULL;
2190   msize -= sizeof(struct GNUNET_TESTBED_OperationFailureEventMessage);
2191   emsg = (const char *) &msg[1];
2192   if ('\0' != emsg[msize - 1])
2193   {
2194     GNUNET_break (0);
2195     return NULL;
2196   }
2197   return emsg;
2198 }
2199
2200
2201 /**
2202  * Function to return the operation id for a controller. The operation id is
2203  * created from the controllers host id and its internal operation counter.
2204  *
2205  * @param controller the handle to the controller whose operation id has to be incremented
2206  * @return the incremented operation id.
2207  */
2208 uint64_t
2209 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller *controller)
2210 {
2211   uint64_t op_id;
2212
2213   op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2214   op_id = op_id << 32;
2215   op_id |= (uint64_t) controller->operation_counter++;
2216   return op_id;
2217 }
2218
2219
2220 /**
2221  * Function called when a shutdown peers operation is ready
2222  *
2223  * @param cls the closure from GNUNET_TESTBED_operation_create_()
2224  */
2225 static void
2226 opstart_shutdown_peers (void *cls)
2227 {
2228   struct OperationContext *opc = cls;
2229   struct GNUNET_MQ_Envelope *env;
2230   struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
2231
2232   opc->state = OPC_STATE_STARTED;
2233   env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
2234   msg->operation_id = GNUNET_htonll (opc->id);
2235   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
2236   GNUNET_MQ_send (opc->c->mq, env);
2237 }
2238
2239
2240 /**
2241  * Callback which will be called when shutdown peers operation is released
2242  *
2243  * @param cls the closure from GNUNET_TESTBED_operation_create_()
2244  */
2245 static void
2246 oprelease_shutdown_peers (void *cls)
2247 {
2248   struct OperationContext *opc = cls;
2249
2250   switch (opc->state)
2251   {
2252   case OPC_STATE_STARTED:
2253     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
2254
2255   /* no break; continue */
2256   case OPC_STATE_INIT:
2257     GNUNET_free (opc->data);
2258     break;
2259
2260   case OPC_STATE_FINISHED:
2261     break;
2262   }
2263   GNUNET_free (opc);
2264 }
2265
2266
2267 /**
2268  * Stops and destroys all peers.  Is equivalent of calling
2269  * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers,
2270  * except that the peer stop event and operation finished event corresponding to
2271  * the respective functions are not generated.  This function should be called
2272  * when there are no other pending operations.  If there are pending operations,
2273  * it will return NULL
2274  *
2275  * @param c the controller to send this message to
2276  * @param op_cls closure for the operation
2277  * @param cb the callback to call when all peers are stopped and destroyed
2278  * @param cb_cls the closure for the callback
2279  * @return operation handle on success; NULL if any pending operations are
2280  *           present
2281  */
2282 struct GNUNET_TESTBED_Operation *
2283 GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c,
2284                                void *op_cls,
2285                                GNUNET_TESTBED_OperationCompletionCallback cb,
2286                                void *cb_cls)
2287 {
2288   struct OperationContext *opc;
2289   struct ShutdownPeersData *data;
2290
2291   if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
2292     return NULL;
2293   data = GNUNET_new (struct ShutdownPeersData);
2294   data->cb = cb;
2295   data->cb_cls = cb_cls;
2296   opc = GNUNET_new (struct OperationContext);
2297   opc->c = c;
2298   opc->op_cls = op_cls;
2299   opc->data = data;
2300   opc->id = GNUNET_TESTBED_get_next_op_id (c);
2301   opc->type = OP_SHUTDOWN_PEERS;
2302   opc->state = OPC_STATE_INIT;
2303   opc->op = GNUNET_TESTBED_operation_create_ (opc,
2304                                               &opstart_shutdown_peers,
2305                                               &oprelease_shutdown_peers);
2306   GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
2307                                           opc->op);
2308   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2309   return opc->op;
2310 }
2311
2312
2313 /**
2314  * Return the index of the peer inside of the total peer array,
2315  * aka. the peer's "unique ID".
2316  *
2317  * @param peer Peer handle.
2318  *
2319  * @return The peer's unique ID.
2320  */
2321 uint32_t
2322 GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer)
2323 {
2324   return peer->unique_id;
2325 }
2326
2327
2328 /**
2329  * Remove a barrier and it was the last one in the barrier hash map, destroy the
2330  * hash map
2331  *
2332  * @param barrier the barrier to remove
2333  */
2334 void
2335 GNUNET_TESTBED_barrier_remove_ (struct GNUNET_TESTBED_Barrier *barrier)
2336 {
2337   struct GNUNET_TESTBED_Controller *c = barrier->c;
2338
2339   GNUNET_assert (NULL != c->barrier_map);  /* No barriers present */
2340   GNUNET_assert (GNUNET_OK ==
2341                  GNUNET_CONTAINER_multihashmap_remove (c->barrier_map,
2342                                                        &barrier->key,
2343                                                        barrier));
2344   GNUNET_free (barrier->name);
2345   GNUNET_free (barrier);
2346   if (0 == GNUNET_CONTAINER_multihashmap_size (c->barrier_map))
2347   {
2348     GNUNET_CONTAINER_multihashmap_destroy (c->barrier_map);
2349     c->barrier_map = NULL;
2350   }
2351 }
2352
2353
2354 /**
2355  * Initialise a barrier and call the given callback when the required percentage
2356  * of peers (quorum) reach the barrier OR upon error.
2357  *
2358  * @param controller the handle to the controller
2359  * @param name identification name of the barrier
2360  * @param quorum the percentage of peers that is required to reach the barrier.
2361  *   Peers signal reaching a barrier by calling
2362  *   GNUNET_TESTBED_barrier_reached().
2363  * @param cb the callback to call when the barrier is reached or upon error.
2364  *   Cannot be NULL.
2365  * @param cls closure for the above callback
2366  * @param echo GNUNET_YES to echo the barrier crossed status message back to the
2367  *   controller
2368  * @return barrier handle; NULL upon error
2369  */
2370 struct GNUNET_TESTBED_Barrier *
2371 GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller,
2372                               const char *name,
2373                               unsigned int quorum,
2374                               GNUNET_TESTBED_barrier_status_cb cb,
2375                               void *cls,
2376                               int echo)
2377 {
2378   struct GNUNET_TESTBED_BarrierInit *msg;
2379   struct GNUNET_MQ_Envelope *env;
2380   struct GNUNET_TESTBED_Barrier *barrier;
2381   struct GNUNET_HashCode key;
2382   size_t name_len;
2383
2384   GNUNET_assert (quorum <= 100);
2385   GNUNET_assert (NULL != cb);
2386   name_len = strlen (name);
2387   GNUNET_assert (0 < name_len);
2388   GNUNET_CRYPTO_hash (name, name_len, &key);
2389   if (NULL == controller->barrier_map)
2390     controller->barrier_map =
2391       GNUNET_CONTAINER_multihashmap_create (3, GNUNET_YES);
2392   if (GNUNET_YES ==
2393       GNUNET_CONTAINER_multihashmap_contains (controller->barrier_map, &key))
2394   {
2395     GNUNET_break (0);
2396     return NULL;
2397   }
2398   LOG_DEBUG ("Initialising barrier `%s'\n", name);
2399   barrier = GNUNET_new (struct GNUNET_TESTBED_Barrier);
2400   barrier->c = controller;
2401   barrier->name = GNUNET_strdup (name);
2402   barrier->cb = cb;
2403   barrier->cls = cls;
2404   barrier->echo = echo;
2405   GNUNET_memcpy (&barrier->key, &key, sizeof(struct GNUNET_HashCode));
2406   GNUNET_assert (GNUNET_OK ==
2407                  GNUNET_CONTAINER_multihashmap_put (
2408                    controller->barrier_map,
2409                    &barrier->key,
2410                    barrier,
2411                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
2412
2413   env = GNUNET_MQ_msg_extra (msg,
2414                              name_len,
2415                              GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT);
2416   msg->quorum = (uint8_t) quorum;
2417   GNUNET_memcpy (msg->name, barrier->name, name_len);
2418   GNUNET_MQ_send (barrier->c->mq, env);
2419   return barrier;
2420 }
2421
2422
2423 /**
2424  * Initialise a barrier and call the given callback when the required percentage
2425  * of peers (quorum) reach the barrier OR upon error.
2426  *
2427  * @param controller the handle to the controller
2428  * @param name identification name of the barrier
2429  * @param quorum the percentage of peers that is required to reach the barrier.
2430  *   Peers signal reaching a barrier by calling
2431  *   GNUNET_TESTBED_barrier_reached().
2432  * @param cb the callback to call when the barrier is reached or upon error.
2433  *   Cannot be NULL.
2434  * @param cls closure for the above callback
2435  * @return barrier handle; NULL upon error
2436  */
2437 struct GNUNET_TESTBED_Barrier *
2438 GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller,
2439                              const char *name,
2440                              unsigned int quorum,
2441                              GNUNET_TESTBED_barrier_status_cb cb,
2442                              void *cls)
2443 {
2444   return GNUNET_TESTBED_barrier_init_ (controller,
2445                                        name,
2446                                        quorum,
2447                                        cb,
2448                                        cls,
2449                                        GNUNET_YES);
2450 }
2451
2452
2453 /**
2454  * Cancel a barrier.
2455  *
2456  * @param barrier the barrier handle
2457  */
2458 void
2459 GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier)
2460 {
2461   struct GNUNET_MQ_Envelope *env;
2462   struct GNUNET_TESTBED_BarrierCancel *msg;
2463   size_t slen;
2464
2465   slen = strlen (barrier->name);
2466   env =
2467     GNUNET_MQ_msg_extra (msg, slen, GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL);
2468   GNUNET_memcpy (msg->name, barrier->name, slen);
2469   GNUNET_MQ_send (barrier->c->mq, env);
2470   GNUNET_TESTBED_barrier_remove_ (barrier);
2471 }
2472
2473
2474 /* end of testbed_api.c */