From b0474eb7a6aa570c04e4d76fd664caa406b3dd30 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 27 Jun 2016 14:43:43 +0000 Subject: [PATCH] convert testbed_api_barriers to new MQ API --- src/include/gnunet_testbed_service.h | 4 +- src/testbed/test_testbed_api.c | 77 +++++--- src/testbed/test_testbed_api_template.conf | 2 + src/testbed/testbed.h | 4 +- src/testbed/testbed_api_barriers.c | 205 ++++++++++----------- 5 files changed, 153 insertions(+), 139 deletions(-) diff --git a/src/include/gnunet_testbed_service.h b/src/include/gnunet_testbed_service.h index 7f9d25006..781dc0441 100644 --- a/src/include/gnunet_testbed_service.h +++ b/src/include/gnunet_testbed_service.h @@ -1549,7 +1549,7 @@ typedef void * GNUNET_TESTBED_barrier_reached(). * @param cb the callback to call when the barrier is reached or upon error. * Cannot be NULL. - * @param cls closure for the above callback + * @param cb_cls closure for @a cb * @return barrier handle */ struct GNUNET_TESTBED_Barrier * @@ -1557,7 +1557,7 @@ GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller, const char *name, unsigned int quorum, GNUNET_TESTBED_barrier_status_cb cb, - void *cls); + void *cb_cls); /** diff --git a/src/testbed/test_testbed_api.c b/src/testbed/test_testbed_api.c index 83203e71e..19e95f2c2 100644 --- a/src/testbed/test_testbed_api.c +++ b/src/testbed/test_testbed_api.c @@ -90,7 +90,7 @@ static struct GNUNET_ARM_Handle *arm_handle; /** * Abort task identifier */ -static struct GNUNET_SCHEDULER_Task * abort_task; +static struct GNUNET_SCHEDULER_Task *abort_task; /** * The testing result @@ -103,25 +103,25 @@ static int result; */ enum Test { - /** - * Test cases which are not covered by the below ones - */ + /** + * Test cases which are not covered by the below ones + */ OTHER, - /** - * Test where we get a peer config from controller - */ + /** + * Test where we get a peer config from controller + */ PEER_GETCONFIG, - /** - * Test where we connect to a service running on the peer - */ + /** + * Test where we connect to a service running on the peer + */ PEER_SERVICE_CONNECT, - /** - * Test where we get a peer's identity from controller - */ - PEER_DESTROY, + /** + * Test where we get a peer's identity from controller + */ + PEER_DESTROY }; /** @@ -197,7 +197,8 @@ do_abort (void *cls) * @return service handle to return in 'op_result', NULL on error */ static void * -arm_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) +arm_connect_adapter (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg) { FAIL_TEST (NULL == cls, return NULL); FAIL_TEST (OTHER == sub_test, return NULL); @@ -215,7 +216,8 @@ arm_connect_adapter (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) * @param op_result service handle returned from the connect adapter */ static void -arm_disconnect_adapter (void *cls, void *op_result) +arm_disconnect_adapter (void *cls, + void *op_result) { FAIL_TEST (NULL != op_result, return); FAIL_TEST (op_result == arm_handle, return); @@ -238,8 +240,10 @@ arm_disconnect_adapter (void *cls, void *op_result) * operation has executed successfully. */ static void -service_connect_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, - void *ca_result, const char *emsg) +service_connect_comp_cb (void *cls, + struct GNUNET_TESTBED_Operation *op, + void *ca_result, + const char *emsg) { switch (sub_test) { @@ -268,7 +272,8 @@ service_connect_comp_cb (void *cls, struct GNUNET_TESTBED_Operation *op, * operation is successfull */ static void -peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op, +peerinfo_cb (void *cb_cls, + struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) { @@ -299,7 +304,8 @@ peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op, * @param event information about the event */ static void -controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) +controller_cb (void *cls, + const struct GNUNET_TESTBED_EventInformation *event) { switch (event->type) { @@ -365,7 +371,9 @@ controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event) * @param emsg NULL if peer is not NULL; else MAY contain the error description */ static void -peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) +peer_create_cb (void *cls, + struct GNUNET_TESTBED_Peer *peer, + const char *emsg) { struct GNUNET_TESTBED_Peer **peer_ptr; @@ -374,7 +382,10 @@ peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) FAIL_TEST (NULL != peer_ptr, return); *peer_ptr = peer; GNUNET_TESTBED_operation_done (operation); - operation = GNUNET_TESTBED_peer_start (NULL, peer, NULL, NULL); + operation = GNUNET_TESTBED_peer_start (NULL, + peer, + NULL, + NULL); FAIL_TEST (NULL != operation, return); } @@ -386,12 +397,16 @@ peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg) * @param emsg the error message; NULL if host registration is successful */ static void -registration_comp (void *cls, const char *emsg) +registration_comp (void *cls, + const char *emsg) { FAIL_TEST (cls == neighbour, return); reg_handle = NULL; operation = - GNUNET_TESTBED_peer_create (controller, host, cfg, &peer_create_cb, + GNUNET_TESTBED_peer_create (controller, + host, + cfg, + &peer_create_cb, &peer); FAIL_TEST (NULL != operation, return); } @@ -402,12 +417,14 @@ registration_comp (void *cls, const char *emsg) * * @param cls the closure from GNUNET_TESTBED_controller_start() * @param cfg the configuration with which the controller has been started; - * NULL if status is not GNUNET_OK - * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not, + * NULL if status is not #GNUNET_OK + * @param status #GNUNET_OK if the startup is successfull; #GNUNET_SYSERR if not, * GNUNET_TESTBED_controller_stop() shouldn't be called in this case */ static void -status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, int status) +status_cb (void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg_, + int status) { uint64_t event_mask; @@ -440,12 +457,14 @@ status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, int status * Main run function. * * @param cls NULL - * @param args arguments passed to GNUNET_PROGRAM_run + * @param args arguments passed to #GNUNET_PROGRAM_run() * @param cfgfile the path to configuration file * @param cfg the configuration file handle */ static void -run (void *cls, char *const *args, const char *cfgfile, +run (void *cls, + char *const *args, + const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *config) { cfg = GNUNET_CONFIGURATION_dup (config); diff --git a/src/testbed/test_testbed_api_template.conf b/src/testbed/test_testbed_api_template.conf index 296c2b0dc..35317fd1c 100644 --- a/src/testbed/test_testbed_api_template.conf +++ b/src/testbed/test_testbed_api_template.conf @@ -1,3 +1,5 @@ +@INLINE@ ../../contrib/no_forcestart.conf +@INLINE@ ../../contrib/no_autostart_above_core.conf [testbed] AUTOSTART = NO PORT = 12113 diff --git a/src/testbed/testbed.h b/src/testbed/testbed.h index bc93ed8a8..b6119e98f 100644 --- a/src/testbed/testbed.h +++ b/src/testbed/testbed.h @@ -877,8 +877,8 @@ struct GNUNET_TESTBED_BarrierStatusMsg uint16_t name_len GNUNET_PACKED; /** - * the barrier name (NULL terminated) concatenated with an error message (NULL - * terminated) if the status were to indicate an error + * the barrier name (0-terminated) concatenated with an error message + * (0-terminated) if the status were to indicate an error */ char data[0]; }; diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c index 3ec4a905e..74139cc53 100644 --- a/src/testbed/testbed_api_barriers.c +++ b/src/testbed/testbed_api_barriers.c @@ -56,19 +56,9 @@ struct GNUNET_TESTBED_BarrierWaitHandle struct GNUNET_CONFIGURATION_Handle *cfg; /** - * The client connection + * The testbed-barrier service message queue. */ - struct GNUNET_CLIENT_Connection *conn; - - /** - * Transmit handle - */ - struct GNUNET_CLIENT_TransmitHandle *tx; - - /** - * The message to transmit with tx - */ - struct GNUNET_MessageHeader *msg; + struct GNUNET_MQ_Handle *mq; /** * The barrier wait callback @@ -76,98 +66,92 @@ struct GNUNET_TESTBED_BarrierWaitHandle GNUNET_TESTBED_barrier_wait_cb cb; /** - * The closure for the above callback + * The closure for @e cb. */ - void *cls; + void *cb_cls; }; +/** + * Check if barrier status message is well-formed. + * + * @param cls closure + * @param msg received message + * @return #GNUNET_OK if the message is well-formed. + */ +static int +check_status (void *cls, + const struct GNUNET_TESTBED_BarrierStatusMsg *msg) +{ + /* FIXME: this fails to actually check that the message + follows the protocol spec (0-terminations!). However, + not critical as #handle_status() doesn't interpret the + variable-size part anyway right now. */ + return GNUNET_OK; +} + + /** * Type of a function to call when we receive a message * from the service. * * @param cls closure - * @param message received message; NULL on timeout or fatal error + * @param msg received message */ static void -receive_handler (void *cls, - const struct GNUNET_MessageHeader *message) +handle_status (void *cls, + const struct GNUNET_TESTBED_BarrierStatusMsg *msg) { struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; - const struct GNUNET_TESTBED_BarrierStatusMsg *msg; - uint16_t msize; - if (NULL == message) - { - GNUNET_break_op (0); - goto fail; - } - if (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS != ntohs (message->type)) - { - GNUNET_break_op (0); - goto fail; - } - msize = ntohs (message->size); - if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg)) - { - GNUNET_break_op (0); - goto fail; - } - msg = (const struct GNUNET_TESTBED_BarrierStatusMsg *) message; switch (ntohs (msg->status)) { case GNUNET_TESTBED_BARRIERSTATUS_ERROR: - goto fail; + h->cb (h->cb_cls, + h->name, + GNUNET_SYSERR); + break; case GNUNET_TESTBED_BARRIERSTATUS_INITIALISED: + h->cb (h->cb_cls, + h->name, + GNUNET_SYSERR); GNUNET_break (0); - goto fail; + break; case GNUNET_TESTBED_BARRIERSTATUS_CROSSED: - h->cb (h->cls, h->name, GNUNET_OK); - goto destroy; + h->cb (h->cb_cls, + h->name, + GNUNET_OK); + break; default: GNUNET_break_op (0); + h->cb (h->cb_cls, + h->name, + GNUNET_SYSERR); + break; } - - fail: - h->cb (h->cls, h->name, GNUNET_SYSERR); - - destroy: GNUNET_TESTBED_barrier_wait_cancel (h); } /** - * Function called to notify a client about the connection - * begin ready to queue more data. "buf" will be - * NULL and "size" zero if the connection was closed for - * writing in the meantime. + * Generic error handler, called with the appropriate error code and + * the same closure specified at the creation of the message queue. + * Not every message queue implementation supports an error handler. * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf + * @param cls closure with the `struct GNUNET_TESTBED_BarrierWaitHandle *` + * @param error error code */ -static size_t -transmit_notify (void *cls, size_t size, void *buf) +static void +mq_error_handler (void *cls, + enum GNUNET_MQ_Error error) { struct GNUNET_TESTBED_BarrierWaitHandle *h = cls; - uint16_t msize; - h->tx = NULL; - if ((0 == size) || (NULL == buf)) - { - h->cb (h->cls, h->name, GNUNET_SYSERR); - GNUNET_TESTBED_barrier_wait_cancel (h); - return 0; - } - msize = htons (h->msg->size); - GNUNET_assert (msize <= size); - (void) memcpy (buf, h->msg, msize); - GNUNET_free (h->msg); - h->msg = NULL; - GNUNET_CLIENT_receive (h->conn, &receive_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); - return msize; + h->cb (h->cb_cls, + h->name, + GNUNET_SYSERR); + GNUNET_TESTBED_barrier_wait_cancel (h); } @@ -178,64 +162,74 @@ transmit_notify (void *cls, size_t size, void *buf) * * @param name the name of the barrier * @param cb the barrier wait callback - * @param cls the closure for the above callback + * @param cb_cls the closure for @a cb * @return barrier wait handle which can be used to cancel the waiting at * anytime before the callback is called. NULL upon error. */ struct GNUNET_TESTBED_BarrierWaitHandle * GNUNET_TESTBED_barrier_wait (const char *name, GNUNET_TESTBED_barrier_wait_cb cb, - void *cls) + void *cb_cls) { + GNUNET_MQ_hd_var_size (status, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, + struct GNUNET_TESTBED_BarrierStatusMsg); + struct GNUNET_TESTBED_BarrierWaitHandle *h + = GNUNET_new (struct GNUNET_TESTBED_BarrierWaitHandle); + struct GNUNET_MQ_MessageHandler handlers[] = { + make_status_handler (h), + GNUNET_MQ_handler_end () + }; + struct GNUNET_MQ_Envelope *env; struct GNUNET_TESTBED_BarrierWait *msg; - struct GNUNET_CONFIGURATION_Handle *cfg; - struct GNUNET_TESTBED_BarrierWaitHandle *h; - char *cfg_filename; + const char *cfg_filename; size_t name_len; - uint16_t msize; GNUNET_assert (NULL != cb); - GNUNET_assert (NULL != name); cfg_filename = getenv (ENV_TESTBED_CONFIG); if (NULL == cfg_filename) { - LOG (GNUNET_ERROR_TYPE_ERROR, "Are you running under testbed?\n"); + LOG (GNUNET_ERROR_TYPE_ERROR, + "Are you running under testbed?\n"); + GNUNET_free (h); return NULL; } - cfg = GNUNET_CONFIGURATION_create (); - if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_filename)) + h->cfg = GNUNET_CONFIGURATION_create (); + if (GNUNET_OK != + GNUNET_CONFIGURATION_load (h->cfg, + cfg_filename)) { - LOG (GNUNET_ERROR_TYPE_ERROR, "Unable to load configuration from file `%s'\n", + LOG (GNUNET_ERROR_TYPE_ERROR, + "Unable to load configuration from file `%s'\n", cfg_filename); - GNUNET_CONFIGURATION_destroy (cfg); + GNUNET_CONFIGURATION_destroy (h->cfg); + GNUNET_free (h); return NULL; } - h = GNUNET_new (struct GNUNET_TESTBED_BarrierWaitHandle); h->name = GNUNET_strdup (name); - h->cfg = cfg; - h->conn = GNUNET_CLIENT_connect ("testbed-barrier", h->cfg); h->cb = cb; - h->cls = cls; - if (NULL == h->conn) + h->cb_cls = cb_cls; + h->mq = GNUNET_CLIENT_connecT (h->cfg, + "testbed-barrier", + handlers, + &mq_error_handler, + h); + if (NULL == h->mq) { LOG (GNUNET_ERROR_TYPE_ERROR, "Unable to connect to local testbed-barrier service\n"); GNUNET_TESTBED_barrier_wait_cancel (h); return NULL; } - name_len = strlen (name); - msize = sizeof (struct GNUNET_TESTBED_BarrierWait) + name_len; - msg = GNUNET_malloc (msize); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT); - msg->header.size = htons (msize); - (void) memcpy (msg->name, name, name_len); - h->msg = &msg->header; - h->tx = - GNUNET_CLIENT_notify_transmit_ready (h->conn, msize, - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_NO, - &transmit_notify, - h); + name_len = strlen (name); /* NOTE: unusual to not have 0-termination, change? */ + env = GNUNET_MQ_msg_extra (msg, + name_len, + GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT); + memcpy (msg->name, + name, + name_len); + GNUNET_MQ_send (h->mq, + env); return h; } @@ -248,13 +242,12 @@ GNUNET_TESTBED_barrier_wait (const char *name, void GNUNET_TESTBED_barrier_wait_cancel (struct GNUNET_TESTBED_BarrierWaitHandle *h) { + if (NULL != h->mq) + { + GNUNET_MQ_destroy (h->mq); + h->mq = NULL; + } GNUNET_free (h->name); - if (NULL != h->tx) - GNUNET_CLIENT_notify_transmit_ready_cancel (h->tx); - if (NULL != h->conn) - GNUNET_CLIENT_disconnect (h->conn); - if (NULL != h->msg) - GNUNET_free (h->msg); GNUNET_CONFIGURATION_destroy (h->cfg); GNUNET_free (h); } -- 2.25.1