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