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