Implement bus_t.listen() directly in controller_t (the only user).
This will hopefully allow us to later simplify bus_t.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2011 Tobias Brunner
|
||||||
* Copyright (C) 2007-2011 Martin Willi
|
* Copyright (C) 2007-2011 Martin Willi
|
||||||
* Copyright (C) 2011 revosec AG
|
* Copyright (C) 2011 revosec AG
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
@@ -23,7 +24,9 @@
|
|||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
#include <threading/mutex.h>
|
||||||
|
#include <threading/condvar.h>
|
||||||
|
#include <threading/thread.h>
|
||||||
|
|
||||||
typedef struct private_controller_t private_controller_t;
|
typedef struct private_controller_t private_controller_t;
|
||||||
typedef struct interface_listener_t interface_listener_t;
|
typedef struct interface_listener_t interface_listener_t;
|
||||||
@@ -88,6 +91,21 @@ struct interface_listener_t {
|
|||||||
* unique ID, used for various methods
|
* unique ID, used for various methods
|
||||||
*/
|
*/
|
||||||
u_int32_t id;
|
u_int32_t id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mutex to implement wait_for_listener()
|
||||||
|
*/
|
||||||
|
mutex_t *mutex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* condvar to wake a thread waiting in wait_for_listener()
|
||||||
|
*/
|
||||||
|
condvar_t *condvar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flag to indicate whether a listener is done
|
||||||
|
*/
|
||||||
|
bool done;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -109,6 +127,89 @@ struct interface_job_t {
|
|||||||
interface_listener_t listener;
|
interface_listener_t listener;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function properly unregisters a listener that is used
|
||||||
|
* with wait_for_listener()
|
||||||
|
*/
|
||||||
|
static inline bool listener_done(interface_listener_t *listener)
|
||||||
|
{
|
||||||
|
if (listener->mutex)
|
||||||
|
{
|
||||||
|
listener->mutex->lock(listener->mutex);
|
||||||
|
listener->condvar->signal(listener->condvar);
|
||||||
|
listener->done = TRUE;
|
||||||
|
listener->mutex->unlock(listener->mutex);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* thread_cleanup_t handler to unregister and cleanup a listener
|
||||||
|
*/
|
||||||
|
static void listener_cleanup(interface_listener_t *listener)
|
||||||
|
{
|
||||||
|
charon->bus->remove_listener(charon->bus, &listener->public);
|
||||||
|
listener->condvar->destroy(listener->condvar);
|
||||||
|
listener->mutex->destroy(listener->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the listener, executes the job and then waits synchronously until
|
||||||
|
* the listener is done or the timeout occured.
|
||||||
|
*
|
||||||
|
* @note Use 'return listener_done(listener)' to properly unregister a listener
|
||||||
|
*
|
||||||
|
* @returns TRUE in case of a timeout
|
||||||
|
*/
|
||||||
|
static bool wait_for_listener(interface_listener_t *listener, job_t *job,
|
||||||
|
u_int timeout)
|
||||||
|
{
|
||||||
|
bool old, timed_out = FALSE;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
listener->condvar = condvar_create(CONDVAR_TYPE_DEFAULT);
|
||||||
|
listener->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
|
||||||
|
|
||||||
|
charon->bus->add_listener(charon->bus, &listener->public);
|
||||||
|
lib->processor->queue_job(lib->processor, job);
|
||||||
|
|
||||||
|
listener->mutex->lock(listener->mutex);
|
||||||
|
thread_cleanup_push((thread_cleanup_t)listener_cleanup, listener);
|
||||||
|
thread_cleanup_push((thread_cleanup_t)listener->mutex->unlock,
|
||||||
|
listener->mutex);
|
||||||
|
old = thread_cancelability(TRUE);
|
||||||
|
while (!listener->done)
|
||||||
|
{
|
||||||
|
if (timeout)
|
||||||
|
{
|
||||||
|
if (listener->condvar->timed_wait_abs(listener->condvar,
|
||||||
|
listener->mutex, tv))
|
||||||
|
{
|
||||||
|
|
||||||
|
timed_out = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listener->condvar->wait(listener->condvar, listener->mutex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thread_cancelability(old);
|
||||||
|
/* unlock mutex */
|
||||||
|
thread_cleanup_pop(TRUE);
|
||||||
|
thread_cleanup_pop(TRUE);
|
||||||
|
return timed_out;
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(listener_t, listener_log, bool,
|
METHOD(listener_t, listener_log, bool,
|
||||||
interface_listener_t *this, debug_t group, level_t level, int thread,
|
interface_listener_t *this, debug_t group, level_t level, int thread,
|
||||||
ike_sa_t *ike_sa, char* format, va_list args)
|
ike_sa_t *ike_sa, char* format, va_list args)
|
||||||
@@ -117,7 +218,7 @@ METHOD(listener_t, listener_log, bool,
|
|||||||
{
|
{
|
||||||
if (!this->callback(this->param, group, level, ike_sa, format, args))
|
if (!this->callback(this->param, group, level, ike_sa, format, args))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return listener_done(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -144,7 +245,7 @@ METHOD(listener_t, ike_state_change, bool,
|
|||||||
if (peer_cfg->is_mediation(peer_cfg))
|
if (peer_cfg->is_mediation(peer_cfg))
|
||||||
{
|
{
|
||||||
this->status = SUCCESS;
|
this->status = SUCCESS;
|
||||||
return FALSE;
|
return listener_done(this);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -154,7 +255,7 @@ METHOD(listener_t, ike_state_change, bool,
|
|||||||
{ /* proper termination */
|
{ /* proper termination */
|
||||||
this->status = SUCCESS;
|
this->status = SUCCESS;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return listener_done(this);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -172,7 +273,7 @@ METHOD(listener_t, child_state_change, bool,
|
|||||||
{
|
{
|
||||||
case CHILD_INSTALLED:
|
case CHILD_INSTALLED:
|
||||||
this->status = SUCCESS;
|
this->status = SUCCESS;
|
||||||
return FALSE;
|
return listener_done(this);
|
||||||
case CHILD_DESTROYING:
|
case CHILD_DESTROYING:
|
||||||
switch (child_sa->get_state(child_sa))
|
switch (child_sa->get_state(child_sa))
|
||||||
{
|
{
|
||||||
@@ -183,7 +284,7 @@ METHOD(listener_t, child_state_change, bool,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return listener_done(this);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -278,8 +379,7 @@ METHOD(controller_t, initiate, status_t,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (charon->bus->listen(charon->bus, &job.listener.public, &job.public,
|
if (wait_for_listener(&job.listener, &job.public, timeout))
|
||||||
timeout))
|
|
||||||
{
|
{
|
||||||
job.listener.status = OUT_OF_RES;
|
job.listener.status = OUT_OF_RES;
|
||||||
}
|
}
|
||||||
@@ -348,8 +448,7 @@ METHOD(controller_t, terminate_ike, status_t,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (charon->bus->listen(charon->bus, &job.listener.public, &job.public,
|
if (wait_for_listener(&job.listener, &job.public, timeout))
|
||||||
timeout))
|
|
||||||
{
|
{
|
||||||
job.listener.status = OUT_OF_RES;
|
job.listener.status = OUT_OF_RES;
|
||||||
}
|
}
|
||||||
@@ -444,8 +543,7 @@ METHOD(controller_t, terminate_child, status_t,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (charon->bus->listen(charon->bus, &job.listener.public, &job.public,
|
if (wait_for_listener(&job.listener, &job.public, timeout))
|
||||||
timeout))
|
|
||||||
{
|
{
|
||||||
job.listener.status = OUT_OF_RES;
|
job.listener.status = OUT_OF_RES;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user