-fix channel data range to make -1 legal value
[oweals/gnunet.git] / src / testbed / testbed_api_peers.c
1 /*
2       This file is part of GNUnet
3       (C) 2008--2013 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_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
26  * @author Sree Harsha Totakura
27  */
28
29 #include "platform.h"
30 #include "testbed_api_peers.h"
31 #include "testbed_api.h"
32 #include "testbed.h"
33 #include "testbed_api_hosts.h"
34 #include "testbed_api_operations.h"
35
36
37 /**
38  * Peer list DLL head
39  */
40 static struct GNUNET_TESTBED_Peer *peer_list_head;
41
42 /**
43  * Peer list DLL tail
44  */
45 static struct GNUNET_TESTBED_Peer *peer_list_tail;
46
47
48 /**
49  * Adds a peer to the peer list
50  *
51  * @param peer the peer to add to the peer list
52  */
53 void
54 GNUNET_TESTBED_peer_register_ (struct GNUNET_TESTBED_Peer *peer)
55 {
56   GNUNET_CONTAINER_DLL_insert_tail (peer_list_head, peer_list_tail, peer);
57 }
58
59
60 /**
61  * Removes a peer from the peer list
62  *
63  * @param peer the peer to remove
64  */
65 void
66 GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer)
67 {
68   GNUNET_CONTAINER_DLL_remove (peer_list_head, peer_list_tail, peer);
69 }
70
71
72 /**
73  * Frees all peers
74  */
75 void
76 GNUNET_TESTBED_cleanup_peers_ (void)
77 {
78   struct GNUNET_TESTBED_Peer *peer;
79
80   while (NULL != (peer = peer_list_head))
81   {
82     GNUNET_TESTBED_peer_deregister_ (peer);
83     GNUNET_free (peer);
84   }
85 }
86
87
88
89 /**
90  * Function to call to start a peer_create type operation once all
91  * queues the operation is part of declare that the
92  * operation can be activated.
93  *
94  * @param cls the closure from GNUNET_TESTBED_operation_create_()
95  */
96 static void
97 opstart_peer_create (void *cls)
98 {
99   struct OperationContext *opc = cls;
100   struct PeerCreateData *data = opc->data;
101   struct GNUNET_TESTBED_PeerCreateMessage *msg;
102   char *config;
103   char *xconfig;
104   size_t c_size;
105   size_t xc_size;
106   uint16_t msize;
107
108   GNUNET_assert (OP_PEER_CREATE == opc->type);
109   GNUNET_assert (NULL != data);
110   GNUNET_assert (NULL != data->peer);
111   opc->state = OPC_STATE_STARTED;
112   config = GNUNET_CONFIGURATION_serialize (data->cfg, &c_size);
113   xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
114   GNUNET_free (config);
115   msize = xc_size + sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
116   msg = GNUNET_realloc (xconfig, msize);
117   memmove (&msg[1], msg, xc_size);
118   msg->header.size = htons (msize);
119   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER);
120   msg->operation_id = GNUNET_htonll (opc->id);
121   msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host));
122   msg->peer_id = htonl (data->peer->unique_id);
123   msg->config_size = htons ((uint16_t) c_size);
124   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
125   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
126 }
127
128
129 /**
130  * Callback which will be called when peer_create type operation is released
131  *
132  * @param cls the closure from GNUNET_TESTBED_operation_create_()
133  */
134 static void
135 oprelease_peer_create (void *cls)
136 {
137   struct OperationContext *opc = cls;
138
139   switch (opc->state)
140   {
141   case OPC_STATE_STARTED:
142     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
143     /* No break we continue flow */
144   case OPC_STATE_INIT:
145     GNUNET_free (((struct PeerCreateData *) opc->data)->peer);
146     GNUNET_free (opc->data);
147     break;
148   case OPC_STATE_FINISHED:
149     break;
150   }
151   GNUNET_free (opc);
152 }
153
154
155 /**
156  * Function called when a peer destroy operation is ready
157  *
158  * @param cls the closure from GNUNET_TESTBED_operation_create_()
159  */
160 static void
161 opstart_peer_destroy (void *cls)
162 {
163   struct OperationContext *opc = cls;
164   struct GNUNET_TESTBED_Peer *peer = opc->data;
165   struct GNUNET_TESTBED_PeerDestroyMessage *msg;
166
167   GNUNET_assert (OP_PEER_DESTROY == opc->type);
168   GNUNET_assert (NULL != peer);
169   opc->state = OPC_STATE_STARTED;
170   msg = GNUNET_new (struct GNUNET_TESTBED_PeerDestroyMessage);
171   msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerDestroyMessage));
172   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER);
173   msg->peer_id = htonl (peer->unique_id);
174   msg->operation_id = GNUNET_htonll (opc->id);
175   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
176   GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
177 }
178
179
180 /**
181  * Callback which will be called when peer_create type operation is released
182  *
183  * @param cls the closure from GNUNET_TESTBED_operation_create_()
184  */
185 static void
186 oprelease_peer_destroy (void *cls)
187 {
188   struct OperationContext *opc = cls;
189
190   switch (opc->state)
191   {
192   case OPC_STATE_STARTED:
193     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
194     /* no break; continue */
195   case OPC_STATE_INIT:
196     break;
197   case OPC_STATE_FINISHED:
198     break;
199   }
200   GNUNET_free (opc);
201 }
202
203
204 /**
205  * Function called when a peer start operation is ready
206  *
207  * @param cls the closure from GNUNET_TESTBED_operation_create_()
208  */
209 static void
210 opstart_peer_start (void *cls)
211 {
212   struct OperationContext *opc = cls;
213   struct GNUNET_TESTBED_PeerStartMessage *msg;
214   struct PeerEventData *data;
215   struct GNUNET_TESTBED_Peer *peer;
216
217   GNUNET_assert (OP_PEER_START == opc->type);
218   GNUNET_assert (NULL != (data = opc->data));
219   GNUNET_assert (NULL != (peer = data->peer));
220   GNUNET_assert ((TESTBED_PS_CREATED == peer->state) || (TESTBED_PS_STOPPED == peer->state));
221   opc->state = OPC_STATE_STARTED;
222   msg = GNUNET_new (struct GNUNET_TESTBED_PeerStartMessage);
223   msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStartMessage));
224   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_START_PEER);
225   msg->peer_id = htonl (peer->unique_id);
226   msg->operation_id = GNUNET_htonll (opc->id);
227   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
228   GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
229 }
230
231
232 /**
233  * Callback which will be called when peer start type operation is released
234  *
235  * @param cls the closure from GNUNET_TESTBED_operation_create_()
236  */
237 static void
238 oprelease_peer_start (void *cls)
239 {
240   struct OperationContext *opc = cls;
241
242   switch (opc->state)
243   {
244   case OPC_STATE_STARTED:
245     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
246     /* no break; continue */
247   case OPC_STATE_INIT:
248     GNUNET_free (opc->data);
249     break;
250   case OPC_STATE_FINISHED:
251     break;
252   }
253   GNUNET_free (opc);
254 }
255
256
257 /**
258  * Function called when a peer stop operation is ready
259  *
260  * @param cls the closure from GNUNET_TESTBED_operation_create_()
261  */
262 static void
263 opstart_peer_stop (void *cls)
264 {
265   struct OperationContext *opc = cls;
266   struct GNUNET_TESTBED_PeerStopMessage *msg;
267   struct PeerEventData *data;
268   struct GNUNET_TESTBED_Peer *peer;
269
270   GNUNET_assert (NULL != (data = opc->data));
271   GNUNET_assert (NULL != (peer = data->peer));
272   GNUNET_assert (TESTBED_PS_STARTED == peer->state);
273   opc->state = OPC_STATE_STARTED;
274   msg = GNUNET_new (struct GNUNET_TESTBED_PeerStopMessage);
275   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER);
276   msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStopMessage));
277   msg->peer_id = htonl (peer->unique_id);
278   msg->operation_id = GNUNET_htonll (opc->id);
279   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
280   GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
281 }
282
283
284 /**
285  * Callback which will be called when peer stop type operation is released
286  *
287  * @param cls the closure from GNUNET_TESTBED_operation_create_()
288  */
289 static void
290 oprelease_peer_stop (void *cls)
291 {
292   struct OperationContext *opc = cls;
293
294   switch (opc->state)
295   {
296   case OPC_STATE_STARTED:
297     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
298     /* no break; continue */
299   case OPC_STATE_INIT:
300     GNUNET_free (opc->data);
301     break;
302   case OPC_STATE_FINISHED:
303     break;
304   }
305   GNUNET_free (opc);
306 }
307
308
309 /**
310  * Generate PeerGetConfigurationMessage
311  *
312  * @param peer_id the id of the peer whose information we have to get
313  * @param operation_id the ip of the operation that should be represented in the
314  *          message
315  * @return the PeerGetConfigurationMessage
316  */
317 struct GNUNET_TESTBED_PeerGetConfigurationMessage *
318 GNUNET_TESTBED_generate_peergetconfig_msg_ (uint32_t peer_id,
319                                             uint64_t operation_id)
320 {
321   struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
322
323   msg =
324       GNUNET_malloc (sizeof
325                      (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
326   msg->header.size =
327       htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
328   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
329   msg->peer_id = htonl (peer_id);
330   msg->operation_id = GNUNET_htonll (operation_id);
331   return msg;
332 }
333
334
335 /**
336  * Function called when a peer get information operation is ready
337  *
338  * @param cls the closure from GNUNET_TESTBED_operation_create_()
339  */
340 static void
341 opstart_peer_getinfo (void *cls)
342 {
343   struct OperationContext *opc = cls;
344   struct PeerInfoData *data = opc->data;
345   struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
346
347   GNUNET_assert (NULL != data);
348   opc->state = OPC_STATE_STARTED;
349   msg =
350       GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id,
351                                                   opc->id);
352   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
353   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
354 }
355
356
357 /**
358  * Callback which will be called when peer stop type operation is released
359  *
360  * @param cls the closure from GNUNET_TESTBED_operation_create_()
361  */
362 static void
363 oprelease_peer_getinfo (void *cls)
364 {
365   struct OperationContext *opc = cls;
366   struct GNUNET_TESTBED_PeerInformation *data;
367
368   switch (opc->state)
369   {
370   case OPC_STATE_STARTED:
371     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
372     /* no break; continue */
373   case OPC_STATE_INIT:
374     GNUNET_free (opc->data);
375     break;
376   case OPC_STATE_FINISHED:
377     data = opc->data;
378     GNUNET_assert (NULL != data);
379     switch (data->pit)
380     {
381     case GNUNET_TESTBED_PIT_CONFIGURATION:
382       if (NULL != data->result.cfg)
383         GNUNET_CONFIGURATION_destroy (data->result.cfg);
384       break;
385     case GNUNET_TESTBED_PIT_IDENTITY:
386       GNUNET_free (data->result.id);
387       break;
388     default:
389       GNUNET_assert (0);        /* We should never reach here */
390     }
391     GNUNET_free (data);
392     break;
393   }
394   GNUNET_free (opc);
395 }
396
397
398 /**
399  * Function called when a overlay connect operation is ready
400  *
401  * @param cls the closure from GNUNET_TESTBED_operation_create_()
402  */
403 static void
404 opstart_overlay_connect (void *cls)
405 {
406   struct OperationContext *opc = cls;
407   struct GNUNET_TESTBED_OverlayConnectMessage *msg;
408   struct OverlayConnectData *data;
409
410   opc->state = OPC_STATE_STARTED;
411   data = opc->data;
412   GNUNET_assert (NULL != data);
413   msg = GNUNET_new (struct GNUNET_TESTBED_OverlayConnectMessage);
414   msg->header.size =
415       htons (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage));
416   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT);
417   msg->peer1 = htonl (data->p1->unique_id);
418   msg->peer2 = htonl (data->p2->unique_id);
419   msg->operation_id = GNUNET_htonll (opc->id);
420   msg->peer2_host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->p2->host));
421   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
422   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
423 }
424
425
426 /**
427  * Callback which will be called when overlay connect operation is released
428  *
429  * @param cls the closure from GNUNET_TESTBED_operation_create_()
430  */
431 static void
432 oprelease_overlay_connect (void *cls)
433 {
434   struct OperationContext *opc = cls;
435   struct OverlayConnectData *data;
436
437   data = opc->data;
438   switch (opc->state)
439   {
440   case OPC_STATE_INIT:
441     break;
442   case OPC_STATE_STARTED:
443     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
444     break;
445   case OPC_STATE_FINISHED:
446     break;
447   }
448   GNUNET_free (data);
449   GNUNET_free (opc);
450 }
451
452
453 /**
454  * Function called when a peer reconfigure operation is ready
455  *
456  * @param cls the closure from GNUNET_TESTBED_operation_create_()
457  */
458 static void
459 opstart_peer_reconfigure (void *cls)
460 {
461   struct OperationContext *opc = cls;
462   struct PeerReconfigureData *data = opc->data;
463   struct GNUNET_TESTBED_PeerReconfigureMessage *msg;
464   char *xconfig;
465   size_t xc_size;
466   uint16_t msize;
467
468   opc->state = OPC_STATE_STARTED;
469   GNUNET_assert (NULL != data);
470   xc_size = GNUNET_TESTBED_compress_config_ (data->config, data->cfg_size,
471                                              &xconfig);
472   GNUNET_free (data->config);
473   data->config = NULL;
474   GNUNET_assert (xc_size <= UINT16_MAX);
475   msize = (uint16_t) xc_size +
476       sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage);
477   msg = GNUNET_realloc (xconfig, msize);
478   (void) memmove (&msg[1], msg, xc_size);
479   msg->header.size = htons (msize);
480   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER);
481   msg->peer_id = htonl (data->peer->unique_id);
482   msg->operation_id = GNUNET_htonll (opc->id);
483   msg->config_size = htons (data->cfg_size);
484   GNUNET_free (data);
485   opc->data = NULL;
486   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
487   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
488 }
489
490
491 /**
492  * Callback which will be called when a peer reconfigure operation is released
493  *
494  * @param cls the closure from GNUNET_TESTBED_operation_create_()
495  */
496 static void
497 oprelease_peer_reconfigure (void *cls)
498 {
499   struct OperationContext *opc = cls;
500   struct PeerReconfigureData *data = opc->data;
501
502   switch (opc->state)
503   {
504   case OPC_STATE_INIT:
505     GNUNET_free (data->config);
506     GNUNET_free (data);
507     break;
508   case OPC_STATE_STARTED:
509     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
510     break;
511   case OPC_STATE_FINISHED:
512     break;
513   }
514   GNUNET_free (opc);
515 }
516
517
518 /**
519  * Lookup a peer by ID.
520  *
521  * @param id global peer ID assigned to the peer
522  * @return handle to the host, NULL on error
523  */
524 struct GNUNET_TESTBED_Peer *
525 GNUNET_TESTBED_peer_lookup_by_id_ (uint32_t id)
526 {
527   GNUNET_break (0);
528   return NULL;
529 }
530
531
532 /**
533  * Create the given peer at the specified host using the given
534  * controller.  If the given controller is not running on the target
535  * host, it should find or create a controller at the target host and
536  * delegate creating the peer.  Explicit delegation paths can be setup
537  * using 'GNUNET_TESTBED_controller_link'.  If no explicit delegation
538  * path exists, a direct link with a subordinate controller is setup
539  * for the first delegated peer to a particular host; the subordinate
540  * controller is then destroyed once the last peer that was delegated
541  * to the remote host is stopped.
542  *
543  * Creating the peer only creates the handle to manipulate and further
544  * configure the peer; use "GNUNET_TESTBED_peer_start" and
545  * "GNUNET_TESTBED_peer_stop" to actually start/stop the peer's
546  * processes.
547  *
548  * Note that the given configuration will be adjusted by the
549  * controller to avoid port/path conflicts with other peers.
550  * The "final" configuration can be obtained using
551  * 'GNUNET_TESTBED_peer_get_information'.
552  *
553  * @param controller controller process to use
554  * @param host host to run the peer on; cannot be NULL
555  * @param cfg Template configuration to use for the peer. Should exist until
556  *          operation is cancelled or GNUNET_TESTBED_operation_done() is called
557  * @param cb the callback to call when the peer has been created
558  * @param cls the closure to the above callback
559  * @return the operation handle
560  */
561 struct GNUNET_TESTBED_Operation *
562 GNUNET_TESTBED_peer_create (struct GNUNET_TESTBED_Controller *controller,
563                             struct GNUNET_TESTBED_Host *host,
564                             const struct GNUNET_CONFIGURATION_Handle *cfg,
565                             GNUNET_TESTBED_PeerCreateCallback cb, void *cls)
566 {
567
568   struct GNUNET_TESTBED_Peer *peer;
569   struct PeerCreateData *data;
570   struct OperationContext *opc;
571   static uint32_t id_gen;
572
573   peer = GNUNET_new (struct GNUNET_TESTBED_Peer);
574   peer->controller = controller;
575   peer->host = host;
576   peer->unique_id = id_gen++;
577   peer->state = TESTBED_PS_INVALID;
578   data = GNUNET_new (struct PeerCreateData);
579   data->host = host;
580   data->cfg = cfg;
581   data->cb = cb;
582   data->cls = cls;
583   data->peer = peer;
584   opc = GNUNET_new (struct OperationContext);
585   opc->c = controller;
586   opc->data = data;
587   opc->id = GNUNET_TESTBED_get_next_op_id (controller);
588   opc->type = OP_PEER_CREATE;
589   opc->op =
590       GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_create,
591                                         &oprelease_peer_create);
592   GNUNET_TESTBED_operation_queue_insert_ (controller->opq_parallel_operations,
593                                           opc->op);
594   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
595   return opc->op;
596 }
597
598
599 /**
600  * Start the given peer.
601  *
602  * @param op_cls the closure for this operation; will be set in
603  *          event->details.operation_finished.op_cls when this operation fails.
604  * @param peer peer to start
605  * @param pcc function to call upon completion
606  * @param pcc_cls closure for 'pcc'
607  * @return handle to the operation
608  */
609 struct GNUNET_TESTBED_Operation *
610 GNUNET_TESTBED_peer_start (void *op_cls, struct GNUNET_TESTBED_Peer *peer,
611                            GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls)
612 {
613   struct OperationContext *opc;
614   struct PeerEventData *data;
615
616   data = GNUNET_new (struct PeerEventData);
617   data->peer = peer;
618   data->pcc = pcc;
619   data->pcc_cls = pcc_cls;
620   opc = GNUNET_new (struct OperationContext);
621   opc->c = peer->controller;
622   opc->data = data;
623   opc->op_cls = op_cls;
624   opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
625   opc->type = OP_PEER_START;
626   opc->op =
627       GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_start,
628                                         &oprelease_peer_start);
629   GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
630                                           opc->op);
631   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
632   return opc->op;
633 }
634
635
636 /**
637  * Stop the given peer.  The handle remains valid (use
638  * "GNUNET_TESTBED_peer_destroy" to fully clean up the
639  * state of the peer).
640  *
641  * @param op_cls the closure for this operation; will be set in the event
642  *          information
643  * @param peer peer to stop
644  * @param pcc function to call upon completion
645  * @param pcc_cls closure for 'pcc'
646  * @return handle to the operation
647  */
648 struct GNUNET_TESTBED_Operation *
649 GNUNET_TESTBED_peer_stop (void *op_cls,
650                           struct GNUNET_TESTBED_Peer *peer,
651                           GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls)
652 {
653   struct OperationContext *opc;
654   struct PeerEventData *data;
655
656   data = GNUNET_new (struct PeerEventData);
657   data->peer = peer;
658   data->pcc = pcc;
659   data->pcc_cls = pcc_cls;
660   opc = GNUNET_new (struct OperationContext);
661   opc->c = peer->controller;
662   opc->data = data;
663   opc->op_cls = op_cls;
664   opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
665   opc->type = OP_PEER_STOP;
666   opc->op =
667       GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_stop,
668                                         &oprelease_peer_stop);
669   GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
670                                           opc->op);
671   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
672   return opc->op;
673 }
674
675
676 /**
677  * Request information about a peer. The controller callback will not be called
678  * with event type GNUNET_TESTBED_ET_OPERATION_FINISHED when result for this
679  * operation is available. Instead, the GNUNET_TESTBED_PeerInfoCallback() will
680  * be called.
681  * The peer information in the callback is valid until the operation is canceled.
682  *
683  * @param peer peer to request information about
684  * @param pit desired information
685  * @param cb the convenience callback to be called when results for this
686  *          operation are available
687  * @param cb_cls the closure for the above callback
688  * @return handle to the operation
689  */
690 struct GNUNET_TESTBED_Operation *
691 GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer,
692                                      enum GNUNET_TESTBED_PeerInformationType
693                                      pit, GNUNET_TESTBED_PeerInfoCallback cb,
694                                      void *cb_cls)
695 {
696   struct OperationContext *opc;
697   struct PeerInfoData *data;
698
699   GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC != pit);
700   GNUNET_assert (NULL != cb);
701   data = GNUNET_new (struct PeerInfoData);
702   data->peer = peer;
703   data->pit = pit;
704   data->cb = cb;
705   data->cb_cls = cb_cls;
706   opc = GNUNET_new (struct OperationContext);
707   opc->c = peer->controller;
708   opc->data = data;
709   opc->type = OP_PEER_INFO;
710   opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
711   opc->op =
712       GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_getinfo,
713                                         &oprelease_peer_getinfo);
714   GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
715                                           opc->op);
716   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
717   return opc->op;
718 }
719
720
721 /**
722  * Change peer configuration.  Must only be called while the
723  * peer is stopped.  Ports and paths cannot be changed this
724  * way.
725  *
726  * @param peer peer to change configuration for
727  * @param cfg new configuration (differences to existing
728  *            configuration only)
729  * @return handle to the operation
730  */
731 struct GNUNET_TESTBED_Operation *
732 GNUNET_TESTBED_peer_update_configuration (struct GNUNET_TESTBED_Peer *peer,
733                                           const struct
734                                           GNUNET_CONFIGURATION_Handle *cfg)
735 {
736   struct OperationContext *opc;
737   struct PeerReconfigureData *data;
738   size_t csize;
739
740   data = GNUNET_new (struct PeerReconfigureData);
741   data->peer = peer;
742   data->config = GNUNET_CONFIGURATION_serialize (cfg, &csize);
743   if (NULL == data->config)
744   {
745     GNUNET_free (data);
746     return NULL;
747   }
748   if (csize > UINT16_MAX)
749   {
750     GNUNET_break (0);
751     GNUNET_free (data->config);
752     GNUNET_free (data);
753     return NULL;
754   }
755   data->cfg_size = (uint16_t) csize;
756   opc = GNUNET_new (struct OperationContext);
757   opc->c = peer->controller;
758   opc->data = data;
759   opc->type = OP_PEER_RECONFIGURE;
760   opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
761   opc->op =
762       GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_reconfigure,
763                                         &oprelease_peer_reconfigure);
764   GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
765                                           opc->op);
766   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
767   return opc->op;
768 }
769
770
771 /**
772  * Destroy the given peer; the peer should have been
773  * stopped first (if it was started).
774  *
775  * @param peer peer to stop
776  * @return handle to the operation
777  */
778 struct GNUNET_TESTBED_Operation *
779 GNUNET_TESTBED_peer_destroy (struct GNUNET_TESTBED_Peer *peer)
780 {
781   struct OperationContext *opc;
782
783   opc = GNUNET_new (struct OperationContext);
784   opc->data = peer;
785   opc->c = peer->controller;
786   opc->id = GNUNET_TESTBED_get_next_op_id (peer->controller);
787   opc->type = OP_PEER_DESTROY;
788   opc->op =
789       GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_destroy,
790                                         &oprelease_peer_destroy);
791   GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
792                                           opc->op);
793   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
794   return opc->op;
795 }
796
797
798 /**
799  * Manipulate the P2P underlay topology by configuring a link
800  * between two peers.
801  *
802  * @param op_cls closure argument to give with the operation event
803  * @param p1 first peer
804  * @param p2 second peer
805  * @param co option to change
806  * @param ... option-specific values
807  * @return handle to the operation, NULL if configuring the link at this
808  *         time is not allowed
809  */
810 struct GNUNET_TESTBED_Operation *
811 GNUNET_TESTBED_underlay_configure_link (void *op_cls,
812                                         struct GNUNET_TESTBED_Peer *p1,
813                                         struct GNUNET_TESTBED_Peer *p2,
814                                         enum GNUNET_TESTBED_ConnectOption co,
815                                         ...)
816 {
817   GNUNET_break (0);
818   return NULL;
819 }
820
821
822 /**
823  * Both peers must have been started before calling this function.
824  * This function then obtains a HELLO from 'p1', gives it to 'p2'
825  * and asks 'p2' to connect to 'p1'.
826  *
827  * @param op_cls closure argument to give with the operation event
828  * @param cb the callback to call when this operation has finished
829  * @param cb_cls the closure for the above callback
830  * @param p1 first peer
831  * @param p2 second peer
832  * @return handle to the operation, NULL if connecting these two
833  *         peers is fundamentally not possible at this time (peers
834  *         not running or underlay disallows)
835  */
836 struct GNUNET_TESTBED_Operation *
837 GNUNET_TESTBED_overlay_connect (void *op_cls,
838                                 GNUNET_TESTBED_OperationCompletionCallback cb,
839                                 void *cb_cls, struct GNUNET_TESTBED_Peer *p1,
840                                 struct GNUNET_TESTBED_Peer *p2)
841 {
842   struct OperationContext *opc;
843   struct OverlayConnectData *data;
844
845   GNUNET_assert ((TESTBED_PS_STARTED == p1->state) && (TESTBED_PS_STARTED == p2->state));
846   data = GNUNET_new (struct OverlayConnectData);
847   data->p1 = p1;
848   data->p2 = p2;
849   data->cb = cb;
850   data->cb_cls = cb_cls;
851   opc = GNUNET_new (struct OperationContext);
852   opc->data = data;
853   opc->c = p1->controller;
854   opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
855   opc->type = OP_OVERLAY_CONNECT;
856   opc->op_cls = op_cls;
857   opc->op =
858       GNUNET_TESTBED_operation_create_ (opc, &opstart_overlay_connect,
859                                         &oprelease_overlay_connect);
860   GNUNET_TESTBED_host_queue_oc_ (p1->host, opc->op);
861   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
862   return opc->op;
863 }
864
865
866 /**
867  * Function called when a peer manage service operation is ready
868  *
869  * @param cls the closure from GNUNET_TESTBED_operation_create_()
870  */
871 static void
872 opstart_manage_service (void *cls)
873 {
874   struct OperationContext *opc = cls;
875   struct ManageServiceData *data = opc->data;
876   struct GNUNET_TESTBED_ManagePeerServiceMessage *msg;
877
878   GNUNET_assert (NULL != data);
879   msg = GNUNET_malloc (data->msize);
880   msg->header.size = htons (data->msize);
881   msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE);
882   msg->peer_id = htonl (data->peer->unique_id);
883   msg->operation_id = GNUNET_htonll (opc->id);
884   msg->start = (uint8_t) data->start;
885   (void) memcpy (&msg[1], data->service_name, data->msize
886                  - sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage));
887   GNUNET_free (data->service_name);
888   data->service_name = NULL;
889   opc->state = OPC_STATE_STARTED;
890   GNUNET_TESTBED_insert_opc_ (opc->c, opc);
891   GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
892 }
893
894
895 /**
896  * Callback which will be called when peer manage server operation is released
897  *
898  * @param cls the closure from GNUNET_TESTBED_operation_create_()
899  */
900 static void
901 oprelease_manage_service (void *cls)
902 {
903   struct OperationContext *opc = cls;
904   struct ManageServiceData *data;
905
906   data = opc->data;
907   switch (opc->state)
908   {
909   case OPC_STATE_STARTED:
910     GNUNET_TESTBED_remove_opc_ (opc->c, opc);
911     break;
912   case OPC_STATE_INIT:
913     GNUNET_assert (NULL != data);
914     GNUNET_free (data->service_name);
915     break;
916   case OPC_STATE_FINISHED:
917     break;
918   }
919   GNUNET_free_non_null (data);
920   GNUNET_free (opc);
921 }
922
923
924 /**
925  * Start or stop given service at a peer.  This should not be called to
926  * start/stop the peer's ARM service.  Use GNUNET_TESTBED_peer_start(),
927  * GNUNET_TESTBED_peer_stop() for starting/stopping peer's ARM service.  Success
928  * or failure of the generated operation is signalled through the controller
929  * event callback and/or operation completion callback.
930  *
931  * @param op_cls the closure for the operation
932  * @param peer the peer whose service is to be started/stopped
933  * @param service_name the name of the service
934  * @param cb the operation completion callback
935  * @param cb_cls the closure for the operation completion callback
936  * @param start 1 to start the service; 0 to stop the service
937  * @return an operation handle; NULL upon error (peer not running)
938  */
939 struct GNUNET_TESTBED_Operation *
940 GNUNET_TESTBED_peer_manage_service (void *op_cls,
941                                     struct GNUNET_TESTBED_Peer *peer,
942                                     const char *service_name,
943                                     GNUNET_TESTBED_OperationCompletionCallback cb,
944                                     void *cb_cls,
945                                     unsigned int start)
946 {
947   struct ManageServiceData *data;
948   struct OperationContext *opc;
949   size_t msize;
950
951   GNUNET_assert (TESTBED_PS_STARTED == peer->state); /* peer is not running? */
952   msize = strlen (service_name) + 1;
953   msize += sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage);
954   if (GNUNET_SERVER_MAX_MESSAGE_SIZE < msize)
955     return NULL;
956   data = GNUNET_new (struct ManageServiceData);
957   data->cb = cb;
958   data->cb_cls = cb_cls;
959   data->peer = peer;
960   data->service_name = GNUNET_strdup (service_name);
961   data->start = start;
962   data->msize = (uint16_t) msize;
963   opc = GNUNET_new (struct OperationContext);
964   opc->data = data;
965   opc->c = peer->controller;
966   opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
967   opc->type = OP_MANAGE_SERVICE;
968   opc->op_cls = op_cls;
969   opc->op =
970       GNUNET_TESTBED_operation_create_ (opc, &opstart_manage_service,
971                                         &oprelease_manage_service);
972   GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
973                                           opc->op);
974   GNUNET_TESTBED_operation_begin_wait_ (opc->op);
975   return opc->op;
976 }
977
978
979
980 /* end of testbed_api_peers.c */