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