Deferred instantiation of socket implmentations until registration.
authorTobias Brunner <tobias@strongswan.org>
Fri, 15 Oct 2010 15:24:23 +0000 (17:24 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 15 Oct 2010 15:30:21 +0000 (17:30 +0200)
Instantiating the implementations on plugin load was problematic
in case multiple socket plugins were loaded. Now, the first one
registered is instantiated.

src/libcharon/network/socket.h
src/libcharon/network/socket_manager.c
src/libcharon/network/socket_manager.h
src/libcharon/plugins/socket_default/socket_default_plugin.c
src/libcharon/plugins/socket_default/socket_default_socket.c
src/libcharon/plugins/socket_default/socket_default_socket.h
src/libcharon/plugins/socket_dynamic/socket_dynamic_plugin.c
src/libcharon/plugins/socket_dynamic/socket_dynamic_socket.c
src/libcharon/plugins/socket_raw/socket_raw_plugin.c
src/libcharon/plugins/socket_raw/socket_raw_socket.c
src/libcharon/plugins/socket_raw/socket_raw_socket.h

index 5c5a4ed..51b2692 100644 (file)
@@ -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_ @}*/
index 0dbce4b..72a4543 100644 (file)
@@ -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);
index b33d5c7..94185d2 100644 (file)
@@ -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.
index 29549b0..b5dea68 100644 (file)
@@ -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;
 }
index 9834818..e956466 100644 (file)
@@ -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),
index 7550166..89aa6f4 100644 (file)
@@ -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);
 };
 
 /**
index eb3cbb9..a6ff14e 100644 (file)
@@ -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;
 }
index 861ebfd..74dba82 100644 (file)
@@ -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,
index 5b4c044..17a3a8d 100644 (file)
@@ -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;
 }
index 66bc785..f6e87a8 100644 (file)
@@ -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),
index 94cf666..23ff304 100644 (file)
@@ -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);
 };
 
 /**