Annotation of embedaddon/strongswan/src/libcharon/network/socket_manager.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010-2012 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  * Copyright (C) 2010 Martin Willi
                      5:  * Copyright (C) 2010 revosec AG
                      6:  *
                      7:  * This program is free software; you can redistribute it and/or modify it
                      8:  * under the terms of the GNU General Public License as published by the
                      9:  * Free Software Foundation; either version 2 of the License, or (at your
                     10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     11:  *
                     12:  * This program is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     15:  * for more details.
                     16:  */
                     17: 
                     18: #include "socket_manager.h"
                     19: 
                     20: #include <daemon.h>
                     21: #include <threading/thread.h>
                     22: #include <threading/rwlock.h>
                     23: #include <collections/linked_list.h>
                     24: 
                     25: typedef struct private_socket_manager_t private_socket_manager_t;
                     26: 
                     27: /**
                     28:  * Private data of an socket_manager_t object.
                     29:  */
                     30: struct private_socket_manager_t {
                     31: 
                     32:        /**
                     33:         * Public socket_manager_t interface.
                     34:         */
                     35:        socket_manager_t public;
                     36: 
                     37:        /**
                     38:         * List of registered socket constructors
                     39:         */
                     40:        linked_list_t *sockets;
                     41: 
                     42:        /**
                     43:         * Instantiated socket implementation
                     44:         */
                     45:        socket_t *socket;
                     46: 
                     47:        /**
                     48:         * The constructor used to create the current socket
                     49:         */
                     50:        socket_constructor_t create;
                     51: 
                     52:        /**
                     53:         * Lock for sockets list
                     54:         */
                     55:        rwlock_t *lock;
                     56: };
                     57: 
                     58: METHOD(socket_manager_t, receiver, status_t,
                     59:        private_socket_manager_t *this, packet_t **packet)
                     60: {
                     61:        status_t status;
                     62:        this->lock->read_lock(this->lock);
                     63:        if (!this->socket)
                     64:        {
                     65:                DBG1(DBG_NET, "no socket implementation registered, receiving failed");
                     66:                this->lock->unlock(this->lock);
                     67:                return NOT_SUPPORTED;
                     68:        }
                     69:        /* receive is blocking and the thread can be cancelled */
                     70:        thread_cleanup_push((thread_cleanup_t)this->lock->unlock, this->lock);
                     71:        status = this->socket->receive(this->socket, packet);
                     72:        thread_cleanup_pop(TRUE);
                     73:        return status;
                     74: }
                     75: 
                     76: METHOD(socket_manager_t, sender, status_t,
                     77:        private_socket_manager_t *this, packet_t *packet)
                     78: {
                     79:        status_t status;
                     80:        this->lock->read_lock(this->lock);
                     81:        if (!this->socket)
                     82:        {
                     83:                DBG1(DBG_NET, "no socket implementation registered, sending failed");
                     84:                this->lock->unlock(this->lock);
                     85:                return NOT_SUPPORTED;
                     86:        }
                     87:        status = this->socket->send(this->socket, packet);
                     88:        this->lock->unlock(this->lock);
                     89:        return status;
                     90: }
                     91: 
                     92: METHOD(socket_manager_t, get_port, uint16_t,
                     93:        private_socket_manager_t *this, bool nat_t)
                     94: {
                     95:        uint16_t port = 0;
                     96:        this->lock->read_lock(this->lock);
                     97:        if (this->socket)
                     98:        {
                     99:                port = this->socket->get_port(this->socket, nat_t);
                    100:        }
                    101:        this->lock->unlock(this->lock);
                    102:        return port;
                    103: }
                    104: 
                    105: METHOD(socket_manager_t, supported_families, socket_family_t,
                    106:        private_socket_manager_t *this)
                    107: {
                    108:        socket_family_t families = SOCKET_FAMILY_NONE;
                    109:        this->lock->read_lock(this->lock);
                    110:        if (this->socket)
                    111:        {
                    112:                families = this->socket->supported_families(this->socket);
                    113:        }
                    114:        this->lock->unlock(this->lock);
                    115:        return families;
                    116: }
                    117: 
                    118: static void create_socket(private_socket_manager_t *this)
                    119: {
                    120:        socket_constructor_t create;
                    121:        /* remove constructors in order to avoid trying to create broken ones
                    122:         * multiple times */
                    123:        while (this->sockets->remove_first(this->sockets,
                    124:                                                                           (void**)&create) == SUCCESS)
                    125:        {
                    126:                this->socket = create();
                    127:                if (this->socket)
                    128:                {
                    129:                        this->create = create;
                    130:                        break;
                    131:                }
                    132:        }
                    133: }
                    134: 
                    135: METHOD(socket_manager_t, add_socket, void,
                    136:        private_socket_manager_t *this, socket_constructor_t create)
                    137: {
                    138:        this->lock->write_lock(this->lock);
                    139:        this->sockets->insert_last(this->sockets, create);
                    140:        if (!this->socket)
                    141:        {
                    142:                create_socket(this);
                    143:        }
                    144:        this->lock->unlock(this->lock);
                    145: }
                    146: 
                    147: METHOD(socket_manager_t, remove_socket, void,
                    148:        private_socket_manager_t *this, socket_constructor_t create)
                    149: {
                    150:        this->lock->write_lock(this->lock);
                    151:        this->sockets->remove(this->sockets, create, NULL);
                    152:        if (this->create == create)
                    153:        {
                    154:                this->socket->destroy(this->socket);
                    155:                this->socket = NULL;
                    156:                this->create = NULL;
                    157:                create_socket(this);
                    158:        }
                    159:        this->lock->unlock(this->lock);
                    160: }
                    161: 
                    162: METHOD(socket_manager_t, destroy, void,
                    163:        private_socket_manager_t *this)
                    164: {
                    165:        DESTROY_IF(this->socket);
                    166:        this->sockets->destroy(this->sockets);
                    167:        this->lock->destroy(this->lock);
                    168:        free(this);
                    169: }
                    170: 
                    171: /**
                    172:  * See header
                    173:  */
                    174: socket_manager_t *socket_manager_create()
                    175: {
                    176:        private_socket_manager_t *this;
                    177: 
                    178:        INIT(this,
                    179:                .public = {
                    180:                        .send = _sender,
                    181:                        .receive = _receiver,
                    182:                        .get_port = _get_port,
                    183:                        .supported_families = _supported_families,
                    184:                        .add_socket = _add_socket,
                    185:                        .remove_socket = _remove_socket,
                    186:                        .destroy = _destroy,
                    187:                },
                    188:                .sockets = linked_list_create(),
                    189:                .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
                    190:        );
                    191: 
                    192:        return &this->public;
                    193: }
                    194: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>