diff options
11 files changed, 104 insertions, 78 deletions
diff --git a/src/libcharon/network/socket.h b/src/libcharon/network/socket.h index 5c5a4edfb..51b26920f 100644 --- a/src/libcharon/network/socket.h +++ b/src/libcharon/network/socket.h @@ -1,6 +1,7 @@ /* - * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger + * Copyright (C) 2006-2010 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -30,6 +31,11 @@ typedef struct socket_t socket_t; #include <utils/enumerator.h> /** + * Constructor prototype for sockets. + */ +typedef socket_t *(*socket_constructor_t)(); + +/** * Socket interface definition. */ struct socket_t { @@ -42,8 +48,8 @@ struct socket_t { * * @param packet pinter gets address from allocated packet_t * @return - * - SUCCESS when packet successfully received - * - FAILED when unable to receive + * - SUCCESS when packet successfully received + * - FAILED when unable to receive */ status_t (*receive) (socket_t *this, packet_t **packet); @@ -55,10 +61,15 @@ struct socket_t { * * @param packet packet_t to send * @return - * - SUCCESS when packet successfully sent - * - FAILED when unable to send + * - SUCCESS when packet successfully sent + * - FAILED when unable to send */ status_t (*send) (socket_t *this, packet_t *packet); + + /** + * Destroy a socket implementation. + */ + void (*destroy) (socket_t *this); }; #endif /** SOCKET_H_ @}*/ diff --git a/src/libcharon/network/socket_manager.c b/src/libcharon/network/socket_manager.c index 0dbce4b1b..72a454301 100644 --- a/src/libcharon/network/socket_manager.c +++ b/src/libcharon/network/socket_manager.c @@ -1,4 +1,6 @@ /* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperswil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -33,11 +35,21 @@ struct private_socket_manager_t { socket_manager_t public; /** - * List of registered socket + * List of registered socket constructors */ linked_list_t *sockets; /** + * Instantiated socket implementation + */ + socket_t *socket; + + /** + * The constructor used to create the current socket + */ + socket_constructor_t create; + + /** * Lock for sockets list */ rwlock_t *lock; @@ -46,11 +58,9 @@ struct private_socket_manager_t { METHOD(socket_manager_t, receiver, status_t, private_socket_manager_t *this, packet_t **packet) { - socket_t *socket; status_t status; - this->lock->read_lock(this->lock); - if (this->sockets->get_first(this->sockets, (void**)&socket) != SUCCESS) + if (!this->socket) { DBG1(DBG_NET, "no socket implementation registered, receiving failed"); this->lock->unlock(this->lock); @@ -58,7 +68,7 @@ METHOD(socket_manager_t, receiver, status_t, } /* receive is blocking and the thread can be cancelled */ thread_cleanup_push((thread_cleanup_t)this->lock->unlock, this->lock); - status = socket->receive(socket, packet); + status = this->socket->receive(this->socket, packet); thread_cleanup_pop(TRUE); return status; } @@ -66,40 +76,67 @@ METHOD(socket_manager_t, receiver, status_t, METHOD(socket_manager_t, sender, status_t, private_socket_manager_t *this, packet_t *packet) { - socket_t *socket; status_t status; - this->lock->read_lock(this->lock); - if (this->sockets->get_first(this->sockets, (void**)&socket) != SUCCESS) + if (!this->socket) { DBG1(DBG_NET, "no socket implementation registered, sending failed"); this->lock->unlock(this->lock); return NOT_SUPPORTED; } - status = socket->send(socket, packet); + status = this->socket->send(this->socket, packet); this->lock->unlock(this->lock); return status; } +static void create_socket(private_socket_manager_t *this) +{ + socket_constructor_t create; + /* remove constructors in order to avoid trying to create broken ones + * multiple times */ + while (this->sockets->remove_first(this->sockets, + (void**)&create) == SUCCESS) + { + this->socket = create(); + if (this->socket) + { + this->create = create; + break; + } + } +} + METHOD(socket_manager_t, add_socket, void, - private_socket_manager_t *this, socket_t *socket) + private_socket_manager_t *this, socket_constructor_t create) { this->lock->write_lock(this->lock); - this->sockets->insert_last(this->sockets, socket); + this->sockets->insert_last(this->sockets, create); + if (!this->socket) + { + create_socket(this); + } this->lock->unlock(this->lock); } METHOD(socket_manager_t, remove_socket, void, - private_socket_manager_t *this, socket_t *socket) + private_socket_manager_t *this, socket_constructor_t create) { this->lock->write_lock(this->lock); - this->sockets->remove(this->sockets, socket, NULL); + this->sockets->remove(this->sockets, create, NULL); + if (this->create == create) + { + this->socket->destroy(this->socket); + this->socket = NULL; + this->create = NULL; + create_socket(this); + } this->lock->unlock(this->lock); } METHOD(socket_manager_t, destroy, void, private_socket_manager_t *this) { + DESTROY_IF(this->socket); this->sockets->destroy(this->sockets); this->lock->destroy(this->lock); free(this); diff --git a/src/libcharon/network/socket_manager.h b/src/libcharon/network/socket_manager.h index b33d5c71c..94185d21c 100644 --- a/src/libcharon/network/socket_manager.h +++ b/src/libcharon/network/socket_manager.h @@ -1,4 +1,6 @@ /* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperswil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -51,14 +53,18 @@ struct socket_manager_t { status_t (*send) (socket_manager_t *this, packet_t *packet); /** - * Register a socket implementation. + * Register a socket constructor. + * + * @param create constructor for the socket */ - void (*add_socket)(socket_manager_t *this, socket_t *socket); + void (*add_socket)(socket_manager_t *this, socket_constructor_t create); /** - * Unregister a registered socket implementation. + * Unregister a registered socket constructor. + * + * @param create constructor for the socket */ - void (*remove_socket)(socket_manager_t *this, socket_t *socket); + void (*remove_socket)(socket_manager_t *this, socket_constructor_t create); /** * Destroy a socket_manager_t. diff --git a/src/libcharon/plugins/socket_default/socket_default_plugin.c b/src/libcharon/plugins/socket_default/socket_default_plugin.c index 29549b0b1..b5dea68b6 100644 --- a/src/libcharon/plugins/socket_default/socket_default_plugin.c +++ b/src/libcharon/plugins/socket_default/socket_default_plugin.c @@ -1,4 +1,6 @@ /* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperswil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -31,17 +33,13 @@ struct private_socket_default_plugin_t { */ socket_default_plugin_t public; - /** - * Socket instance. - */ - socket_default_socket_t *socket; }; METHOD(plugin_t, destroy, void, private_socket_default_plugin_t *this) { - charon->socket->remove_socket(charon->socket, &this->socket->socket); - this->socket->destroy(this->socket); + charon->socket->remove_socket(charon->socket, + (socket_constructor_t)socket_default_socket_create); free(this); } @@ -58,15 +56,10 @@ plugin_t *socket_default_plugin_create() .destroy = _destroy, }, }, - .socket = socket_default_socket_create(), ); - if (!this->socket) - { - free(this); - return NULL; - } - charon->socket->add_socket(charon->socket, &this->socket->socket); + charon->socket->add_socket(charon->socket, + (socket_constructor_t)socket_default_socket_create); return &this->public.plugin; } diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index 983481808..e95646643 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2009 Tobias Brunner + * Copyright (C) 2006-2010 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -546,7 +546,7 @@ static int open_socket(private_socket_default_socket_t *this, return skt; } -METHOD(socket_default_socket_t, destroy, void, +METHOD(socket_t, destroy, void, private_socket_default_socket_t *this) { if (this->ipv4) @@ -580,8 +580,8 @@ socket_default_socket_t *socket_default_socket_create() .socket = { .send = _sender, .receive = _receiver, + .destroy = _destroy, }, - .destroy = _destroy, }, .max_packet = lib->settings->get_int(lib->settings, "charon.max_packet", MAX_PACKET), diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.h b/src/libcharon/plugins/socket_default/socket_default_socket.h index 755016662..89aa6f435 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.h +++ b/src/libcharon/plugins/socket_default/socket_default_socket.h @@ -35,10 +35,6 @@ struct socket_default_socket_t { */ socket_t socket; - /** - * Destroy a socket_default_socket_t. - */ - void (*destroy)(socket_default_socket_t *this); }; /** diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c index eb3cbb9d6..a6ff14efd 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c @@ -1,4 +1,6 @@ /* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperswil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -31,17 +33,13 @@ struct private_socket_dynamic_plugin_t { */ socket_dynamic_plugin_t public; - /** - * Socket instance. - */ - socket_dynamic_socket_t *socket; }; METHOD(plugin_t, destroy, void, private_socket_dynamic_plugin_t *this) { - charon->socket->remove_socket(charon->socket, &this->socket->socket); - this->socket->destroy(this->socket); + charon->socket->remove_socket(charon->socket, + (socket_constructor_t)socket_dynamic_socket_create); free(this); } @@ -58,15 +56,10 @@ plugin_t *socket_dynamic_plugin_create() .destroy = _destroy, }, }, - .socket = socket_dynamic_socket_create(), ); - if (!this->socket) - { - free(this); - return NULL; - } - charon->socket->add_socket(charon->socket, &this->socket->socket); + charon->socket->add_socket(charon->socket, + (socket_constructor_t)socket_dynamic_socket_create); return &this->public.plugin; } diff --git a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c index 861ebfd6f..74dba82cc 100644 --- a/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c +++ b/src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2009 Tobias Brunner + * Copyright (C) 2006-2010 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -572,7 +572,7 @@ METHOD(socket_t, sender, status_t, return SUCCESS; } -METHOD(socket_dynamic_socket_t, destroy, void, +METHOD(socket_t, destroy, void, private_socket_dynamic_socket_t *this) { enumerator_t *enumerator; @@ -605,8 +605,8 @@ socket_dynamic_socket_t *socket_dynamic_socket_create() .socket = { .send = _sender, .receive = _receiver, + .destroy = _destroy, }, - .destroy = _destroy, }, .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), .max_packet = lib->settings->get_int(lib->settings, diff --git a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c b/src/libcharon/plugins/socket_raw/socket_raw_plugin.c index 5b4c044f6..17a3a8db7 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_plugin.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_plugin.c @@ -1,4 +1,6 @@ /* + * Copyright (C) 2010 Tobias Brunner + * Hochschule fuer Technik Rapperswil * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -31,17 +33,13 @@ struct private_socket_raw_plugin_t { */ socket_raw_plugin_t public; - /** - * Raw socket instance. - */ - socket_raw_socket_t *socket; }; METHOD(plugin_t, destroy, void, private_socket_raw_plugin_t *this) { - charon->socket->remove_socket(charon->socket, &this->socket->socket); - this->socket->destroy(this->socket); + charon->socket->remove_socket(charon->socket, + (socket_constructor_t)socket_raw_socket_create); free(this); } @@ -58,15 +56,10 @@ plugin_t *socket_raw_plugin_create() .destroy = _destroy, }, }, - .socket = socket_raw_socket_create(), ); - if (!this->socket) - { - free(this); - return NULL; - } - charon->socket->add_socket(charon->socket, &this->socket->socket); + charon->socket->add_socket(charon->socket, + (socket_constructor_t)socket_raw_socket_create); return &this->public.plugin; } diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.c b/src/libcharon/plugins/socket_raw/socket_raw_socket.c index 66bc78526..f6e87a86f 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.c +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.c @@ -1,6 +1,7 @@ /* - * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger + * Copyright (C) 2006-2010 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi + * Copyright (C) 2006 Daniel Roethlisberger * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -612,7 +613,7 @@ static int open_recv_socket(private_socket_raw_socket_t *this, int family) return skt; } -METHOD(socket_raw_socket_t, destroy, void, +METHOD(socket_t, destroy, void, private_socket_raw_socket_t *this) { if (this->recv4) @@ -654,8 +655,8 @@ socket_raw_socket_t *socket_raw_socket_create() .socket = { .send = _sender, .receive = _receiver, + .destroy = _destroy, }, - .destroy = _destroy, }, .max_packet = lib->settings->get_int(lib->settings, "charon.max_packet", MAX_PACKET), diff --git a/src/libcharon/plugins/socket_raw/socket_raw_socket.h b/src/libcharon/plugins/socket_raw/socket_raw_socket.h index 94cf666e8..23ff304a8 100644 --- a/src/libcharon/plugins/socket_raw/socket_raw_socket.h +++ b/src/libcharon/plugins/socket_raw/socket_raw_socket.h @@ -41,10 +41,6 @@ struct socket_raw_socket_t { */ socket_t socket; - /** - * Destroy a socket_raw_socket_t. - */ - void (*destroy)(socket_raw_socket_t *this); }; /** |