Annotation of embedaddon/strongswan/src/libcharon/network/socket_manager.c, revision 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>