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