2 This file is part of GNUnet
3 (C) 2008--2012 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file testbed/testbed_api_peers.c
23 * @brief management of the knowledge about peers in this library
24 * (we know the peer ID, its host, pending operations, etc.)
25 * @author Christian Grothoff
28 #include "testbed_api_peers.h"
29 #include "testbed_api.h"
31 #include "testbed_api_hosts.h"
32 #include "testbed_api_operations.h"
35 * Function to call to start a peer_create type operation once all
36 * queues the operation is part of declare that the
37 * operation can be activated.
39 * @param cls the closure from GNUNET_TESTBED_operation_create_()
42 opstart_peer_create (void *cls)
44 struct OperationContext *opc = cls;
45 struct PeerCreateData *data;
46 struct GNUNET_TESTBED_PeerCreateMessage *msg;
53 GNUNET_assert (OP_PEER_CREATE == opc->type);
55 GNUNET_assert (NULL != data);
56 GNUNET_assert (NULL != data->peer);
57 config = GNUNET_CONFIGURATION_serialize (data->cfg, &c_size);
58 xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
60 msize = xc_size + sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
61 msg = GNUNET_realloc (xconfig, msize);
62 memmove (&msg[1], msg, xc_size);
63 msg->header.size = htons (msize);
64 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER);
65 msg->operation_id = GNUNET_htonll (opc->id);
66 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host));
67 msg->peer_id = htonl (data->peer->unique_id);
68 msg->config_size = htonl (c_size);
69 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head,
70 opc->c->ocq_tail, opc);
71 GNUNET_TESTBED_queue_message_ (opc->c,
72 (struct GNUNET_MessageHeader *) msg);
77 * Callback which will be called when peer_create type operation is released
79 * @param cls the closure from GNUNET_TESTBED_operation_create_()
82 oprelease_peer_create (void *cls)
84 struct OperationContext *opc = cls;
86 GNUNET_assert (NULL != opc->data);
87 GNUNET_free (opc->data);
88 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
94 * Lookup a peer by ID.
96 * @param id global peer ID assigned to the peer
97 * @return handle to the host, NULL on error
99 struct GNUNET_TESTBED_Peer *
100 GNUNET_TESTBED_peer_lookup_by_id_ (uint32_t id)
108 * Create the given peer at the specified host using the given
109 * controller. If the given controller is not running on the target
110 * host, it should find or create a controller at the target host and
111 * delegate creating the peer. Explicit delegation paths can be setup
112 * using 'GNUNET_TESTBED_controller_link'. If no explicit delegation
113 * path exists, a direct link with a subordinate controller is setup
114 * for the first delegated peer to a particular host; the subordinate
115 * controller is then destroyed once the last peer that was delegated
116 * to the remote host is stopped. This function is used in particular
117 * if some other controller has already assigned a unique ID to the
120 * Creating the peer only creates the handle to manipulate and further
121 * configure the peer; use "GNUNET_TESTBED_peer_start" and
122 * "GNUNET_TESTBED_peer_stop" to actually start/stop the peer's
125 * Note that the given configuration will be adjusted by the
126 * controller to avoid port/path conflicts with other peers.
127 * The "final" configuration can be obtained using
128 * 'GNUNET_TESTBED_peer_get_information'.
130 * @param unique_id unique ID for this peer
131 * @param controller controller process to use
132 * @param host host to run the peer on
133 * @param cfg Template configuration to use for the peer. Should exist until
134 * operation is cancelled or GNUNET_TESTBED_operation_done() is called
135 * @param cb the callback to call when the peer has been created
136 * @param cls the closure to the above callback
137 * @return the operation handle
139 struct GNUNET_TESTBED_Operation *
140 GNUNET_TESTBED_peer_create_with_id_ (uint32_t unique_id,
141 struct GNUNET_TESTBED_Controller *controller,
142 struct GNUNET_TESTBED_Host *host,
143 const struct GNUNET_CONFIGURATION_Handle *cfg,
144 GNUNET_TESTBED_PeerCreateCallback cb,
147 struct GNUNET_TESTBED_Peer *peer;
148 struct PeerCreateData *data;
149 struct OperationContext *opc;
151 peer = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer));
152 peer->controller = controller;
154 peer->unique_id = unique_id;
155 peer->state = PS_INVALID;
156 data = GNUNET_malloc (sizeof (struct PeerCreateData));
162 opc = GNUNET_malloc (sizeof (struct OperationContext));
165 opc->id = controller->operation_counter++;
166 opc->type = OP_PEER_CREATE;
167 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_create,
168 &oprelease_peer_create);
169 GNUNET_TESTBED_operation_queue_insert_ (controller->opq_peer_create, opc->op);
175 * Create the given peer at the specified host using the given
176 * controller. If the given controller is not running on the target
177 * host, it should find or create a controller at the target host and
178 * delegate creating the peer. Explicit delegation paths can be setup
179 * using 'GNUNET_TESTBED_controller_link'. If no explicit delegation
180 * path exists, a direct link with a subordinate controller is setup
181 * for the first delegated peer to a particular host; the subordinate
182 * controller is then destroyed once the last peer that was delegated
183 * to the remote host is stopped.
185 * Creating the peer only creates the handle to manipulate and further
186 * configure the peer; use "GNUNET_TESTBED_peer_start" and
187 * "GNUNET_TESTBED_peer_stop" to actually start/stop the peer's
190 * Note that the given configuration will be adjusted by the
191 * controller to avoid port/path conflicts with other peers.
192 * The "final" configuration can be obtained using
193 * 'GNUNET_TESTBED_peer_get_information'.
195 * @param controller controller process to use
196 * @param host host to run the peer on
197 * @param cfg Template configuration to use for the peer. Should exist until
198 * operation is cancelled or GNUNET_TESTBED_operation_done() is called
199 * @param cb the callback to call when the peer has been created
200 * @param cls the closure to the above callback
201 * @return the operation handle
203 struct GNUNET_TESTBED_Operation *
204 GNUNET_TESTBED_peer_create (struct GNUNET_TESTBED_Controller *controller,
205 struct GNUNET_TESTBED_Host *host,
206 const struct GNUNET_CONFIGURATION_Handle *cfg,
207 GNUNET_TESTBED_PeerCreateCallback cb,
210 static uint32_t id_gen;
212 return GNUNET_TESTBED_peer_create_with_id_ (++id_gen,
221 * Start the given peer.
223 * @param peer peer to start
224 * @return handle to the operation
226 struct GNUNET_TESTBED_Operation *
227 GNUNET_TESTBED_peer_start (struct GNUNET_TESTBED_Peer *peer)
229 struct GNUNET_TESTBED_Operation *op;
230 struct GNUNET_TESTBED_PeerStartMessage *msg;
232 GNUNET_assert ((PS_CREATED == peer->state) || (PS_STOPPED == peer->state));
233 op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation));
234 op->operation_id = peer->controller->operation_counter++;
235 op->controller = peer->controller;
236 op->type = OP_PEER_START;
238 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerStartMessage));
239 msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStartMessage));
240 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_STARTPEER);
241 msg->peer_id = htonl (peer->unique_id);
242 msg->operation_id = GNUNET_htonll (op->operation_id);
243 GNUNET_CONTAINER_DLL_insert_tail (peer->controller->op_head,
244 peer->controller->op_tail, op);
245 GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
251 * Stop the given peer. The handle remains valid (use
252 * "GNUNET_TESTBED_peer_destroy" to fully clean up the
253 * state of the peer).
255 * @param peer peer to stop
256 * @return handle to the operation
258 struct GNUNET_TESTBED_Operation *
259 GNUNET_TESTBED_peer_stop (struct GNUNET_TESTBED_Peer *peer)
261 struct GNUNET_TESTBED_Operation *op;
262 struct GNUNET_TESTBED_PeerStopMessage *msg;
264 GNUNET_assert (PS_STARTED == peer->state);
265 op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation));
266 op->operation_id = peer->controller->operation_counter++;
267 op->controller = peer->controller;
268 op->type = OP_PEER_STOP;
270 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerStopMessage));
271 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_STOPPEER);
272 msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStopMessage));
273 msg->peer_id = htonl (peer->unique_id);
274 msg->operation_id = GNUNET_htonll (op->operation_id);
275 GNUNET_CONTAINER_DLL_insert_tail (peer->controller->op_head,
276 peer->controller->op_tail, op);
277 GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
283 * Request information about a peer.
285 * @param peer peer to request information about
286 * @param pit desired information
287 * @return handle to the operation
289 struct GNUNET_TESTBED_Operation *
290 GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer,
291 enum GNUNET_TESTBED_PeerInformationType pit)
293 struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
294 struct GNUNET_TESTBED_Operation *op;
295 struct PeerInfoData *data;
297 GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC != pit);
298 data = GNUNET_malloc (sizeof (struct PeerInfoData));
301 op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation));
302 op->type = OP_PEER_INFO;
303 op->operation_id = peer->controller->operation_counter++;
304 op->controller = peer->controller;
306 msg = GNUNET_malloc (sizeof (struct
307 GNUNET_TESTBED_PeerGetConfigurationMessage));
308 msg->header.size = htons
309 (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
310 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG);
311 msg->peer_id = htonl (peer->unique_id);
312 msg->operation_id = GNUNET_htonll (op->operation_id);
313 GNUNET_CONTAINER_DLL_insert_tail (peer->controller->op_head,
314 peer->controller->op_tail, op);
315 GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
321 * Change peer configuration. Must only be called while the
322 * peer is stopped. Ports and paths cannot be changed this
325 * @param peer peer to change configuration for
326 * @param cfg new configuration (differences to existing
327 * configuration only)
328 * @return handle to the operation
330 struct GNUNET_TESTBED_Operation *
331 GNUNET_TESTBED_peer_update_configuration (struct GNUNET_TESTBED_Peer *peer,
332 const struct GNUNET_CONFIGURATION_Handle *cfg)
334 // FIXME: handle locally or delegate...
341 * Destroy the given peer; the peer should have been
342 * stopped first (if it was started).
344 * @param peer peer to stop
345 * @return handle to the operation
347 struct GNUNET_TESTBED_Operation *
348 GNUNET_TESTBED_peer_destroy (struct GNUNET_TESTBED_Peer *peer)
350 struct GNUNET_TESTBED_Operation *op;
351 struct PeerDestroyData *data;
352 struct GNUNET_TESTBED_PeerDestroyMessage *msg;
354 data = GNUNET_malloc (sizeof (struct PeerDestroyData));
356 op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation));
357 op->operation_id = peer->controller->operation_counter++;
358 op->controller = peer->controller;
359 op->type = OP_PEER_DESTROY;
361 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerDestroyMessage));
362 msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerDestroyMessage));
363 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER);
364 msg->peer_id = htonl (peer->unique_id);
365 msg->operation_id = GNUNET_htonll (op->operation_id);
366 GNUNET_CONTAINER_DLL_insert_tail (peer->controller->op_head,
367 peer->controller->op_tail, op);
368 GNUNET_TESTBED_queue_message_ (peer->controller,
369 (struct GNUNET_MessageHeader *) msg);
375 * Manipulate the P2P underlay topology by configuring a link
378 * @param op_cls closure argument to give with the operation event
379 * @param p1 first peer
380 * @param p2 second peer
381 * @param co option to change
382 * @param ... option-specific values
383 * @return handle to the operation, NULL if configuring the link at this
384 * time is not allowed
386 struct GNUNET_TESTBED_Operation *
387 GNUNET_TESTBED_underlay_configure_link (void *op_cls,
388 struct GNUNET_TESTBED_Peer *p1,
389 struct GNUNET_TESTBED_Peer *p2,
390 enum GNUNET_TESTBED_ConnectOption co, ...)
399 * Both peers must have been started before calling this function.
400 * This function then obtains a HELLO from 'p1', gives it to 'p2'
401 * and asks 'p2' to connect to 'p1'.
403 * @param op_cls closure argument to give with the operation event
404 * @param p1 first peer
405 * @param p2 second peer
406 * @return handle to the operation, NULL if connecting these two
407 * peers is fundamentally not possible at this time (peers
408 * not running or underlay disallows)
410 struct GNUNET_TESTBED_Operation *
411 GNUNET_TESTBED_overlay_connect (void *op_cls,
412 struct GNUNET_TESTBED_Peer *p1,
413 struct GNUNET_TESTBED_Peer *p2)
415 struct GNUNET_TESTBED_Operation *op;
416 struct OverlayConnectData *data;
417 struct GNUNET_TESTBED_OverlayConnectMessage *msg;
419 GNUNET_assert ((PS_STARTED == p1->state) && (PS_STARTED == p2->state));
420 GNUNET_assert (p1->controller == p2->controller);
421 data = GNUNET_malloc (sizeof (struct OverlayConnectData));
424 op = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Operation));
425 op->controller = p1->controller;
426 op->operation_id = op->controller->operation_counter++;
427 op->type = OP_OVERLAY_CONNECT;
429 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage));
430 msg->header.size = htons (sizeof (struct
431 GNUNET_TESTBED_OverlayConnectMessage));
432 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT);
433 msg->peer1 = htonl (p1->unique_id);
434 msg->peer2 = htonl (p2->unique_id);
435 msg->operation_id = GNUNET_htonll (op->operation_id);
436 GNUNET_CONTAINER_DLL_insert_tail (op->controller->op_head,
437 op->controller->op_tail, op);
438 GNUNET_TESTBED_queue_message_ (op->controller,
439 (struct GNUNET_MessageHeader *) msg);
445 /* end of testbed_api_peers.c */