2 This file is part of GNUnet
3 Copyright (C) 2008--2013 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file testbed/testbed_api_peers.c
21 * @brief management of the knowledge about peers in this library
22 * (we know the peer ID, its host, pending operations, etc.)
23 * @author Christian Grothoff
24 * @author Sree Harsha Totakura
28 #include "testbed_api_peers.h"
29 #include "testbed_api.h"
31 #include "testbed_api_hosts.h"
32 #include "testbed_api_operations.h"
38 static struct GNUNET_TESTBED_Peer *peer_list_head;
43 static struct GNUNET_TESTBED_Peer *peer_list_tail;
47 * Adds a peer to the peer list
49 * @param peer the peer to add to the peer list
52 GNUNET_TESTBED_peer_register_ (struct GNUNET_TESTBED_Peer *peer)
54 GNUNET_CONTAINER_DLL_insert_tail (peer_list_head, peer_list_tail, peer);
59 * Removes a peer from the peer list
61 * @param peer the peer to remove
64 GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer)
66 GNUNET_CONTAINER_DLL_remove (peer_list_head, peer_list_tail, peer);
74 GNUNET_TESTBED_cleanup_peers_ (void)
76 struct GNUNET_TESTBED_Peer *peer;
78 while (NULL != (peer = peer_list_head))
80 GNUNET_TESTBED_peer_deregister_ (peer);
88 * Function to call to start a peer_create type operation once all
89 * queues the operation is part of declare that the
90 * operation can be activated.
92 * @param cls the closure from GNUNET_TESTBED_operation_create_()
95 opstart_peer_create (void *cls)
97 struct OperationContext *opc = cls;
98 struct PeerCreateData *data = opc->data;
99 struct GNUNET_TESTBED_PeerCreateMessage *msg;
100 struct GNUNET_MQ_Envelope *env;
106 GNUNET_assert (OP_PEER_CREATE == opc->type);
107 GNUNET_assert (NULL != data);
108 GNUNET_assert (NULL != data->peer);
109 opc->state = OPC_STATE_STARTED;
110 config = GNUNET_CONFIGURATION_serialize (data->cfg,
112 xc_size = GNUNET_TESTBED_compress_config_ (config,
115 GNUNET_free (config);
116 env = GNUNET_MQ_msg_extra (msg,
118 GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER);
119 msg->operation_id = GNUNET_htonll (opc->id);
120 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host));
121 msg->peer_id = htonl (data->peer->unique_id);
122 msg->config_size = htons ((uint16_t) c_size);
123 GNUNET_memcpy (&msg[1],
126 GNUNET_MQ_send (opc->c->mq,
128 GNUNET_free (xconfig);
129 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
134 * Callback which will be called when peer_create type operation is released
136 * @param cls the closure from GNUNET_TESTBED_operation_create_()
139 oprelease_peer_create (void *cls)
141 struct OperationContext *opc = cls;
145 case OPC_STATE_STARTED:
146 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
147 /* No break we continue flow */
149 GNUNET_free (((struct PeerCreateData *) opc->data)->peer);
150 GNUNET_free (opc->data);
152 case OPC_STATE_FINISHED:
160 * Function called when a peer destroy operation is ready
162 * @param cls the closure from GNUNET_TESTBED_operation_create_()
165 opstart_peer_destroy (void *cls)
167 struct OperationContext *opc = cls;
168 struct GNUNET_TESTBED_Peer *peer = opc->data;
169 struct GNUNET_TESTBED_PeerDestroyMessage *msg;
170 struct GNUNET_MQ_Envelope *env;
172 GNUNET_assert (OP_PEER_DESTROY == opc->type);
173 GNUNET_assert (NULL != peer);
174 opc->state = OPC_STATE_STARTED;
175 env = GNUNET_MQ_msg (msg,
176 GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER);
177 msg->peer_id = htonl (peer->unique_id);
178 msg->operation_id = GNUNET_htonll (opc->id);
179 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
180 GNUNET_MQ_send (peer->controller->mq,
186 * Callback which will be called when peer_create type operation is released
188 * @param cls the closure from GNUNET_TESTBED_operation_create_()
191 oprelease_peer_destroy (void *cls)
193 struct OperationContext *opc = cls;
197 case OPC_STATE_STARTED:
198 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
199 /* no break; continue */
202 case OPC_STATE_FINISHED:
210 * Function called when a peer start operation is ready
212 * @param cls the closure from GNUNET_TESTBED_operation_create_()
215 opstart_peer_start (void *cls)
217 struct OperationContext *opc = cls;
218 struct GNUNET_TESTBED_PeerStartMessage *msg;
219 struct GNUNET_MQ_Envelope *env;
220 struct PeerEventData *data;
221 struct GNUNET_TESTBED_Peer *peer;
223 GNUNET_assert (OP_PEER_START == opc->type);
224 GNUNET_assert (NULL != (data = opc->data));
225 GNUNET_assert (NULL != (peer = data->peer));
226 GNUNET_assert ((TESTBED_PS_CREATED == peer->state) || (TESTBED_PS_STOPPED == peer->state));
227 opc->state = OPC_STATE_STARTED;
228 env = GNUNET_MQ_msg (msg,
229 GNUNET_MESSAGE_TYPE_TESTBED_START_PEER);
230 msg->peer_id = htonl (peer->unique_id);
231 msg->operation_id = GNUNET_htonll (opc->id);
232 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
233 GNUNET_MQ_send (peer->controller->mq,
239 * Callback which will be called when peer start type operation is released
241 * @param cls the closure from GNUNET_TESTBED_operation_create_()
244 oprelease_peer_start (void *cls)
246 struct OperationContext *opc = cls;
250 case OPC_STATE_STARTED:
251 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
252 /* no break; continue */
254 GNUNET_free (opc->data);
256 case OPC_STATE_FINISHED:
264 * Function called when a peer stop operation is ready
266 * @param cls the closure from GNUNET_TESTBED_operation_create_()
269 opstart_peer_stop (void *cls)
271 struct OperationContext *opc = cls;
272 struct GNUNET_TESTBED_PeerStopMessage *msg;
273 struct PeerEventData *data;
274 struct GNUNET_TESTBED_Peer *peer;
275 struct GNUNET_MQ_Envelope *env;
277 GNUNET_assert (NULL != (data = opc->data));
278 GNUNET_assert (NULL != (peer = data->peer));
279 GNUNET_assert (TESTBED_PS_STARTED == peer->state);
280 opc->state = OPC_STATE_STARTED;
281 env = GNUNET_MQ_msg (msg,
282 GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER);
283 msg->peer_id = htonl (peer->unique_id);
284 msg->operation_id = GNUNET_htonll (opc->id);
285 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
286 GNUNET_MQ_send (peer->controller->mq,
292 * Callback which will be called when peer stop type operation is released
294 * @param cls the closure from GNUNET_TESTBED_operation_create_()
297 oprelease_peer_stop (void *cls)
299 struct OperationContext *opc = cls;
303 case OPC_STATE_STARTED:
304 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
305 /* no break; continue */
307 GNUNET_free (opc->data);
309 case OPC_STATE_FINISHED:
317 * Generate PeerGetConfigurationMessage
319 * @param peer_id the id of the peer whose information we have to get
320 * @param operation_id the ip of the operation that should be represented in the
322 * @return the PeerGetConfigurationMessage
324 struct GNUNET_TESTBED_PeerGetConfigurationMessage *
325 GNUNET_TESTBED_generate_peergetconfig_msg_ (uint32_t peer_id,
326 uint64_t operation_id)
328 struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
331 GNUNET_malloc (sizeof
332 (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
334 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
335 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
336 msg->peer_id = htonl (peer_id);
337 msg->operation_id = GNUNET_htonll (operation_id);
343 * Function called when a peer get information operation is ready
345 * @param cls the closure from GNUNET_TESTBED_operation_create_()
348 opstart_peer_getinfo (void *cls)
350 struct OperationContext *opc = cls;
351 struct PeerInfoData *data = opc->data;
352 struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
354 GNUNET_assert (NULL != data);
355 opc->state = OPC_STATE_STARTED;
357 GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id,
359 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
360 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
365 * Callback which will be called when peer stop type operation is released
367 * @param cls the closure from GNUNET_TESTBED_operation_create_()
370 oprelease_peer_getinfo (void *cls)
372 struct OperationContext *opc = cls;
373 struct GNUNET_TESTBED_PeerInformation *data;
377 case OPC_STATE_STARTED:
378 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
379 /* no break; continue */
381 GNUNET_free (opc->data);
383 case OPC_STATE_FINISHED:
385 GNUNET_assert (NULL != data);
388 case GNUNET_TESTBED_PIT_CONFIGURATION:
389 if (NULL != data->result.cfg)
390 GNUNET_CONFIGURATION_destroy (data->result.cfg);
392 case GNUNET_TESTBED_PIT_IDENTITY:
393 GNUNET_free (data->result.id);
396 GNUNET_assert (0); /* We should never reach here */
406 * Function called when a overlay connect operation is ready
408 * @param cls the closure from GNUNET_TESTBED_operation_create_()
411 opstart_overlay_connect (void *cls)
413 struct OperationContext *opc = cls;
414 struct GNUNET_MQ_Envelope *env;
415 struct GNUNET_TESTBED_OverlayConnectMessage *msg;
416 struct OverlayConnectData *data;
418 opc->state = OPC_STATE_STARTED;
420 GNUNET_assert (NULL != data);
421 env = GNUNET_MQ_msg (msg,
422 GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT);
423 msg->peer1 = htonl (data->p1->unique_id);
424 msg->peer2 = htonl (data->p2->unique_id);
425 msg->operation_id = GNUNET_htonll (opc->id);
426 msg->peer2_host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->p2->host));
427 GNUNET_TESTBED_insert_opc_ (opc->c,
429 GNUNET_MQ_send (opc->c->mq,
435 * Callback which will be called when overlay connect operation is released
437 * @param cls the closure from GNUNET_TESTBED_operation_create_()
440 oprelease_overlay_connect (void *cls)
442 struct OperationContext *opc = cls;
443 struct OverlayConnectData *data;
450 case OPC_STATE_STARTED:
451 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
453 case OPC_STATE_FINISHED:
462 * Function called when a peer reconfigure operation is ready
464 * @param cls the closure from GNUNET_TESTBED_operation_create_()
467 opstart_peer_reconfigure (void *cls)
469 struct OperationContext *opc = cls;
470 struct PeerReconfigureData *data = opc->data;
471 struct GNUNET_MQ_Envelope *env;
472 struct GNUNET_TESTBED_PeerReconfigureMessage *msg;
476 opc->state = OPC_STATE_STARTED;
477 GNUNET_assert (NULL != data);
478 xc_size = GNUNET_TESTBED_compress_config_ (data->config,
481 GNUNET_free (data->config);
483 GNUNET_assert (xc_size < UINT16_MAX - sizeof (*msg));
484 env = GNUNET_MQ_msg_extra (msg,
486 GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER);
487 msg->peer_id = htonl (data->peer->unique_id);
488 msg->operation_id = GNUNET_htonll (opc->id);
489 msg->config_size = htons (data->cfg_size);
490 GNUNET_memcpy (&msg[1],
493 GNUNET_free (xconfig);
496 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
497 GNUNET_MQ_send (opc->c->mq,
503 * Callback which will be called when a peer reconfigure operation is released
505 * @param cls the closure from GNUNET_TESTBED_operation_create_()
508 oprelease_peer_reconfigure (void *cls)
510 struct OperationContext *opc = cls;
511 struct PeerReconfigureData *data = opc->data;
516 GNUNET_free (data->config);
519 case OPC_STATE_STARTED:
520 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
522 case OPC_STATE_FINISHED:
530 * Lookup a peer by ID.
532 * @param id global peer ID assigned to the peer
533 * @return handle to the host, NULL on error
535 struct GNUNET_TESTBED_Peer *
536 GNUNET_TESTBED_peer_lookup_by_id_ (uint32_t id)
544 * Create the given peer at the specified host using the given
545 * controller. If the given controller is not running on the target
546 * host, it should find or create a controller at the target host and
547 * delegate creating the peer. Explicit delegation paths can be setup
548 * using 'GNUNET_TESTBED_controller_link'. If no explicit delegation
549 * path exists, a direct link with a subordinate controller is setup
550 * for the first delegated peer to a particular host; the subordinate
551 * controller is then destroyed once the last peer that was delegated
552 * to the remote host is stopped.
554 * Creating the peer only creates the handle to manipulate and further
555 * configure the peer; use "GNUNET_TESTBED_peer_start" and
556 * "GNUNET_TESTBED_peer_stop" to actually start/stop the peer's
559 * Note that the given configuration will be adjusted by the
560 * controller to avoid port/path conflicts with other peers.
561 * The "final" configuration can be obtained using
562 * 'GNUNET_TESTBED_peer_get_information'.
564 * @param controller controller process to use
565 * @param host host to run the peer on; cannot be NULL
566 * @param cfg Template configuration to use for the peer. Should exist until
567 * operation is cancelled or GNUNET_TESTBED_operation_done() is called
568 * @param cb the callback to call when the peer has been created
569 * @param cls the closure to the above callback
570 * @return the operation handle
572 struct GNUNET_TESTBED_Operation *
573 GNUNET_TESTBED_peer_create (struct GNUNET_TESTBED_Controller *controller,
574 struct GNUNET_TESTBED_Host *host,
575 const struct GNUNET_CONFIGURATION_Handle *cfg,
576 GNUNET_TESTBED_PeerCreateCallback cb, void *cls)
579 struct GNUNET_TESTBED_Peer *peer;
580 struct PeerCreateData *data;
581 struct OperationContext *opc;
582 static uint32_t id_gen;
584 peer = GNUNET_new (struct GNUNET_TESTBED_Peer);
585 peer->controller = controller;
587 peer->unique_id = id_gen++;
588 peer->state = TESTBED_PS_INVALID;
589 data = GNUNET_new (struct PeerCreateData);
595 opc = GNUNET_new (struct OperationContext);
598 opc->id = GNUNET_TESTBED_get_next_op_id (controller);
599 opc->type = OP_PEER_CREATE;
601 GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_create,
602 &oprelease_peer_create);
603 GNUNET_TESTBED_operation_queue_insert_ (controller->opq_parallel_operations,
605 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
611 * Start the given peer.
613 * @param op_cls the closure for this operation; will be set in
614 * event->details.operation_finished.op_cls when this operation fails.
615 * @param peer peer to start
616 * @param pcc function to call upon completion
617 * @param pcc_cls closure for 'pcc'
618 * @return handle to the operation
620 struct GNUNET_TESTBED_Operation *
621 GNUNET_TESTBED_peer_start (void *op_cls, struct GNUNET_TESTBED_Peer *peer,
622 GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls)
624 struct OperationContext *opc;
625 struct PeerEventData *data;
627 data = GNUNET_new (struct PeerEventData);
630 data->pcc_cls = pcc_cls;
631 opc = GNUNET_new (struct OperationContext);
632 opc->c = peer->controller;
634 opc->op_cls = op_cls;
635 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
636 opc->type = OP_PEER_START;
638 GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_start,
639 &oprelease_peer_start);
640 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
642 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
648 * Stop the given peer. The handle remains valid (use
649 * "GNUNET_TESTBED_peer_destroy" to fully clean up the
650 * state of the peer).
652 * @param op_cls the closure for this operation; will be set in the event
654 * @param peer peer to stop
655 * @param pcc function to call upon completion
656 * @param pcc_cls closure for 'pcc'
657 * @return handle to the operation
659 struct GNUNET_TESTBED_Operation *
660 GNUNET_TESTBED_peer_stop (void *op_cls,
661 struct GNUNET_TESTBED_Peer *peer,
662 GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls)
664 struct OperationContext *opc;
665 struct PeerEventData *data;
667 data = GNUNET_new (struct PeerEventData);
670 data->pcc_cls = pcc_cls;
671 opc = GNUNET_new (struct OperationContext);
672 opc->c = peer->controller;
674 opc->op_cls = op_cls;
675 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
676 opc->type = OP_PEER_STOP;
678 GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_stop,
679 &oprelease_peer_stop);
680 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
682 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
688 * Request information about a peer. The controller callback will not be called
689 * with event type GNUNET_TESTBED_ET_OPERATION_FINISHED when result for this
690 * operation is available. Instead, the GNUNET_TESTBED_PeerInfoCallback() will
692 * The peer information in the callback is valid until the operation is canceled.
694 * @param peer peer to request information about
695 * @param pit desired information
696 * @param cb the convenience callback to be called when results for this
697 * operation are available
698 * @param cb_cls the closure for the above callback
699 * @return handle to the operation
701 struct GNUNET_TESTBED_Operation *
702 GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer,
703 enum GNUNET_TESTBED_PeerInformationType
704 pit, GNUNET_TESTBED_PeerInfoCallback cb,
707 struct OperationContext *opc;
708 struct PeerInfoData *data;
710 GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC != pit);
711 GNUNET_assert (NULL != cb);
712 data = GNUNET_new (struct PeerInfoData);
716 data->cb_cls = cb_cls;
717 opc = GNUNET_new (struct OperationContext);
718 opc->c = peer->controller;
720 opc->type = OP_PEER_INFO;
721 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
723 GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_getinfo,
724 &oprelease_peer_getinfo);
725 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
727 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
733 * Change peer configuration. Must only be called while the
734 * peer is stopped. Ports and paths cannot be changed this
737 * @param peer peer to change configuration for
738 * @param cfg new configuration (differences to existing
739 * configuration only)
740 * @return handle to the operation
742 struct GNUNET_TESTBED_Operation *
743 GNUNET_TESTBED_peer_update_configuration (struct GNUNET_TESTBED_Peer *peer,
745 GNUNET_CONFIGURATION_Handle *cfg)
747 struct OperationContext *opc;
748 struct PeerReconfigureData *data;
751 data = GNUNET_new (struct PeerReconfigureData);
753 data->config = GNUNET_CONFIGURATION_serialize (cfg, &csize);
754 if (NULL == data->config)
759 if (csize > UINT16_MAX)
762 GNUNET_free (data->config);
766 data->cfg_size = (uint16_t) csize;
767 opc = GNUNET_new (struct OperationContext);
768 opc->c = peer->controller;
770 opc->type = OP_PEER_RECONFIGURE;
771 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
773 GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_reconfigure,
774 &oprelease_peer_reconfigure);
775 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
777 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
783 * Destroy the given peer; the peer should have been
784 * stopped first (if it was started).
786 * @param peer peer to stop
787 * @return handle to the operation
789 struct GNUNET_TESTBED_Operation *
790 GNUNET_TESTBED_peer_destroy (struct GNUNET_TESTBED_Peer *peer)
792 struct OperationContext *opc;
794 opc = GNUNET_new (struct OperationContext);
796 opc->c = peer->controller;
797 opc->id = GNUNET_TESTBED_get_next_op_id (peer->controller);
798 opc->type = OP_PEER_DESTROY;
800 GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_destroy,
801 &oprelease_peer_destroy);
802 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
804 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
810 * Manipulate the P2P underlay topology by configuring a link
813 * @param op_cls closure argument to give with the operation event
814 * @param p1 first peer
815 * @param p2 second peer
816 * @param co option to change
817 * @param ... option-specific values
818 * @return handle to the operation, NULL if configuring the link at this
819 * time is not allowed
821 struct GNUNET_TESTBED_Operation *
822 GNUNET_TESTBED_underlay_configure_link (void *op_cls,
823 struct GNUNET_TESTBED_Peer *p1,
824 struct GNUNET_TESTBED_Peer *p2,
825 enum GNUNET_TESTBED_ConnectOption co,
834 * Both peers must have been started before calling this function.
835 * This function then obtains a HELLO from 'p1', gives it to 'p2'
836 * and asks 'p2' to connect to 'p1'.
838 * @param op_cls closure argument to give with the operation event
839 * @param cb the callback to call when this operation has finished
840 * @param cb_cls the closure for the above callback
841 * @param p1 first peer
842 * @param p2 second peer
843 * @return handle to the operation, NULL if connecting these two
844 * peers is fundamentally not possible at this time (peers
845 * not running or underlay disallows)
847 struct GNUNET_TESTBED_Operation *
848 GNUNET_TESTBED_overlay_connect (void *op_cls,
849 GNUNET_TESTBED_OperationCompletionCallback cb,
850 void *cb_cls, struct GNUNET_TESTBED_Peer *p1,
851 struct GNUNET_TESTBED_Peer *p2)
853 struct OperationContext *opc;
854 struct OverlayConnectData *data;
856 GNUNET_assert ((TESTBED_PS_STARTED == p1->state) && (TESTBED_PS_STARTED == p2->state));
857 data = GNUNET_new (struct OverlayConnectData);
861 data->cb_cls = cb_cls;
862 opc = GNUNET_new (struct OperationContext);
864 opc->c = p1->controller;
865 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
866 opc->type = OP_OVERLAY_CONNECT;
867 opc->op_cls = op_cls;
869 GNUNET_TESTBED_operation_create_ (opc, &opstart_overlay_connect,
870 &oprelease_overlay_connect);
871 GNUNET_TESTBED_host_queue_oc_ (p1->host, opc->op);
872 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
878 * Function called when a peer manage service operation is ready
880 * @param cls the closure from GNUNET_TESTBED_operation_create_()
883 opstart_manage_service (void *cls)
885 struct OperationContext *opc = cls;
886 struct ManageServiceData *data = opc->data;
887 struct GNUNET_MQ_Envelope *env;
888 struct GNUNET_TESTBED_ManagePeerServiceMessage *msg;
891 GNUNET_assert (NULL != data);
892 xlen = data->msize - sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage);
893 env = GNUNET_MQ_msg_extra (msg,
895 GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE);
896 msg->peer_id = htonl (data->peer->unique_id);
897 msg->operation_id = GNUNET_htonll (opc->id);
898 msg->start = (uint8_t) data->start;
899 GNUNET_memcpy (&msg[1],
902 GNUNET_free (data->service_name);
903 data->service_name = NULL;
904 opc->state = OPC_STATE_STARTED;
905 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
906 GNUNET_MQ_send (opc->c->mq,
912 * Callback which will be called when peer manage server operation is released
914 * @param cls the closure from GNUNET_TESTBED_operation_create_()
917 oprelease_manage_service (void *cls)
919 struct OperationContext *opc = cls;
920 struct ManageServiceData *data;
925 case OPC_STATE_STARTED:
926 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
929 GNUNET_assert (NULL != data);
930 GNUNET_free (data->service_name);
932 case OPC_STATE_FINISHED:
935 GNUNET_free_non_null (data);
941 * Start or stop given service at a peer. This should not be called to
942 * start/stop the peer's ARM service. Use GNUNET_TESTBED_peer_start(),
943 * GNUNET_TESTBED_peer_stop() for starting/stopping peer's ARM service. Success
944 * or failure of the generated operation is signalled through the controller
945 * event callback and/or operation completion callback.
947 * @param op_cls the closure for the operation
948 * @param peer the peer whose service is to be started/stopped
949 * @param service_name the name of the service
950 * @param cb the operation completion callback
951 * @param cb_cls the closure for the operation completion callback
952 * @param start 1 to start the service; 0 to stop the service
953 * @return an operation handle; NULL upon error (peer not running)
955 struct GNUNET_TESTBED_Operation *
956 GNUNET_TESTBED_peer_manage_service (void *op_cls,
957 struct GNUNET_TESTBED_Peer *peer,
958 const char *service_name,
959 GNUNET_TESTBED_OperationCompletionCallback cb,
963 struct ManageServiceData *data;
964 struct OperationContext *opc;
967 GNUNET_assert (TESTBED_PS_STARTED == peer->state); /* peer is not running? */
968 msize = strlen (service_name) + 1;
969 msize += sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage);
970 if (GNUNET_MAX_MESSAGE_SIZE < msize)
972 data = GNUNET_new (struct ManageServiceData);
974 data->cb_cls = cb_cls;
976 data->service_name = GNUNET_strdup (service_name);
978 data->msize = (uint16_t) msize;
979 opc = GNUNET_new (struct OperationContext);
981 opc->c = peer->controller;
982 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
983 opc->type = OP_MANAGE_SERVICE;
984 opc->op_cls = op_cls;
986 GNUNET_TESTBED_operation_create_ (opc, &opstart_manage_service,
987 &oprelease_manage_service);
988 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
990 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
996 /* end of testbed_api_peers.c */