From 8e3f14baab65317ea7a1ba6bc7543b7e5aa116f8 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Fri, 26 Aug 2011 10:42:42 +0200 Subject: [PATCH] bus->listen() and the controller wrappers accept a timeout to wait for callbacks --- src/conftest/actions.c | 7 ++--- src/libcharon/bus/bus.c | 30 +++++++++++++++++++--- src/libcharon/bus/bus.h | 4 ++- src/libcharon/control/controller.c | 25 +++++++++++++----- src/libcharon/control/controller.h | 14 +++++++--- .../plugins/load_tester/load_tester_plugin.c | 2 +- src/libcharon/plugins/maemo/maemo_service.c | 2 +- src/libcharon/plugins/medcli/medcli_config.c | 2 +- src/libcharon/plugins/nm/nm_service.c | 2 +- src/libcharon/plugins/smp/smp.c | 10 ++++---- src/libcharon/plugins/stroke/stroke_control.c | 16 ++++++------ src/libcharon/plugins/uci/uci_control.c | 6 ++--- .../processing/jobs/initiate_mediation_job.c | 2 +- src/libcharon/processing/jobs/start_action_job.c | 2 +- 14 files changed, 85 insertions(+), 39 deletions(-) diff --git a/src/conftest/actions.c b/src/conftest/actions.c index 1844d0c..7532e95 100644 --- a/src/conftest/actions.c +++ b/src/conftest/actions.c @@ -65,7 +65,7 @@ static job_requeue_t initiate(char *config) { DBG1(DBG_CFG, "initiating IKE_SA for CHILD_SA config '%s'", config); charon->controller->initiate(charon->controller, peer_cfg, child_cfg, - NULL, NULL); + NULL, NULL, 0); } else { @@ -207,7 +207,7 @@ static job_requeue_t close_ike(char *config) if (id) { DBG1(DBG_CFG, "closing IKE_SA '%s'", config); - charon->controller->terminate_ike(charon->controller, id, NULL, NULL); + charon->controller->terminate_ike(charon->controller, id, NULL, NULL, 0); } else { @@ -246,7 +246,8 @@ static job_requeue_t close_child(char *config) if (id) { DBG1(DBG_CFG, "closing CHILD_SA '%s'", config); - charon->controller->terminate_child(charon->controller, id, NULL, NULL); + charon->controller->terminate_child(charon->controller, id, + NULL, NULL, 0); } else { diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c index f2f59d7..74bd0ec 100644 --- a/src/libcharon/bus/bus.c +++ b/src/libcharon/bus/bus.c @@ -151,11 +151,20 @@ static void listener_cleanup(cleanup_data_t *data) entry_destroy(data->entry); } -METHOD(bus_t, listen_, void, - private_bus_t *this, listener_t *listener, job_t *job) +METHOD(bus_t, listen_, bool, + private_bus_t *this, listener_t *listener, job_t *job, u_int timeout) { - bool old; + bool old, timed_out = FALSE; cleanup_data_t data; + timeval_t tv, add; + + if (timeout) + { + add.tv_sec = timeout / 1000; + add.tv_usec = (timeout - (add.tv_sec * 1000)) * 1000; + time_monotonic(&tv); + timeradd(&tv, &add, &tv); + } data.this = this; data.entry = entry_create(listener, TRUE); @@ -168,13 +177,26 @@ METHOD(bus_t, listen_, void, old = thread_cancelability(TRUE); while (data.entry->blocker) { - data.entry->condvar->wait(data.entry->condvar, this->mutex); + if (timeout) + { + if (data.entry->condvar->timed_wait_abs(data.entry->condvar, + this->mutex, tv)) + { + timed_out = TRUE; + break; + } + } + else + { + data.entry->condvar->wait(data.entry->condvar, this->mutex); + } } thread_cancelability(old); thread_cleanup_pop(FALSE); /* unlock mutex */ thread_cleanup_pop(TRUE); entry_destroy(data.entry); + return timed_out; } METHOD(bus_t, set_sa, void, diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h index 2ade796..69060d3 100644 --- a/src/libcharon/bus/bus.h +++ b/src/libcharon/bus/bus.h @@ -152,8 +152,10 @@ struct bus_t { * * @param listener listener to register * @param job job to execute asynchronously when registered, or NULL + * @param timeout max timeout in ms to listen for events, 0 to disable + * @return TRUE if timed out */ - void (*listen)(bus_t *this, listener_t *listener, job_t *job); + bool (*listen)(bus_t *this, listener_t *listener, job_t *job, u_int timeout); /** * Set the IKE_SA the calling thread is using. diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c index 5317971..0f24796 100644 --- a/src/libcharon/control/controller.c +++ b/src/libcharon/control/controller.c @@ -240,7 +240,7 @@ METHOD(job_t, initiate_execute, void, METHOD(controller_t, initiate, status_t, private_controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, - controller_cb_t callback, void *param) + controller_cb_t callback, void *param, u_int timeout) { interface_job_t job = { .listener = { @@ -267,7 +267,11 @@ METHOD(controller_t, initiate, status_t, } else { - charon->bus->listen(charon->bus, &job.listener.public, &job.public); + if (charon->bus->listen(charon->bus, &job.listener.public, &job.public, + timeout)) + { + job.listener.status = OUT_OF_RES; + } } return job.listener.status; } @@ -296,7 +300,7 @@ METHOD(job_t, terminate_ike_execute, void, METHOD(controller_t, terminate_ike, status_t, controller_t *this, u_int32_t unique_id, - controller_cb_t callback, void *param) + controller_cb_t callback, void *param, u_int timeout) { ike_sa_t *ike_sa; interface_job_t job = { @@ -333,7 +337,11 @@ METHOD(controller_t, terminate_ike, status_t, } else { - charon->bus->listen(charon->bus, &job.listener.public, &job.public); + if (charon->bus->listen(charon->bus, &job.listener.public, &job.public, + timeout)) + { + job.listener.status = OUT_OF_RES; + } /* checkin of the ike_sa happened in the thread that executed the job */ charon->bus->set_sa(charon->bus, NULL); } @@ -363,7 +371,8 @@ METHOD(job_t, terminate_child_execute, void, } METHOD(controller_t, terminate_child, status_t, - controller_t *this, u_int32_t reqid, controller_cb_t callback, void *param) + controller_t *this, u_int32_t reqid, + controller_cb_t callback, void *param, u_int timeout) { ike_sa_t *ike_sa; child_sa_t *child_sa; @@ -424,7 +433,11 @@ METHOD(controller_t, terminate_child, status_t, } else { - charon->bus->listen(charon->bus, &job.listener.public, &job.public); + if (charon->bus->listen(charon->bus, &job.listener.public, &job.public, + timeout)) + { + job.listener.status = OUT_OF_RES; + } /* checkin of the ike_sa happened in the thread that executed the job */ charon->bus->set_sa(charon->bus, NULL); } diff --git a/src/libcharon/control/controller.h b/src/libcharon/control/controller.h index 81c83d9..6adaef1 100644 --- a/src/libcharon/control/controller.h +++ b/src/libcharon/control/controller.h @@ -83,14 +83,16 @@ struct controller_t { * @param child_cfg child_cfg to set up CHILD_SA from * @param cb logging callback * @param param parameter to include in each call of cb + * @param timeout timeout in ms to wait for callbacks, 0 to disable * @return * - SUCCESS, if CHILD_SA established * - FAILED, if setup failed * - NEED_MORE, if callback returned FALSE + * - OUT_OF_RES if timed out */ status_t (*initiate)(controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, - controller_cb_t callback, void *param); + controller_cb_t callback, void *param, u_int timeout); /** * Terminate an IKE_SA and all of its CHILD_SAs. @@ -102,13 +104,16 @@ struct controller_t { * @param unique_id unique id of the IKE_SA to terminate. * @param cb logging callback * @param param parameter to include in each call of cb + * @param timeout timeout in ms to wait for callbacks, 0 to disable * @return * - SUCCESS, if CHILD_SA terminated * - NOT_FOUND, if no such CHILD_SA found * - NEED_MORE, if callback returned FALSE + * - OUT_OF_RES if timed out */ status_t (*terminate_ike)(controller_t *this, u_int32_t unique_id, - controller_cb_t callback, void *param); + controller_cb_t callback, void *param, + u_int timeout); /** * Terminate a CHILD_SA. @@ -116,13 +121,16 @@ struct controller_t { * @param reqid reqid of the CHILD_SA to terminate * @param cb logging callback * @param param parameter to include in each call of cb + * @param timeout timeout in ms to wait for callbacks, 0 to disable * @return * - SUCCESS, if CHILD_SA terminated * - NOT_FOUND, if no such CHILD_SA found * - NEED_MORE, if callback returned FALSE + * - OUT_OF_RES if timed out */ status_t (*terminate_child)(controller_t *this, u_int32_t reqid, - controller_cb_t callback, void *param); + controller_cb_t callback, void *param, + u_int timeout); /** * Destroy a controller_t instance. diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c index f274022..b260a97 100644 --- a/src/libcharon/plugins/load_tester/load_tester_plugin.c +++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c @@ -148,7 +148,7 @@ static job_requeue_t do_load_test(private_load_tester_plugin_t *this) charon->controller->initiate(charon->controller, peer_cfg, child_cfg->get_ref(child_cfg), - NULL, NULL); + NULL, NULL, 0); if (s) { sleep(s); diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c index d6ba8fa..6675e1d 100644 --- a/src/libcharon/plugins/maemo/maemo_service.c +++ b/src/libcharon/plugins/maemo/maemo_service.c @@ -217,7 +217,7 @@ static void disconnect(private_maemo_service_t *this) id = ike_sa->get_unique_id(ike_sa); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); charon->controller->terminate_ike(charon->controller, id, - NULL, NULL); + NULL, NULL, 0); } this->current = (g_free(this->current), NULL); this->status = VPN_STATUS_DISCONNECTED; diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c index 52bbd6d..cc6662b 100644 --- a/src/libcharon/plugins/medcli/medcli_config.c +++ b/src/libcharon/plugins/medcli/medcli_config.c @@ -335,7 +335,7 @@ static job_requeue_t initiate_config(peer_cfg_t *peer_cfg) peer_cfg->get_ref(peer_cfg); enumerator->destroy(enumerator); charon->controller->initiate(charon->controller, - peer_cfg, child_cfg, NULL, NULL); + peer_cfg, child_cfg, NULL, NULL, 0); } else { diff --git a/src/libcharon/plugins/nm/nm_service.c b/src/libcharon/plugins/nm/nm_service.c index 65218d0..a6783fc 100644 --- a/src/libcharon/plugins/nm/nm_service.c +++ b/src/libcharon/plugins/nm/nm_service.c @@ -640,7 +640,7 @@ static gboolean disconnect(NMVPNPlugin *plugin, GError **err) id = ike_sa->get_unique_id(ike_sa); enumerator->destroy(enumerator); charon->controller->terminate_ike(charon->controller, id, - controller_cb_empty, NULL); + controller_cb_empty, NULL, 0); return TRUE; } } diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c index ea54dbf..68935aa 100644 --- a/src/libcharon/plugins/smp/smp.c +++ b/src/libcharon/plugins/smp/smp.c @@ -421,14 +421,14 @@ static void request_control_terminate(xmlTextReaderPtr reader, if (ike) { status = charon->controller->terminate_ike( - charon->controller, id, - (controller_cb_t)xml_callback, writer); + charon->controller, id, + (controller_cb_t)xml_callback, writer, 0); } else { status = charon->controller->terminate_child( - charon->controller, id, - (controller_cb_t)xml_callback, writer); + charon->controller, id, + (controller_cb_t)xml_callback, writer, 0); } /* */ xmlTextWriterEndElement(writer); @@ -490,7 +490,7 @@ static void request_control_initiate(xmlTextReaderPtr reader, { status = charon->controller->initiate(charon->controller, peer, child, (controller_cb_t)xml_callback, - writer); + writer, 0); } else { diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c index 972606d..f0d8f3b 100644 --- a/src/libcharon/plugins/stroke/stroke_control.c +++ b/src/libcharon/plugins/stroke/stroke_control.c @@ -103,14 +103,14 @@ static void charon_initiate(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, if (msg->output_verbosity < 0) { charon->controller->initiate(charon->controller, peer_cfg, child_cfg, - NULL, NULL); + NULL, NULL, 0); } else { stroke_log_info_t info = { msg->output_verbosity, out }; charon->controller->initiate(charon->controller, peer_cfg, child_cfg, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } } @@ -277,12 +277,12 @@ METHOD(stroke_control_t, terminate, void, if (child) { charon->controller->terminate_child(charon->controller, id, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } else { charon->controller->terminate_ike(charon->controller, id, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } return; } @@ -333,7 +333,7 @@ METHOD(stroke_control_t, terminate, void, while (enumerator->enumerate(enumerator, &del)) { charon->controller->terminate_child(charon->controller, del, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } enumerator->destroy(enumerator); @@ -341,7 +341,7 @@ METHOD(stroke_control_t, terminate, void, while (enumerator->enumerate(enumerator, &del)) { charon->controller->terminate_ike(charon->controller, del, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } enumerator->destroy(enumerator); @@ -515,7 +515,7 @@ METHOD(stroke_control_t, purge_ike, void, while (enumerator->enumerate(enumerator, &del)) { charon->controller->terminate_ike(charon->controller, del, - (controller_cb_t)stroke_log, &info); + (controller_cb_t)stroke_log, &info, 0); } enumerator->destroy(enumerator); list->destroy(list); @@ -544,7 +544,7 @@ static void charon_route(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg, } } else - { + { if (charon->traps->install(charon->traps, peer_cfg, child_cfg)) { fprintf(out, "'%s' routed\n", name); diff --git a/src/libcharon/plugins/uci/uci_control.c b/src/libcharon/plugins/uci/uci_control.c index caf8acf..bb08de2 100644 --- a/src/libcharon/plugins/uci/uci_control.c +++ b/src/libcharon/plugins/uci/uci_control.c @@ -148,8 +148,8 @@ static void initiate(private_uci_control_t *this, char *name) enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); if (enumerator->enumerate(enumerator, &child_cfg) && charon->controller->initiate(charon->controller, peer_cfg, - child_cfg->get_ref(child_cfg), - controller_cb_empty, NULL) == SUCCESS) + child_cfg->get_ref(child_cfg), + controller_cb_empty, NULL, 0) == SUCCESS) { write_fifo(this, "connection '%s' established\n", name); } @@ -183,7 +183,7 @@ static void terminate(private_uci_control_t *this, char *name) id = ike_sa->get_unique_id(ike_sa); enumerator->destroy(enumerator); charon->controller->terminate_ike(charon->controller, id, - controller_cb_empty, NULL); + controller_cb_empty, NULL, 0); write_fifo(this, "connection '%s' terminated\n", name); return; } diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.c b/src/libcharon/processing/jobs/initiate_mediation_job.c index b310c81..183484a 100644 --- a/src/libcharon/processing/jobs/initiate_mediation_job.c +++ b/src/libcharon/processing/jobs/initiate_mediation_job.c @@ -126,7 +126,7 @@ static void initiate(private_initiate_mediation_job_t *this) mediation_cfg->get_ref(mediation_cfg); if (charon->controller->initiate(charon->controller, mediation_cfg, - NULL, (controller_cb_t)initiate_callback, this) != SUCCESS) + NULL, (controller_cb_t)initiate_callback, this, 0) != SUCCESS) { mediation_cfg->destroy(mediation_cfg); mediated_cfg->destroy(mediated_cfg); diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c index 8f924bc..35f70e1 100644 --- a/src/libcharon/processing/jobs/start_action_job.c +++ b/src/libcharon/processing/jobs/start_action_job.c @@ -66,7 +66,7 @@ METHOD(job_t, execute, void, charon->controller->initiate(charon->controller, peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg), - NULL, NULL); + NULL, NULL, 0); break; case ACTION_ROUTE: DBG1(DBG_JOB, "start action: route '%s'", name); -- 2.7.4