added connection management to TNCCS manager
[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
58 /**
59 * private data of tnccs_manager
60 */
61 struct private_tnccs_manager_t {
62
63 /**
64 * public functions
65 */
66 tnccs_manager_t public;
67
68 /**
69 * list of TNCCS protocol entries
70 */
71 linked_list_t *protocols;
72
73 /**
74 * connection ID counter
75 */
76 TNC_ConnectionID connection_id;
77
78 /**
79 * list of TNCCS connection entries
80 */
81 linked_list_t *connections;
82
83 /**
84 * rwlock to lock TNCCS protocol and connection entries
85 */
86 rwlock_t *lock;
87
88 };
89
90 METHOD(tnccs_manager_t, add_method, void,
91 private_tnccs_manager_t *this, tnccs_type_t type,
92 tnccs_constructor_t constructor)
93 {
94 tnccs_entry_t *entry = malloc_thing(tnccs_entry_t);
95
96 entry->type = type;
97 entry->constructor = constructor;
98
99 this->lock->write_lock(this->lock);
100 this->protocols->insert_last(this->protocols, entry);
101 this->lock->unlock(this->lock);
102 }
103
104 METHOD(tnccs_manager_t, remove_method, void,
105 private_tnccs_manager_t *this, tnccs_constructor_t constructor)
106 {
107 enumerator_t *enumerator;
108 tnccs_entry_t *entry;
109
110 this->lock->write_lock(this->lock);
111 enumerator = this->protocols->create_enumerator(this->protocols);
112 while (enumerator->enumerate(enumerator, &entry))
113 {
114 if (constructor == entry->constructor)
115 {
116 this->protocols->remove_at(this->protocols, enumerator);
117 free(entry);
118 }
119 }
120 enumerator->destroy(enumerator);
121 this->lock->unlock(this->lock);
122 }
123
124 METHOD(tnccs_manager_t, create_instance, tnccs_t*,
125 private_tnccs_manager_t *this, tnccs_type_t type, bool is_server)
126 {
127 enumerator_t *enumerator;
128 tnccs_entry_t *entry;
129 tnccs_t *protocol = NULL;
130
131 this->lock->read_lock(this->lock);
132 enumerator = this->protocols->create_enumerator(this->protocols);
133 while (enumerator->enumerate(enumerator, &entry))
134 {
135 if (type == entry->type)
136 {
137 protocol = entry->constructor(is_server);
138 if (protocol)
139 {
140 break;
141 }
142 }
143 }
144 enumerator->destroy(enumerator);
145 this->lock->unlock(this->lock);
146 return protocol;
147 }
148
149 METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID,
150 private_tnccs_manager_t *this, tnccs_t *tnccs)
151 {
152 tnccs_connection_entry_t *entry = malloc_thing(tnccs_connection_entry_t);
153
154 entry->id = ++this->connection_id;
155 entry->tnccs = tnccs;
156
157 this->lock->write_lock(this->lock);
158 this->connections->insert_last(this->connections, entry);
159 this->lock->unlock(this->lock);
160
161 DBG1(DBG_TNC, "assigned TNCCS Connection ID %u", entry->id);
162 return entry->id;
163 }
164
165 METHOD(tnccs_manager_t, remove_connection, void,
166 private_tnccs_manager_t *this, TNC_ConnectionID id)
167 {
168 enumerator_t *enumerator;
169 tnccs_connection_entry_t *entry;
170
171 this->lock->write_lock(this->lock);
172 enumerator = this->connections->create_enumerator(this->connections);
173 while (enumerator->enumerate(enumerator, &entry))
174 {
175 if (id == entry->id)
176 {
177 this->connections->remove_at(this->connections, enumerator);
178 free(entry);
179 DBG1(DBG_TNC, "removed TNCCS Connection ID %u", id);
180 }
181 }
182 enumerator->destroy(enumerator);
183 this->lock->unlock(this->lock);
184 }
185
186 METHOD(tnccs_manager_t, destroy, void,
187 private_tnccs_manager_t *this)
188 {
189 this->protocols->destroy_function(this->protocols, free);
190 this->connections->destroy_function(this->connections, free);
191 this->lock->destroy(this->lock);
192 free(this);
193 }
194
195 /*
196 * See header
197 */
198 tnccs_manager_t *tnccs_manager_create()
199 {
200 private_tnccs_manager_t *this;
201
202 INIT(this,
203 .public = {
204 .add_method = _add_method,
205 .remove_method = _remove_method,
206 .create_instance = _create_instance,
207 .create_connection = _create_connection,
208 .remove_connection = _remove_connection,
209 .destroy = _destroy,
210 },
211 .protocols = linked_list_create(),
212 .connections = linked_list_create(),
213 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
214 );
215
216 return &this->public;
217 }
218