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