1 /*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
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/
11 *
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
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
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.
23 *
24 * Based on mod_skel by
25 * Anthony Minessale II <anthm@freeswitch.org>
26 *
27 * Contributor(s):
28 *
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>
34 *
35 * kazoo.c -- Sends FreeSWITCH events to an AMQP broker
36 *
37 */
38
39 #include "mod_kazoo.h"
40
41 #define KZ_DEFAULT_STREAM_PRE_ALLOCATE 8192
42
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)
45
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);
50
read_cookie_from_file(char * filename)51 static int read_cookie_from_file(char *filename) {
52 int fd;
53 char cookie[MAXATOMLEN + 1];
54 char *end;
55 struct stat buf;
56 ssize_t res;
57
58 if (!stat(filename, &buf)) {
59 if ((buf.st_mode & S_IRWXG) || (buf.st_mode & S_IRWXO)) {
60 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s must only be accessible by owner only.\n", filename);
61 return 2;
62 }
63 if (buf.st_size > MAXATOMLEN) {
64 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s contains a cookie larger than the maximum atom size of %d.\n", filename, MAXATOMLEN);
65 return 2;
66 }
67 fd = open(filename, O_RDONLY);
68 if (fd < 1) {
69 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to open cookie file %s : %d.\n", filename, errno);
70 return 2;
71 }
72
73 if ((res = read(fd, cookie, MAXATOMLEN)) < 1) {
74 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie file %s : %d.\n", filename, errno);
75 }
76
77 cookie[MAXATOMLEN] = '\0';
78
79 /* replace any end of line characters with a null */
80 if ((end = strchr(cookie, '\n'))) {
81 *end = '\0';
82 }
83
84 if ((end = strchr(cookie, '\r'))) {
85 *end = '\0';
86 }
87
88 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie from file %s: %s\n", filename, cookie);
89
90 set_pref_ei_cookie(cookie);
91 return 0;
92 } else {
93 /* don't error here, because we might be blindly trying to read $HOME/.erlang.cookie, and that can fail silently */
94 return 1;
95 }
96 }
97
kz_set_hostname()98 void kz_set_hostname()
99 {
100 if (kazoo_globals.hostname == NULL) {
101 char hostname[NODENAME_MAX];
102 memcpy(hostname, switch_core_get_hostname(), NODENAME_MAX);
103 kazoo_globals.hostname_ent = gethostbyname(hostname);
104 if(kazoo_globals.hostname_ent != NULL) {
105 kazoo_globals.hostname = switch_core_strdup(kazoo_globals.pool, kazoo_globals.hostname_ent->h_name);
106 } else {
107 kazoo_globals.hostname = switch_core_strdup(kazoo_globals.pool, hostname);
108 }
109 }
110 }
111
kazoo_ei_config(switch_xml_t cfg)112 switch_status_t kazoo_ei_config(switch_xml_t cfg) {
113 switch_xml_t child, param;
114 char* kazoo_var_prefix = NULL;
115 char* profile_vars_prefix = NULL;
116 char* sep_array[KZ_MAX_SEPARATE_STRINGS];
117 int array_len, i;
118 kazoo_globals.send_all_headers = 0;
119 kazoo_globals.send_all_private_headers = 1;
120 kazoo_globals.connection_timeout = 500;
121 kazoo_globals.ei_receive_timeout = 200;
122 kazoo_globals.receive_msg_preallocate = 2000;
123 kazoo_globals.event_stream_preallocate = KZ_DEFAULT_STREAM_PRE_ALLOCATE;
124 kazoo_globals.send_msg_batch = 10;
125 kazoo_globals.event_stream_framing = 2;
126 kazoo_globals.event_stream_keepalive = 1;
127 kazoo_globals.event_stream_queue_timeout = 200000;
128 kazoo_globals.node_receiver_queue_timeout = 100000;
129 kazoo_globals.node_sender_queue_timeout = 0;
130 kazoo_globals.port = 0;
131 kazoo_globals.io_fault_tolerance = 3;
132 kazoo_globals.io_fault_tolerance_sleep = 100000; // 100 ms
133 kazoo_globals.json_encoding = ERLANG_TUPLE;
134 kazoo_globals.delay_before_initial_fetch = 10000000;
135
136 kazoo_globals.legacy_events = SWITCH_FALSE;
137 kazoo_globals.expand_headers_on_fetch = SWITCH_TRUE;
138
139 kz_set_tweak(KZ_TWEAK_INTERACTION_ID);
140 kz_set_tweak(KZ_TWEAK_EXPORT_VARS);
141 kz_set_tweak(KZ_TWEAK_SWITCH_URI);
142 kz_set_tweak(KZ_TWEAK_REPLACES_CALL_ID);
143 kz_set_tweak(KZ_TWEAK_LOOPBACK_VARS);
144 kz_set_tweak(KZ_TWEAK_CALLER_ID);
145 kz_set_tweak(KZ_TWEAK_TRANSFERS);
146 kz_set_tweak(KZ_TWEAK_BRIDGE);
147 kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_ALEG);
148 kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_CALL_ID);
149 kz_set_tweak(KZ_TWEAK_BRIDGE_VARIABLES);
150 kz_set_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER);
151
152
153
154 if ((child = switch_xml_child(cfg, "settings"))) {
155 for (param = switch_xml_child(child, "param"); param; param = param->next) {
156 char *var = (char *) switch_xml_attr_soft(param, "name");
157 char *val = (char *) switch_xml_attr_soft(param, "value");
158
159 if (!strcmp(var, "listen-ip")) {
160 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind ip address: %s\n", val);
161 set_pref_ip(val);
162 } else if (!strcmp(var, "listen-port")) {
163 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind port: %s\n", val);
164 kazoo_globals.port = atoi(val);
165 } else if (!strcmp(var, "cookie")) {
166 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie: %s\n", val);
167 set_pref_ei_cookie(val);
168 } else if (!strcmp(var, "cookie-file")) {
169 if (read_cookie_from_file(val) == 1) {
170 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie from %s\n", val);
171 }
172 } else if (!strcmp(var, "nodename")) {
173 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set node name: %s\n", val);
174 set_pref_ei_nodename(val);
175 } else if (!strcmp(var, "shortname")) {
176 kazoo_globals.ei_shortname = switch_true(val);
177 } else if (!strcmp(var, "kazoo-var-prefix")) {
178 kazoo_var_prefix = switch_core_strdup(kazoo_globals.pool, val);
179 } else if (!strcmp(var, "set-profile-vars-prefix")) {
180 profile_vars_prefix = switch_core_strdup(kazoo_globals.pool, val);
181 } else if (!strcmp(var, "compat-rel")) {
182 if (atoi(val) >= 7)
183 kazoo_globals.ei_compat_rel = atoi(val);
184 else
185 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid compatibility release '%s' specified\n", val);
186 } else if (!strcmp(var, "nat-map")) {
187 kazoo_globals.nat_map = switch_true(val);
188 } else if (!strcmp(var, "send-all-headers")) {
189 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-headers: %s\n", val);
190 kazoo_globals.send_all_headers = switch_true(val);
191 } else if (!strcmp(var, "send-all-private-headers")) {
192 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-private-headers: %s\n", val);
193 kazoo_globals.send_all_private_headers = switch_true(val);
194 } else if (!strcmp(var, "connection-timeout")) {
195 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set connection-timeout: %s\n", val);
196 kazoo_globals.connection_timeout = atoi(val);
197 } else if (!strcmp(var, "receive-timeout")) {
198 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-timeout: %s\n", val);
199 kazoo_globals.ei_receive_timeout = atoi(val);
200 } else if (!strcmp(var, "receive-msg-preallocate")) {
201 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-msg-preallocate: %s\n", val);
202 kazoo_globals.receive_msg_preallocate = atoi(val);
203 } else if (!strcmp(var, "event-stream-preallocate")) {
204 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-preallocate: %s\n", val);
205 kazoo_globals.event_stream_preallocate = atoi(val);
206 } else if (!strcmp(var, "send-msg-batch-size")) {
207 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-msg-batch-size: %s\n", val);
208 kazoo_globals.send_msg_batch = atoi(val);
209 } else if (!strcmp(var, "event-stream-framing")) {
210 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-framing: %s\n", val);
211 kazoo_globals.event_stream_framing = atoi(val);
212
213 } else if (!strcmp(var, "event-stream-keep-alive")) {
214 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-keep-alive: %s\n", val);
215 kazoo_globals.event_stream_keepalive = switch_true(val);
216
217 } else if (!strcmp(var, "io-fault-tolerance")) {
218 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set io-fault-tolerance: %s\n", val);
219 kazoo_globals.io_fault_tolerance = atoi(val);
220 } else if (!strcmp(var, "io-fault-tolerance-sleep-micro")) {
221 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
222 kazoo_globals.io_fault_tolerance_sleep = atoi(val);
223 } else if (!strcmp(var, "io-fault-tolerance-sleep-ms")) {
224 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
225 kazoo_globals.io_fault_tolerance_sleep = atoi(val) * 1000;
226 } else if (!strcmp(var, "io-fault-tolerance-sleep-sec")) {
227 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
228 kazoo_globals.io_fault_tolerance_sleep = atoi(val) * 1000000;
229
230
231 } else if (!strcmp(var, "node-worker-threads")) {
232 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set node-worker-threads: %s\n", val);
233 kazoo_globals.node_worker_threads = atoi(val);
234 } else if (!strcmp(var, "json-term-encoding")) {
235 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set json-term-encoding: %s\n", val);
236 if(!strcmp(val, "map")) {
237 kazoo_globals.json_encoding = ERLANG_MAP;
238 }
239 } else if (!strcmp(var, "legacy-events")) {
240 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set legacy-events: %s\n", val);
241 kazoo_globals.legacy_events = switch_true(val);
242 } else if (!strcmp(var, "expand-headers-on-fetch")) {
243 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set expand-headers-on-fetch: %s\n", val);
244 kazoo_globals.expand_headers_on_fetch = switch_true(val);
245 } else if (!strcmp(var, "node-receiver-queue-timeout")) {
246 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
247 kazoo_globals.node_receiver_queue_timeout = atoi(val);
248 } else if (!strcmp(var, "node-sender-queue-timeout")) {
249 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
250 kazoo_globals.node_sender_queue_timeout = atoi(val);
251 } else if (!strcmp(var, "event-stream-queue-timeout")) {
252 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
253 kazoo_globals.event_stream_queue_timeout = atoi(val);
254 } else if (!strcmp(var, "delay-before-initial-fetch-micro")) {
255 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
256 kazoo_globals.delay_before_initial_fetch = atoi(val);
257 } else if (!strcmp(var, "delay-before-initial-fetch-ms")) {
258 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
259 kazoo_globals.delay_before_initial_fetch = atoi(val) * 1000;
260 } else if (!strcmp(var, "delay-before-initial-fetch-sec")) {
261 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val);
262 kazoo_globals.delay_before_initial_fetch = atoi(val) * 1000000;
263 } else {
264 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unknown config option %s : %s\n", var, val);
265 }
266 }
267 }
268
269 if ((child = switch_xml_child(cfg, "tweaks"))) {
270 char *default_tweaks = (char *) switch_xml_attr_soft(child, "default");
271 if (default_tweaks && !zstr(default_tweaks)) {
272 int i, v = switch_true(default_tweaks) ? 1 : 0;
273 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set tweak default : %s\n", default_tweaks);
274 for (i = 0; i < KZ_TWEAK_MAX; i++) kazoo_globals.tweaks[i] = v;
275 }
276 for (param = switch_xml_child(child, "tweak"); param; param = param->next) {
277 kz_tweak_t tweak = KZ_TWEAK_MAX;
278 char *var = (char *) switch_xml_attr_soft(param, "name");
279 char *val = (char *) switch_xml_attr_soft(param, "value");
280 if(var && val && kz_name_tweak(var, &tweak) == SWITCH_STATUS_SUCCESS) {
281 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set tweak %s : %s\n", var, val);
282 if(switch_true(val)) {
283 kz_set_tweak(tweak);
284 } else {
285 kz_clear_tweak(tweak);
286 }
287 }
288 }
289 }
290
291 if ((child = switch_xml_child(cfg, "variables"))) {
292 for (param = switch_xml_child(child, "variable"); param; param = param->next) {
293 char *var = (char *) switch_xml_attr_soft(param, "name");
294 char *val = (char *) switch_xml_attr_soft(param, "value");
295 if(var && val) {
296 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set core variable %s : %s\n", var, val);
297 switch_core_set_variable(var, val);
298 }
299 }
300 }
301
302 if ((child = switch_xml_child(cfg, "event-filter"))) {
303 switch_hash_t *filter;
304
305 switch_core_hash_init(&filter);
306 for (param = switch_xml_child(child, "header"); param; param = param->next) {
307 char *var = (char *) switch_xml_attr_soft(param, "name");
308 switch_core_hash_insert(filter, var, "1");
309 }
310 kazoo_globals.event_filter = filter;
311 }
312
313 if (kazoo_globals.receive_msg_preallocate < 0) {
314 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid receive message preallocate value, disabled\n");
315 kazoo_globals.receive_msg_preallocate = 0;
316 }
317
318 if (kazoo_globals.event_stream_preallocate < 0) {
319 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream preallocate value, disabled\n");
320 kazoo_globals.event_stream_preallocate = 0;
321 }
322
323 if (kazoo_globals.send_msg_batch < 1) {
324 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid send message batch size, reverting to default\n");
325 kazoo_globals.send_msg_batch = 10;
326 }
327
328 if (kazoo_globals.io_fault_tolerance < 1) {
329 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid I/O fault tolerance, reverting to default\n");
330 kazoo_globals.io_fault_tolerance = 10;
331 }
332
333 if (!kazoo_globals.event_filter) {
334 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Event filter not found in configuration, using default\n");
335 kazoo_globals.event_filter = create_default_filter();
336 }
337
338 if (kazoo_globals.event_stream_framing < 1 || kazoo_globals.event_stream_framing > 4) {
339 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream framing value, using default\n");
340 kazoo_globals.event_stream_framing = 2;
341 }
342
343 if (zstr(kazoo_var_prefix)) {
344 kazoo_var_prefix = switch_core_strdup(kazoo_globals.pool, "ecallmgr_;cav_");
345 }
346
347 if (zstr(profile_vars_prefix)) {
348 profile_vars_prefix = switch_core_strdup(kazoo_globals.pool, "effective_;origination_");
349 }
350
351 kazoo_globals.kazoo_var_prefixes = switch_core_alloc(kazoo_globals.pool, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS);
352 array_len = switch_separate_string(kazoo_var_prefix, ';', sep_array, KZ_MAX_SEPARATE_STRINGS - 1);
353 for(i=0; i < array_len; i++) {
354 char var[100];
355 sprintf(var, "variable_%s", sep_array[i]);
356 kazoo_globals.kazoo_var_prefixes[i] = switch_core_strdup(kazoo_globals.pool, var);
357 }
358
359 kazoo_globals.profile_vars_prefixes = switch_core_alloc(kazoo_globals.pool, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS);
360 array_len = switch_separate_string(profile_vars_prefix, ';', sep_array, KZ_MAX_SEPARATE_STRINGS - 1);
361 for(i=0; i < array_len; i++) {
362 kazoo_globals.profile_vars_prefixes[i] = switch_core_strdup(kazoo_globals.pool, sep_array[i]);
363 }
364
365 if (!kazoo_globals.node_worker_threads) {
366 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Number of node worker threads not found in configuration, using default\n");
367 kazoo_globals.node_worker_threads = 10;
368 }
369
370 if (zstr(kazoo_globals.ip)) {
371 set_pref_ip("0.0.0.0");
372 }
373
374 if (zstr(kazoo_globals.ei_cookie)) {
375 int res;
376 char *home_dir = getenv("HOME");
377 char path_buf[1024];
378
379 if (!zstr(home_dir)) {
380 /* $HOME/.erlang.cookie */
381 switch_snprintf(path_buf, sizeof (path_buf), "%s%s%s", home_dir, SWITCH_PATH_SEPARATOR, ".erlang.cookie");
382 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for cookie at path: %s\n", path_buf);
383
384 res = read_cookie_from_file(path_buf);
385 if (res) {
386 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No cookie or valid cookie file specified, using default cookie\n");
387 set_pref_ei_cookie("ClueCon");
388 }
389 }
390 }
391
392 if (!kazoo_globals.ei_nodename) {
393 set_pref_ei_nodename("freeswitch");
394 }
395
396 if (!kazoo_globals.nat_map) {
397 kazoo_globals.nat_map = 0;
398 }
399
400 return SWITCH_STATUS_SUCCESS;
401 }
402
kazoo_config_handlers(switch_xml_t cfg)403 switch_status_t kazoo_config_handlers(switch_xml_t cfg)
404 {
405 switch_xml_t def = NULL;
406 switch_xml_t child, param;
407 char* xml = NULL;
408 kazoo_config_ptr definitions = NULL, fetch_handlers = NULL, event_handlers = NULL;
409 kazoo_event_profile_ptr events = NULL;
410
411 xml = strndup(kz_default_config, kz_default_config_size);
412 def = switch_xml_parse_str_dup(xml);
413
414 kz_xml_process(def);
415 kz_xml_process(cfg);
416
417 if ((child = switch_xml_child(cfg, "variables"))) {
418 for (param = switch_xml_child(child, "variable"); param; param = param->next) {
419 char *var = (char *) switch_xml_attr_soft(param, "name");
420 char *val = (char *) switch_xml_attr_soft(param, "value");
421 if(var && val) {
422 switch_core_set_variable(var, val);
423 }
424 }
425 } else if ((child = switch_xml_child(def, "variables"))) {
426 for (param = switch_xml_child(child, "variable"); param; param = param->next) {
427 char *var = (char *) switch_xml_attr_soft(param, "name");
428 char *val = (char *) switch_xml_attr_soft(param, "value");
429 if(var && val) {
430 switch_core_set_variable(var, val);
431 }
432 }
433 }
434
435 definitions = kazoo_config_definitions(cfg);
436 if(definitions == NULL) {
437 if(kazoo_globals.definitions == NULL) {
438 definitions = kazoo_config_definitions(def);
439 } else {
440 definitions = kazoo_globals.definitions;
441 }
442 }
443
444 fetch_handlers = kazoo_config_fetch_handlers(definitions, cfg);
445 if(fetch_handlers == NULL) {
446 if(kazoo_globals.fetch_handlers == NULL) {
447 fetch_handlers = kazoo_config_fetch_handlers(definitions, def);
448 } else {
449 fetch_handlers = kazoo_globals.fetch_handlers;
450 }
451 }
452
453 event_handlers = kazoo_config_event_handlers(definitions, cfg);
454 if(event_handlers == NULL) {
455 if(kazoo_globals.event_handlers == NULL) {
456 event_handlers = kazoo_config_event_handlers(definitions, def);
457 } else {
458 event_handlers = kazoo_globals.event_handlers;
459 }
460 }
461
462 if(event_handlers != NULL) {
463 events = (kazoo_event_profile_ptr) switch_core_hash_find(event_handlers->hash, "default");
464 }
465
466 if(events == NULL) {
467 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get default handler for events\n");
468 destroy_config(&event_handlers);
469 event_handlers = kazoo_config_event_handlers(definitions, def);
470 events = (kazoo_event_profile_ptr) switch_core_hash_find(event_handlers->hash, "default");
471 }
472
473 if(kazoo_globals.events != events) {
474 bind_event_profiles(events->events);
475 kazoo_globals.events = events;
476 }
477
478 if(kazoo_globals.event_handlers != event_handlers) {
479 kazoo_config_ptr tmp = kazoo_globals.event_handlers;
480 kazoo_globals.event_handlers = event_handlers;
481 destroy_config(&tmp);
482 }
483
484 if(kazoo_globals.fetch_handlers != fetch_handlers) {
485 kazoo_config_ptr tmp = kazoo_globals.fetch_handlers;
486 kazoo_globals.fetch_handlers = fetch_handlers;
487 rebind_fetch_profiles(fetch_handlers);
488 destroy_config(&tmp);
489 }
490
491 if(kazoo_globals.definitions != definitions) {
492 kazoo_config_ptr tmp = kazoo_globals.definitions;
493 kazoo_globals.definitions = definitions;
494 destroy_config(&tmp);
495 }
496
497
498 switch_xml_free(def);
499 switch_safe_free(xml);
500
501 return SWITCH_STATUS_SUCCESS;
502 }
503
kazoo_load_config()504 switch_status_t kazoo_load_config()
505 {
506 char *cf = "kazoo.conf";
507 switch_xml_t cfg, xml;
508 if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
509 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf);
510 return SWITCH_STATUS_FALSE;
511 } else {
512 kazoo_ei_config(cfg);
513 kazoo_config_handlers(cfg);
514 switch_xml_free(xml);
515 }
516
517 return SWITCH_STATUS_SUCCESS;
518 }
519
kazoo_destroy_config()520 void kazoo_destroy_config()
521 {
522 destroy_config(&kazoo_globals.event_handlers);
523 destroy_config(&kazoo_globals.fetch_handlers);
524 destroy_config(&kazoo_globals.definitions);
525 }
526
kazoo_config_events(kazoo_config_ptr definitions,switch_memory_pool_t * pool,switch_xml_t cfg,kazoo_event_profile_ptr profile)527 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 {
529 switch_xml_t events, event;
530 kazoo_event_ptr prv = NULL, cur = NULL;
531
532
533 if ((events = switch_xml_child(cfg, "events")) != NULL) {
534 for (event = switch_xml_child(events, "event"); event; event = event->next) {
535 const char *var = switch_xml_attr(event, "name");
536 cur = (kazoo_event_ptr) switch_core_alloc(pool, sizeof(kazoo_event_t));
537 memset(cur, 0, sizeof(kazoo_event_t));
538 if(prv == NULL) {
539 profile->events = prv = cur;
540 } else {
541 prv->next = cur;
542 prv = cur;
543 }
544 cur->profile = profile;
545 cur->name = switch_core_strdup(pool, var);
546 kazoo_config_filters(pool, event, &cur->filter);
547 kazoo_config_fields(definitions, pool, event, &cur->fields);
548 if (switch_xml_child(event, "logging") != NULL) {
549 kazoo_config_loglevels(pool, event, &cur->logging);
550 }
551 }
552 }
553
554 return SWITCH_STATUS_SUCCESS;
555
556 }
557
558
kazoo_config_fetch_handler(kazoo_config_ptr definitions,kazoo_config_ptr root,switch_xml_t cfg,kazoo_fetch_profile_ptr * ptr)559 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 {
561 kazoo_fetch_profile_ptr profile = NULL;
562 switch_xml_t params, param;
563 switch_xml_section_t fetch_section;
564 int fetch_timeout = 2000000;
565 switch_memory_pool_t *pool = NULL;
566
567 char *name = (char *) switch_xml_attr_soft(cfg, "name");
568 if (zstr(name)) {
569 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing name in profile\n");
570 return SWITCH_STATUS_GENERR;
571 }
572
573 if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
574 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocation pool for new profile : %s\n", name);
575 return SWITCH_STATUS_GENERR;
576 }
577
578 profile = switch_core_alloc(pool, sizeof(kazoo_fetch_profile_t));
579 profile->pool = pool;
580 profile->root = root;
581 profile->name = switch_core_strdup(profile->pool, name);
582
583 fetch_section = switch_xml_parse_section_string(name);
584
585 if ((params = switch_xml_child(cfg, "params")) != NULL) {
586 for (param = switch_xml_child(params, "param"); param; param = param->next) {
587 char *var = (char *) switch_xml_attr_soft(param, "name");
588 char *val = (char *) switch_xml_attr_soft(param, "value");
589
590 if (!var) {
591 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param missing 'name' attribute\n", name);
592 continue;
593 }
594
595 if (!val) {
596 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param[%s] missing 'value' attribute\n", name, var);
597 continue;
598 }
599
600 if (!strncmp(var, "fetch-timeout", 13)) {
601 fetch_timeout = atoi(val);
602 } else if (!strncmp(var, "fetch-section", 13)) {
603 fetch_section = switch_xml_parse_section_string(val);
604 }
605 }
606 }
607
608 if (fetch_section == SWITCH_XML_SECTION_RESULT) {
609 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Fetch Profile[%s] invalid fetch-section: %s\n", name, switch_xml_toxml(cfg, SWITCH_FALSE));
610 goto err;
611 }
612
613
614 profile->fetch_timeout = fetch_timeout;
615 profile->section = fetch_section;
616 kazoo_config_fields(definitions, pool, cfg, &profile->fields);
617 kazoo_config_loglevels(pool, cfg, &profile->logging);
618
619 if(root) {
620 if ( switch_core_hash_insert(root->hash, name, (void *) profile) != SWITCH_STATUS_SUCCESS) {
621 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to insert new fetch profile [%s] into kazoo profile hash\n", name);
622 goto err;
623 }
624 }
625
626 if(ptr)
627 *ptr = profile;
628
629 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "fetch handler profile %s successfully configured\n", name);
630 return SWITCH_STATUS_SUCCESS;
631
632 err:
633 /* Cleanup */
634 if(pool) {
635 switch_core_destroy_memory_pool(&pool);
636 }
637 return SWITCH_STATUS_GENERR;
638
639 }
640
kazoo_config_event_handler(kazoo_config_ptr definitions,kazoo_config_ptr root,switch_xml_t cfg,kazoo_event_profile_ptr * ptr)641 switch_status_t kazoo_config_event_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_event_profile_ptr *ptr)
642 {
643 kazoo_event_profile_ptr profile = NULL;
644 switch_memory_pool_t *pool = NULL;
645
646 char *name = (char *) switch_xml_attr_soft(cfg, "name");
647 if (zstr(name)) {
648 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing name in profile\n");
649 return SWITCH_STATUS_GENERR;
650 }
651
652 if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
653 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocation pool for new profile : %s\n", name);
654 return SWITCH_STATUS_GENERR;
655 }
656
657 profile = switch_core_alloc(pool, sizeof(kazoo_event_profile_t));
658 profile->pool = pool;
659 profile->root = root;
660 profile->name = switch_core_strdup(profile->pool, name);
661
662 kazoo_config_filters(pool, cfg, &profile->filter);
663 kazoo_config_fields(definitions, pool, cfg, &profile->fields);
664 kazoo_config_events(definitions, pool, cfg, profile);
665 kazoo_config_loglevels(pool, cfg, &profile->logging);
666
667 if(root) {
668 if ( switch_core_hash_insert(root->hash, name, (void *) profile) != SWITCH_STATUS_SUCCESS) {
669 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to insert new profile [%s] into kazoo profile hash\n", name);
670 goto err;
671 }
672 }
673
674 if(ptr)
675 *ptr = profile;
676
677 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "event handler profile %s successfully configured\n", name);
678 return SWITCH_STATUS_SUCCESS;
679
680 err:
681 /* Cleanup */
682 if(pool) {
683 switch_core_destroy_memory_pool(&pool);
684 }
685 return SWITCH_STATUS_GENERR;
686
687 }
688
689
690
691 /* For Emacs:
692 * Local Variables:
693 * mode:c
694 * indent-tabs-mode:t
695 * tab-width:4
696 * c-basic-offset:4
697 * End:
698 * For VIM:
699 * vim:set softtabstop=4 shiftwidth=4 tabstop=4
700 */
701