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