2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
16 #include "attribute_manager.h"
19 #include <utils/linked_list.h>
20 #include <threading/rwlock.h>
22 typedef struct private_attribute_manager_t private_attribute_manager_t
;
25 * private data of attribute_manager
27 struct private_attribute_manager_t
{
32 attribute_manager_t
public;
35 * list of registered providers
37 linked_list_t
*providers
;
40 * list of registered handlers
42 linked_list_t
*handlers
;
45 * rwlock provider list
51 * Data to pass to enumerator filters
54 /** server/peer identity */
56 /** requesting/assigned virtual IP */
61 * Implementation of attribute_manager_t.acquire_address.
63 static host_t
* acquire_address(private_attribute_manager_t
*this,
64 char *pool
, identification_t
*id
,
67 enumerator_t
*enumerator
;
68 attribute_provider_t
*current
;
71 this->lock
->read_lock(this->lock
);
72 enumerator
= this->providers
->create_enumerator(this->providers
);
73 while (enumerator
->enumerate(enumerator
, ¤t
))
75 host
= current
->acquire_address(current
, pool
, id
, requested
);
81 enumerator
->destroy(enumerator
);
82 this->lock
->unlock(this->lock
);
86 DBG1(DBG_CFG
, "acquiring address from pool '%s' failed", pool
);
92 * Implementation of attribute_manager_t.release_address.
94 static void release_address(private_attribute_manager_t
*this,
95 char *pool
, host_t
*address
, identification_t
*id
)
97 enumerator_t
*enumerator
;
98 attribute_provider_t
*current
;
101 this->lock
->read_lock(this->lock
);
102 enumerator
= this->providers
->create_enumerator(this->providers
);
103 while (enumerator
->enumerate(enumerator
, ¤t
))
105 if (current
->release_address(current
, pool
, address
, id
))
111 enumerator
->destroy(enumerator
);
112 this->lock
->unlock(this->lock
);
116 DBG1(DBG_CFG
, "releasing address to pool '%s' failed", pool
);
121 * inner enumerator constructor for responder attributes
123 static enumerator_t
*responder_enum_create(attribute_provider_t
*provider
,
126 return provider
->create_attribute_enumerator(provider
, data
->id
, data
->vip
);
130 * Implementation of attribute_manager_t.create_responder_enumerator
132 static enumerator_t
* create_responder_enumerator(
133 private_attribute_manager_t
*this, identification_t
*id
, host_t
*vip
)
135 enum_data_t
*data
= malloc_thing(enum_data_t
);
139 this->lock
->read_lock(this->lock
);
140 return enumerator_create_cleaner(
141 enumerator_create_nested(
142 this->providers
->create_enumerator(this->providers
),
143 (void*)responder_enum_create
, data
, free
),
144 (void*)this->lock
->unlock
, this->lock
);
148 * Implementation of attribute_manager_t.add_provider.
150 static void add_provider(private_attribute_manager_t
*this,
151 attribute_provider_t
*provider
)
153 this->lock
->write_lock(this->lock
);
154 this->providers
->insert_last(this->providers
, provider
);
155 this->lock
->unlock(this->lock
);
159 * Implementation of attribute_manager_t.remove_provider.
161 static void remove_provider(private_attribute_manager_t
*this,
162 attribute_provider_t
*provider
)
164 this->lock
->write_lock(this->lock
);
165 this->providers
->remove(this->providers
, provider
, NULL
);
166 this->lock
->unlock(this->lock
);
170 * Implementation of attribute_manager_t.handle
172 static attribute_handler_t
* handle(private_attribute_manager_t
*this,
173 identification_t
*server
, attribute_handler_t
*handler
,
174 configuration_attribute_type_t type
, chunk_t data
)
176 enumerator_t
*enumerator
;
177 attribute_handler_t
*current
, *handled
= NULL
;
179 this->lock
->read_lock(this->lock
);
181 /* try to find the passed handler */
182 enumerator
= this->handlers
->create_enumerator(this->handlers
);
183 while (enumerator
->enumerate(enumerator
, ¤t
))
185 if (current
== handler
&& current
->handle(current
, server
, type
, data
))
191 enumerator
->destroy(enumerator
);
193 { /* handler requesting this attribute not found, try any other */
194 enumerator
= this->handlers
->create_enumerator(this->handlers
);
195 while (enumerator
->enumerate(enumerator
, ¤t
))
197 if (current
->handle(current
, server
, type
, data
))
203 enumerator
->destroy(enumerator
);
205 this->lock
->unlock(this->lock
);
209 DBG1(DBG_CFG
, "handling %N attribute failed",
210 configuration_attribute_type_names
, type
);
216 * Implementation of attribute_manager_t.release
218 static void release(private_attribute_manager_t
*this,
219 attribute_handler_t
*handler
,
220 identification_t
*server
,
221 configuration_attribute_type_t type
, chunk_t data
)
223 enumerator_t
*enumerator
;
224 attribute_handler_t
*current
;
226 this->lock
->read_lock(this->lock
);
227 enumerator
= this->handlers
->create_enumerator(this->handlers
);
228 while (enumerator
->enumerate(enumerator
, ¤t
))
230 if (current
== handler
)
232 current
->release(current
, server
, type
, data
);
236 enumerator
->destroy(enumerator
);
237 this->lock
->unlock(this->lock
);
241 * Enumerator implementation to enumerate nested initiator attributes
244 /** implements enumerator_t */
247 private_attribute_manager_t
*this;
248 /** currently processing handler */
249 attribute_handler_t
*handler
;
250 /** outer enumerator over handlers */
252 /** inner enumerator over current handlers attributes */
254 /** server ID we want attributes for */
255 identification_t
*id
;
256 /** virtual IP we are requesting along with attriubutes */
258 } initiator_enumerator_t
;
261 * Enumerator implementation for initiator attributes
263 static bool initiator_enumerate(initiator_enumerator_t
*this,
264 attribute_handler_t
**handler
,
265 configuration_attribute_type_t
*type
,
268 /* enumerate inner attributes using outer handler enumerator */
269 while (!this->inner
|| !this->inner
->enumerate(this->inner
, type
, value
))
271 if (!this->outer
->enumerate(this->outer
, &this->handler
))
275 DESTROY_IF(this->inner
);
276 this->inner
= this->handler
->create_attribute_enumerator(this->handler
,
277 this->id
, this->vip
);
279 /* inject the handler as additional attribute */
280 *handler
= this->handler
;
285 * Cleanup function of initiator attribute enumerator
287 static void initiator_destroy(initiator_enumerator_t
*this)
289 this->this->lock
->unlock(this->this->lock
);
290 this->outer
->destroy(this->outer
);
291 DESTROY_IF(this->inner
);
296 * Implementation of attribute_manager_t.create_initiator_enumerator
298 static enumerator_t
* create_initiator_enumerator(
299 private_attribute_manager_t
*this, identification_t
*id
, host_t
*vip
)
301 initiator_enumerator_t
*enumerator
= malloc_thing(initiator_enumerator_t
);
303 this->lock
->read_lock(this->lock
);
304 enumerator
->public.enumerate
= (void*)initiator_enumerate
;
305 enumerator
->public.destroy
= (void*)initiator_destroy
;
306 enumerator
->this = this;
308 enumerator
->vip
= vip
;
309 enumerator
->outer
= this->handlers
->create_enumerator(this->handlers
);
310 enumerator
->inner
= NULL
;
311 enumerator
->handler
= NULL
;
313 return &enumerator
->public;
317 * Implementation of attribute_manager_t.add_handler
319 static void add_handler(private_attribute_manager_t
*this,
320 attribute_handler_t
*handler
)
322 this->lock
->write_lock(this->lock
);
323 this->handlers
->insert_last(this->handlers
, handler
);
324 this->lock
->unlock(this->lock
);
328 * Implementation of attribute_manager_t.remove_handler
330 static void remove_handler(private_attribute_manager_t
*this,
331 attribute_handler_t
*handler
)
333 this->lock
->write_lock(this->lock
);
334 this->handlers
->remove(this->handlers
, handler
, NULL
);
335 this->lock
->unlock(this->lock
);
339 * Implementation of attribute_manager_t.destroy
341 static void destroy(private_attribute_manager_t
*this)
343 this->providers
->destroy(this->providers
);
344 this->handlers
->destroy(this->handlers
);
345 this->lock
->destroy(this->lock
);
352 attribute_manager_t
*attribute_manager_create()
354 private_attribute_manager_t
*this = malloc_thing(private_attribute_manager_t
);
356 this->public.acquire_address
= (host_t
*(*)(attribute_manager_t
*, char*, identification_t
*,host_t
*))acquire_address
;
357 this->public.release_address
= (void(*)(attribute_manager_t
*, char *, host_t
*, identification_t
*))release_address
;
358 this->public.create_responder_enumerator
= (enumerator_t
*(*)(attribute_manager_t
*, identification_t
*, host_t
*))create_responder_enumerator
;
359 this->public.add_provider
= (void(*)(attribute_manager_t
*, attribute_provider_t
*provider
))add_provider
;
360 this->public.remove_provider
= (void(*)(attribute_manager_t
*, attribute_provider_t
*provider
))remove_provider
;
361 this->public.handle
= (attribute_handler_t
*(*)(attribute_manager_t
*,identification_t
*, attribute_handler_t
*, configuration_attribute_type_t
, chunk_t
))handle
;
362 this->public.release
= (void(*)(attribute_manager_t
*, attribute_handler_t
*, identification_t
*, configuration_attribute_type_t
, chunk_t
))release
;
363 this->public.create_initiator_enumerator
= (enumerator_t
*(*)(attribute_manager_t
*, identification_t
*, host_t
*))create_initiator_enumerator
;
364 this->public.add_handler
= (void(*)(attribute_manager_t
*, attribute_handler_t
*))add_handler
;
365 this->public.remove_handler
= (void(*)(attribute_manager_t
*, attribute_handler_t
*))remove_handler
;
366 this->public.destroy
= (void(*)(attribute_manager_t
*))destroy
;
368 this->providers
= linked_list_create();
369 this->handlers
= linked_list_create();
370 this->lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
);
372 return &this->public;