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>