Introduce an optional logger_t.vlog() method with format string and arguments
[strongswan.git] / src / libcharon / bus / bus.c
1 /*
2 * Copyright (C) 2011-2012 Tobias Brunner
3 * Copyright (C) 2006 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "bus.h"
18
19 #include <stdint.h>
20
21 #include <threading/thread.h>
22 #include <threading/thread_value.h>
23 #include <threading/mutex.h>
24 #include <threading/rwlock.h>
25
26 typedef struct private_bus_t private_bus_t;
27
28 /**
29 * Private data of a bus_t object.
30 */
31 struct private_bus_t {
32 /**
33 * Public part of a bus_t object.
34 */
35 bus_t public;
36
37 /**
38 * List of registered listeners as entry_t.
39 */
40 linked_list_t *listeners;
41
42 /**
43 * List of registered loggers for each log group as log_entry_t.
44 * Loggers are ordered by descending log level.
45 * The extra list stores all loggers so we can properly unregister them.
46 */
47 linked_list_t *loggers[DBG_MAX + 1];
48
49 /**
50 * Maximum log level of any registered logger for each log group.
51 * This allows to check quickly if a log message has to be logged at all.
52 */
53 level_t max_level[DBG_MAX + 1];
54
55 /**
56 * Same as max level, but for loggers using the vlog() method.
57 */
58 level_t max_vlevel[DBG_MAX + 1];
59
60 /**
61 * Mutex for the list of listeners, recursively.
62 */
63 mutex_t *mutex;
64
65 /**
66 * Read-write lock for the list of loggers.
67 */
68 rwlock_t *log_lock;
69
70 /**
71 * Thread local storage the threads IKE_SA
72 */
73 thread_value_t *thread_sa;
74 };
75
76 typedef struct entry_t entry_t;
77
78 /**
79 * a listener entry
80 */
81 struct entry_t {
82
83 /**
84 * registered listener interface
85 */
86 listener_t *listener;
87
88 /**
89 * are we currently calling this listener
90 */
91 int calling;
92
93 };
94
95 typedef struct log_entry_t log_entry_t;
96
97 /**
98 * a logger entry
99 */
100 struct log_entry_t {
101
102 /**
103 * registered logger interface
104 */
105 logger_t *logger;
106
107 /**
108 * registered log levels per group
109 */
110 level_t levels[DBG_MAX];
111
112 };
113
114 METHOD(bus_t, add_listener, void,
115 private_bus_t *this, listener_t *listener)
116 {
117 entry_t *entry;
118
119 INIT(entry,
120 .listener = listener,
121 );
122
123 this->mutex->lock(this->mutex);
124 this->listeners->insert_last(this->listeners, entry);
125 this->mutex->unlock(this->mutex);
126 }
127
128 METHOD(bus_t, remove_listener, void,
129 private_bus_t *this, listener_t *listener)
130 {
131 enumerator_t *enumerator;
132 entry_t *entry;
133
134 this->mutex->lock(this->mutex);
135 enumerator = this->listeners->create_enumerator(this->listeners);
136 while (enumerator->enumerate(enumerator, &entry))
137 {
138 if (entry->listener == listener)
139 {
140 this->listeners->remove_at(this->listeners, enumerator);
141 free(entry);
142 break;
143 }
144 }
145 enumerator->destroy(enumerator);
146 this->mutex->unlock(this->mutex);
147 }
148
149 /**
150 * Register a logger on the given log group according to the requested level
151 */
152 static inline void register_logger(private_bus_t *this, debug_t group,
153 log_entry_t *entry)
154 {
155 enumerator_t *enumerator;
156 linked_list_t *loggers;
157 log_entry_t *current;
158 level_t level;
159
160 loggers = this->loggers[group];
161 level = entry->levels[group];
162
163 enumerator = loggers->create_enumerator(loggers);
164 while (enumerator->enumerate(enumerator, (void**)&current))
165 {
166 if (current->levels[group] <= level)
167 {
168 break;
169 }
170 }
171 loggers->insert_before(loggers, enumerator, entry);
172 enumerator->destroy(enumerator);
173
174 if (entry->logger->log)
175 {
176 this->max_level[group] = max(this->max_level[group], level);
177 }
178 if (entry->logger->vlog)
179 {
180 this->max_vlevel[group] = max(this->max_vlevel[group], level);
181 }
182 }
183
184 /**
185 * Unregister a logger from all log groups (destroys the log_entry_t)
186 */
187 static inline void unregister_logger(private_bus_t *this, logger_t *logger)
188 {
189 enumerator_t *enumerator;
190 linked_list_t *loggers;
191 log_entry_t *entry, *found = NULL;
192
193 loggers = this->loggers[DBG_MAX];
194 enumerator = loggers->create_enumerator(loggers);
195 while (enumerator->enumerate(enumerator, &entry))
196 {
197 if (entry->logger == logger)
198 {
199 loggers->remove_at(loggers, enumerator);
200 found = entry;
201 break;
202 }
203 }
204 enumerator->destroy(enumerator);
205
206 if (found)
207 {
208 debug_t group;
209
210 for (group = 0; group < DBG_MAX; group++)
211 {
212 if (found->levels[group] > LEVEL_SILENT)
213 {
214 loggers = this->loggers[group];
215 loggers->remove(loggers, found, NULL);
216
217 this->max_level[group] = LEVEL_SILENT;
218 this->max_vlevel[group] = LEVEL_SILENT;
219 if (loggers->get_first(loggers, (void**)&entry) == SUCCESS)
220 {
221 this->max_level[group] = entry->levels[group];
222 this->max_vlevel[group] = entry->levels[group];
223 }
224 }
225 }
226 free(found);
227 }
228 }
229
230 METHOD(bus_t, add_logger, void,
231 private_bus_t *this, logger_t *logger)
232 {
233 log_entry_t *entry;
234 debug_t group;
235
236 INIT(entry,
237 .logger = logger,
238 );
239
240 this->log_lock->write_lock(this->log_lock);
241 unregister_logger(this, logger);
242 for (group = 0; group < DBG_MAX; group++)
243 {
244 entry->levels[group] = logger->get_level(logger, group);
245 if (entry->levels[group] > LEVEL_SILENT)
246 {
247 register_logger(this, group, entry);
248 }
249 }
250 this->loggers[DBG_MAX]->insert_last(this->loggers[DBG_MAX], entry);
251 this->log_lock->unlock(this->log_lock);
252 }
253
254 METHOD(bus_t, remove_logger, void,
255 private_bus_t *this, logger_t *logger)
256 {
257 this->log_lock->write_lock(this->log_lock);
258 unregister_logger(this, logger);
259 this->log_lock->unlock(this->log_lock);
260 }
261
262 METHOD(bus_t, set_sa, void,
263 private_bus_t *this, ike_sa_t *ike_sa)
264 {
265 this->thread_sa->set(this->thread_sa, ike_sa);
266 }
267
268 METHOD(bus_t, get_sa, ike_sa_t*,
269 private_bus_t *this)
270 {
271 return this->thread_sa->get(this->thread_sa);
272 }
273
274 /**
275 * data associated to a signal, passed to callback
276 */
277 typedef struct {
278 /** associated IKE_SA */
279 ike_sa_t *ike_sa;
280 /** invoking thread */
281 long thread;
282 /** debug group */
283 debug_t group;
284 /** debug level */
285 level_t level;
286 /** message/fmt */
287 char *message;
288 /** argument list if message is a format string for vlog() */
289 va_list args;
290 } log_data_t;
291
292 /**
293 * logger->log() invocation as a invoke_function callback
294 */
295 static void log_cb(log_entry_t *entry, log_data_t *data)
296 {
297 if (entry->logger->log && entry->levels[data->group] >= data->level)
298 {
299 entry->logger->log(entry->logger, data->group, data->level,
300 data->thread, data->ike_sa, data->message);
301 }
302 }
303
304 /**
305 * logger->vlog() invocation as a invoke_function callback
306 */
307 static void vlog_cb(log_entry_t *entry, log_data_t *data)
308 {
309 if (entry->logger->vlog && entry->levels[data->group] >= data->level)
310 {
311 va_list copy;
312
313 va_copy(copy, data->args);
314 entry->logger->vlog(entry->logger, data->group, data->level,
315 data->thread, data->ike_sa, data->message, copy);
316 va_end(copy);
317 }
318 }
319
320 METHOD(bus_t, vlog, void,
321 private_bus_t *this, debug_t group, level_t level,
322 char* format, va_list args)
323 {
324 linked_list_t *loggers;
325 log_data_t data;
326
327 this->log_lock->read_lock(this->log_lock);
328 loggers = this->loggers[group];
329
330 if (this->max_level[group] >= level)
331 {
332 char buf[1024];
333 ssize_t len;
334
335 data.ike_sa = this->thread_sa->get(this->thread_sa);
336 data.thread = thread_current_id();
337 data.group = group;
338 data.level = level;
339 data.message = buf;
340
341 va_copy(data.args, args);
342 len = vsnprintf(data.message, sizeof(buf), format, data.args);
343 va_end(data.args);
344 if (len >= sizeof(buf))
345 {
346 len++;
347 data.message = malloc(len);
348 len = vsnprintf(data.message, len, format, args);
349 }
350 if (len > 0)
351 {
352 loggers->invoke_function(loggers, (linked_list_invoke_t)log_cb,
353 &data);
354 }
355 if (data.message != buf)
356 {
357 free(data.message);
358 }
359 }
360 if (this->max_vlevel[group] >= level)
361 {
362 data.ike_sa = this->thread_sa->get(this->thread_sa);
363 data.thread = thread_current_id();
364 data.group = group;
365 data.level = level;
366 data.message = format;
367
368 va_copy(data.args, args);
369 loggers->invoke_function(loggers, (linked_list_invoke_t)vlog_cb, &data);
370 va_end(data.args);
371 }
372
373 this->log_lock->unlock(this->log_lock);
374 }
375
376 METHOD(bus_t, log_, void,
377 private_bus_t *this, debug_t group, level_t level, char* format, ...)
378 {
379 va_list args;
380
381 va_start(args, format);
382 vlog(this, group, level, format, args);
383 va_end(args);
384 }
385
386 /**
387 * unregister a listener
388 */
389 static inline void unregister_listener(private_bus_t *this, entry_t *entry,
390 enumerator_t *enumerator)
391 {
392 this->listeners->remove_at(this->listeners, enumerator);
393 free(entry);
394 }
395
396 METHOD(bus_t, alert, void,
397 private_bus_t *this, alert_t alert, ...)
398 {
399 enumerator_t *enumerator;
400 ike_sa_t *ike_sa;
401 entry_t *entry;
402 va_list args;
403 bool keep;
404
405 ike_sa = this->thread_sa->get(this->thread_sa);
406
407 this->mutex->lock(this->mutex);
408 enumerator = this->listeners->create_enumerator(this->listeners);
409 while (enumerator->enumerate(enumerator, &entry))
410 {
411 if (entry->calling || !entry->listener->alert)
412 {
413 continue;
414 }
415 entry->calling++;
416 va_start(args, alert);
417 keep = entry->listener->alert(entry->listener, ike_sa, alert, args);
418 va_end(args);
419 entry->calling--;
420 if (!keep)
421 {
422 unregister_listener(this, entry, enumerator);
423 }
424 }
425 enumerator->destroy(enumerator);
426 this->mutex->unlock(this->mutex);
427 }
428
429 METHOD(bus_t, ike_state_change, void,
430 private_bus_t *this, ike_sa_t *ike_sa, ike_sa_state_t state)
431 {
432 enumerator_t *enumerator;
433 entry_t *entry;
434 bool keep;
435
436 this->mutex->lock(this->mutex);
437 enumerator = this->listeners->create_enumerator(this->listeners);
438 while (enumerator->enumerate(enumerator, &entry))
439 {
440 if (entry->calling || !entry->listener->ike_state_change)
441 {
442 continue;
443 }
444 entry->calling++;
445 keep = entry->listener->ike_state_change(entry->listener, ike_sa, state);
446 entry->calling--;
447 if (!keep)
448 {
449 unregister_listener(this, entry, enumerator);
450 }
451 }
452 enumerator->destroy(enumerator);
453 this->mutex->unlock(this->mutex);
454 }
455
456 METHOD(bus_t, child_state_change, void,
457 private_bus_t *this, child_sa_t *child_sa, child_sa_state_t state)
458 {
459 enumerator_t *enumerator;
460 ike_sa_t *ike_sa;
461 entry_t *entry;
462 bool keep;
463
464 ike_sa = this->thread_sa->get(this->thread_sa);
465
466 this->mutex->lock(this->mutex);
467 enumerator = this->listeners->create_enumerator(this->listeners);
468 while (enumerator->enumerate(enumerator, &entry))
469 {
470 if (entry->calling || !entry->listener->child_state_change)
471 {
472 continue;
473 }
474 entry->calling++;
475 keep = entry->listener->child_state_change(entry->listener, ike_sa,
476 child_sa, state);
477 entry->calling--;
478 if (!keep)
479 {
480 unregister_listener(this, entry, enumerator);
481 }
482 }
483 enumerator->destroy(enumerator);
484 this->mutex->unlock(this->mutex);
485 }
486
487 METHOD(bus_t, message, void,
488 private_bus_t *this, message_t *message, bool incoming, bool plain)
489 {
490 enumerator_t *enumerator;
491 ike_sa_t *ike_sa;
492 entry_t *entry;
493 bool keep;
494
495 ike_sa = this->thread_sa->get(this->thread_sa);
496
497 this->mutex->lock(this->mutex);
498 enumerator = this->listeners->create_enumerator(this->listeners);
499 while (enumerator->enumerate(enumerator, &entry))
500 {
501 if (entry->calling || !entry->listener->message)
502 {
503 continue;
504 }
505 entry->calling++;
506 keep = entry->listener->message(entry->listener, ike_sa,
507 message, incoming, plain);
508 entry->calling--;
509 if (!keep)
510 {
511 unregister_listener(this, entry, enumerator);
512 }
513 }
514 enumerator->destroy(enumerator);
515 this->mutex->unlock(this->mutex);
516 }
517
518 METHOD(bus_t, ike_keys, void,
519 private_bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
520 chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
521 ike_sa_t *rekey, shared_key_t *shared)
522 {
523 enumerator_t *enumerator;
524 entry_t *entry;
525 bool keep;
526
527 this->mutex->lock(this->mutex);
528 enumerator = this->listeners->create_enumerator(this->listeners);
529 while (enumerator->enumerate(enumerator, &entry))
530 {
531 if (entry->calling || !entry->listener->ike_keys)
532 {
533 continue;
534 }
535 entry->calling++;
536 keep = entry->listener->ike_keys(entry->listener, ike_sa, dh, dh_other,
537 nonce_i, nonce_r, rekey, shared);
538 entry->calling--;
539 if (!keep)
540 {
541 unregister_listener(this, entry, enumerator);
542 }
543 }
544 enumerator->destroy(enumerator);
545 this->mutex->unlock(this->mutex);
546 }
547
548 METHOD(bus_t, child_keys, void,
549 private_bus_t *this, child_sa_t *child_sa, bool initiator,
550 diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r)
551 {
552 enumerator_t *enumerator;
553 ike_sa_t *ike_sa;
554 entry_t *entry;
555 bool keep;
556
557 ike_sa = this->thread_sa->get(this->thread_sa);
558
559 this->mutex->lock(this->mutex);
560 enumerator = this->listeners->create_enumerator(this->listeners);
561 while (enumerator->enumerate(enumerator, &entry))
562 {
563 if (entry->calling || !entry->listener->child_keys)
564 {
565 continue;
566 }
567 entry->calling++;
568 keep = entry->listener->child_keys(entry->listener, ike_sa,
569 child_sa, initiator, dh, nonce_i, nonce_r);
570 entry->calling--;
571 if (!keep)
572 {
573 unregister_listener(this, entry, enumerator);
574 }
575 }
576 enumerator->destroy(enumerator);
577 this->mutex->unlock(this->mutex);
578 }
579
580 METHOD(bus_t, child_updown, void,
581 private_bus_t *this, child_sa_t *child_sa, bool up)
582 {
583 enumerator_t *enumerator;
584 ike_sa_t *ike_sa;
585 entry_t *entry;
586 bool keep;
587
588 ike_sa = this->thread_sa->get(this->thread_sa);
589
590 this->mutex->lock(this->mutex);
591 enumerator = this->listeners->create_enumerator(this->listeners);
592 while (enumerator->enumerate(enumerator, &entry))
593 {
594 if (entry->calling || !entry->listener->child_updown)
595 {
596 continue;
597 }
598 entry->calling++;
599 keep = entry->listener->child_updown(entry->listener,
600 ike_sa, child_sa, up);
601 entry->calling--;
602 if (!keep)
603 {
604 unregister_listener(this, entry, enumerator);
605 }
606 }
607 enumerator->destroy(enumerator);
608 this->mutex->unlock(this->mutex);
609 }
610
611 METHOD(bus_t, child_rekey, void,
612 private_bus_t *this, child_sa_t *old, child_sa_t *new)
613 {
614 enumerator_t *enumerator;
615 ike_sa_t *ike_sa;
616 entry_t *entry;
617 bool keep;
618
619 ike_sa = this->thread_sa->get(this->thread_sa);
620
621 this->mutex->lock(this->mutex);
622 enumerator = this->listeners->create_enumerator(this->listeners);
623 while (enumerator->enumerate(enumerator, &entry))
624 {
625 if (entry->calling || !entry->listener->child_rekey)
626 {
627 continue;
628 }
629 entry->calling++;
630 keep = entry->listener->child_rekey(entry->listener, ike_sa,
631 old, new);
632 entry->calling--;
633 if (!keep)
634 {
635 unregister_listener(this, entry, enumerator);
636 }
637 }
638 enumerator->destroy(enumerator);
639 this->mutex->unlock(this->mutex);
640 }
641
642 METHOD(bus_t, ike_updown, void,
643 private_bus_t *this, ike_sa_t *ike_sa, bool up)
644 {
645 enumerator_t *enumerator;
646 entry_t *entry;
647 bool keep;
648
649 this->mutex->lock(this->mutex);
650 enumerator = this->listeners->create_enumerator(this->listeners);
651 while (enumerator->enumerate(enumerator, &entry))
652 {
653 if (entry->calling || !entry->listener->ike_updown)
654 {
655 continue;
656 }
657 entry->calling++;
658 keep = entry->listener->ike_updown(entry->listener, ike_sa, up);
659 entry->calling--;
660 if (!keep)
661 {
662 unregister_listener(this, entry, enumerator);
663 }
664 }
665 enumerator->destroy(enumerator);
666 this->mutex->unlock(this->mutex);
667
668 /* a down event for IKE_SA implicitly downs all CHILD_SAs */
669 if (!up)
670 {
671 enumerator_t *enumerator;
672 child_sa_t *child_sa;
673
674 enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
675 while (enumerator->enumerate(enumerator, (void**)&child_sa))
676 {
677 child_updown(this, child_sa, FALSE);
678 }
679 enumerator->destroy(enumerator);
680 }
681 }
682
683 METHOD(bus_t, ike_rekey, void,
684 private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
685 {
686 enumerator_t *enumerator;
687 entry_t *entry;
688 bool keep;
689
690 this->mutex->lock(this->mutex);
691 enumerator = this->listeners->create_enumerator(this->listeners);
692 while (enumerator->enumerate(enumerator, &entry))
693 {
694 if (entry->calling || !entry->listener->ike_rekey)
695 {
696 continue;
697 }
698 entry->calling++;
699 keep = entry->listener->ike_rekey(entry->listener, old, new);
700 entry->calling--;
701 if (!keep)
702 {
703 unregister_listener(this, entry, enumerator);
704 }
705 }
706 enumerator->destroy(enumerator);
707 this->mutex->unlock(this->mutex);
708 }
709
710 METHOD(bus_t, ike_reestablish, void,
711 private_bus_t *this, ike_sa_t *old, ike_sa_t *new)
712 {
713 enumerator_t *enumerator;
714 entry_t *entry;
715 bool keep;
716
717 this->mutex->lock(this->mutex);
718 enumerator = this->listeners->create_enumerator(this->listeners);
719 while (enumerator->enumerate(enumerator, &entry))
720 {
721 if (entry->calling || !entry->listener->ike_reestablish)
722 {
723 continue;
724 }
725 entry->calling++;
726 keep = entry->listener->ike_reestablish(entry->listener, old, new);
727 entry->calling--;
728 if (!keep)
729 {
730 unregister_listener(this, entry, enumerator);
731 }
732 }
733 enumerator->destroy(enumerator);
734 this->mutex->unlock(this->mutex);
735 }
736
737 METHOD(bus_t, authorize, bool,
738 private_bus_t *this, bool final)
739 {
740 enumerator_t *enumerator;
741 ike_sa_t *ike_sa;
742 entry_t *entry;
743 bool keep, success = TRUE;
744
745 ike_sa = this->thread_sa->get(this->thread_sa);
746
747 this->mutex->lock(this->mutex);
748 enumerator = this->listeners->create_enumerator(this->listeners);
749 while (enumerator->enumerate(enumerator, &entry))
750 {
751 if (entry->calling || !entry->listener->authorize)
752 {
753 continue;
754 }
755 entry->calling++;
756 keep = entry->listener->authorize(entry->listener, ike_sa,
757 final, &success);
758 entry->calling--;
759 if (!keep)
760 {
761 unregister_listener(this, entry, enumerator);
762 }
763 if (!success)
764 {
765 break;
766 }
767 }
768 enumerator->destroy(enumerator);
769 this->mutex->unlock(this->mutex);
770 if (!success)
771 {
772 alert(this, ALERT_AUTHORIZATION_FAILED);
773 }
774 return success;
775 }
776
777 METHOD(bus_t, narrow, void,
778 private_bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
779 linked_list_t *local, linked_list_t *remote)
780 {
781 enumerator_t *enumerator;
782 ike_sa_t *ike_sa;
783 entry_t *entry;
784 bool keep;
785
786 ike_sa = this->thread_sa->get(this->thread_sa);
787
788 this->mutex->lock(this->mutex);
789 enumerator = this->listeners->create_enumerator(this->listeners);
790 while (enumerator->enumerate(enumerator, &entry))
791 {
792 if (entry->calling || !entry->listener->narrow)
793 {
794 continue;
795 }
796 entry->calling++;
797 keep = entry->listener->narrow(entry->listener, ike_sa, child_sa,
798 type, local, remote);
799 entry->calling--;
800 if (!keep)
801 {
802 unregister_listener(this, entry, enumerator);
803 }
804 }
805 enumerator->destroy(enumerator);
806 this->mutex->unlock(this->mutex);
807 }
808
809 METHOD(bus_t, assign_vips, void,
810 private_bus_t *this, ike_sa_t *ike_sa, bool assign)
811 {
812 enumerator_t *enumerator;
813 entry_t *entry;
814 bool keep;
815
816 this->mutex->lock(this->mutex);
817 enumerator = this->listeners->create_enumerator(this->listeners);
818 while (enumerator->enumerate(enumerator, &entry))
819 {
820 if (entry->calling || !entry->listener->assign_vips)
821 {
822 continue;
823 }
824 entry->calling++;
825 keep = entry->listener->assign_vips(entry->listener, ike_sa, assign);
826 entry->calling--;
827 if (!keep)
828 {
829 unregister_listener(this, entry, enumerator);
830 }
831 }
832 enumerator->destroy(enumerator);
833 this->mutex->unlock(this->mutex);
834 }
835
836 METHOD(bus_t, destroy, void,
837 private_bus_t *this)
838 {
839 debug_t group;
840 for (group = 0; group < DBG_MAX; group++)
841 {
842 this->loggers[group]->destroy(this->loggers[group]);
843 }
844 this->loggers[DBG_MAX]->destroy_function(this->loggers[DBG_MAX],
845 (void*)free);
846 this->listeners->destroy_function(this->listeners, (void*)free);
847 this->thread_sa->destroy(this->thread_sa);
848 this->log_lock->destroy(this->log_lock);
849 this->mutex->destroy(this->mutex);
850 free(this);
851 }
852
853 /*
854 * Described in header.
855 */
856 bus_t *bus_create()
857 {
858 private_bus_t *this;
859 debug_t group;
860
861 INIT(this,
862 .public = {
863 .add_listener = _add_listener,
864 .remove_listener = _remove_listener,
865 .add_logger = _add_logger,
866 .remove_logger = _remove_logger,
867 .set_sa = _set_sa,
868 .get_sa = _get_sa,
869 .log = _log_,
870 .vlog = _vlog,
871 .alert = _alert,
872 .ike_state_change = _ike_state_change,
873 .child_state_change = _child_state_change,
874 .message = _message,
875 .ike_keys = _ike_keys,
876 .child_keys = _child_keys,
877 .ike_updown = _ike_updown,
878 .ike_rekey = _ike_rekey,
879 .ike_reestablish = _ike_reestablish,
880 .child_updown = _child_updown,
881 .child_rekey = _child_rekey,
882 .authorize = _authorize,
883 .narrow = _narrow,
884 .assign_vips = _assign_vips,
885 .destroy = _destroy,
886 },
887 .listeners = linked_list_create(),
888 .mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
889 .log_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
890 .thread_sa = thread_value_create(NULL),
891 );
892
893 for (group = 0; group <= DBG_MAX; group++)
894 {
895 this->loggers[group] = linked_list_create();
896 this->max_level[group] = LEVEL_SILENT;
897 this->max_vlevel[group] = LEVEL_SILENT;
898 }
899
900 return &this->public;
901 }