Replaced builder_t objects by simple builder_function_t functions
[strongswan.git] / src / libstrongswan / credentials / credential_factory.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * 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 <stdint.h>
17 #include <pthread.h>
18
19 #include "credential_factory.h"
20
21 #include <debug.h>
22 #include <utils/linked_list.h>
23 #include <utils/mutex.h>
24 #include <credentials/certificates/x509.h>
25
26 ENUM(credential_type_names, CRED_PRIVATE_KEY, CRED_CERTIFICATE,
27 "CRED_PRIVATE_KEY",
28 "CRED_PUBLIC_KEY",
29 "CRED_CERTIFICATE",
30 "CRED_PLUTO_CERT",
31 );
32
33 typedef struct private_credential_factory_t private_credential_factory_t;
34
35 /**
36 * private data of credential_factory
37 */
38 struct private_credential_factory_t {
39
40 /**
41 * public functions
42 */
43 credential_factory_t public;
44
45 /**
46 * list with entry_t
47 */
48 linked_list_t *constructors;
49
50 /**
51 * Thread specific recursiveness counter
52 */
53 pthread_key_t recursive;
54
55 /**
56 * lock access to builders
57 */
58 rwlock_t *lock;
59 };
60
61 typedef struct entry_t entry_t;
62 struct entry_t {
63 /** kind of credential builder */
64 credential_type_t type;
65 /** subtype of credential, e.g. certificate_type_t */
66 int subtype;
67 /** builder function */
68 builder_function_t constructor;
69 };
70
71 /**
72 * Implementation of credential_factory_t.add_builder_constructor.
73 */
74 static void add_builder(private_credential_factory_t *this,
75 credential_type_t type, int subtype,
76 builder_function_t constructor)
77 {
78 entry_t *entry = malloc_thing(entry_t);
79
80 entry->type = type;
81 entry->subtype = subtype;
82 entry->constructor = constructor;
83 this->lock->write_lock(this->lock);
84 this->constructors->insert_last(this->constructors, entry);
85 this->lock->unlock(this->lock);
86 }
87
88 /**
89 * Implementation of credential_factory_t.remove_builder.
90 */
91 static void remove_builder(private_credential_factory_t *this,
92 builder_function_t constructor)
93 {
94 enumerator_t *enumerator;
95 entry_t *entry;
96
97 this->lock->write_lock(this->lock);
98 enumerator = this->constructors->create_enumerator(this->constructors);
99 while (enumerator->enumerate(enumerator, &entry))
100 {
101 if (entry->constructor == constructor)
102 {
103 this->constructors->remove_at(this->constructors, enumerator);
104 free(entry);
105 }
106 }
107 enumerator->destroy(enumerator);
108 this->lock->unlock(this->lock);
109 }
110
111 /**
112 * Implementation of credential_factory_t.create.
113 */
114 static void* create(private_credential_factory_t *this, credential_type_t type,
115 int subtype, ...)
116 {
117 enumerator_t *enumerator;
118 entry_t *entry;
119 va_list args;
120 void *construct = NULL;
121 int failures = 0;
122 uintptr_t level;
123
124 level = (uintptr_t)pthread_getspecific(this->recursive);
125 pthread_setspecific(this->recursive, (void*)level + 1);
126
127 this->lock->read_lock(this->lock);
128 enumerator = this->constructors->create_enumerator(this->constructors);
129 while (enumerator->enumerate(enumerator, &entry))
130 {
131 if (entry->type == type && entry->subtype == subtype)
132 {
133 va_start(args, subtype);
134 construct = entry->constructor(subtype, args);
135 va_end(args);
136 if (construct)
137 {
138 break;
139 }
140 failures++;
141 }
142 }
143 enumerator->destroy(enumerator);
144 this->lock->unlock(this->lock);
145
146 if (!construct && !level)
147 {
148 enum_name_t *names = key_type_names;
149
150 if (type == CRED_CERTIFICATE)
151 {
152 names = certificate_type_names;
153 }
154 DBG1("building %N - %N failed, tried %d builders",
155 credential_type_names, type, names, subtype, failures);
156 }
157 pthread_setspecific(this->recursive, (void*)level);
158 return construct;
159 }
160
161 /**
162 * Implementation of credential_factory_t.destroy
163 */
164 static void destroy(private_credential_factory_t *this)
165 {
166 this->constructors->destroy_function(this->constructors, free);
167 pthread_key_delete(this->recursive);
168 this->lock->destroy(this->lock);
169 free(this);
170 }
171
172 /*
173 * see header file
174 */
175 credential_factory_t *credential_factory_create()
176 {
177 private_credential_factory_t *this = malloc_thing(private_credential_factory_t);
178
179 this->public.create = (void*(*)(credential_factory_t*, credential_type_t type, int subtype, ...))create;
180 this->public.add_builder = (void(*)(credential_factory_t*,credential_type_t type, int subtype, builder_function_t constructor))add_builder;
181 this->public.remove_builder = (void(*)(credential_factory_t*,builder_function_t constructor))remove_builder;
182 this->public.destroy = (void(*)(credential_factory_t*))destroy;
183
184 this->constructors = linked_list_create();
185 pthread_key_create(&this->recursive, NULL);
186 this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
187
188 return &this->public;
189 }
190