introduced printf() specifiers for:
[strongswan.git] / src / charon / bus / bus.c
1 /**
2 * @file bus.c
3 *
4 * @brief Implementation of bus_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include "bus.h"
24
25 typedef struct private_bus_t private_bus_t;
26
27 /**
28 * Private data of a bus_t object.
29 */
30 struct private_bus_t {
31 /**
32 * Public part of a bus_t object.
33 */
34 bus_t public;
35
36 /**
37 * List of registered listeners implementing the bus_t interface
38 */
39 linked_list_t *listeners;
40
41 /**
42 * Thread local storage for a unique, simple thread ID
43 */
44 pthread_key_t thread_id;
45
46 /**
47 * Thread local storage the threads IKE_SA
48 */
49 pthread_key_t thread_sa;
50
51 };
52
53 /**
54 * Get a unique thread number for a calling thread. Since
55 * pthread_self returns large and ugly numbers, use this function
56 * for logging; these numbers are incremental starting at 1
57 */
58 static int get_thread_number(private_bus_t *this)
59 {
60 static int current_num = 0, stored_num;
61
62 stored_num = (int)pthread_getspecific(this->thread_id);
63 if (stored_num == 0)
64 { /* first call of current thread */
65 pthread_setspecific(this->thread_id, (void*)++current_num);
66 return current_num;
67 }
68 else
69 {
70 return stored_num;
71 }
72 }
73
74 /**
75 * Implementation of bus_t.add_listener.
76 */
77 static void add_listener(private_bus_t *this, bus_listener_t *listener)
78 {
79 this->listeners->insert_last(this->listeners, (void*)listener);
80 }
81
82 /**
83 * Implementation of bus_t.set_sa.
84 */
85 static void set_sa(private_bus_t *this, ike_sa_t *ike_sa)
86 {
87 pthread_setspecific(this->thread_sa, ike_sa);
88 }
89
90 /**
91 * Implementation of bus_t.signal.
92 */
93 static void signal_(private_bus_t *this, signal_t signal, level_t condition,
94 char* format, ...)
95 {
96 iterator_t *iterator;
97 bus_listener_t *listener;
98 va_list args;
99 ike_sa_t *ike_sa;
100 int thread;
101
102 ike_sa = pthread_getspecific(this->thread_sa);
103 thread = get_thread_number(this);
104 va_start(args, format);
105
106 iterator = this->listeners->create_iterator(this->listeners, TRUE);
107 while (iterator->iterate(iterator, (void**)&listener))
108 {
109 listener->signal(listener, thread, ike_sa,
110 signal, condition, format, args);
111 }
112 iterator->destroy(iterator);
113 va_end(args);
114 }
115
116 /**
117 * Implementation of bus_t.destroy.
118 */
119 static void destroy(private_bus_t *this)
120 {
121 this->listeners->destroy(this->listeners);
122 free(this);
123 }
124
125 /*
126 * Described in header.
127 */
128 bus_t *bus_create()
129 {
130 private_bus_t *this = malloc_thing(private_bus_t);
131
132 this->public.add_listener = (void(*)(bus_t*,bus_listener_t*))add_listener;
133 this->public.set_sa = (void(*)(bus_t*,ike_sa_t*))set_sa;
134 this->public.signal = (void(*)(bus_t*,signal_t,level_t,char*,...))signal_;
135 this->public.destroy = (void(*)(bus_t*)) destroy;
136
137 this->listeners = linked_list_create();
138 pthread_key_create(&this->thread_id, NULL);
139 pthread_key_create(&this->thread_sa, NULL);
140
141 return &(this->public);
142 }