2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
24 * Based on mod_skel by
25 * Anthony Minessale II <anthm@freeswitch.org>
29 * Daniel Bryars <danb@aeriandi.com>
30 * Tim Brown <tim.brown@aeriandi.com>
31 * Anthony Minessale II <anthm@freeswitch.org>
32 * William King <william.king@quentustech.com>
33 * Mike Jerris <mike@jerris.com>
35 * kazoo.c -- Sends FreeSWITCH events to an AMQP broker
39 #include "mod_kazoo.h"
41 #define KZ_DEFAULT_STREAM_PRE_ALLOCATE 8192
43 #define KAZOO_DECLARE_GLOBAL_STRING_FUNC(fname, vname) static void __attribute__((__unused__)) fname(const char *string) { if (!string) return;\
44 if (vname) {free(vname); vname = NULL;}vname = strdup(string);} static void fname(const char *string)
46 KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip
, kazoo_globals
.ip
);
47 KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_cookie
, kazoo_globals
.ei_cookie
);
48 KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_nodename
, kazoo_globals
.ei_nodename
);
49 //KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_kazoo_var_prefix, kazoo_globals.kazoo_var_prefix);
51 static int read_cookie_from_file(char *filename
) {
53 char cookie
[MAXATOMLEN
+ 1];
57 if (!stat(filename
, &buf
)) {
58 if ((buf
.st_mode
& S_IRWXG
) || (buf
.st_mode
& S_IRWXO
)) {
59 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "%s must only be accessible by owner only.\n", filename
);
62 if (buf
.st_size
> MAXATOMLEN
) {
63 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "%s contains a cookie larger than the maximum atom size of %d.\n", filename
, MAXATOMLEN
);
66 fd
= open(filename
, O_RDONLY
);
68 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Unable to open cookie file %s : %d.\n", filename
, errno
);
72 if (read(fd
, cookie
, MAXATOMLEN
) < 1) {
73 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Unable to read cookie file %s : %d.\n", filename
, errno
);
76 cookie
[MAXATOMLEN
] = '\0';
78 /* replace any end of line characters with a null */
79 if ((end
= strchr(cookie
, '\n'))) {
83 if ((end
= strchr(cookie
, '\r'))) {
87 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set cookie from file %s: %s\n", filename
, cookie
);
89 set_pref_ei_cookie(cookie
);
92 /* don't error here, because we might be blindly trying to read $HOME/.erlang.cookie, and that can fail silently */
97 void kz_set_hostname()
99 if (kazoo_globals
.hostname
== NULL
) {
100 char hostname
[NODENAME_MAX
];
101 memcpy(hostname
, switch_core_get_hostname(), NODENAME_MAX
);
102 kazoo_globals
.hostname_ent
= gethostbyname(hostname
);
103 if(kazoo_globals
.hostname_ent
!= NULL
) {
104 kazoo_globals
.hostname
= switch_core_strdup(kazoo_globals
.pool
, kazoo_globals
.hostname_ent
->h_name
);
106 kazoo_globals
.hostname
= switch_core_strdup(kazoo_globals
.pool
, hostname
);
111 switch_status_t
kazoo_ei_config(switch_xml_t cfg
) {
112 switch_xml_t child
, param
;
113 char* kazoo_var_prefix
= NULL
;
114 char* profile_vars_prefix
= NULL
;
115 char* sep_array
[KZ_MAX_SEPARATE_STRINGS
];
117 kazoo_globals
.send_all_headers
= 0;
118 kazoo_globals
.send_all_private_headers
= 1;
119 kazoo_globals
.connection_timeout
= 500;
120 kazoo_globals
.ei_receive_timeout
= 200;
121 kazoo_globals
.receive_msg_preallocate
= 2000;
122 kazoo_globals
.event_stream_preallocate
= KZ_DEFAULT_STREAM_PRE_ALLOCATE
;
123 kazoo_globals
.send_msg_batch
= 10;
124 kazoo_globals
.event_stream_framing
= 2;
125 kazoo_globals
.event_stream_keepalive
= 1;
126 kazoo_globals
.event_stream_queue_timeout
= 200000;
127 kazoo_globals
.node_receiver_queue_timeout
= 100000;
128 kazoo_globals
.node_sender_queue_timeout
= 0;
129 kazoo_globals
.port
= 0;
130 kazoo_globals
.io_fault_tolerance
= 3;
131 kazoo_globals
.io_fault_tolerance_sleep
= 100000; // 100 ms
132 kazoo_globals
.json_encoding
= ERLANG_TUPLE
;
133 kazoo_globals
.delay_before_initial_fetch
= 10000000;
135 kazoo_globals
.legacy_events
= SWITCH_FALSE
;
136 kazoo_globals
.expand_headers_on_fetch
= SWITCH_TRUE
;
138 kz_set_tweak(KZ_TWEAK_INTERACTION_ID
);
139 kz_set_tweak(KZ_TWEAK_EXPORT_VARS
);
140 kz_set_tweak(KZ_TWEAK_SWITCH_URI
);
141 kz_set_tweak(KZ_TWEAK_REPLACES_CALL_ID
);
142 kz_set_tweak(KZ_TWEAK_LOOPBACK_VARS
);
143 kz_set_tweak(KZ_TWEAK_CALLER_ID
);
144 kz_set_tweak(KZ_TWEAK_TRANSFERS
);
145 kz_set_tweak(KZ_TWEAK_BRIDGE
);
146 kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_ALEG
);
147 kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_CALL_ID
);
148 kz_set_tweak(KZ_TWEAK_BRIDGE_VARIABLES
);
149 kz_set_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER
);
153 if ((child
= switch_xml_child(cfg
, "settings"))) {
154 for (param
= switch_xml_child(child
, "param"); param
; param
= param
->next
) {
155 char *var
= (char *) switch_xml_attr_soft(param
, "name");
156 char *val
= (char *) switch_xml_attr_soft(param
, "value");
158 if (!strcmp(var
, "listen-ip")) {
159 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set bind ip address: %s\n", val
);
161 } else if (!strcmp(var
, "listen-port")) {
162 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set bind port: %s\n", val
);
163 kazoo_globals
.port
= atoi(val
);
164 } else if (!strcmp(var
, "cookie")) {
165 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set cookie: %s\n", val
);
166 set_pref_ei_cookie(val
);
167 } else if (!strcmp(var
, "cookie-file")) {
168 if (read_cookie_from_file(val
) == 1) {
169 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Unable to read cookie from %s\n", val
);
171 } else if (!strcmp(var
, "nodename")) {
172 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set node name: %s\n", val
);
173 set_pref_ei_nodename(val
);
174 } else if (!strcmp(var
, "shortname")) {
175 kazoo_globals
.ei_shortname
= switch_true(val
);
176 } else if (!strcmp(var
, "kazoo-var-prefix")) {
177 kazoo_var_prefix
= switch_core_strdup(kazoo_globals
.pool
, val
);
178 } else if (!strcmp(var
, "set-profile-vars-prefix")) {
179 profile_vars_prefix
= switch_core_strdup(kazoo_globals
.pool
, val
);
180 } else if (!strcmp(var
, "compat-rel")) {
182 kazoo_globals
.ei_compat_rel
= atoi(val
);
184 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Invalid compatibility release '%s' specified\n", val
);
185 } else if (!strcmp(var
, "nat-map")) {
186 kazoo_globals
.nat_map
= switch_true(val
);
187 } else if (!strcmp(var
, "send-all-headers")) {
188 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set send-all-headers: %s\n", val
);
189 kazoo_globals
.send_all_headers
= switch_true(val
);
190 } else if (!strcmp(var
, "send-all-private-headers")) {
191 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set send-all-private-headers: %s\n", val
);
192 kazoo_globals
.send_all_private_headers
= switch_true(val
);
193 } else if (!strcmp(var
, "connection-timeout")) {
194 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set connection-timeout: %s\n", val
);
195 kazoo_globals
.connection_timeout
= atoi(val
);
196 } else if (!strcmp(var
, "receive-timeout")) {
197 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set receive-timeout: %s\n", val
);
198 kazoo_globals
.ei_receive_timeout
= atoi(val
);
199 } else if (!strcmp(var
, "receive-msg-preallocate")) {
200 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set receive-msg-preallocate: %s\n", val
);
201 kazoo_globals
.receive_msg_preallocate
= atoi(val
);
202 } else if (!strcmp(var
, "event-stream-preallocate")) {
203 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set event-stream-preallocate: %s\n", val
);
204 kazoo_globals
.event_stream_preallocate
= atoi(val
);
205 } else if (!strcmp(var
, "send-msg-batch-size")) {
206 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set send-msg-batch-size: %s\n", val
);
207 kazoo_globals
.send_msg_batch
= atoi(val
);
208 } else if (!strcmp(var
, "event-stream-framing")) {
209 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set event-stream-framing: %s\n", val
);
210 kazoo_globals
.event_stream_framing
= atoi(val
);
212 } else if (!strcmp(var
, "event-stream-keep-alive")) {
213 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set event-stream-keep-alive: %s\n", val
);
214 kazoo_globals
.event_stream_keepalive
= switch_true(val
);
216 } else if (!strcmp(var
, "io-fault-tolerance")) {
217 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set io-fault-tolerance: %s\n", val
);
218 kazoo_globals
.io_fault_tolerance
= atoi(val
);
219 } else if (!strcmp(var
, "io-fault-tolerance-sleep-micro")) {
220 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set %s : %s\n", var
, val
);
221 kazoo_globals
.io_fault_tolerance_sleep
= atoi(val
);
222 } else if (!strcmp(var
, "io-fault-tolerance-sleep-ms")) {
223 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set %s : %s\n", var
, val
);
224 kazoo_globals
.io_fault_tolerance_sleep
= atoi(val
) * 1000;
225 } else if (!strcmp(var
, "io-fault-tolerance-sleep-sec")) {
226 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set %s : %s\n", var
, val
);
227 kazoo_globals
.io_fault_tolerance_sleep
= atoi(val
) * 1000000;
230 } else if (!strcmp(var
, "node-worker-threads")) {
231 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set node-worker-threads: %s\n", val
);
232 kazoo_globals
.node_worker_threads
= atoi(val
);
233 } else if (!strcmp(var
, "json-term-encoding")) {
234 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set json-term-encoding: %s\n", val
);
235 if(!strcmp(val
, "map")) {
236 kazoo_globals
.json_encoding
= ERLANG_MAP
;
238 } else if (!strcmp(var
, "legacy-events")) {
239 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set legacy-events: %s\n", val
);
240 kazoo_globals
.legacy_events
= switch_true(val
);
241 } else if (!strcmp(var
, "expand-headers-on-fetch")) {
242 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set expand-headers-on-fetch: %s\n", val
);
243 kazoo_globals
.expand_headers_on_fetch
= switch_true(val
);
244 } else if (!strcmp(var
, "node-receiver-queue-timeout")) {
245 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set %s : %s\n", var
, val
);
246 kazoo_globals
.node_receiver_queue_timeout
= atoi(val
);
247 } else if (!strcmp(var
, "node-sender-queue-timeout")) {
248 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set %s : %s\n", var
, val
);
249 kazoo_globals
.node_sender_queue_timeout
= atoi(val
);
250 } else if (!strcmp(var
, "event-stream-queue-timeout")) {
251 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set %s : %s\n", var
, val
);
252 kazoo_globals
.event_stream_queue_timeout
= atoi(val
);
253 } else if (!strcmp(var
, "delay-before-initial-fetch-micro")) {
254 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set %s : %s\n", var
, val
);
255 kazoo_globals
.delay_before_initial_fetch
= atoi(val
);
256 } else if (!strcmp(var
, "delay-before-initial-fetch-ms")) {
257 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set %s : %s\n", var
, val
);
258 kazoo_globals
.delay_before_initial_fetch
= atoi(val
) * 1000;
259 } else if (!strcmp(var
, "delay-before-initial-fetch-sec")) {
260 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set %s : %s\n", var
, val
);
261 kazoo_globals
.delay_before_initial_fetch
= atoi(val
) * 1000000;
263 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "unknown config option %s : %s\n", var
, val
);
268 if ((child
= switch_xml_child(cfg
, "tweaks"))) {
269 char *default_tweaks
= (char *) switch_xml_attr_soft(child
, "default");
270 if (default_tweaks
&& !zstr(default_tweaks
)) {
271 int i
, v
= switch_true(default_tweaks
) ? 1 : 0;
272 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set tweak default : %s\n", default_tweaks
);
273 for (i
= 0; i
< KZ_TWEAK_MAX
; i
++) kazoo_globals
.tweaks
[i
] = v
;
275 for (param
= switch_xml_child(child
, "tweak"); param
; param
= param
->next
) {
276 kz_tweak_t tweak
= KZ_TWEAK_MAX
;
277 char *var
= (char *) switch_xml_attr_soft(param
, "name");
278 char *val
= (char *) switch_xml_attr_soft(param
, "value");
279 if(var
&& val
&& kz_name_tweak(var
, &tweak
) == SWITCH_STATUS_SUCCESS
) {
280 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set tweak %s : %s\n", var
, val
);
281 if(switch_true(val
)) {
284 kz_clear_tweak(tweak
);
290 if ((child
= switch_xml_child(cfg
, "variables"))) {
291 for (param
= switch_xml_child(child
, "variable"); param
; param
= param
->next
) {
292 char *var
= (char *) switch_xml_attr_soft(param
, "name");
293 char *val
= (char *) switch_xml_attr_soft(param
, "value");
295 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "Set core variable %s : %s\n", var
, val
);
296 switch_core_set_variable(var
, val
);
301 if ((child
= switch_xml_child(cfg
, "event-filter"))) {
302 switch_hash_t
*filter
;
304 switch_core_hash_init(&filter
);
305 for (param
= switch_xml_child(child
, "header"); param
; param
= param
->next
) {
306 char *var
= (char *) switch_xml_attr_soft(param
, "name");
307 switch_core_hash_insert(filter
, var
, "1");
309 kazoo_globals
.event_filter
= filter
;
312 if (kazoo_globals
.receive_msg_preallocate
< 0) {
313 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Invalid receive message preallocate value, disabled\n");
314 kazoo_globals
.receive_msg_preallocate
= 0;
317 if (kazoo_globals
.event_stream_preallocate
< 0) {
318 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Invalid event stream preallocate value, disabled\n");
319 kazoo_globals
.event_stream_preallocate
= 0;
322 if (kazoo_globals
.send_msg_batch
< 1) {
323 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Invalid send message batch size, reverting to default\n");
324 kazoo_globals
.send_msg_batch
= 10;
327 if (kazoo_globals
.io_fault_tolerance
< 1) {
328 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Invalid I/O fault tolerance, reverting to default\n");
329 kazoo_globals
.io_fault_tolerance
= 10;
332 if (!kazoo_globals
.event_filter
) {
333 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Event filter not found in configuration, using default\n");
334 kazoo_globals
.event_filter
= create_default_filter();
337 if (kazoo_globals
.event_stream_framing
< 1 || kazoo_globals
.event_stream_framing
> 4) {
338 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Invalid event stream framing value, using default\n");
339 kazoo_globals
.event_stream_framing
= 2;
342 if (zstr(kazoo_var_prefix
)) {
343 kazoo_var_prefix
= switch_core_strdup(kazoo_globals
.pool
, "ecallmgr_;cav_");
346 if (zstr(profile_vars_prefix
)) {
347 profile_vars_prefix
= switch_core_strdup(kazoo_globals
.pool
, "effective_;origination_");
350 kazoo_globals
.kazoo_var_prefixes
= switch_core_alloc(kazoo_globals
.pool
, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS
);
351 array_len
= switch_separate_string(kazoo_var_prefix
, ';', sep_array
, KZ_MAX_SEPARATE_STRINGS
- 1);
352 for(i
=0; i
< array_len
; i
++) {
354 sprintf(var
, "variable_%s", sep_array
[i
]);
355 kazoo_globals
.kazoo_var_prefixes
[i
] = switch_core_strdup(kazoo_globals
.pool
, var
);
358 kazoo_globals
.profile_vars_prefixes
= switch_core_alloc(kazoo_globals
.pool
, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS
);
359 array_len
= switch_separate_string(profile_vars_prefix
, ';', sep_array
, KZ_MAX_SEPARATE_STRINGS
- 1);
360 for(i
=0; i
< array_len
; i
++) {
361 kazoo_globals
.profile_vars_prefixes
[i
] = switch_core_strdup(kazoo_globals
.pool
, sep_array
[i
]);
364 if (!kazoo_globals
.node_worker_threads
) {
365 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "Number of node worker threads not found in configuration, using default\n");
366 kazoo_globals
.node_worker_threads
= 10;
369 if (zstr(kazoo_globals
.ip
)) {
370 set_pref_ip("0.0.0.0");
373 if (zstr(kazoo_globals
.ei_cookie
)) {
375 char *home_dir
= getenv("HOME");
378 if (!zstr(home_dir
)) {
379 /* $HOME/.erlang.cookie */
380 switch_snprintf(path_buf
, sizeof (path_buf
), "%s%s%s", home_dir
, SWITCH_PATH_SEPARATOR
, ".erlang.cookie");
381 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_DEBUG
, "Checking for cookie at path: %s\n", path_buf
);
383 res
= read_cookie_from_file(path_buf
);
385 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_WARNING
, "No cookie or valid cookie file specified, using default cookie\n");
386 set_pref_ei_cookie("ClueCon");
391 if (!kazoo_globals
.ei_nodename
) {
392 set_pref_ei_nodename("freeswitch");
395 if (!kazoo_globals
.nat_map
) {
396 kazoo_globals
.nat_map
= 0;
399 return SWITCH_STATUS_SUCCESS
;
402 switch_status_t
kazoo_config_handlers(switch_xml_t cfg
)
404 switch_xml_t def
= NULL
;
405 switch_xml_t child
, param
;
407 kazoo_config_ptr definitions
= NULL
, fetch_handlers
= NULL
, event_handlers
= NULL
;
408 kazoo_event_profile_ptr events
= NULL
;
410 xml
= strndup(kz_default_config
, kz_default_config_size
);
411 def
= switch_xml_parse_str_dup(xml
);
416 if ((child
= switch_xml_child(cfg
, "variables"))) {
417 for (param
= switch_xml_child(child
, "variable"); param
; param
= param
->next
) {
418 char *var
= (char *) switch_xml_attr_soft(param
, "name");
419 char *val
= (char *) switch_xml_attr_soft(param
, "value");
421 switch_core_set_variable(var
, val
);
424 } else if ((child
= switch_xml_child(def
, "variables"))) {
425 for (param
= switch_xml_child(child
, "variable"); param
; param
= param
->next
) {
426 char *var
= (char *) switch_xml_attr_soft(param
, "name");
427 char *val
= (char *) switch_xml_attr_soft(param
, "value");
429 switch_core_set_variable(var
, val
);
434 definitions
= kazoo_config_definitions(cfg
);
435 if(definitions
== NULL
) {
436 if(kazoo_globals
.definitions
== NULL
) {
437 definitions
= kazoo_config_definitions(def
);
439 definitions
= kazoo_globals
.definitions
;
443 fetch_handlers
= kazoo_config_fetch_handlers(definitions
, cfg
);
444 if(fetch_handlers
== NULL
) {
445 if(kazoo_globals
.fetch_handlers
== NULL
) {
446 fetch_handlers
= kazoo_config_fetch_handlers(definitions
, def
);
448 fetch_handlers
= kazoo_globals
.fetch_handlers
;
452 event_handlers
= kazoo_config_event_handlers(definitions
, cfg
);
453 if(event_handlers
== NULL
) {
454 if(kazoo_globals
.event_handlers
== NULL
) {
455 event_handlers
= kazoo_config_event_handlers(definitions
, def
);
457 event_handlers
= kazoo_globals
.event_handlers
;
461 if(event_handlers
!= NULL
) {
462 events
= (kazoo_event_profile_ptr
) switch_core_hash_find(event_handlers
->hash
, "default");
466 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Failed to get default handler for events\n");
467 destroy_config(&event_handlers
);
468 event_handlers
= kazoo_config_event_handlers(definitions
, def
);
469 events
= (kazoo_event_profile_ptr
) switch_core_hash_find(event_handlers
->hash
, "default");
472 if(kazoo_globals
.events
!= events
) {
473 bind_event_profiles(events
->events
);
474 kazoo_globals
.events
= events
;
477 if(kazoo_globals
.event_handlers
!= event_handlers
) {
478 kazoo_config_ptr tmp
= kazoo_globals
.event_handlers
;
479 kazoo_globals
.event_handlers
= event_handlers
;
480 destroy_config(&tmp
);
483 if(kazoo_globals
.fetch_handlers
!= fetch_handlers
) {
484 kazoo_config_ptr tmp
= kazoo_globals
.fetch_handlers
;
485 kazoo_globals
.fetch_handlers
= fetch_handlers
;
486 rebind_fetch_profiles(fetch_handlers
);
487 destroy_config(&tmp
);
490 if(kazoo_globals
.definitions
!= definitions
) {
491 kazoo_config_ptr tmp
= kazoo_globals
.definitions
;
492 kazoo_globals
.definitions
= definitions
;
493 destroy_config(&tmp
);
497 switch_xml_free(def
);
498 switch_safe_free(xml
);
500 return SWITCH_STATUS_SUCCESS
;
503 switch_status_t
kazoo_load_config()
505 char *cf
= "kazoo.conf";
506 switch_xml_t cfg
, xml
;
507 if (!(xml
= switch_xml_open_cfg(cf
, &cfg
, NULL
))) {
508 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Failed to open configuration file %s\n", cf
);
509 return SWITCH_STATUS_FALSE
;
511 kazoo_ei_config(cfg
);
512 kazoo_config_handlers(cfg
);
513 switch_xml_free(xml
);
516 return SWITCH_STATUS_SUCCESS
;
519 void kazoo_destroy_config()
521 destroy_config(&kazoo_globals
.event_handlers
);
522 destroy_config(&kazoo_globals
.fetch_handlers
);
523 destroy_config(&kazoo_globals
.definitions
);
526 switch_status_t
kazoo_config_events(kazoo_config_ptr definitions
, switch_memory_pool_t
*pool
, switch_xml_t cfg
, kazoo_event_profile_ptr profile
)
528 switch_xml_t events
, event
;
529 kazoo_event_ptr prv
= NULL
, cur
= NULL
;
532 if ((events
= switch_xml_child(cfg
, "events")) != NULL
) {
533 for (event
= switch_xml_child(events
, "event"); event
; event
= event
->next
) {
534 const char *var
= switch_xml_attr(event
, "name");
535 cur
= (kazoo_event_ptr
) switch_core_alloc(pool
, sizeof(kazoo_event_t
));
536 memset(cur
, 0, sizeof(kazoo_event_t
));
538 profile
->events
= prv
= cur
;
543 cur
->profile
= profile
;
544 cur
->name
= switch_core_strdup(pool
, var
);
545 kazoo_config_filters(pool
, event
, &cur
->filter
);
546 kazoo_config_fields(definitions
, pool
, event
, &cur
->fields
);
547 if (switch_xml_child(event
, "logging") != NULL
) {
548 kazoo_config_loglevels(pool
, event
, &cur
->logging
);
553 return SWITCH_STATUS_SUCCESS
;
558 switch_status_t
kazoo_config_fetch_handler(kazoo_config_ptr definitions
, kazoo_config_ptr root
, switch_xml_t cfg
, kazoo_fetch_profile_ptr
*ptr
)
560 kazoo_fetch_profile_ptr profile
= NULL
;
561 switch_xml_t params
, param
;
562 switch_xml_section_t fetch_section
;
563 int fetch_timeout
= 2000000;
564 switch_memory_pool_t
*pool
= NULL
;
566 char *name
= (char *) switch_xml_attr_soft(cfg
, "name");
569 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "missing name in profile\n");
571 return SWITCH_STATUS_GENERR
;
574 if (switch_core_new_memory_pool(&pool
) != SWITCH_STATUS_SUCCESS
) {
575 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "error allocation pool for new profile : %s\n", name
);
577 return SWITCH_STATUS_GENERR
;
580 profile
= switch_core_alloc(pool
, sizeof(kazoo_fetch_profile_t
));
581 profile
->pool
= pool
;
582 profile
->root
= root
;
583 profile
->name
= switch_core_strdup(profile
->pool
, name
);
585 fetch_section
= switch_xml_parse_section_string(name
);
587 if ((params
= switch_xml_child(cfg
, "params")) != NULL
) {
589 for (param
= switch_xml_child(params
, "param"); param
; param
= param
->next
) {
590 char *var
= (char *) switch_xml_attr_soft(param
, "name");
591 char *val
= (char *) switch_xml_attr_soft(param
, "value");
594 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_CRIT
, "Profile[%s] param missing 'name' attribute\n", name
);
599 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_CRIT
, "Profile[%s] param[%s] missing 'value' attribute\n", name
, var
);
603 if (!strncmp(var
, "fetch-timeout", 13)) {
604 fetch_timeout
= atoi(val
);
605 } else if (!strncmp(var
, "fetch-section", 13)) {
606 fetch_section
= switch_xml_parse_section_string(val
);
611 if (fetch_section
== SWITCH_XML_SECTION_RESULT
) {
612 char *tmp
= switch_xml_toxml(cfg
, SWITCH_FALSE
);
613 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_CRIT
, "Fetch Profile[%s] invalid fetch-section: %s\n", name
, tmp
);
619 profile
->fetch_timeout
= fetch_timeout
;
620 profile
->section
= fetch_section
;
621 kazoo_config_fields(definitions
, pool
, cfg
, &profile
->fields
);
622 kazoo_config_loglevels(pool
, cfg
, &profile
->logging
);
625 if ( switch_core_hash_insert(root
->hash
, name
, (void *) profile
) != SWITCH_STATUS_SUCCESS
) {
626 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "failed to insert new fetch profile [%s] into kazoo profile hash\n", name
);
635 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "fetch handler profile %s successfully configured\n", name
);
637 return SWITCH_STATUS_SUCCESS
;
642 switch_core_destroy_memory_pool(&pool
);
645 return SWITCH_STATUS_GENERR
;
649 switch_status_t
kazoo_config_event_handler(kazoo_config_ptr definitions
, kazoo_config_ptr root
, switch_xml_t cfg
, kazoo_event_profile_ptr
*ptr
)
651 kazoo_event_profile_ptr profile
= NULL
;
652 switch_memory_pool_t
*pool
= NULL
;
654 char *name
= (char *) switch_xml_attr_soft(cfg
, "name");
656 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "missing name in profile\n");
657 return SWITCH_STATUS_GENERR
;
660 if (switch_core_new_memory_pool(&pool
) != SWITCH_STATUS_SUCCESS
) {
661 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "error allocation pool for new profile : %s\n", name
);
662 return SWITCH_STATUS_GENERR
;
665 profile
= switch_core_alloc(pool
, sizeof(kazoo_event_profile_t
));
666 profile
->pool
= pool
;
667 profile
->root
= root
;
668 profile
->name
= switch_core_strdup(profile
->pool
, name
);
670 kazoo_config_filters(pool
, cfg
, &profile
->filter
);
671 kazoo_config_fields(definitions
, pool
, cfg
, &profile
->fields
);
672 kazoo_config_events(definitions
, pool
, cfg
, profile
);
673 kazoo_config_loglevels(pool
, cfg
, &profile
->logging
);
676 if ( switch_core_hash_insert(root
->hash
, name
, (void *) profile
) != SWITCH_STATUS_SUCCESS
) {
677 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_ERROR
, "Failed to insert new profile [%s] into kazoo profile hash\n", name
);
685 switch_log_printf(SWITCH_CHANNEL_LOG
, SWITCH_LOG_INFO
, "event handler profile %s successfully configured\n", name
);
686 return SWITCH_STATUS_SUCCESS
;
691 switch_core_destroy_memory_pool(&pool
);
693 return SWITCH_STATUS_GENERR
;
707 * vim:set softtabstop=4 shiftwidth=4 tabstop=4