monotone

monotone Mtn Source Tree

Root/botan/libstate.cpp

1/*************************************************
2* Library Internal/Global State Source File *
3* (C) 1999-2006 The Botan Project *
4*************************************************/
5
6#include <botan/libstate.h>
7#include <botan/config.h>
8#include <botan/modules.h>
9#include <botan/engine.h>
10#include <botan/x509stat.h>
11#include <botan/stl_util.h>
12#include <botan/mutex.h>
13#include <botan/timers.h>
14#include <botan/charset.h>
15#include <algorithm>
16#include <stdlib.h>
17
18namespace Botan {
19
20/*************************************************
21* Botan's global state *
22*************************************************/
23namespace {
24
25Library_State* global_lib_state = 0;
26
27}
28
29/*************************************************
30* Access the global state object *
31*************************************************/
32Library_State& global_state()
33 {
34 if(!global_lib_state)
35 {
36 abort();
37 throw Invalid_State("Library was not initialized correctly");
38 }
39 return (*global_lib_state);
40 }
41
42/*************************************************
43* Set a new global state object *
44*************************************************/
45void set_global_state(Library_State* new_state)
46 {
47 delete swap_global_state(new_state);
48 }
49
50/*************************************************
51* Swap two global state objects *
52*************************************************/
53Library_State* swap_global_state(Library_State* new_state)
54 {
55 Library_State* old_state = global_lib_state;
56 global_lib_state = new_state;
57 return old_state;
58 }
59
60/*************************************************
61* Increment the Engine iterator *
62*************************************************/
63Engine* Library_State::Engine_Iterator::next()
64 {
65 return lib.get_engine_n(n++);
66 }
67
68/*************************************************
69* Get a new mutex object *
70*************************************************/
71Mutex* Library_State::get_mutex() const
72 {
73 return mutex_factory->make();
74 }
75
76/*************************************************
77* Get a persistent named mutex object *
78*************************************************/
79Mutex* Library_State::get_named_mutex(const std::string& name)
80 {
81 Mutex* mux = search_map<std::string, Mutex*>(locks, name, 0);
82 if(mux)
83 return mux;
84 return (locks[name] = get_mutex());
85 }
86
87/*************************************************
88* Get an allocator by its name *
89*************************************************/
90Allocator* Library_State::get_allocator(const std::string& type) const
91 {
92 Named_Mutex_Holder lock("allocator");
93
94 if(type != "")
95 return search_map<std::string, Allocator*>(alloc_factory, type, 0);
96
97 if(!cached_default_allocator)
98 {
99 std::string chosen = config().option("base/default_allocator");
100
101 if(chosen == "")
102 chosen = "malloc";
103
104 cached_default_allocator =
105 search_map<std::string, Allocator*>(alloc_factory, chosen, 0);
106 }
107
108 return cached_default_allocator;
109 }
110
111/*************************************************
112* Create a new name to object mapping *
113*************************************************/
114void Library_State::add_allocator(Allocator* allocator)
115 {
116 Named_Mutex_Holder lock("allocator");
117
118 allocator->init();
119
120 allocators.push_back(allocator);
121 alloc_factory[allocator->type()] = allocator;
122 }
123
124/*************************************************
125* Set the default allocator type *
126*************************************************/
127void Library_State::set_default_allocator(const std::string& type) const
128 {
129 Named_Mutex_Holder lock("allocator");
130
131 if(type == "")
132 return;
133
134 config().set("conf", "base/default_allocator", type);
135 cached_default_allocator = 0;
136 }
137
138/*************************************************
139* Set the high resolution clock implementation *
140*************************************************/
141void Library_State::set_timer(Timer* new_timer)
142 {
143 if(new_timer)
144 {
145 delete timer;
146 timer = new_timer;
147 }
148 }
149
150/*************************************************
151* Read a high resolution clock *
152*************************************************/
153u64bit Library_State::system_clock() const
154 {
155 return (timer) ? timer->clock() : 0;
156 }
157
158/*************************************************
159* Set the global PRNG *
160*************************************************/
161void Library_State::set_prng(RandomNumberGenerator* new_rng)
162 {
163 Named_Mutex_Holder lock("rng");
164
165 delete rng;
166 rng = new_rng;
167 }
168
169/*************************************************
170* Get bytes from the global PRNG *
171*************************************************/
172void Library_State::randomize(byte out[], u32bit length)
173 {
174 Named_Mutex_Holder lock("rng");
175
176 rng->randomize(out, length);
177 }
178
179/*************************************************
180* Add a new entropy source to use *
181*************************************************/
182void Library_State::add_entropy_source(EntropySource* src, bool last_in_list)
183 {
184 Named_Mutex_Holder lock("rng");
185
186 if(last_in_list)
187 entropy_sources.push_back(src);
188 else
189 entropy_sources.insert(entropy_sources.begin(), src);
190 }
191
192/*************************************************
193* Add some bytes of entropy to the global PRNG *
194*************************************************/
195void Library_State::add_entropy(const byte in[], u32bit length)
196 {
197 Named_Mutex_Holder lock("rng");
198
199 rng->add_entropy(in, length);
200 }
201
202/*************************************************
203* Add some bytes of entropy to the global PRNG *
204*************************************************/
205void Library_State::add_entropy(EntropySource& source, bool slow_poll)
206 {
207 Named_Mutex_Holder lock("rng");
208
209 rng->add_entropy(source, slow_poll);
210 }
211
212/*************************************************
213* Gather entropy for our PRNG object *
214*************************************************/
215u32bit Library_State::seed_prng(bool slow_poll, u32bit bits_to_get)
216 {
217 Named_Mutex_Holder lock("rng");
218
219 u32bit bits = 0;
220 for(u32bit j = 0; j != entropy_sources.size(); ++j)
221 {
222 bits += rng->add_entropy(*(entropy_sources[j]), slow_poll);
223
224 if(bits_to_get && bits >= bits_to_get)
225 return bits;
226 }
227
228 return bits;
229 }
230
231/*************************************************
232* Get an engine out of the list *
233*************************************************/
234Engine* Library_State::get_engine_n(u32bit n) const
235 {
236 Named_Mutex_Holder lock("engine");
237
238 if(n >= engines.size())
239 return 0;
240 return engines[n];
241 }
242
243/*************************************************
244* Add a new engine to the list *
245*************************************************/
246void Library_State::add_engine(Engine* engine)
247 {
248 Named_Mutex_Holder lock("engine");
249 engines.insert(engines.begin(), engine);
250 }
251
252/*************************************************
253* Set the character set transcoder object *
254*************************************************/
255void Library_State::set_transcoder(class Charset_Transcoder* transcoder)
256 {
257 if(this->transcoder)
258 delete this->transcoder;
259 this->transcoder = transcoder;
260 }
261
262/*************************************************
263* Transcode a string from one charset to another *
264*************************************************/
265std::string Library_State::transcode(const std::string str,
266 Character_Set to,
267 Character_Set from) const
268 {
269 if(!transcoder)
270 throw Invalid_State("Library_State::transcode: No transcoder set");
271
272 return transcoder->transcode(str, to, from);
273 }
274
275/*************************************************
276* Set the X509 global state class *
277*************************************************/
278void Library_State::set_x509_state(X509_GlobalState* new_x509_state_obj)
279 {
280 delete x509_state_obj;
281 x509_state_obj = new_x509_state_obj;
282 }
283
284/*************************************************
285* Get the X509 global state class *
286*************************************************/
287X509_GlobalState& Library_State::x509_state()
288 {
289 if(!x509_state_obj)
290 x509_state_obj = new X509_GlobalState();
291
292 return (*x509_state_obj);
293 }
294
295/*************************************************
296* Set the UI object state *
297*************************************************/
298void Library_State::set_ui(UI* new_ui)
299 {
300 delete ui;
301 ui = new_ui;
302 }
303
304/*************************************************
305* Send a pulse to the UI object *
306*************************************************/
307void Library_State::pulse(Pulse_Type pulse_type) const
308 {
309 if(ui)
310 ui->pulse(pulse_type);
311 }
312
313/*************************************************
314* Set the configuration object *
315*************************************************/
316Config& Library_State::config() const
317 {
318 if(!config_obj)
319 throw Invalid_State("Library_State::config(): No config set");
320
321 return (*config_obj);
322 }
323
324/*************************************************
325* Load modules *
326*************************************************/
327void Library_State::load(Modules& modules)
328 {
329 set_timer(modules.timer());
330 set_transcoder(modules.transcoder());
331
332 std::vector<Allocator*> mod_allocs = modules.allocators();
333 for(u32bit j = 0; j != mod_allocs.size(); j++)
334 add_allocator(mod_allocs[j]);
335
336 set_default_allocator(modules.default_allocator());
337
338 std::vector<Engine*> mod_engines = modules.engines();
339 for(u32bit j = 0; j != mod_engines.size(); ++j)
340 {
341 Named_Mutex_Holder lock("engine");
342 engines.push_back(mod_engines[j]);
343 }
344
345 std::vector<EntropySource*> sources = modules.entropy_sources();
346 for(u32bit j = 0; j != sources.size(); ++j)
347 add_entropy_source(sources[j]);
348 }
349
350/*************************************************
351* Library_State Constructor *
352*************************************************/
353Library_State::Library_State(Mutex_Factory* mutex_factory)
354 {
355 if(!mutex_factory)
356 throw Exception("Library_State: no mutex found");
357
358 this->mutex_factory = mutex_factory;
359 this->timer = new Timer();
360 this->transcoder = 0;
361 this->config_obj = new Config();
362
363 locks["settings"] = get_mutex();
364 locks["allocator"] = get_mutex();
365 locks["rng"] = get_mutex();
366 locks["engine"] = get_mutex();
367 rng = 0;
368 cached_default_allocator = 0;
369 x509_state_obj = 0;
370 ui = 0;
371 }
372
373/*************************************************
374* Library_State Destructor *
375*************************************************/
376Library_State::~Library_State()
377 {
378 delete x509_state_obj;
379 delete transcoder;
380 delete rng;
381 delete timer;
382 delete config_obj;
383 delete ui;
384
385 std::for_each(entropy_sources.begin(), entropy_sources.end(),
386 del_fun<EntropySource>());
387 std::for_each(engines.begin(), engines.end(), del_fun<Engine>());
388
389 cached_default_allocator = 0;
390
391 for(u32bit j = 0; j != allocators.size(); j++)
392 {
393 allocators[j]->destroy();
394 delete allocators[j];
395 }
396
397 std::for_each(locks.begin(), locks.end(),
398 delete2nd<std::map<std::string, Mutex*>::value_type>);
399
400 delete mutex_factory;
401 }
402
403}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status