fixed memory leak in EAP-TTLS piggy-back mode
[strongswan.git] / src / libcharon / 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 <utils/linked_list.h>
19 #include <threading/rwlock.h>
20
21 typedef struct private_tnccs_manager_t private_tnccs_manager_t;
22 typedef struct tnccs_entry_t tnccs_entry_t;
23
24 /**
25 * TNCCS constructor entry
26 */
27 struct tnccs_entry_t {
28
29 /**
30 * TNCCS protocol type
31 */
32 tnccs_type_t type;
33
34 /**
35 * constructor function to create instance
36 */
37 tnccs_constructor_t constructor;
38 };
39
40 /**
41 * private data of tnccs_manager
42 */
43 struct private_tnccs_manager_t {
44
45 /**
46 * public functions
47 */
48 tnccs_manager_t public;
49
50 /**
51 * list of tnccs_entry_t's
52 */
53 linked_list_t *protocols;
54
55 /**
56 * rwlock to lock methods
57 */
58 rwlock_t *lock;
59 };
60
61 METHOD(tnccs_manager_t, add_method, void,
62 private_tnccs_manager_t *this, tnccs_type_t type,
63 tnccs_constructor_t constructor)
64 {
65 tnccs_entry_t *entry = malloc_thing(tnccs_entry_t);
66
67 entry->type = type;
68 entry->constructor = constructor;
69
70 this->lock->write_lock(this->lock);
71 this->protocols->insert_last(this->protocols, entry);
72 this->lock->unlock(this->lock);
73 }
74
75 METHOD(tnccs_manager_t, remove_method, void,
76 private_tnccs_manager_t *this, tnccs_constructor_t constructor)
77 {
78 enumerator_t *enumerator;
79 tnccs_entry_t *entry;
80
81 this->lock->write_lock(this->lock);
82 enumerator = this->protocols->create_enumerator(this->protocols);
83 while (enumerator->enumerate(enumerator, &entry))
84 {
85 if (constructor == entry->constructor)
86 {
87 this->protocols->remove_at(this->protocols, enumerator);
88 free(entry);
89 }
90 }
91 enumerator->destroy(enumerator);
92 this->lock->unlock(this->lock);
93 }
94
95 METHOD(tnccs_manager_t, create_instance, tnccs_t*,
96 private_tnccs_manager_t *this, tnccs_type_t type, bool is_server)
97 {
98 enumerator_t *enumerator;
99 tnccs_entry_t *entry;
100 tnccs_t *protocol = NULL;
101
102 this->lock->read_lock(this->lock);
103 enumerator = this->protocols->create_enumerator(this->protocols);
104 while (enumerator->enumerate(enumerator, &entry))
105 {
106 if (type == entry->type)
107 {
108 protocol = entry->constructor(is_server);
109 if (protocol)
110 {
111 break;
112 }
113 }
114 }
115 enumerator->destroy(enumerator);
116 this->lock->unlock(this->lock);
117 return protocol;
118 }
119
120 METHOD(tnccs_manager_t, destroy, void,
121 private_tnccs_manager_t *this)
122 {
123 this->protocols->destroy_function(this->protocols, free);
124 this->lock->destroy(this->lock);
125 free(this);
126 }
127
128 /*
129 * See header
130 */
131 tnccs_manager_t *tnccs_manager_create()
132 {
133 private_tnccs_manager_t *this;
134
135 INIT(this,
136 .public = {
137 .add_method = _add_method,
138 .remove_method = _remove_method,
139 .create_instance = _create_instance,
140 .destroy = _destroy,
141 },
142 .protocols = linked_list_create(),
143 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
144 );
145
146 return &this->public;
147 }
148