implemented send_message() callback function
[strongswan.git] / src / libcharon / tnc / tnccs / tnccs_manager.c
1 /*
2 * Copyright (C) 2010 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "tnccs_manager.h"
17
18 #include <debug.h>
19 #include <utils/linked_list.h>
20 #include <threading/rwlock.h>
21
22 typedef struct private_tnccs_manager_t private_tnccs_manager_t;
23 typedef struct tnccs_entry_t tnccs_entry_t;
24 typedef struct tnccs_connection_entry_t tnccs_connection_entry_t;
25
26 /**
27 * TNCCS constructor entry
28 */
29 struct tnccs_entry_t {
30
31 /**
32 * TNCCS protocol type
33 */
34 tnccs_type_t type;
35
36 /**
37 * constructor function to create instance
38 */
39 tnccs_constructor_t constructor;
40 };
41
42 /**
43 * TNCCS connection entry
44 */
45 struct tnccs_connection_entry_t {
46
47 /**
48 * TNCCS connection ID
49 */
50 TNC_ConnectionID id;
51
52 /**
53 * TNCCS instance
54 */
55 tnccs_t *tnccs;
56
57 /** TNCCS send message function
58 *
59 */
60 tnccs_send_message_t send_message;
61 };
62
63 /**
64 * private data of tnccs_manager
65 */
66 struct private_tnccs_manager_t {
67
68 /**
69 * public functions
70 */
71 tnccs_manager_t public;
72
73 /**
74 * list of TNCCS protocol entries
75 */
76 linked_list_t *protocols;
77
78 /**
79 * connection ID counter
80 */
81 TNC_ConnectionID connection_id;
82
83 /**
84 * list of TNCCS connection entries
85 */
86 linked_list_t *connections;
87
88 /**
89 * rwlock to lock TNCCS protocol and connection entries
90 */
91 rwlock_t *lock;
92
93 };
94
95 METHOD(tnccs_manager_t, add_method, void,
96 private_tnccs_manager_t *this, tnccs_type_t type,
97 tnccs_constructor_t constructor)
98 {
99 tnccs_entry_t *entry = malloc_thing(tnccs_entry_t);
100
101 entry->type = type;
102 entry->constructor = constructor;
103
104 this->lock->write_lock(this->lock);
105 this->protocols->insert_last(this->protocols, entry);
106 this->lock->unlock(this->lock);
107 }
108
109 METHOD(tnccs_manager_t, remove_method, void,
110 private_tnccs_manager_t *this, tnccs_constructor_t constructor)
111 {
112 enumerator_t *enumerator;
113 tnccs_entry_t *entry;
114
115 this->lock->write_lock(this->lock);
116 enumerator = this->protocols->create_enumerator(this->protocols);
117 while (enumerator->enumerate(enumerator, &entry))
118 {
119 if (constructor == entry->constructor)
120 {
121 this->protocols->remove_at(this->protocols, enumerator);
122 free(entry);
123 }
124 }
125 enumerator->destroy(enumerator);
126 this->lock->unlock(this->lock);
127 }
128
129 METHOD(tnccs_manager_t, create_instance, tnccs_t*,
130 private_tnccs_manager_t *this, tnccs_type_t type, bool is_server)
131 {
132 enumerator_t *enumerator;
133 tnccs_entry_t *entry;
134 tnccs_t *protocol = NULL;
135
136 this->lock->read_lock(this->lock);
137 enumerator = this->protocols->create_enumerator(this->protocols);
138 while (enumerator->enumerate(enumerator, &entry))
139 {
140 if (type == entry->type)
141 {
142 protocol = entry->constructor(is_server);
143 if (protocol)
144 {
145 break;
146 }
147 }
148 }
149 enumerator->destroy(enumerator);
150 this->lock->unlock(this->lock);
151 return protocol;
152 }
153
154 METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID,
155 private_tnccs_manager_t *this, tnccs_t *tnccs,
156 tnccs_send_message_t send_message)
157 {
158 tnccs_connection_entry_t *entry = malloc_thing(tnccs_connection_entry_t);
159
160 entry->id = ++this->connection_id;
161 entry->tnccs = tnccs;
162 entry->send_message = send_message;
163
164 this->lock->write_lock(this->lock);
165 this->connections->insert_last(this->connections, entry);
166 this->lock->unlock(this->lock);
167
168 DBG1(DBG_TNC, "assigned TNCCS Connection ID %u", entry->id);
169 return entry->id;
170 }
171
172 METHOD(tnccs_manager_t, remove_connection, void,
173 private_tnccs_manager_t *this, TNC_ConnectionID id)
174 {
175 enumerator_t *enumerator;
176 tnccs_connection_entry_t *entry;
177
178 this->lock->write_lock(this->lock);
179 enumerator = this->connections->create_enumerator(this->connections);
180 while (enumerator->enumerate(enumerator, &entry))
181 {
182 if (id == entry->id)
183 {
184 this->connections->remove_at(this->connections, enumerator);
185 free(entry);
186 DBG1(DBG_TNC, "removed TNCCS Connection ID %u", id);
187 }
188 }
189 enumerator->destroy(enumerator);
190 this->lock->unlock(this->lock);
191 }
192
193 METHOD(tnccs_manager_t, send_message, TNC_Result,
194 private_tnccs_manager_t *this, TNC_ConnectionID id,
195 TNC_BufferReference message,
196 TNC_UInt32 message_len,
197 TNC_MessageType message_type)
198 {
199 enumerator_t *enumerator;
200 tnccs_connection_entry_t *entry;
201 tnccs_send_message_t send_message;
202 tnccs_t *tnccs = NULL;
203
204 this->lock->write_lock(this->lock);
205 enumerator = this->connections->create_enumerator(this->connections);
206 while (enumerator->enumerate(enumerator, &entry))
207 {
208 if (id == entry->id)
209 {
210 tnccs = entry->tnccs;
211 send_message = entry->send_message;
212 break;
213 }
214 }
215 enumerator->destroy(enumerator);
216 this->lock->unlock(this->lock);
217
218 if (tnccs)
219 {
220 send_message(tnccs, message, message_len, message_type);
221 return TNC_RESULT_SUCCESS;
222 }
223 return TNC_RESULT_FATAL;
224 }
225
226 METHOD(tnccs_manager_t, destroy, void,
227 private_tnccs_manager_t *this)
228 {
229 this->protocols->destroy_function(this->protocols, free);
230 this->connections->destroy_function(this->connections, free);
231 this->lock->destroy(this->lock);
232 free(this);
233 }
234
235 /*
236 * See header
237 */
238 tnccs_manager_t *tnccs_manager_create()
239 {
240 private_tnccs_manager_t *this;
241
242 INIT(this,
243 .public = {
244 .add_method = _add_method,
245 .remove_method = _remove_method,
246 .create_instance = _create_instance,
247 .create_connection = _create_connection,
248 .remove_connection = _remove_connection,
249 .send_message = _send_message,
250 .destroy = _destroy,
251 },
252 .protocols = linked_list_create(),
253 .connections = linked_list_create(),
254 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
255 );
256
257 return &this->public;
258 }
259