aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/testbed/Makefile.am8
-rw-r--r--src/testbed/gnunet-service-testbed.c4
-rw-r--r--src/testbed/gnunet-service-testbed.h21
-rw-r--r--src/testbed/gnunet-service-testbed_peers.c340
-rw-r--r--src/testbed/test_testbed_api_peer_reconfiguration.c192
-rw-r--r--src/testbed/testbed.h17
-rw-r--r--src/testbed/testbed_api.c33
-rw-r--r--src/testbed/testbed_api.h5
-rw-r--r--src/testbed/testbed_api_peers.c102
-rw-r--r--src/testbed/testbed_api_peers.h22
10 files changed, 685 insertions, 59 deletions
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index 43435bf9e..3f3d6db55 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -132,6 +132,7 @@ check_PROGRAMS = \
132 test_testbed_api_testbed_run \ 132 test_testbed_api_testbed_run \
133 test_testbed_api_test \ 133 test_testbed_api_test \
134 test_testbed_api_test_timeout \ 134 test_testbed_api_test_timeout \
135 test_testbed_api_peer_reconfiguration \
135 test_testbed_api_peers_manage_services \ 136 test_testbed_api_peers_manage_services \
136 test_testbed_api_topology \ 137 test_testbed_api_topology \
137 test_testbed_api_topology_clique \ 138 test_testbed_api_topology_clique \
@@ -162,6 +163,7 @@ if ENABLE_TEST_RUN
162 test_testbed_api_test \ 163 test_testbed_api_test \
163 test_testbed_api_test_timeout \ 164 test_testbed_api_test_timeout \
164 test_testbed_api_statistics \ 165 test_testbed_api_statistics \
166 test_testbed_api_peer_reconfiguration \
165 test_testbed_api_peers_manage_services \ 167 test_testbed_api_peers_manage_services \
166 test_testbed_api_topology \ 168 test_testbed_api_topology \
167 test_testbed_api_topology_clique \ 169 test_testbed_api_topology_clique \
@@ -338,6 +340,12 @@ test_testbed_api_peers_manage_services_LDADD = \
338 $(top_builddir)/src/util/libgnunetutil.la \ 340 $(top_builddir)/src/util/libgnunetutil.la \
339 libgnunettestbed.la 341 libgnunettestbed.la
340 342
343test_testbed_api_peer_reconfiguration_SOURCES = \
344 test_testbed_api_peer_reconfiguration.c
345test_testbed_api_peer_reconfiguration_LDADD = \
346 $(top_builddir)/src/util/libgnunetutil.la \
347 libgnunettestbed.la
348
341EXTRA_DIST = \ 349EXTRA_DIST = \
342 test_testbed_api.conf \ 350 test_testbed_api.conf \
343 test_testbed_api_test_timeout.conf \ 351 test_testbed_api_test_timeout.conf \
diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c
index 6bca3d9cd..4e73680c9 100644
--- a/src/testbed/gnunet-service-testbed.c
+++ b/src/testbed/gnunet-service-testbed.c
@@ -762,6 +762,7 @@ GST_clear_fopcq ()
762 case OP_LINK_CONTROLLERS: 762 case OP_LINK_CONTROLLERS:
763 case OP_GET_SLAVE_CONFIG: 763 case OP_GET_SLAVE_CONFIG:
764 case OP_MANAGE_SERVICE: 764 case OP_MANAGE_SERVICE:
765 case OP_PEER_RECONFIGURE:
765 break; 766 break;
766 case OP_FORWARDED: 767 case OP_FORWARDED:
767 GNUNET_assert (0); 768 GNUNET_assert (0);
@@ -793,6 +794,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
793 GST_free_roccq (); 794 GST_free_roccq ();
794 GST_free_nccq (); 795 GST_free_nccq ();
795 GST_neighbour_list_clean(); 796 GST_neighbour_list_clean();
797 GST_free_prcq ();
796 /* Clear peer list */ 798 /* Clear peer list */
797 GST_destroy_peers (); 799 GST_destroy_peers ();
798 /* Clear route list */ 800 /* Clear route list */
@@ -895,6 +897,8 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
895 sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)}, 897 sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)},
896 {&GST_handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, 898 {&GST_handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS,
897 sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)}, 899 sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)},
900 {&GST_handle_peer_reconfigure, NULL,
901 GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER, 0},
898 {NULL, NULL, 0, 0} 902 {NULL, NULL, 0, 0}
899 }; 903 };
900 char *logfile; 904 char *logfile;
diff --git a/src/testbed/gnunet-service-testbed.h b/src/testbed/gnunet-service-testbed.h
index bdf0f4cce..55ad08421 100644
--- a/src/testbed/gnunet-service-testbed.h
+++ b/src/testbed/gnunet-service-testbed.h
@@ -717,6 +717,20 @@ GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
717 717
718 718
719/** 719/**
720 * Handler for GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages.
721 * Should stop the peer asyncronously, destroy it and create it again with the
722 * new configuration.
723 *
724 * @param cls NULL
725 * @param client identification of the client
726 * @param message the actual message
727 */
728void
729GST_handle_peer_reconfigure (void *cls, struct GNUNET_SERVER_Client *client,
730 const struct GNUNET_MessageHeader *message);
731
732
733/**
720 * Frees the ManageServiceContext queue 734 * Frees the ManageServiceContext queue
721 */ 735 */
722void 736void
@@ -770,6 +784,13 @@ GST_free_roccq ();
770 784
771 785
772/** 786/**
787 * Cleans up the Peer reconfigure context list
788 */
789void
790GST_free_prcq ();
791
792
793/**
773 * Initializes the cache 794 * Initializes the cache
774 * 795 *
775 * @param size the size of the cache 796 * @param size the size of the cache
diff --git a/src/testbed/gnunet-service-testbed_peers.c b/src/testbed/gnunet-service-testbed_peers.c
index 3de4af03a..34c1bf085 100644
--- a/src/testbed/gnunet-service-testbed_peers.c
+++ b/src/testbed/gnunet-service-testbed_peers.c
@@ -85,6 +85,61 @@ struct ManageServiceContext
85 85
86 86
87/** 87/**
88 * Context information for peer re-configure operations
89 */
90struct PeerReconfigureContext
91{
92 /**
93 * DLL next for inclusoin in peer reconfigure operations list
94 */
95 struct PeerReconfigureContext *next;
96
97 /**
98 * DLL prev
99 */
100 struct PeerReconfigureContext *prev;
101
102 /**
103 * The client which gave this operation to us
104 */
105 struct GNUNET_SERVER_Client *client;
106
107 /**
108 * The configuration handle to use as the new template
109 */
110 struct GNUNET_CONFIGURATION_Handle *cfg;
111
112 /**
113 * The id of the operation
114 */
115 uint64_t op_id;
116
117 /**
118 * The id of the peer which has to be reconfigured
119 */
120 uint32_t peer_id;
121
122 /**
123 * The the peer stopped? Used while cleaning up this context to decide
124 * whether the asynchronous stop request through Testing/ARM API has to be
125 * cancelled
126 */
127 uint8_t stopped;
128};
129
130/**
131 * The DLL head for the peer reconfigure list
132 */
133static struct PeerReconfigureContext *prc_head;
134
135/**
136 * The DLL tail for the peer reconfigure list
137 */
138static struct PeerReconfigureContext *prc_tail;
139
140
141
142/**
88 * DLL head for queue of manage service requests 143 * DLL head for queue of manage service requests
89 */ 144 */
90static struct ManageServiceContext *mctx_head; 145static struct ManageServiceContext *mctx_head;
@@ -253,10 +308,7 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
253 struct ForwardedOperationContext *fo_ctxt; 308 struct ForwardedOperationContext *fo_ctxt;
254 struct Route *route; 309 struct Route *route;
255 struct Peer *peer; 310 struct Peer *peer;
256 char *config; 311 char *emsg;
257 size_t dest_size;
258 int ret;
259 uint32_t config_size;
260 uint32_t host_id; 312 uint32_t host_id;
261 uint32_t peer_id; 313 uint32_t peer_id;
262 uint16_t msize; 314 uint16_t msize;
@@ -272,8 +324,17 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
272 msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message; 324 msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
273 host_id = ntohl (msg->host_id); 325 host_id = ntohl (msg->host_id);
274 peer_id = ntohl (msg->peer_id); 326 peer_id = ntohl (msg->peer_id);
275 if (UINT32_MAX == peer_id) 327 if (VALID_PEER_ID (peer_id))
276 { 328 {
329 (void) GNUNET_asprintf (&emsg, "Peer with ID %u already exists", peer_id);
330 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
331 emsg);
332 GNUNET_free (emsg);
333 GNUNET_SERVER_receive_done (client, GNUNET_OK);
334 return;
335 }
336 if (UINT32_MAX == peer_id)
337 {
277 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), 338 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
278 "Cannot create peer with given ID"); 339 "Cannot create peer with given ID");
279 GNUNET_SERVER_receive_done (client, GNUNET_OK); 340 GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -281,39 +342,14 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
281 } 342 }
282 if (host_id == GST_context->host_id) 343 if (host_id == GST_context->host_id)
283 { 344 {
284 char *emsg;
285
286 /* We are responsible for this peer */ 345 /* We are responsible for this peer */
287 msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage); 346 cfg = GNUNET_TESTBED_extract_config_ (message);
288 config_size = ntohl (msg->config_size); 347 if (NULL == cfg)
289 config = GNUNET_malloc (config_size);
290 dest_size = config_size;
291 if (Z_OK !=
292 (ret =
293 uncompress ((Bytef *) config, (uLongf *) & dest_size,
294 (const Bytef *) &msg[1], (uLong) msize)))
295 {
296 GNUNET_break (0); /* uncompression error */
297 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
298 return;
299 }
300 if (config_size != dest_size)
301 {
302 GNUNET_break (0); /* Uncompressed config size mismatch */
303 GNUNET_free (config);
304 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
305 return;
306 }
307 cfg = GNUNET_CONFIGURATION_create ();
308 if (GNUNET_OK !=
309 GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
310 { 348 {
311 GNUNET_break (0); /* Configuration parsing error */ 349 GNUNET_break (0);
312 GNUNET_free (config);
313 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); 350 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
314 return; 351 return;
315 } 352 }
316 GNUNET_free (config);
317 GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID", 353 GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID",
318 (unsigned long long) peer_id); 354 (unsigned long long) peer_id);
319 peer = GNUNET_malloc (sizeof (struct Peer)); 355 peer = GNUNET_malloc (sizeof (struct Peer));
@@ -359,7 +395,6 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
359 GNUNET_SERVER_receive_done (client, GNUNET_OK); 395 GNUNET_SERVER_receive_done (client, GNUNET_OK);
360 return; 396 return;
361 } 397 }
362
363 peer = GNUNET_malloc (sizeof (struct Peer)); 398 peer = GNUNET_malloc (sizeof (struct Peer));
364 peer->is_remote = GNUNET_YES; 399 peer->is_remote = GNUNET_YES;
365 peer->id = peer_id; 400 peer->id = peer_id;
@@ -369,7 +404,7 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
369 GNUNET_SERVER_client_keep (client); 404 GNUNET_SERVER_client_keep (client);
370 fo_ctxt->client = client; 405 fo_ctxt->client = client;
371 fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id); 406 fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
372 fo_ctxt->cls = peer; //GST_slave_list[route->dest]->controller; 407 fo_ctxt->cls = peer;
373 fo_ctxt->type = OP_PEER_CREATE; 408 fo_ctxt->type = OP_PEER_CREATE;
374 fo_ctxt->opc = 409 fo_ctxt->opc =
375 GNUNET_TESTBED_forward_operation_msg_ (GST_slave_list 410 GNUNET_TESTBED_forward_operation_msg_ (GST_slave_list
@@ -405,7 +440,7 @@ GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
405 peer_id = ntohl (msg->peer_id); 440 peer_id = ntohl (msg->peer_id);
406 LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n", 441 LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
407 peer_id, GNUNET_ntohll (msg->operation_id)); 442 peer_id, GNUNET_ntohll (msg->operation_id));
408 if ((GST_peer_list_size <= peer_id) || (NULL == GST_peer_list[peer_id])) 443 if (!VALID_PEER_ID (peer_id))
409 { 444 {
410 LOG (GNUNET_ERROR_TYPE_ERROR, 445 LOG (GNUNET_ERROR_TYPE_ERROR,
411 "Asked to destroy a non existent peer with id: %u\n", peer_id); 446 "Asked to destroy a non existent peer with id: %u\n", peer_id);
@@ -448,6 +483,40 @@ GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
448 483
449 484
450/** 485/**
486 * Stats a peer
487 *
488 * @param peer the peer to start
489 * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
490 */
491static int
492start_peer (struct Peer *peer)
493{
494 GNUNET_assert (GNUNET_NO == peer->is_remote);
495 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer))
496 return GNUNET_SYSERR;
497 peer->details.local.is_running = GNUNET_YES;
498 return GNUNET_OK;
499}
500
501
502/**
503 * Stops a peer
504 *
505 * @param peer the peer to stop
506 * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
507 */
508static int
509stop_peer (struct Peer *peer)
510{
511 GNUNET_assert (GNUNET_NO == peer->is_remote);
512 if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer))
513 return GNUNET_SYSERR;
514 peer->details.local.is_running = GNUNET_NO;
515 return GNUNET_OK;
516}
517
518
519/**
451 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages 520 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
452 * 521 *
453 * @param cls NULL 522 * @param cls NULL
@@ -466,7 +535,7 @@ GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
466 535
467 msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message; 536 msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
468 peer_id = ntohl (msg->peer_id); 537 peer_id = ntohl (msg->peer_id);
469 if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) 538 if (!VALID_PEER_ID (peer_id))
470 { 539 {
471 GNUNET_break (0); 540 GNUNET_break (0);
472 LOG (GNUNET_ERROR_TYPE_ERROR, 541 LOG (GNUNET_ERROR_TYPE_ERROR,
@@ -495,14 +564,13 @@ GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
495 GNUNET_SERVER_receive_done (client, GNUNET_OK); 564 GNUNET_SERVER_receive_done (client, GNUNET_OK);
496 return; 565 return;
497 } 566 }
498 if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer)) 567 if (GNUNET_OK != start_peer (peer))
499 { 568 {
500 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), 569 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
501 "Failed to start"); 570 "Failed to start");
502 GNUNET_SERVER_receive_done (client, GNUNET_OK); 571 GNUNET_SERVER_receive_done (client, GNUNET_OK);
503 return; 572 return;
504 } 573 }
505 peer->details.local.is_running = GNUNET_YES;
506 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); 574 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
507 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); 575 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT);
508 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); 576 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
@@ -535,7 +603,7 @@ GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
535 msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message; 603 msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
536 peer_id = ntohl (msg->peer_id); 604 peer_id = ntohl (msg->peer_id);
537 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PEER_STOP for peer %u\n", peer_id); 605 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PEER_STOP for peer %u\n", peer_id);
538 if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) 606 if (!VALID_PEER_ID (peer_id))
539 { 607 {
540 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), 608 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
541 "Peer not found"); 609 "Peer not found");
@@ -565,7 +633,7 @@ GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
565 GNUNET_SERVER_receive_done (client, GNUNET_OK); 633 GNUNET_SERVER_receive_done (client, GNUNET_OK);
566 return; 634 return;
567 } 635 }
568 if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer)) 636 if (GNUNET_OK != stop_peer (peer))
569 { 637 {
570 LOG (GNUNET_ERROR_TYPE_WARNING, "Stopping peer %u failed\n", peer_id); 638 LOG (GNUNET_ERROR_TYPE_WARNING, "Stopping peer %u failed\n", peer_id);
571 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), 639 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
@@ -574,7 +642,6 @@ GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
574 return; 642 return;
575 } 643 }
576 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id); 644 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id);
577 peer->details.local.is_running = GNUNET_NO;
578 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); 645 reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
579 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); 646 reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT);
580 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); 647 reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
@@ -601,6 +668,7 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
601{ 668{
602 const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; 669 const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
603 struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply; 670 struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
671 struct ForwardedOperationContext *fopc;
604 struct Peer *peer; 672 struct Peer *peer;
605 char *config; 673 char *config;
606 char *xconfig; 674 char *xconfig;
@@ -611,7 +679,8 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
611 679
612 msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message; 680 msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
613 peer_id = ntohl (msg->peer_id); 681 peer_id = ntohl (msg->peer_id);
614 if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) 682 LOG_DEBUG ("Received GET_CONFIG for peer %u\n", peer_id);
683 if (!VALID_PEER_ID (peer_id))
615 { 684 {
616 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), 685 GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
617 "Peer not found"); 686 "Peer not found");
@@ -621,8 +690,6 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
621 peer = GST_peer_list[peer_id]; 690 peer = GST_peer_list[peer_id];
622 if (GNUNET_YES == peer->is_remote) 691 if (GNUNET_YES == peer->is_remote)
623 { 692 {
624 struct ForwardedOperationContext *fopc;
625
626 LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id); 693 LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id);
627 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); 694 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
628 GNUNET_SERVER_client_keep (client); 695 GNUNET_SERVER_client_keep (client);
@@ -666,6 +733,189 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
666 733
667 734
668/** 735/**
736 * Cleans up the given PeerReconfigureContext
737 *
738 * @param prc the PeerReconfigureContext
739 */
740static void
741cleanup_prc (struct PeerReconfigureContext *prc)
742{
743 struct Peer *peer;
744
745 if (VALID_PEER_ID (prc->peer_id))
746 {
747 peer = GST_peer_list [prc->peer_id];
748 if (1 != prc->stopped)
749 {
750 GNUNET_TESTING_peer_stop_async_cancel (peer->details.local.peer);
751 stop_peer (peer); /* Stop the peer synchronously */
752 }
753 }
754 if (NULL != prc->cfg)
755 GNUNET_CONFIGURATION_destroy (prc->cfg);
756 GNUNET_SERVER_client_drop (prc->client);
757 GNUNET_CONTAINER_DLL_remove (prc_head, prc_tail, prc);
758 GNUNET_free (prc);
759}
760
761
762/**
763 * Cleans up the Peer reconfigure context list
764 */
765void
766GST_free_prcq ()
767{
768 while (NULL != prc_head)
769 cleanup_prc (prc_head);
770}
771
772
773/**
774 * Callback to inform whether the peer is running or stopped.
775 *
776 * @param cls the closure given to GNUNET_TESTING_peer_stop_async()
777 * @param peer the respective peer whose status is being reported
778 * @param success GNUNET_YES if the peer is stopped; GNUNET_SYSERR upon any
779 * error
780 */
781static void
782prc_stop_cb (void *cls, struct GNUNET_TESTING_Peer *p, int success)
783{
784 struct PeerReconfigureContext *prc = cls;
785 struct Peer *peer;
786 char *emsg;
787
788 GNUNET_assert (VALID_PEER_ID (prc->peer_id));
789 peer = GST_peer_list [prc->peer_id];
790 GNUNET_assert (GNUNET_NO == peer->is_remote);
791 GNUNET_TESTING_peer_destroy (peer->details.local.peer);
792 GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
793 peer->details.local.cfg = prc->cfg;
794 prc->cfg = NULL;
795 prc->stopped = 1;
796 emsg = NULL;
797 peer->details.local.peer
798 = GNUNET_TESTING_peer_configure (GST_context->system,
799 peer->details.local.cfg, peer->id,
800 NULL /* Peer id */ ,
801 &emsg);
802 if (NULL == peer->details.local.peer)
803 {
804 GST_send_operation_fail_msg (prc->client, prc->op_id, emsg);
805 goto cleanup;
806 }
807 if (GNUNET_OK != start_peer (peer))
808 {
809
810 GST_send_operation_fail_msg (prc->client, prc->op_id,
811 "Failed to start reconfigured peer");
812 goto cleanup;
813 }
814 GST_send_operation_success_msg (prc->client, prc->op_id);
815
816 cleanup:
817 cleanup_prc (prc);
818 return;
819}
820
821
822/**
823 * Handler for GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages.
824 * Should stop the peer asyncronously, destroy it and create it again with the
825 * new configuration.
826 *
827 * @param cls NULL
828 * @param client identification of the client
829 * @param message the actual message
830 */
831void
832GST_handle_peer_reconfigure (void *cls, struct GNUNET_SERVER_Client *client,
833 const struct GNUNET_MessageHeader *message)
834{
835 const struct GNUNET_TESTBED_PeerReconfigureMessage *msg;
836 struct Peer *peer;
837 struct GNUNET_CONFIGURATION_Handle *cfg;
838 struct ForwardedOperationContext *fopc;
839 struct PeerReconfigureContext *prc;
840 uint64_t op_id;
841 uint32_t peer_id;
842 uint16_t msize;
843
844 msize = ntohs (message->size);
845 if (msize <= sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage))
846 {
847 GNUNET_break_op (0);
848 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
849 return;
850 }
851 msg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) message;
852 peer_id = ntohl (msg->peer_id);
853 op_id = GNUNET_ntohll (msg->operation_id);
854 if (!VALID_PEER_ID (peer_id))
855 {
856 GNUNET_break (0);
857 GST_send_operation_fail_msg (client, op_id, "Peer not found");
858 GNUNET_SERVER_receive_done (client, GNUNET_OK);
859 return;
860 }
861 peer = GST_peer_list[peer_id];
862 if (GNUNET_YES == peer->is_remote)
863 {
864 LOG_DEBUG ("Forwarding PEER_RECONFIGURE for peer: %u\n", peer_id);
865 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
866 GNUNET_SERVER_client_keep (client);
867 fopc->client = client;
868 fopc->operation_id = op_id;
869 fopc->type = OP_PEER_RECONFIGURE;
870 fopc->opc =
871 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
872 slave->controller,
873 fopc->operation_id, &msg->header,
874 &GST_forwarded_operation_reply_relay,
875 fopc);
876 fopc->timeout_task =
877 GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout,
878 fopc);
879 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
880 GNUNET_SERVER_receive_done (client, GNUNET_OK);
881 return;
882 }
883 LOG_DEBUG ("Received PEER_RECONFIGURE for peer %u\n", peer_id);
884 if (0 < peer->reference_cnt)
885 {
886 GNUNET_break (0);
887 GST_send_operation_fail_msg (client, op_id, "Peer in use");
888 GNUNET_SERVER_receive_done (client, GNUNET_OK);
889 return;
890 }
891 if (GNUNET_YES == peer->destroy_flag)
892 {
893 GNUNET_break (0);
894 GST_send_operation_fail_msg (client, op_id, "Peer is being destroyed");
895 GNUNET_SERVER_receive_done (client, GNUNET_OK);
896 return;
897 }
898 cfg = GNUNET_TESTBED_extract_config_ (message);
899 if (NULL == cfg)
900 {
901 GNUNET_break (0);
902 GST_send_operation_fail_msg (client, op_id, "Compression error");
903 GNUNET_SERVER_receive_done (client, GNUNET_OK);
904 return;
905 }
906 prc = GNUNET_malloc (sizeof (struct PeerReconfigureContext));
907 prc->cfg = cfg;
908 prc->peer_id = peer_id;
909 prc->op_id = op_id;
910 prc->client = client;
911 GNUNET_SERVER_client_keep (client);
912 GNUNET_CONTAINER_DLL_insert_tail (prc_head, prc_tail, prc);
913 GNUNET_TESTING_peer_stop_async (peer->details.local.peer, prc_stop_cb, prc);
914 GNUNET_SERVER_receive_done (client, GNUNET_OK);
915}
916
917
918/**
669 * Cleanup the context information created for managing a peer's service 919 * Cleanup the context information created for managing a peer's service
670 * 920 *
671 * @param mctx the ManageServiceContext 921 * @param mctx the ManageServiceContext
diff --git a/src/testbed/test_testbed_api_peer_reconfiguration.c b/src/testbed/test_testbed_api_peer_reconfiguration.c
new file mode 100644
index 000000000..398eab85c
--- /dev/null
+++ b/src/testbed/test_testbed_api_peer_reconfiguration.c
@@ -0,0 +1,192 @@
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/test_testbed_api_peer_reconfiguration.c
23 * @brief testcase for testing GNUNET_TESTBED_peer_manage_service()
24 * implementation
25 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
26 */
27
28#include "platform.h"
29#include "gnunet_common.h"
30#include "gnunet_testbed_service.h"
31
32/**
33 * Number of peers we want to start
34 */
35#define NUM_PEERS 1
36
37/**
38 * The array of peers; we get them from the testbed
39 */
40static struct GNUNET_TESTBED_Peer **peers;
41
42/**
43 * Operation handle
44 */
45static struct GNUNET_TESTBED_Operation *op;
46
47/**
48 * Abort task identifier
49 */
50static GNUNET_SCHEDULER_TaskIdentifier abort_task;
51
52/**
53 * States in this test
54 */
55enum {
56
57 /**
58 * Test has just been initialized
59 */
60 STATE_INIT,
61
62 /**
63 * Peers have been started
64 */
65 STATE_PEER_STARTED,
66
67 /**
68 * Peer has been reconfigured. Test completed successfully
69 */
70 STATE_PEER_RECONFIGURED
71
72} state;
73
74/**
75 * Fail testcase
76 */
77#define FAIL_TEST(cond, ret) do { \
78 if (!(cond)) { \
79 GNUNET_break(0); \
80 if (GNUNET_SCHEDULER_NO_TASK != abort_task) \
81 GNUNET_SCHEDULER_cancel (abort_task); \
82 abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL); \
83 ret; \
84 } \
85 } while (0)
86
87
88/**
89 * Abort task
90 *
91 * @param cls NULL
92 * @param tc scheduler task context
93 */
94static void
95do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
96{
97 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting\n");
98 abort_task = GNUNET_SCHEDULER_NO_TASK;
99 if (NULL != op)
100 {
101 GNUNET_TESTBED_operation_done (op);
102 op = NULL;
103 }
104 GNUNET_SCHEDULER_shutdown();
105}
106
107
108/**
109 * Signature of the event handler function called by the
110 * respective event controller.
111 *
112 * @param cls closure
113 * @param event information about the event
114 */
115static void
116controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
117{
118 if (STATE_PEER_STARTED != state)
119 return;
120 if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type)
121 {
122 GNUNET_TESTBED_operation_done (op);
123 op = NULL;
124 FAIL_TEST (0, return);
125 }
126 if (NULL != event->details.operation_finished.emsg)
127 {
128 fprintf (stderr, "Operation failed: %s\n",
129 event->details.operation_finished.emsg);
130 GNUNET_TESTBED_operation_done (op);
131 op = NULL;
132 FAIL_TEST (0, return);
133 }
134 GNUNET_TESTBED_operation_done (op);
135 state = STATE_PEER_RECONFIGURED;
136 GNUNET_SCHEDULER_cancel (abort_task);
137 abort_task = GNUNET_SCHEDULER_NO_TASK;
138 GNUNET_SCHEDULER_shutdown ();
139}
140
141
142/**
143 * Signature of a main function for a testcase.
144 *
145 * @param cls closure
146 * @param num_peers number of peers in 'peers'
147 * @param peers_ handle to peers run in the testbed
148 * @param links_succeeded the number of overlay link connection attempts that
149 * succeeded
150 * @param links_failed the number of overlay link connection attempts that
151 * failed
152 */
153static void
154test_master (void *cls, unsigned int num_peers,
155 struct GNUNET_TESTBED_Peer **peers_,
156 unsigned int links_succeeded,
157 unsigned int links_failed)
158{
159 struct GNUNET_CONFIGURATION_Handle *cfg;
160
161 FAIL_TEST (NUM_PEERS == num_peers, return);
162 state = STATE_PEER_STARTED;
163 peers = peers_;
164 cfg = GNUNET_CONFIGURATION_create ();
165 FAIL_TEST (GNUNET_OK == GNUNET_CONFIGURATION_parse
166 (cfg, "test_testbed_api_testbed_run_topologyrandom.conf"), return);
167 op = GNUNET_TESTBED_peer_update_configuration (peers[0], cfg);
168 GNUNET_CONFIGURATION_destroy (cfg);
169 FAIL_TEST (NULL != op, return);
170 abort_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
171 (GNUNET_TIME_UNIT_SECONDS, 30),
172 &do_abort, NULL);
173}
174
175
176/**
177 * Main function
178 */
179int
180main (int argc, char **argv)
181{
182 state = STATE_INIT;
183 (void) GNUNET_TESTBED_test_run ("test_testbed_api_peer_reconfiguration",
184 "test_testbed_api.conf",
185 NUM_PEERS,
186 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED,
187 &controller_cb, NULL,
188 &test_master, NULL);
189 if (STATE_PEER_RECONFIGURED != state)
190 return 1;
191 return 0;
192}
diff --git a/src/testbed/testbed.h b/src/testbed/testbed.h
index ed4e27dc6..904e7acba 100644
--- a/src/testbed/testbed.h
+++ b/src/testbed/testbed.h
@@ -219,14 +219,14 @@ struct GNUNET_TESTBED_PeerCreateMessage
219 struct GNUNET_MessageHeader header; 219 struct GNUNET_MessageHeader header;
220 220
221 /** 221 /**
222 * Unique operation id 222 * On which host should the peer be started?
223 */ 223 */
224 uint64_t operation_id GNUNET_PACKED; 224 uint32_t host_id GNUNET_PACKED;
225 225
226 /** 226 /**
227 * On which host should the peer be started? 227 * Unique operation id
228 */ 228 */
229 uint32_t host_id GNUNET_PACKED; 229 uint64_t operation_id GNUNET_PACKED;
230 230
231 /** 231 /**
232 * Unique ID for the peer. 232 * Unique ID for the peer.
@@ -236,7 +236,7 @@ struct GNUNET_TESTBED_PeerCreateMessage
236 /** 236 /**
237 * Size of the uncompressed configuration 237 * Size of the uncompressed configuration
238 */ 238 */
239 uint32_t config_size GNUNET_PACKED; 239 uint16_t config_size GNUNET_PACKED;
240 240
241 /* followed by serialized peer configuration; 241 /* followed by serialized peer configuration;
242 * gzip'ed configuration file in INI format */ 242 * gzip'ed configuration file in INI format */
@@ -252,7 +252,7 @@ struct GNUNET_TESTBED_PeerReconfigureMessage
252{ 252{
253 253
254 /** 254 /**
255 * Type is GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER 255 * Type is GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER
256 */ 256 */
257 struct GNUNET_MessageHeader header; 257 struct GNUNET_MessageHeader header;
258 258
@@ -266,6 +266,11 @@ struct GNUNET_TESTBED_PeerReconfigureMessage
266 */ 266 */
267 uint64_t operation_id GNUNET_PACKED; 267 uint64_t operation_id GNUNET_PACKED;
268 268
269 /**
270 * The length of the serialized configuration when uncompressed
271 */
272 uint16_t config_size GNUNET_PACKED;
273
269 /* followed by serialized peer configuration; 274 /* followed by serialized peer configuration;
270 * gzip'ed configuration file in INI format */ 275 * gzip'ed configuration file in INI format */
271 276
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c
index 207f2658f..01df06729 100644
--- a/src/testbed/testbed_api.c
+++ b/src/testbed/testbed_api.c
@@ -455,6 +455,8 @@ handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
455 opc->data = NULL; 455 opc->data = NULL;
456 } 456 }
457 break; 457 break;
458 case OP_PEER_RECONFIGURE:
459 break;
458 default: 460 default:
459 GNUNET_assert (0); 461 GNUNET_assert (0);
460 } 462 }
@@ -780,6 +782,7 @@ handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
780 struct OperationContext *opc; 782 struct OperationContext *opc;
781 const char *emsg; 783 const char *emsg;
782 uint64_t op_id; 784 uint64_t op_id;
785 uint64_t mask;
783 struct GNUNET_TESTBED_EventInformation event; 786 struct GNUNET_TESTBED_EventInformation event;
784 787
785 op_id = GNUNET_ntohll (msg->operation_id); 788 op_id = GNUNET_ntohll (msg->operation_id);
@@ -814,8 +817,8 @@ handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
814 event.op_cls = opc->op_cls; 817 event.op_cls = opc->op_cls;
815 event.details.operation_finished.emsg = emsg; 818 event.details.operation_finished.emsg = emsg;
816 event.details.operation_finished.generic = NULL; 819 event.details.operation_finished.generic = NULL;
817 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) && 820 mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
818 (NULL != c->cc)) 821 if ((0 != (mask & c->event_mask)) && (NULL != c->cc))
819 { 822 {
820 exop_insert (event.op); 823 exop_insert (event.op);
821 c->cc (c->cc_cls, &event); 824 c->cc (c->cc_cls, &event);
@@ -1939,6 +1942,28 @@ GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1939 xdata = (const Bytef *) &imsg[1]; 1942 xdata = (const Bytef *) &imsg[1];
1940 } 1943 }
1941 break; 1944 break;
1945 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER:
1946 {
1947 const struct GNUNET_TESTBED_PeerCreateMessage *imsg;
1948
1949 imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg;
1950 data_len = ntohs (imsg->config_size);
1951 xdata_len = ntohs (imsg->header.size) -
1952 sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1953 xdata = (const Bytef *) &imsg[1];
1954 }
1955 break;
1956 case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER:
1957 {
1958 const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg;
1959
1960 imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg;
1961 data_len = ntohs (imsg->config_size);
1962 xdata_len = ntohs (imsg->header.size) -
1963 sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage);
1964 xdata = (const Bytef *) &imsg[1];
1965 }
1966 break;
1942 default: 1967 default:
1943 GNUNET_assert (0); 1968 GNUNET_assert (0);
1944 } 1969 }
@@ -1946,7 +1971,7 @@ GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1946 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len))) 1971 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
1947 { 1972 {
1948 GNUNET_free (data); 1973 GNUNET_free (data);
1949 GNUNET_break_op (0); 1974 GNUNET_break_op (0); /* Un-compression failure */
1950 return NULL; 1975 return NULL;
1951 } 1976 }
1952 cfg = GNUNET_CONFIGURATION_create (); 1977 cfg = GNUNET_CONFIGURATION_create ();
@@ -1956,7 +1981,7 @@ GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1956 GNUNET_NO)) 1981 GNUNET_NO))
1957 { 1982 {
1958 GNUNET_free (data); 1983 GNUNET_free (data);
1959 GNUNET_break_op (0); 1984 GNUNET_break_op (0); /* De-serialization failure */
1960 return NULL; 1985 return NULL;
1961 } 1986 }
1962 GNUNET_free (data); 1987 GNUNET_free (data);
diff --git a/src/testbed/testbed_api.h b/src/testbed/testbed_api.h
index 320289bb0..dbeea9243 100644
--- a/src/testbed/testbed_api.h
+++ b/src/testbed/testbed_api.h
@@ -67,6 +67,11 @@ enum OperationType
67 */ 67 */
68 OP_PEER_INFO, 68 OP_PEER_INFO,
69 69
70 /**
71 * Reconfigure a peer
72 */
73 OP_PEER_RECONFIGURE,
74
70 /** 75 /**
71 * Overlay connection operation 76 * Overlay connection operation
72 */ 77 */
diff --git a/src/testbed/testbed_api_peers.c b/src/testbed/testbed_api_peers.c
index 8341a96a3..e9328ffb8 100644
--- a/src/testbed/testbed_api_peers.c
+++ b/src/testbed/testbed_api_peers.c
@@ -120,7 +120,7 @@ opstart_peer_create (void *cls)
120 msg->operation_id = GNUNET_htonll (opc->id); 120 msg->operation_id = GNUNET_htonll (opc->id);
121 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host)); 121 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host));
122 msg->peer_id = htonl (data->peer->unique_id); 122 msg->peer_id = htonl (data->peer->unique_id);
123 msg->config_size = htonl (c_size); 123 msg->config_size = htons ((uint16_t) c_size);
124 GNUNET_TESTBED_insert_opc_ (opc->c, opc); 124 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
125 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header); 125 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
126} 126}
@@ -457,6 +457,71 @@ oprelease_overlay_connect (void *cls)
457 457
458 458
459/** 459/**
460 * Function called when a peer reconfigure operation is ready
461 *
462 * @param cls the closure from GNUNET_TESTBED_operation_create_()
463 */
464static void
465opstart_peer_reconfigure (void *cls)
466{
467 struct OperationContext *opc = cls;
468 struct PeerReconfigureData *data = opc->data;
469 struct GNUNET_TESTBED_PeerReconfigureMessage *msg;
470 char *xconfig;
471 size_t xc_size;
472 uint16_t msize;
473
474 opc->state = OPC_STATE_STARTED;
475 GNUNET_assert (NULL != data);
476 xc_size = GNUNET_TESTBED_compress_config_ (data->config, data->cfg_size,
477 &xconfig);
478 GNUNET_free (data->config);
479 data->config = NULL;
480 GNUNET_assert (xc_size <= UINT16_MAX);
481 msize = (uint16_t) xc_size +
482 sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage);
483 msg = GNUNET_realloc (xconfig, msize);
484 (void) memmove (&msg[1], msg, xc_size);
485 msg->header.size = htons (msize);
486 msg->header.type = htons (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_free (data);
491 opc->data = NULL;
492 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
493 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
494}
495
496
497/**
498 * Callback which will be called when a peer reconfigure operation is released
499 *
500 * @param cls the closure from GNUNET_TESTBED_operation_create_()
501 */
502static void
503oprelease_peer_reconfigure (void *cls)
504{
505 struct OperationContext *opc = cls;
506 struct PeerReconfigureData *data = opc->data;
507
508 switch (opc->state)
509 {
510 case OPC_STATE_INIT:
511 GNUNET_free (data->config);
512 GNUNET_free (data);
513 break;
514 case OPC_STATE_STARTED:
515 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
516 break;
517 case OPC_STATE_FINISHED:
518 break;
519 }
520 GNUNET_free (opc);
521}
522
523
524/**
460 * Lookup a peer by ID. 525 * Lookup a peer by ID.
461 * 526 *
462 * @param id global peer ID assigned to the peer 527 * @param id global peer ID assigned to the peer
@@ -673,9 +738,38 @@ GNUNET_TESTBED_peer_update_configuration (struct GNUNET_TESTBED_Peer *peer,
673 const struct 738 const struct
674 GNUNET_CONFIGURATION_Handle *cfg) 739 GNUNET_CONFIGURATION_Handle *cfg)
675{ 740{
676 // FIXME: handle locally or delegate... 741 struct OperationContext *opc;
677 GNUNET_break (0); 742 struct PeerReconfigureData *data;
678 return NULL; 743 size_t csize;
744
745 data = GNUNET_malloc (sizeof (struct PeerReconfigureData));
746 data->peer = peer;
747 data->config = GNUNET_CONFIGURATION_serialize (cfg, &csize);
748 if (NULL == data->config)
749 {
750 GNUNET_free (data);
751 return NULL;
752 }
753 if (csize > UINT16_MAX)
754 {
755 GNUNET_break (0);
756 GNUNET_free (data->config);
757 GNUNET_free (data);
758 return NULL;
759 }
760 data->cfg_size = (uint16_t) csize;
761 opc = GNUNET_malloc (sizeof (struct OperationContext));
762 opc->c = peer->controller;
763 opc->data = data;
764 opc->type = OP_PEER_RECONFIGURE;
765 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
766 opc->op =
767 GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_reconfigure,
768 &oprelease_peer_reconfigure);
769 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
770 opc->op);
771 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
772 return opc->op;
679} 773}
680 774
681 775
diff --git a/src/testbed/testbed_api_peers.h b/src/testbed/testbed_api_peers.h
index 10deed67d..50fb29bf6 100644
--- a/src/testbed/testbed_api_peers.h
+++ b/src/testbed/testbed_api_peers.h
@@ -196,6 +196,28 @@ struct PeerInfoData
196 196
197 197
198/** 198/**
199 * Data for the operations of type OP_PEER_RECONFIGURE
200 */
201struct PeerReconfigureData
202{
203 /**
204 * The peer whose information has been requested
205 */
206 struct GNUNET_TESTBED_Peer *peer;
207
208 /**
209 * The serialized new configuration template
210 */
211 char *config;
212
213 /**
214 * the size of the serialized configuration
215 */
216 uint16_t cfg_size;
217};
218
219
220/**
199 * Data structure for OperationType OP_OVERLAY_CONNECT 221 * Data structure for OperationType OP_OVERLAY_CONNECT
200 */ 222 */
201struct OverlayConnectData 223struct OverlayConnectData