1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, 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  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Michael Jerris <mike@jerris.com>
28  * Paul D. Tinsley <pdt at jackhammer.org>
29  * Marcel Barbulescu <marcelbarbulescu@gmail.com>
30  * Joseph Sullivan <jossulli@amazon.com>
31  * Seven Du <dujinfang@gmail.com>
32  * Andrey Volk <andywolk@gmail.com>
33  *
34  * switch_core.c -- Main Core Library
35  *
36  */
37 
38 
39 
40 #include <switch.h>
41 #include <switch_ssl.h>
42 #include <switch_stun.h>
43 #include <switch_nat.h>
44 #include "private/switch_core_pvt.h"
45 #include <switch_curl.h>
46 #include <switch_msrp.h>
47 #ifndef WIN32
48 #include <switch_private.h>
49 #ifdef HAVE_SETRLIMIT
50 #include <sys/resource.h>
51 #endif
52 #endif
53 #include <errno.h>
54 #include <sqlite3.h>
55 #ifdef HAVE_SYS_PRCTL_H
56 #include <sys/prctl.h>
57 #endif
58 #ifdef SOLARIS_PRIVILEGES
59 #include <priv.h>
60 #endif
61 
62 #ifdef WIN32
63 #define popen _popen
64 #define pclose _pclose
65 #endif
66 
67 SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = { 0 };
68 SWITCH_DECLARE_DATA switch_filenames SWITCH_GLOBAL_filenames = { 0 };
69 
70 /* The main runtime obj we keep this hidden for ourselves */
71 struct switch_runtime runtime = { 0 };
72 static void switch_load_core_config(const char *file);
73 
send_heartbeat(void)74 static void send_heartbeat(void)
75 {
76 	switch_event_t *event;
77 	switch_core_time_duration_t duration;
78 
79 	switch_core_measure_time(switch_core_uptime(), &duration);
80 
81 	if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) {
82 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");
83 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time",
84 								"%u year%s, "
85 								"%u day%s, "
86 								"%u hour%s, "
87 								"%u minute%s, "
88 								"%u second%s, "
89 								"%u millisecond%s, "
90 								"%u microsecond%s",
91 								duration.yr, duration.yr == 1 ? "" : "s",
92 								duration.day, duration.day == 1 ? "" : "s",
93 								duration.hr, duration.hr == 1 ? "" : "s",
94 								duration.min, duration.min == 1 ? "" : "s",
95 								duration.sec, duration.sec == 1 ? "" : "s",
96 								duration.ms, duration.ms == 1 ? "" : "s", duration.mms, duration.mms == 1 ? "" : "s");
97 
98 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Version", "%s", switch_version_full());
99 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Uptime-msec", "%"SWITCH_TIME_T_FMT, switch_core_uptime() / 1000);
100 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count());
101 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Max-Sessions", "%u", switch_core_session_limit(0));
102 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec", "%u", runtime.sps);
103 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec-Last", "%u", runtime.sps_last);
104 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec-Max", "%u", runtime.sps_peak);
105 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec-FiveMin", "%u", runtime.sps_peak_fivemin);
106 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Since-Startup", "%" SWITCH_SIZE_T_FMT, switch_core_session_id() - 1);
107 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Peak-Max", "%u", runtime.sessions_peak);
108 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Peak-FiveMin", "%u", runtime.sessions_peak_fivemin);
109 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Idle-CPU", "%f", switch_core_idle_cpu());
110 		switch_event_fire(&event);
111 	}
112 }
113 
114 static char main_ip4[256] = "";
115 static char main_ip6[256] = "";
116 
check_ip(void)117 static void check_ip(void)
118 {
119 	char guess_ip4[256] = "";
120 	char guess_ip6[256] = "";
121 	char old_ip4[256] = "";
122 	char old_ip6[256] = "";
123 	int ok4 = 1, ok6 = 1;
124 	int mask = 0;
125 	switch_status_t check6, check4;
126 	switch_event_t *event;
127 	char *hostname = switch_core_get_variable("hostname");
128 
129 	gethostname(runtime.hostname, sizeof(runtime.hostname));
130 
131 	if (zstr(hostname)) {
132 		switch_core_set_variable("hostname", runtime.hostname);
133 	} else if (strcmp(hostname, runtime.hostname)) {
134 		if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
135 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "hostname-change");
136 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "old-hostname", hostname ? hostname : "nil");
137 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "new-hostname", runtime.hostname);
138 			switch_event_fire(&event);
139 		}
140 
141 		switch_core_set_variable("hostname", runtime.hostname);
142 	}
143 
144 	check4 = switch_find_local_ip(guess_ip4, sizeof(guess_ip4), &mask, AF_INET);
145 	check6 = switch_find_local_ip(guess_ip6, sizeof(guess_ip6), NULL, AF_INET6);
146 
147 	if (check6 != SWITCH_STATUS_SUCCESS && (zstr(main_ip6) || !strcasecmp(main_ip6, "::1"))) {
148 		check6 = SWITCH_STATUS_SUCCESS;
149 	}
150 
151 	if (check4 != SWITCH_STATUS_SUCCESS) {
152 		ok4 = 2;
153 	} else if (!*main_ip4) {
154 		switch_set_string(main_ip4, guess_ip4);
155 	} else {
156 		if (!(ok4 = !strcmp(main_ip4, guess_ip4))) {
157 			struct in_addr in;
158 
159 			in.s_addr = mask;
160 			switch_set_string(old_ip4, main_ip4);
161 			switch_set_string(main_ip4, guess_ip4);
162 			switch_core_set_variable("local_ip_v4", guess_ip4);
163 			switch_core_set_variable("local_mask_v4", inet_ntoa(in));
164 		}
165 	}
166 
167 	if (check6 != SWITCH_STATUS_SUCCESS) {
168 		ok6 = 2;
169 	} else if (!*main_ip6) {
170 		switch_set_string(main_ip6, guess_ip6);
171 	} else {
172 		if (!(ok6 = !strcmp(main_ip6, guess_ip6))) {
173 			switch_set_string(old_ip6, main_ip6);
174 			switch_set_string(main_ip6, guess_ip6);
175 			switch_core_set_variable("local_ip_v6", guess_ip6);
176 		}
177 	}
178 
179 	if (!ok4 || !ok6) {
180 		if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
181 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change");
182 			if (!ok4) {
183 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", old_ip4);
184 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", main_ip4);
185 			}
186 			if (!ok6) {
187 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v6", old_ip6);
188 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v6", main_ip6);
189 			}
190 			switch_event_fire(&event);
191 		}
192 	}
193 
194 	if (ok4 == 2 || ok6 == 2) {
195 		if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
196 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-outage");
197 
198 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-status-v4", ok4 == 2 ? "disconnected" : "active");
199 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-v4", main_ip4);
200 
201 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-status-v6", ok6 == 2 ? "disconnected" : "active");
202 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-v6", main_ip6);
203 
204 			switch_event_fire(&event);
205 		}
206 	}
207 
208 }
209 
SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback)210 SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback)
211 {
212 	send_heartbeat();
213 
214 	/* reschedule this task */
215 	task->runtime = switch_epoch_time_now(NULL) + runtime.event_heartbeat_interval;
216 }
217 
218 
SWITCH_STANDARD_SCHED_FUNC(check_ip_callback)219 SWITCH_STANDARD_SCHED_FUNC(check_ip_callback)
220 {
221 	check_ip();
222 
223 	/* reschedule this task */
224 	task->runtime = switch_epoch_time_now(NULL) + 60;
225 }
226 
227 
switch_core_set_console(const char * console)228 SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console)
229 {
230 	if ((runtime.console = fopen(console, "a")) == 0) {
231 		fprintf(stderr, "Cannot open output file %s.\n", console);
232 		return SWITCH_STATUS_FALSE;
233 	}
234 
235 	return SWITCH_STATUS_SUCCESS;
236 }
237 
switch_core_get_console(void)238 SWITCH_DECLARE(FILE *) switch_core_get_console(void)
239 {
240 	return runtime.console;
241 }
242 
243 #ifdef HAVE_SYS_IOCTL_H
244 #include <sys/ioctl.h>
245 #endif
switch_core_screen_size(int * x,int * y)246 SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y)
247 {
248 
249 #ifdef WIN32
250 	CONSOLE_SCREEN_BUFFER_INFO csbi;
251 	int ret;
252 
253 	if ((ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ), &csbi))) {
254 		if (x) *x = csbi.dwSize.X;
255 		if (y) *y = csbi.dwSize.Y;
256 	}
257 
258 #elif defined(TIOCGWINSZ)
259 	struct winsize w;
260 	ioctl(0, TIOCGWINSZ, &w);
261 
262 	if (x) *x = w.ws_col;
263 	if (y) *y = w.ws_row;
264 #else
265 	if (x) *x = 80;
266 	if (y) *y = 24;
267 #endif
268 
269 }
270 
switch_core_data_channel(switch_text_channel_t channel)271 SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel)
272 {
273 	return runtime.console;
274 }
275 
276 
switch_core_remove_state_handler(const switch_state_handler_table_t * state_handler)277 SWITCH_DECLARE(void) switch_core_remove_state_handler(const switch_state_handler_table_t *state_handler)
278 {
279 	int index, tmp_index = 0;
280 	const switch_state_handler_table_t *tmp[SWITCH_MAX_STATE_HANDLERS + 1] = { 0 };
281 
282 	switch_mutex_lock(runtime.global_mutex);
283 
284 	for (index = 0; index < runtime.state_handler_index; index++) {
285 		const switch_state_handler_table_t *cur = runtime.state_handlers[index];
286 		runtime.state_handlers[index] = NULL;
287 		if (cur == state_handler) {
288 			continue;
289 		}
290 		tmp[tmp_index++] = cur;
291 	}
292 
293 	runtime.state_handler_index = 0;
294 
295 	for (index = 0; index < tmp_index; index++) {
296 		runtime.state_handlers[runtime.state_handler_index++] = tmp[index];
297 	}
298 	switch_mutex_unlock(runtime.global_mutex);
299 }
300 
301 
switch_core_add_state_handler(const switch_state_handler_table_t * state_handler)302 SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler)
303 {
304 	int index;
305 
306 	switch_mutex_lock(runtime.global_mutex);
307 	index = runtime.state_handler_index;
308 
309 	if (index > (SWITCH_MAX_STATE_HANDLERS - 1)) {
310 		index = -1;
311 	} else {
312 		runtime.state_handlers[index] = state_handler;
313 		runtime.state_handler_index++;
314 	}
315 
316 	switch_mutex_unlock(runtime.global_mutex);
317 	return index;
318 }
319 
switch_core_get_state_handler(int index)320 SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index)
321 {
322 
323 	if (index >= SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) {
324 		return NULL;
325 	}
326 
327 	return runtime.state_handlers[index];
328 }
329 
switch_core_dump_variables(switch_stream_handle_t * stream)330 SWITCH_DECLARE(void) switch_core_dump_variables(switch_stream_handle_t *stream)
331 {
332 	switch_event_header_t *hi;
333 
334 	switch_mutex_lock(runtime.global_mutex);
335 	for (hi = runtime.global_vars->headers; hi; hi = hi->next) {
336 		stream->write_function(stream, "%s=%s\n", hi->name, hi->value);
337 	}
338 	switch_mutex_unlock(runtime.global_mutex);
339 }
340 
switch_core_get_hostname(void)341 SWITCH_DECLARE(const char *) switch_core_get_hostname(void)
342 {
343 	return runtime.hostname;
344 }
345 
switch_core_get_switchname(void)346 SWITCH_DECLARE(const char *) switch_core_get_switchname(void)
347 {
348 	if (!zstr(runtime.switchname)) return runtime.switchname;
349 	return runtime.hostname;
350 }
351 
switch_core_get_domain(switch_bool_t dup)352 SWITCH_DECLARE(char *) switch_core_get_domain(switch_bool_t dup)
353 {
354 	char *domain;
355 	const char *var;
356 
357 	switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
358 	if (!(var = switch_core_get_variable("domain"))) {
359 		var = "freeswitch.local";
360 	}
361 	if (dup) {
362 		domain = strdup(var);
363 	} else {
364 		domain = (char *) var;
365 	}
366 	switch_thread_rwlock_unlock(runtime.global_var_rwlock);
367 
368 	return domain;
369 }
370 
switch_core_get_variables(switch_event_t ** event)371 SWITCH_DECLARE(switch_status_t) switch_core_get_variables(switch_event_t **event)
372 {
373 	switch_status_t status;
374 	switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
375 	status = switch_event_dup(event, runtime.global_vars);
376 	switch_thread_rwlock_unlock(runtime.global_var_rwlock);
377 	return status;
378 }
379 
switch_core_get_variable(const char * varname)380 SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname)
381 {
382 	char *val;
383 	switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
384 	val = (char *) switch_event_get_header(runtime.global_vars, varname);
385 	switch_thread_rwlock_unlock(runtime.global_var_rwlock);
386 	return val;
387 }
388 
switch_core_get_variable_dup(const char * varname)389 SWITCH_DECLARE(char *) switch_core_get_variable_dup(const char *varname)
390 {
391 	char *val = NULL, *v;
392 
393 	if (varname) {
394 		switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
395 		if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) {
396 			val = strdup(v);
397 		}
398 		switch_thread_rwlock_unlock(runtime.global_var_rwlock);
399 	}
400 
401 	return val;
402 }
403 
switch_core_get_variable_pdup(const char * varname,switch_memory_pool_t * pool)404 SWITCH_DECLARE(char *) switch_core_get_variable_pdup(const char *varname, switch_memory_pool_t *pool)
405 {
406 	char *val = NULL, *v;
407 
408 	if (varname) {
409 		switch_thread_rwlock_rdlock(runtime.global_var_rwlock);
410 		if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) {
411 			val = switch_core_strdup(pool, v);
412 		}
413 		switch_thread_rwlock_unlock(runtime.global_var_rwlock);
414 	}
415 
416 	return val;
417 }
418 
switch_core_unset_variables(void)419 static void switch_core_unset_variables(void)
420 {
421 	switch_thread_rwlock_wrlock(runtime.global_var_rwlock);
422 	switch_event_destroy(&runtime.global_vars);
423 	switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA);
424 	switch_thread_rwlock_unlock(runtime.global_var_rwlock);
425 }
426 
switch_core_set_variable(const char * varname,const char * value)427 SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *value)
428 {
429 	char *val;
430 
431 	if (varname) {
432 		switch_thread_rwlock_wrlock(runtime.global_var_rwlock);
433 		val = (char *) switch_event_get_header(runtime.global_vars, varname);
434 		if (val) {
435 			switch_event_del_header(runtime.global_vars, varname);
436 		}
437 		if (value) {
438 			char *v = strdup(value);
439 			switch_string_var_check(v, SWITCH_TRUE);
440 			switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v);
441 		} else {
442 			switch_event_del_header(runtime.global_vars, varname);
443 		}
444 		switch_thread_rwlock_unlock(runtime.global_var_rwlock);
445 	}
446 }
447 
switch_core_set_var_conditional(const char * varname,const char * value,const char * val2)448 SWITCH_DECLARE(switch_bool_t) switch_core_set_var_conditional(const char *varname, const char *value, const char *val2)
449 {
450 	char *val;
451 
452 	if (varname) {
453 		switch_thread_rwlock_wrlock(runtime.global_var_rwlock);
454 		val = (char *) switch_event_get_header(runtime.global_vars, varname);
455 
456 		if (val) {
457 			if (!val2 || strcmp(val, val2) != 0) {
458 				switch_thread_rwlock_unlock(runtime.global_var_rwlock);
459 				return SWITCH_FALSE;
460 			}
461 			switch_event_del_header(runtime.global_vars, varname);
462 		} else if (!zstr(val2)) {
463 			switch_thread_rwlock_unlock(runtime.global_var_rwlock);
464 			return SWITCH_FALSE;
465 		}
466 
467 		if (value) {
468 			char *v = strdup(value);
469 			switch_string_var_check(v, SWITCH_TRUE);
470 			switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v);
471 		} else {
472 			switch_event_del_header(runtime.global_vars, varname);
473 		}
474 		switch_thread_rwlock_unlock(runtime.global_var_rwlock);
475 	}
476 	return SWITCH_TRUE;
477 }
478 
switch_core_get_uuid(void)479 SWITCH_DECLARE(char *) switch_core_get_uuid(void)
480 {
481 	return runtime.uuid_str;
482 }
483 
484 
switch_core_service_thread(switch_thread_t * thread,void * obj)485 static void *SWITCH_THREAD_FUNC switch_core_service_thread(switch_thread_t *thread, void *obj)
486 {
487 	switch_core_session_t *session = obj;
488 	switch_channel_t *channel;
489 	switch_frame_t *read_frame = NULL;
490 
491 //  switch_assert(thread != NULL);
492 //  switch_assert(session != NULL);
493 
494 	if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
495 		return NULL;
496 	}
497 
498 	switch_mutex_lock(session->frame_read_mutex);
499 
500 	channel = switch_core_session_get_channel(session);
501 
502 	switch_channel_set_flag(channel, CF_SERVICE);
503 	while (switch_channel_test_flag(channel, CF_SERVICE)) {
504 
505 		if (switch_channel_test_flag(channel, CF_SERVICE_AUDIO)) {
506 			switch (switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) {
507 			case SWITCH_STATUS_SUCCESS:
508 			case SWITCH_STATUS_TIMEOUT:
509 			case SWITCH_STATUS_BREAK:
510 				break;
511 			default:
512 				switch_channel_clear_flag(channel, CF_SERVICE);
513 				break;
514 			}
515 		}
516 
517 		if (switch_channel_test_flag(channel, CF_SERVICE_VIDEO) && switch_channel_test_flag(channel, CF_VIDEO)) {
518 			switch (switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) {
519 			case SWITCH_STATUS_SUCCESS:
520 			case SWITCH_STATUS_TIMEOUT:
521 			case SWITCH_STATUS_BREAK:
522 				break;
523 			default:
524 				switch_channel_clear_flag(channel, CF_SERVICE);
525 				break;
526 			}
527 		}
528 	}
529 
530 	switch_mutex_unlock(session->frame_read_mutex);
531 
532 	switch_channel_clear_flag(channel, CF_SERVICE_AUDIO);
533 	switch_channel_clear_flag(channel, CF_SERVICE_VIDEO);
534 
535 	switch_core_session_rwunlock(session);
536 
537 	return NULL;
538 }
539 
540 /* Either add a timeout here or make damn sure the thread cannot get hung somehow (my preference) */
switch_core_thread_session_end(switch_core_session_t * session)541 SWITCH_DECLARE(void) switch_core_thread_session_end(switch_core_session_t *session)
542 {
543 	switch_channel_t *channel;
544 	switch_assert(session);
545 
546 	channel = switch_core_session_get_channel(session);
547 	switch_assert(channel);
548 
549 	switch_channel_clear_flag(channel, CF_SERVICE);
550 	switch_channel_clear_flag(channel, CF_SERVICE_AUDIO);
551 	switch_channel_clear_flag(channel, CF_SERVICE_VIDEO);
552 
553 	switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);
554 
555 }
556 
switch_core_service_session_av(switch_core_session_t * session,switch_bool_t audio,switch_bool_t video)557 SWITCH_DECLARE(void) switch_core_service_session_av(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video)
558 {
559 	switch_channel_t *channel;
560 	switch_assert(session);
561 
562 	channel = switch_core_session_get_channel(session);
563 	switch_assert(channel);
564 
565 	if (audio) switch_channel_set_flag(channel, CF_SERVICE_AUDIO);
566 	if (video) switch_channel_set_flag(channel, CF_SERVICE_VIDEO);
567 
568 	switch_core_session_launch_thread(session, (void *(*)(switch_thread_t *,void *))switch_core_service_thread, session);
569 }
570 
571 /* This function abstracts the thread creation for modules by allowing you to pass a function ptr and
572    a void object and trust that that the function will be run in a thread with arg  This lets
573    you request and activate a thread without giving up any knowledge about what is in the thread
574    neither the core nor the calling module know anything about each other.
575 
576    This thread is expected to never exit until the application exits so the func is responsible
577    to make sure that is the case.
578 
579    The typical use for this is so switch_loadable_module.c can start up a thread for each module
580    passing the table of module methods as a session obj into the core without actually allowing
581    the core to have any clue and keeping switch_loadable_module.c from needing any thread code.
582 
583 */
584 
switch_core_launch_thread(switch_thread_start_t func,void * obj,switch_memory_pool_t * pool)585 SWITCH_DECLARE(switch_thread_t *) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool_t *pool)
586 {
587 	switch_thread_t *thread = NULL;
588 	switch_threadattr_t *thd_attr = NULL;
589 	switch_core_thread_session_t *ts;
590 	int mypool;
591 
592 	mypool = pool ? 0 : 1;
593 
594 	if (!pool && switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
595 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory pool\n");
596 		return NULL;
597 	}
598 
599 	switch_threadattr_create(&thd_attr, pool);
600 
601 	if ((ts = switch_core_alloc(pool, sizeof(*ts))) == 0) {
602 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory\n");
603 	} else {
604 		if (mypool) {
605 			ts->pool = pool;
606 		}
607 		ts->objs[0] = obj;
608 		ts->objs[1] = thread;
609 		switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
610 		switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME);
611 		switch_thread_create(&thread, thd_attr, func, ts, pool);
612 	}
613 
614 	return thread;
615 }
616 
switch_core_set_globals(void)617 SWITCH_DECLARE(void) switch_core_set_globals(void)
618 {
619 #define BUFSIZE 1024
620 #ifdef WIN32
621 	char lpPathBuffer[BUFSIZE];
622 	DWORD dwBufSize = BUFSIZE;
623 	char base_dir[1024];
624 	char *lastbacklash;
625 	char *tmp;
626 
627 	GetModuleFileName(NULL, base_dir, BUFSIZE);
628 	lastbacklash = strrchr(base_dir, '\\');
629 	base_dir[(lastbacklash - base_dir)] = '\0';
630 	/* set base_dir as cwd, to be able to use relative paths in scripting languages (e.g. mod_lua) when FS is running as a service or while debugging FS using visual studio */
631 	SetCurrentDirectory(base_dir);
632 	tmp = switch_string_replace(base_dir, "\\", "/");
633 	strcpy(base_dir, tmp);
634 	free(tmp);
635 
636 #else
637 	char base_dir[1024] = SWITCH_PREFIX_DIR;
638 #endif
639 
640 	/* Order of precedence for, eg, rundir:
641 	 *   -run
642 	 *   -base
643 	 *   --with-rundir
644 	 *   --prefix
645 	 */
646 
647 	if (!SWITCH_GLOBAL_dirs.mod_dir && (SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(BUFSIZE))) {
648 		if (SWITCH_GLOBAL_dirs.base_dir)
649 			switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s%smod", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
650 		else
651 #ifdef SWITCH_MOD_DIR
652 			switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s", SWITCH_MOD_DIR);
653 #else
654 			switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s%smod", base_dir, SWITCH_PATH_SEPARATOR);
655 #endif
656 	}
657 
658 	if (!SWITCH_GLOBAL_dirs.lib_dir && (SWITCH_GLOBAL_dirs.lib_dir = (char *) malloc(BUFSIZE))) {
659 		if (SWITCH_GLOBAL_dirs.base_dir)
660 			switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s%slib", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
661 		else
662 #ifdef SWITCH_LIB_DIR
663 			switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s", SWITCH_LIB_DIR);
664 #else
665 			switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s%slib", base_dir, SWITCH_PATH_SEPARATOR);
666 #endif
667 	}
668 
669 	if (!SWITCH_GLOBAL_dirs.conf_dir && (SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(BUFSIZE))) {
670 		if (SWITCH_GLOBAL_dirs.base_dir)
671 			switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s%sconf", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
672 		else
673 #ifdef SWITCH_CONF_DIR
674 			switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s", SWITCH_CONF_DIR);
675 #else
676 			switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s%sconf", base_dir, SWITCH_PATH_SEPARATOR);
677 #endif
678 	}
679 
680 	if (!SWITCH_GLOBAL_dirs.log_dir && (SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(BUFSIZE))) {
681 		if (SWITCH_GLOBAL_dirs.base_dir)
682 			switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s%slog", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
683 		else
684 #ifdef SWITCH_LOG_DIR
685 			switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s", SWITCH_LOG_DIR);
686 #else
687 			switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s%slog", base_dir, SWITCH_PATH_SEPARATOR);
688 #endif
689 	}
690 
691 	if (!SWITCH_GLOBAL_dirs.run_dir && (SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(BUFSIZE))) {
692 		if (SWITCH_GLOBAL_dirs.base_dir)
693 			switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s%srun", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
694 		else
695 #ifdef SWITCH_RUN_DIR
696 			switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s", SWITCH_RUN_DIR);
697 #else
698 			switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s%srun", base_dir, SWITCH_PATH_SEPARATOR);
699 #endif
700 	}
701 
702 	if (!SWITCH_GLOBAL_dirs.recordings_dir && (SWITCH_GLOBAL_dirs.recordings_dir = (char *) malloc(BUFSIZE))) {
703 		if (SWITCH_GLOBAL_dirs.base_dir)
704 			switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s%srecordings", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
705 		else
706 #ifdef SWITCH_RECORDINGS_DIR
707 			switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s", SWITCH_RECORDINGS_DIR);
708 #else
709 			switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s%srecordings", base_dir, SWITCH_PATH_SEPARATOR);
710 #endif
711 	}
712 
713 	if (!SWITCH_GLOBAL_dirs.sounds_dir && (SWITCH_GLOBAL_dirs.sounds_dir = (char *) malloc(BUFSIZE))) {
714 		if (SWITCH_GLOBAL_dirs.base_dir)
715 			switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s%ssounds", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
716 		else
717 #ifdef SWITCH_SOUNDS_DIR
718 			switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s", SWITCH_SOUNDS_DIR);
719 #else
720 			switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s%ssounds", base_dir, SWITCH_PATH_SEPARATOR);
721 #endif
722 	}
723 
724 	if (!SWITCH_GLOBAL_dirs.storage_dir && (SWITCH_GLOBAL_dirs.storage_dir = (char *) malloc(BUFSIZE))) {
725 		if (SWITCH_GLOBAL_dirs.base_dir)
726 			switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s%sstorage", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
727 		else
728 #ifdef SWITCH_STORAGE_DIR
729 			switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s", SWITCH_STORAGE_DIR);
730 #else
731 			switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s%sstorage", base_dir, SWITCH_PATH_SEPARATOR);
732 #endif
733 	}
734 
735 	if (!SWITCH_GLOBAL_dirs.cache_dir && (SWITCH_GLOBAL_dirs.cache_dir = (char *) malloc(BUFSIZE))) {
736 		if (SWITCH_GLOBAL_dirs.base_dir)
737 			switch_snprintf(SWITCH_GLOBAL_dirs.cache_dir, BUFSIZE, "%s%scache", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
738 		else
739 #ifdef SWITCH_CACHE_DIR
740 			switch_snprintf(SWITCH_GLOBAL_dirs.cache_dir, BUFSIZE, "%s", SWITCH_CACHE_DIR);
741 #else
742 			switch_snprintf(SWITCH_GLOBAL_dirs.cache_dir, BUFSIZE, "%s%scache", base_dir, SWITCH_PATH_SEPARATOR);
743 #endif
744 	}
745 
746 	if (!SWITCH_GLOBAL_dirs.db_dir && (SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(BUFSIZE))) {
747 		if (SWITCH_GLOBAL_dirs.base_dir)
748 			switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s%sdb", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
749 		else
750 #ifdef SWITCH_DB_DIR
751 			switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s", SWITCH_DB_DIR);
752 #else
753 			switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s%sdb", base_dir, SWITCH_PATH_SEPARATOR);
754 #endif
755 	}
756 
757 	if (!SWITCH_GLOBAL_dirs.script_dir && (SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(BUFSIZE))) {
758 		if (SWITCH_GLOBAL_dirs.base_dir)
759 			switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s%sscripts", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
760 		else
761 #ifdef SWITCH_SCRIPT_DIR
762 			switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s", SWITCH_SCRIPT_DIR);
763 #else
764 			switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s%sscripts", base_dir, SWITCH_PATH_SEPARATOR);
765 #endif
766 	}
767 
768 	if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) {
769 		if (SWITCH_GLOBAL_dirs.base_dir)
770 			switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s%shtdocs", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
771 		else
772 #ifdef SWITCH_HTDOCS_DIR
773 			switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s", SWITCH_HTDOCS_DIR);
774 #else
775 			switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s%shtdocs", base_dir, SWITCH_PATH_SEPARATOR);
776 #endif
777 	}
778 
779 	if (!SWITCH_GLOBAL_dirs.grammar_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) {
780 		if (SWITCH_GLOBAL_dirs.base_dir)
781 			switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
782 		else
783 #ifdef SWITCH_GRAMMAR_DIR
784 			switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s", SWITCH_GRAMMAR_DIR);
785 #else
786 			switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", base_dir, SWITCH_PATH_SEPARATOR);
787 #endif
788 	}
789 
790 	if (!SWITCH_GLOBAL_dirs.fonts_dir && (SWITCH_GLOBAL_dirs.fonts_dir = (char *) malloc(BUFSIZE))) {
791 		if (SWITCH_GLOBAL_dirs.base_dir)
792 			switch_snprintf(SWITCH_GLOBAL_dirs.fonts_dir, BUFSIZE, "%s%sfonts", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
793 		else
794 #ifdef SWITCH_FONTS_DIR
795 			switch_snprintf(SWITCH_GLOBAL_dirs.fonts_dir, BUFSIZE, "%s", SWITCH_FONTS_DIR);
796 #else
797 			switch_snprintf(SWITCH_GLOBAL_dirs.fonts_dir, BUFSIZE, "%s%sfonts", base_dir, SWITCH_PATH_SEPARATOR);
798 #endif
799 	}
800 
801 	if (!SWITCH_GLOBAL_dirs.images_dir && (SWITCH_GLOBAL_dirs.images_dir = (char *) malloc(BUFSIZE))) {
802 		if (SWITCH_GLOBAL_dirs.base_dir)
803 			switch_snprintf(SWITCH_GLOBAL_dirs.images_dir, BUFSIZE, "%s%simages", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
804 		else
805 #ifdef SWITCH_IMAGES_DIR
806 			switch_snprintf(SWITCH_GLOBAL_dirs.images_dir, BUFSIZE, "%s", SWITCH_IMAGES_DIR);
807 #else
808 			switch_snprintf(SWITCH_GLOBAL_dirs.images_dir, BUFSIZE, "%s%simages", base_dir, SWITCH_PATH_SEPARATOR);
809 #endif
810 	}
811 
812 	if (!SWITCH_GLOBAL_dirs.data_dir && (SWITCH_GLOBAL_dirs.data_dir = (char *) malloc(BUFSIZE))) {
813 		if (SWITCH_GLOBAL_dirs.base_dir)
814 			switch_snprintf(SWITCH_GLOBAL_dirs.data_dir, BUFSIZE, "%s", SWITCH_GLOBAL_dirs.base_dir);
815 		else
816 #ifdef SWITCH_DATA_DIR
817 			switch_snprintf(SWITCH_GLOBAL_dirs.data_dir, BUFSIZE, "%s", SWITCH_DATA_DIR);
818 #else
819 			switch_snprintf(SWITCH_GLOBAL_dirs.data_dir, BUFSIZE, "%s", base_dir);
820 #endif
821 	}
822 
823 	if (!SWITCH_GLOBAL_dirs.localstate_dir && (SWITCH_GLOBAL_dirs.localstate_dir = (char *) malloc(BUFSIZE))) {
824 		if (SWITCH_GLOBAL_dirs.base_dir)
825 			switch_snprintf(SWITCH_GLOBAL_dirs.localstate_dir, BUFSIZE, "%s", SWITCH_GLOBAL_dirs.base_dir);
826 		else
827 #ifdef SWITCH_LOCALSTATE_DIR
828 			switch_snprintf(SWITCH_GLOBAL_dirs.localstate_dir, BUFSIZE, "%s", SWITCH_LOCALSTATE_DIR);
829 #else
830 			switch_snprintf(SWITCH_GLOBAL_dirs.localstate_dir, BUFSIZE, "%s", base_dir);
831 #endif
832 	}
833 
834 	if (!SWITCH_GLOBAL_dirs.certs_dir && (SWITCH_GLOBAL_dirs.certs_dir = (char *) malloc(BUFSIZE))) {
835 		if (SWITCH_GLOBAL_dirs.base_dir)
836 			switch_snprintf(SWITCH_GLOBAL_dirs.certs_dir, BUFSIZE, "%s%scert", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
837 		else
838 #ifdef SWITCH_CERTS_DIR
839 			switch_snprintf(SWITCH_GLOBAL_dirs.certs_dir, BUFSIZE, "%s", SWITCH_CERTS_DIR);
840 #else
841 			switch_snprintf(SWITCH_GLOBAL_dirs.certs_dir, BUFSIZE, "%s%scert", base_dir, SWITCH_PATH_SEPARATOR);
842 #endif
843 	}
844 
845 	if (!SWITCH_GLOBAL_dirs.temp_dir && (SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(BUFSIZE))) {
846 #ifdef SWITCH_TEMP_DIR
847 		switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", SWITCH_TEMP_DIR);
848 #else
849 #ifdef WIN32
850 		GetTempPath(dwBufSize, lpPathBuffer);
851 		lpPathBuffer[strlen(lpPathBuffer)-1] = 0;
852 		tmp = switch_string_replace(lpPathBuffer, "\\", "/");
853 		strcpy(lpPathBuffer, tmp);
854 		free(tmp);
855 		switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer);
856 #else
857 		switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp");
858 #endif
859 #endif
860 	}
861 
862 	if (!SWITCH_GLOBAL_filenames.conf_name && (SWITCH_GLOBAL_filenames.conf_name = (char *) malloc(BUFSIZE))) {
863 		switch_snprintf(SWITCH_GLOBAL_filenames.conf_name, BUFSIZE, "%s", "freeswitch.xml");
864 	}
865 
866 	/* Do this last because it being empty is part of the above logic */
867 	if (!SWITCH_GLOBAL_dirs.base_dir && (SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(BUFSIZE))) {
868 		switch_snprintf(SWITCH_GLOBAL_dirs.base_dir, BUFSIZE, "%s", base_dir);
869 	}
870 
871 	switch_assert(SWITCH_GLOBAL_dirs.base_dir);
872 	switch_assert(SWITCH_GLOBAL_dirs.mod_dir);
873 	switch_assert(SWITCH_GLOBAL_dirs.lib_dir);
874 	switch_assert(SWITCH_GLOBAL_dirs.conf_dir);
875 	switch_assert(SWITCH_GLOBAL_dirs.log_dir);
876 	switch_assert(SWITCH_GLOBAL_dirs.run_dir);
877 	switch_assert(SWITCH_GLOBAL_dirs.db_dir);
878 	switch_assert(SWITCH_GLOBAL_dirs.script_dir);
879 	switch_assert(SWITCH_GLOBAL_dirs.htdocs_dir);
880 	switch_assert(SWITCH_GLOBAL_dirs.grammar_dir);
881 	switch_assert(SWITCH_GLOBAL_dirs.fonts_dir);
882 	switch_assert(SWITCH_GLOBAL_dirs.images_dir);
883 	switch_assert(SWITCH_GLOBAL_dirs.recordings_dir);
884 	switch_assert(SWITCH_GLOBAL_dirs.sounds_dir);
885 	switch_assert(SWITCH_GLOBAL_dirs.certs_dir);
886 	switch_assert(SWITCH_GLOBAL_dirs.temp_dir);
887 	switch_assert(SWITCH_GLOBAL_dirs.data_dir);
888 	switch_assert(SWITCH_GLOBAL_dirs.localstate_dir);
889 
890 	switch_assert(SWITCH_GLOBAL_filenames.conf_name);
891 }
892 
893 
switch_core_set_process_privileges(void)894 SWITCH_DECLARE(int32_t) switch_core_set_process_privileges(void)
895 {
896 #ifdef SOLARIS_PRIVILEGES
897 	priv_set_t *basicset;
898 
899 	/* make the process privilege-aware */
900 	setpflags(PRIV_AWARE, 1);
901 
902 	/* reset the privileges to basic */
903 	basicset = priv_str_to_set("basic", ",", NULL);
904 	if (setppriv(PRIV_SET, PRIV_EFFECTIVE, basicset) != 0) {
905 		fprintf(stderr, "ERROR: Failed to acquire basic privileges (%s)\n", strerror(errno));
906 	}
907 
908 	/* we need high-resolution clock, and this requires a non-basic privilege */
909 	if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_CLOCK_HIGHRES, NULL) < 0) {
910 		fprintf(stderr, "ERROR: Failed to acquire proc_clock_highres privilege (%s)\n", strerror(errno));
911 		return -1;
912 	}
913 
914 	/* need this for setrlimit */
915 	if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_SYS_RESOURCE, NULL) < 0) {
916 		fprintf(stderr, "ERROR: Failed to acquire sys_resource privilege (%s)\n", strerror(errno));
917 		return -1;
918 	}
919 
920 	/* we need to read directories belonging to other uid */
921 	if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_FILE_DAC_SEARCH, NULL) < 0) {
922 		fprintf(stderr, "ERROR: Failed to acquire file_dac_search privilege (%s)\n", strerror(errno));
923 		return -1;
924 	}
925 #endif
926 	return 0;
927 }
928 
set_low_priority(void)929 SWITCH_DECLARE(int32_t) set_low_priority(void)
930 {
931 #ifdef WIN32
932 	return SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
933 #else
934 #if defined(USE_SCHED_SETSCHEDULER) && ! defined(SOLARIS_PRIVILEGES)
935 	/*
936 	 * Try to use a normal scheduler
937 	 */
938 	struct sched_param sched = { 0 };
939 	sched.sched_priority = 0;
940 	if (sched_setscheduler(0, SCHED_OTHER, &sched) < 0) {
941 		fprintf(stderr, "ERROR: Failed to set SCHED_OTHER scheduler (%s)\n", strerror(errno));
942 		return -1;
943 	}
944 #endif
945 
946 #ifdef HAVE_SETPRIORITY
947 	/*
948 	 * setpriority() works on FreeBSD (6.2), nice() doesn't
949 	 */
950 	if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) {
951 		fprintf(stderr, "ERROR: Could not set nice level\n");
952 		return -1;
953 	}
954 #else
955 	if (nice(19) != 19) {
956 		fprintf(stderr, "ERROR: Could not set nice level\n");
957 		return -1;
958 	}
959 #endif
960 
961 	return 0;
962 #endif
963 }
964 
set_realtime_priority(void)965 SWITCH_DECLARE(int32_t) set_realtime_priority(void)
966 {
967 #ifdef WIN32
968 	return SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
969 #else
970 #ifdef USE_SCHED_SETSCHEDULER
971 	/*
972 	 * Try to use a round-robin scheduler
973 	 * with a fallback if that does not work
974 	 */
975 	struct sched_param sched = { 0 };
976 	sched.sched_priority = SWITCH_PRI_LOW;
977 #endif
978 
979 #ifdef SOLARIS_PRIVILEGES
980 	/* request the privileges to elevate the priority */
981 	if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_PRIOCNTL, NULL) < 0) {
982 #ifdef PRIV_PROC_PRIOUP
983 		/* fallback to PRIV_PROC_PRIOUP on SmartOS */
984 		fprintf(stderr, "WARN: Failed to acquire proc_priocntl privilege (%s)\n", strerror(errno));
985 		if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_PRIOUP, NULL) < 0) {
986 			fprintf(stderr, "ERROR: Failed to acquire proc_prioup privilege (%s)\n", strerror(errno));
987 			return -1;
988 		}
989 #else
990 		fprintf(stderr, "ERROR: Failed to acquire proc_priocntl privilege (%s)\n", strerror(errno));
991 		return -1;
992 #endif
993 	}
994 
995 	if (sched_setscheduler(0, SCHED_FIFO, &sched) < 0) {
996 		fprintf(stderr, "WARN: Failed to set SCHED_FIFO scheduler (%s)\n", strerror(errno));
997 	} else {
998 		return 0;
999 	}
1000 
1001 	if (setpriority(PRIO_PROCESS, 0, -10) < 0) {
1002 		fprintf(stderr, "ERROR: Could not set nice level\n");
1003 		return -1;
1004 	}
1005 
1006 	return 0;
1007 #else
1008 
1009 #ifdef USE_SCHED_SETSCHEDULER
1010 	if (sched_setscheduler(0, SCHED_FIFO, &sched) < 0) {
1011 		fprintf(stderr, "ERROR: Failed to set SCHED_FIFO scheduler (%s)\n", strerror(errno));
1012 		sched.sched_priority = 0;
1013 		if (sched_setscheduler(0, SCHED_OTHER, &sched) < 0 ) {
1014 			fprintf(stderr, "ERROR: Failed to set SCHED_OTHER scheduler (%s)\n", strerror(errno));
1015 			return -1;
1016 		}
1017 	}
1018 #endif
1019 
1020 #ifdef HAVE_SETPRIORITY
1021 	/*
1022 	 * setpriority() works on FreeBSD (6.2), nice() doesn't
1023 	 */
1024 	if (setpriority(PRIO_PROCESS, getpid(), -10) < 0) {
1025 		fprintf(stderr, "ERROR: Could not set nice level\n");
1026 		return -1;
1027 	}
1028 #else
1029 	if (nice(-10) != -10) {
1030 		fprintf(stderr, "ERROR: Could not set nice level\n");
1031 		return -1;
1032 	}
1033 #endif
1034 #endif
1035 	return 0;
1036 #endif
1037 }
1038 
switch_core_cpu_count(void)1039 SWITCH_DECLARE(uint32_t) switch_core_cpu_count(void)
1040 {
1041 	return runtime.cpu_count;
1042 }
1043 
set_normal_priority(void)1044 SWITCH_DECLARE(int32_t) set_normal_priority(void)
1045 {
1046 	return 0;
1047 }
1048 
set_auto_priority(void)1049 SWITCH_DECLARE(int32_t) set_auto_priority(void)
1050 {
1051 #ifndef WIN32
1052 	runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN);
1053 #else
1054 	SYSTEM_INFO sysinfo;
1055 	GetSystemInfo( &sysinfo );
1056 	runtime.cpu_count = sysinfo.dwNumberOfProcessors;
1057 #endif
1058 
1059 	if (!runtime.cpu_count) runtime.cpu_count = 1;
1060 
1061 	return set_realtime_priority();
1062 
1063 
1064 	// ERROR: code not reachable on Windows Visual Studio Express 2008 return 0;
1065 }
1066 
change_user_group(const char * user,const char * group)1067 SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)
1068 {
1069 #ifndef WIN32
1070 	uid_t runas_uid = 0;
1071 	gid_t runas_gid = 0;
1072 	struct passwd *runas_pw = NULL;
1073 
1074 	if (user) {
1075 		/*
1076 		 * Lookup user information in the system's db
1077 		 */
1078 		runas_pw = getpwnam(user);
1079 		if (!runas_pw) {
1080 			fprintf(stderr, "ERROR: Unknown user \"%s\"\n", user);
1081 			return -1;
1082 		}
1083 		runas_uid = runas_pw->pw_uid;
1084 	}
1085 
1086 	if (group) {
1087 		struct group *gr = NULL;
1088 
1089 		/*
1090 		 * Lookup group information in the system's db
1091 		 */
1092 		gr = getgrnam(group);
1093 		if (!gr) {
1094 			fprintf(stderr, "ERROR: Unknown group \"%s\"\n", group);
1095 			return -1;
1096 		}
1097 		runas_gid = gr->gr_gid;
1098 	}
1099 
1100 	if (runas_uid && getuid() == runas_uid && (!runas_gid || runas_gid == getgid())) {
1101 		/* already running as the right user and group, nothing to do! */
1102 		return 0;
1103 	}
1104 
1105 	if (runas_uid) {
1106 #ifdef SOLARIS_PRIVILEGES
1107 		/* request the privilege to set the UID */
1108 		if (priv_set(PRIV_ON, PRIV_EFFECTIVE, PRIV_PROC_SETID, NULL) < 0) {
1109 			fprintf(stderr, "ERROR: Failed to acquire proc_setid privilege (%s)\n", strerror(errno));
1110 			return -1;
1111 		}
1112 #endif
1113 #ifdef HAVE_SETGROUPS
1114 		/*
1115 		 * Drop all group memberships prior to changing anything
1116 		 * or else we're going to inherit the parent's list of groups
1117 		 * (which is not what we want...)
1118 		 */
1119 		if (setgroups(0, NULL) < 0) {
1120 			fprintf(stderr, "ERROR: Failed to drop group access list\n");
1121 			return -1;
1122 		}
1123 #endif
1124 		if (runas_gid) {
1125 			/*
1126 			 * A group has been passed, switch to it
1127 			 * (without loading the user's other groups)
1128 			 */
1129 			if (setgid(runas_gid) < 0) {
1130 				fprintf(stderr, "ERROR: Failed to change gid!\n");
1131 				return -1;
1132 			}
1133 		} else {
1134 			/*
1135 			 * No group has been passed, use the user's primary group in this case
1136 			 */
1137 			if (setgid(runas_pw->pw_gid) < 0) {
1138 				fprintf(stderr, "ERROR: Failed to change gid!\n");
1139 				return -1;
1140 			}
1141 #ifdef HAVE_INITGROUPS
1142 			/*
1143 			 * Set all the other groups the user is a member of
1144 			 * (This can be really useful for fine-grained access control)
1145 			 */
1146 			if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) {
1147 				fprintf(stderr, "ERROR: Failed to set group access list for user\n");
1148 				return -1;
1149 			}
1150 #endif
1151 		}
1152 
1153 		/*
1154 		 * Finally drop all privileges by switching to the new userid
1155 		 */
1156 		if (setuid(runas_uid) < 0) {
1157 			fprintf(stderr, "ERROR: Failed to change uid!\n");
1158 			return -1;
1159 		}
1160 #ifdef HAVE_SYS_PRCTL_H
1161 		if (prctl(PR_SET_DUMPABLE, 1) < 0) {
1162 			fprintf(stderr, "ERROR: Failed to enable core dumps!\n");
1163 			return -1;
1164 		}
1165 #endif
1166 	}
1167 #endif
1168 	return 0;
1169 }
1170 
switch_core_runtime_loop(int bg)1171 SWITCH_DECLARE(void) switch_core_runtime_loop(int bg)
1172 {
1173 #ifdef WIN32
1174 	HANDLE shutdown_event;
1175 	char path[256] = "";
1176 #endif
1177 	if (bg) {
1178 #ifdef WIN32
1179 		switch_snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid());
1180 		shutdown_event = CreateEvent(NULL, FALSE, FALSE, path);
1181 		if (shutdown_event) {
1182 			WaitForSingleObject(shutdown_event, INFINITE);
1183 		}
1184 #else
1185 		while (runtime.running) {
1186 			switch_yield(1000000);
1187 		}
1188 #endif
1189 	} else {
1190 		/* wait for console input */
1191 		switch_console_loop();
1192 	}
1193 }
1194 
switch_core_mime_ext2type(const char * ext)1195 SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext)
1196 {
1197 	if (!ext) {
1198 		return NULL;
1199 	}
1200 	return (const char *) switch_core_hash_find(runtime.mime_types, ext);
1201 }
1202 
switch_core_mime_type2ext(const char * mime)1203 SWITCH_DECLARE(const char *) switch_core_mime_type2ext(const char *mime)
1204 {
1205 	if (!mime) {
1206 		return NULL;
1207 	}
1208 	return (const char *) switch_core_hash_find(runtime.mime_type_exts, mime);
1209 }
1210 
switch_core_mime_index(void)1211 SWITCH_DECLARE(switch_hash_index_t *) switch_core_mime_index(void)
1212 {
1213 	return switch_core_hash_first(runtime.mime_types);
1214 }
1215 
switch_core_mime_add_type(const char * type,const char * ext)1216 SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext)
1217 {
1218 	char *ptype = NULL;
1219 	char *ext_list = NULL;
1220 	int argc = 0;
1221 	char *argv[20] = { 0 };
1222 	int x;
1223 	switch_status_t status = SWITCH_STATUS_FALSE;
1224 
1225 	switch_assert(type);
1226 	switch_assert(ext);
1227 
1228 	ptype = switch_core_permanent_strdup(type);
1229 	ext_list = strdup(ext);
1230 
1231 	switch_assert(ext_list);
1232 
1233 	/* Map each file extension to this MIME type if not already mapped.  Map the MIME type to the first file extension in the list if not already mapped. */
1234 	if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
1235 		int is_mapped_type = switch_core_hash_find(runtime.mime_type_exts, ptype) != NULL;
1236 		for (x = 0; x < argc; x++) {
1237 			if (argv[x] && ptype) {
1238 				if (!switch_core_hash_find(runtime.mime_types, ext)) {
1239 					switch_core_hash_insert(runtime.mime_types, argv[x], ptype);
1240 				}
1241 				if (!is_mapped_type) {
1242 					switch_core_hash_insert(runtime.mime_type_exts, ptype, switch_core_permanent_strdup(argv[x]));
1243 					is_mapped_type = 1;
1244 				}
1245 			}
1246 		}
1247 
1248 		status = SWITCH_STATUS_SUCCESS;
1249 	}
1250 
1251 	free(ext_list);
1252 
1253 	return status;
1254 }
1255 
load_mime_types(void)1256 static void load_mime_types(void)
1257 {
1258 	char *cf = "mime.types";
1259 	FILE *fd = NULL;
1260 	char *line_buf = NULL;
1261 	switch_size_t llen = 0;
1262 	char *mime_path = NULL;
1263 
1264 	mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf);
1265 	switch_assert(mime_path);
1266 
1267 	fd = fopen(mime_path, "rb");
1268 
1269 	if (fd == NULL) {
1270 		goto end;
1271 	}
1272 
1273 	while ((switch_fp_read_dline(fd, &line_buf, &llen))) {
1274 		char *p;
1275 		char *type = line_buf;
1276 
1277 		if (*line_buf == '#') {
1278 			continue;
1279 		}
1280 
1281 		if ((p = strchr(line_buf, '\r')) || (p = strchr(line_buf, '\n'))) {
1282 			*p = '\0';
1283 		}
1284 
1285 		if ((p = strchr(type, '\t')) || (p = strchr(type, ' '))) {
1286 			*p++ = '\0';
1287 
1288 			while (*p == ' ' || *p == '\t') {
1289 				p++;
1290 			}
1291 
1292 			switch_core_mime_add_type(type, p);
1293 		}
1294 
1295 	}
1296 
1297 	switch_safe_free(line_buf);
1298 	fclose(fd);
1299 
1300   end:
1301 
1302 	switch_safe_free(mime_path);
1303 
1304 }
1305 
switch_core_setrlimits(void)1306 SWITCH_DECLARE(void) switch_core_setrlimits(void)
1307 {
1308 #ifdef HAVE_SETRLIMIT
1309 	struct rlimit rlp;
1310 
1311 	/*
1312 	   Setting the stack size on FreeBSD results in an instant crash.
1313 
1314 	   If anyone knows how to fix this,
1315 	   feel free to submit a patch to https://freeswitch.org/jira
1316 	 */
1317 
1318 #ifndef __FreeBSD__
1319 	memset(&rlp, 0, sizeof(rlp));
1320 	rlp.rlim_cur = SWITCH_THREAD_STACKSIZE;
1321 	rlp.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE;
1322 	setrlimit(RLIMIT_STACK, &rlp);
1323 #endif
1324 
1325 	memset(&rlp, 0, sizeof(rlp));
1326 	rlp.rlim_cur = 999999;
1327 	rlp.rlim_max = 999999;
1328 	setrlimit(RLIMIT_NOFILE, &rlp);
1329 
1330 	memset(&rlp, 0, sizeof(rlp));
1331 	rlp.rlim_cur = RLIM_INFINITY;
1332 	rlp.rlim_max = RLIM_INFINITY;
1333 
1334 	setrlimit(RLIMIT_CPU, &rlp);
1335 	setrlimit(RLIMIT_DATA, &rlp);
1336 	setrlimit(RLIMIT_FSIZE, &rlp);
1337 #ifdef RLIMIT_NPROC
1338 	setrlimit(RLIMIT_NPROC, &rlp);
1339 #endif
1340 #ifdef RLIMIT_RTPRIO
1341 	setrlimit(RLIMIT_RTPRIO, &rlp);
1342 #endif
1343 
1344 #if !defined(__OpenBSD__) && !defined(__NetBSD__)
1345 	setrlimit(RLIMIT_AS, &rlp);
1346 #endif
1347 #endif
1348 	return;
1349 }
1350 
1351 typedef struct {
1352 	switch_memory_pool_t *pool;
1353 	switch_hash_t *hash;
1354 } switch_ip_list_t;
1355 
1356 static switch_ip_list_t IP_LIST = { 0 };
1357 
switch_check_network_list_ip_port_token(const char * ip_str,int port,const char * list_name,const char ** token)1358 SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_port_token(const char *ip_str, int port, const char *list_name, const char **token)
1359 {
1360 	switch_network_list_t *list;
1361 	ip_t  ip, mask, net;
1362 	uint32_t bits;
1363 	char *ipv6 = strchr(ip_str,':');
1364 	switch_bool_t ok = SWITCH_FALSE;
1365 	char *ipv4 = NULL;
1366 
1367 	if (!list_name) {
1368 		return SWITCH_FALSE;
1369 	}
1370 
1371 	if ((ipv4 = switch_network_ipv4_mapped_ipv6_addr(ip_str))) {
1372 		ip_str = ipv4;
1373 		ipv6 = NULL;
1374 	}
1375 
1376 	switch_mutex_lock(runtime.global_mutex);
1377 	if (ipv6) {
1378 		switch_inet_pton(AF_INET6, ip_str, &ip);
1379 	} else {
1380 		switch_inet_pton(AF_INET, ip_str, &ip);
1381 		ip.v4 = htonl(ip.v4);
1382 	}
1383 
1384 	if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) {
1385 		if (ipv6) {
1386 			ok = switch_network_list_validate_ip6_port_token(list, ip, port, token);
1387 		} else {
1388 			ok = switch_network_list_validate_ip_port_token(list, ip.v4, port, token);
1389 		}
1390 	} else if (strchr(list_name, '/')) {
1391 		if (strchr(list_name, ',')) {
1392 			char *list_name_dup = strdup(list_name);
1393 			char *argv[32];
1394 			int argc;
1395 
1396 			switch_assert(list_name_dup);
1397 
1398 			if ((argc = switch_separate_string(list_name_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
1399 				int i;
1400 				for (i = 0; i < argc; i++) {
1401 					switch_parse_cidr(argv[i], &net, &mask, &bits);
1402 					if (ipv6) {
1403 						if ((ok = switch_testv6_subnet(ip, net, mask))){
1404 							break;
1405 						}
1406 					} else {
1407 						if ((ok = switch_test_subnet(ip.v4, net.v4, mask.v4))) {
1408 							break;
1409 						}
1410 					}
1411 				}
1412 			}
1413 			free(list_name_dup);
1414 		} else {
1415 			switch_parse_cidr(list_name, &net, &mask, &bits);
1416 
1417 			if (ipv6) {
1418 				ok = switch_testv6_subnet(ip, net, mask);
1419 			} else {
1420 				ok = switch_test_subnet(ip.v4, net.v4, mask.v4);
1421 			}
1422 		}
1423 	}
1424 
1425 	switch_safe_free(ipv4);
1426 	switch_mutex_unlock(runtime.global_mutex);
1427 
1428 	return ok;
1429 }
1430 
switch_check_network_list_ip_token(const char * ip_str,const char * list_name,const char ** token)1431 SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token)
1432 {
1433 	return switch_check_network_list_ip_port_token(ip_str, 0, list_name, token);
1434 }
1435 
switch_load_network_lists(switch_bool_t reload)1436 SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
1437 {
1438 	switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, x_node = NULL, cfg = NULL;
1439 	switch_network_list_t *rfc_list, *list;
1440 	char guess_ip[16] = "";
1441 	int mask = 0;
1442 	char guess_mask[16] = "";
1443 	char *tmp_name;
1444 	struct in_addr in;
1445 
1446 	switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET);
1447 	in.s_addr = mask;
1448 	switch_set_string(guess_mask, inet_ntoa(in));
1449 
1450 	switch_mutex_lock(runtime.global_mutex);
1451 
1452 	if (IP_LIST.hash) {
1453 		switch_core_hash_destroy(&IP_LIST.hash);
1454 	}
1455 
1456 	if (IP_LIST.pool) {
1457 		switch_core_destroy_memory_pool(&IP_LIST.pool);
1458 	}
1459 
1460 	memset(&IP_LIST, 0, sizeof(IP_LIST));
1461 	switch_core_new_memory_pool(&IP_LIST.pool);
1462 	switch_core_hash_init(&IP_LIST.hash);
1463 
1464 
1465 	tmp_name = "rfc6598.auto";
1466 	switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
1467 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
1468 	switch_network_list_add_cidr(rfc_list, "100.64.0.0/10", SWITCH_TRUE);
1469 	switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
1470 
1471 	tmp_name = "rfc1918.auto";
1472 	switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
1473 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
1474 	switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE);
1475 	switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE);
1476 	switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE);
1477 	switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_TRUE);
1478 	switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
1479 
1480 	tmp_name = "wan.auto";
1481 	switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
1482 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
1483 	switch_network_list_add_cidr(rfc_list, "0.0.0.0/8", SWITCH_FALSE);
1484 	switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE);
1485 	switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE);
1486 	switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE);
1487 	switch_network_list_add_cidr(rfc_list, "169.254.0.0/16", SWITCH_FALSE);
1488 	switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE);
1489 	switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
1490 
1491 	tmp_name = "wan_v6.auto";
1492 	switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
1493 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
1494 	switch_network_list_add_cidr(rfc_list, "0.0.0.0/0", SWITCH_FALSE);
1495 	switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE);
1496 	switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
1497 
1498 
1499 	tmp_name = "wan_v4.auto";
1500 	switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
1501 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
1502 	switch_network_list_add_cidr(rfc_list, "0.0.0.0/8", SWITCH_FALSE);
1503 	switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE);
1504 	switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE);
1505 	switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE);
1506 	switch_network_list_add_cidr(rfc_list, "169.254.0.0/16", SWITCH_FALSE);
1507 	switch_network_list_add_cidr(rfc_list, "::/0", SWITCH_FALSE);
1508 	switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
1509 
1510 
1511 	tmp_name = "any_v6.auto";
1512 	switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
1513 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
1514 	switch_network_list_add_cidr(rfc_list, "0.0.0.0/0", SWITCH_FALSE);
1515 	switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
1516 
1517 
1518 	tmp_name = "any_v4.auto";
1519 	switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);
1520 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);
1521 	switch_network_list_add_cidr(rfc_list, "::/0", SWITCH_FALSE);
1522 	switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
1523 
1524 
1525 	tmp_name = "nat.auto";
1526 	switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
1527 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
1528 	if (switch_network_list_add_host_mask(rfc_list, guess_ip, guess_mask, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
1529 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (deny) to list %s\n", guess_ip, guess_mask, tmp_name);
1530 	}
1531 	switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE);
1532 	switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE);
1533 	switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE);
1534 	switch_network_list_add_cidr(rfc_list, "100.64.0.0/10", SWITCH_TRUE);
1535 	switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
1536 
1537 	tmp_name = "loopback.auto";
1538 	switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
1539 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
1540 	switch_network_list_add_cidr(rfc_list, "127.0.0.0/8", SWITCH_TRUE);
1541 	switch_network_list_add_cidr(rfc_list, "::1/128", SWITCH_TRUE);
1542 	switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
1543 
1544 	tmp_name = "localnet.auto";
1545 	switch_network_list_create(&list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
1546 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
1547 
1548 	if (switch_network_list_add_host_mask(list, guess_ip, guess_mask, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
1549 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (allow) to list %s\n", guess_ip, guess_mask, tmp_name);
1550 	}
1551 	switch_core_hash_insert(IP_LIST.hash, tmp_name, list);
1552 
1553 
1554 	if ((xml = switch_xml_open_cfg("acl.conf", &cfg, NULL))) {
1555 		if ((x_lists = switch_xml_child(cfg, "network-lists"))) {
1556 			for (x_list = switch_xml_child(x_lists, "list"); x_list; x_list = x_list->next) {
1557 				const char *name = switch_xml_attr(x_list, "name");
1558 				const char *dft = switch_xml_attr(x_list, "default");
1559 				switch_bool_t default_type = SWITCH_TRUE;
1560 
1561 				if (zstr(name)) {
1562 					continue;
1563 				}
1564 
1565 				if (dft) {
1566 					default_type = switch_true(dft);
1567 				}
1568 
1569 				if (switch_network_list_create(&list, name, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) {
1570 					abort();
1571 				}
1572 
1573 				if (reload) {
1574 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny");
1575 				} else {
1576 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny");
1577 				}
1578 
1579 
1580 				for (x_node = switch_xml_child(x_list, "node"); x_node; x_node = x_node->next) {
1581 					const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL, *port = NULL;
1582 					switch_bool_t ok = default_type;
1583 					const char *type = switch_xml_attr(x_node, "type");
1584 					switch_network_port_range_t port_range;
1585 					char *argv[MAX_NETWORK_PORTS] = { 0 };
1586 					int argc = 0, i;
1587 
1588 					if (type) {
1589 						ok = switch_true(type);
1590 					}
1591 
1592 					cidr = switch_xml_attr(x_node, "cidr");
1593 					host = switch_xml_attr(x_node, "host");
1594 					mask = switch_xml_attr(x_node, "mask");
1595 					domain = switch_xml_attr(x_node, "domain");
1596 
1597 					memset(&port_range, 0, sizeof(switch_network_port_range_t));
1598 
1599 					if( (port = switch_xml_attr(x_node, "port")) != NULL) {
1600 						port_range.port = atoi(port);
1601 					}
1602 
1603 					if( (port = switch_xml_attr(x_node, "ports")) != NULL) {
1604 						argc = switch_separate_string((char*)port, ',', argv, (sizeof(argv) / sizeof(argv[0])));
1605 						for(i=0; i < argc; i++) {
1606 							port_range.ports[i] = atoi(argv[i]);
1607 						}
1608 					}
1609 					if( (port = switch_xml_attr(x_node, "port-min")) != NULL) {
1610 						port_range.min_port = atoi(port);
1611 					}
1612 					if( (port = switch_xml_attr(x_node, "port-max")) != NULL) {
1613 						port_range.max_port = atoi(port);
1614 					}
1615 
1616 					if (domain) {
1617 						switch_event_t *my_params = NULL;
1618 						switch_xml_t x_domain, xml_root;
1619 						switch_xml_t gt, gts, ut, uts;
1620 
1621 						switch_event_create(&my_params, SWITCH_EVENT_GENERAL);
1622 						switch_assert(my_params);
1623 						switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain);
1624 						switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "purpose", "network-list");
1625 
1626 						if (switch_xml_locate_domain(domain, my_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) {
1627 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain);
1628 							switch_event_destroy(&my_params);
1629 							continue;
1630 						}
1631 
1632 						switch_event_destroy(&my_params);
1633 
1634 						if ((ut = switch_xml_child(x_domain, "users"))) {
1635 							x_domain = ut;
1636 						}
1637 
1638 						for (ut = switch_xml_child(x_domain, "user"); ut; ut = ut->next) {
1639 							const char *user_cidr = switch_xml_attr(ut, "cidr");
1640 							const char *id = switch_xml_attr(ut, "id");
1641 
1642 							if (id && user_cidr) {
1643 								char *token = switch_mprintf("%s@%s", id, domain);
1644 								switch_assert(token);
1645 								switch_network_list_add_cidr_token(list, user_cidr, ok, token);
1646 								free(token);
1647 							}
1648 						}
1649 
1650 						for (gts = switch_xml_child(x_domain, "groups"); gts; gts = gts->next) {
1651 							for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) {
1652 								for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) {
1653 									for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) {
1654 										const char *user_cidr = switch_xml_attr(ut, "cidr");
1655 										const char *id = switch_xml_attr(ut, "id");
1656 
1657 										if (id && user_cidr) {
1658 											char *token = switch_mprintf("%s@%s", id, domain);
1659 											switch_assert(token);
1660 											switch_network_list_add_cidr_port_token(list, user_cidr, ok, token, &port_range);
1661 											free(token);
1662 										}
1663 									}
1664 								}
1665 							}
1666 						}
1667 
1668 						switch_xml_free(xml_root);
1669 					} else if (cidr) {
1670 						switch_network_list_add_cidr_port_token(list, cidr, ok, NULL, &port_range);
1671 					} else if (host && mask) {
1672 						switch_network_list_add_host_port_mask(list, host, mask, ok, &port_range);
1673 					}
1674 				}
1675 
1676 				switch_core_hash_insert(IP_LIST.hash, name, list);
1677 			}
1678 		}
1679 
1680 		switch_xml_free(xml);
1681 	}
1682 
1683 	switch_mutex_unlock(runtime.global_mutex);
1684 }
1685 
switch_core_max_dtmf_duration(uint32_t duration)1686 SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration)
1687 {
1688 	if (duration) {
1689 		if (duration > SWITCH_MAX_DTMF_DURATION) {
1690 			duration = SWITCH_MAX_DTMF_DURATION;
1691 		}
1692 		if (duration < SWITCH_MIN_DTMF_DURATION) {
1693 			duration = SWITCH_MIN_DTMF_DURATION;
1694 		}
1695 		runtime.max_dtmf_duration = duration;
1696 		if (duration < runtime.min_dtmf_duration) {
1697 			runtime.min_dtmf_duration = duration;
1698 		}
1699 	}
1700 	return runtime.max_dtmf_duration;
1701 }
1702 
switch_core_default_dtmf_duration(uint32_t duration)1703 SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration)
1704 {
1705 	if (duration) {
1706 		if (duration < SWITCH_MIN_DTMF_DURATION) {
1707 			duration = SWITCH_MIN_DTMF_DURATION;
1708 		}
1709 		if (duration > SWITCH_MAX_DTMF_DURATION) {
1710 			duration = SWITCH_MAX_DTMF_DURATION;
1711 		}
1712 		runtime.default_dtmf_duration = duration;
1713 
1714 		if (duration < runtime.min_dtmf_duration) {
1715 			runtime.min_dtmf_duration = duration;
1716 		}
1717 
1718 		if (duration > runtime.max_dtmf_duration) {
1719 			runtime.max_dtmf_duration = duration;
1720 		}
1721 
1722 	}
1723 	return runtime.default_dtmf_duration;
1724 }
1725 
switch_core_min_dtmf_duration(uint32_t duration)1726 SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration)
1727 {
1728 	if (duration) {
1729 		if (duration < SWITCH_MIN_DTMF_DURATION) {
1730 			duration = SWITCH_MIN_DTMF_DURATION;
1731 		}
1732 		if (duration > SWITCH_MAX_DTMF_DURATION) {
1733 			duration = SWITCH_MAX_DTMF_DURATION;
1734 		}
1735 
1736 		runtime.min_dtmf_duration = duration;
1737 
1738 		if (duration > runtime.max_dtmf_duration) {
1739 			runtime.max_dtmf_duration = duration;
1740 		}
1741 	}
1742 	return runtime.min_dtmf_duration;
1743 }
1744 
switch_core_thread_set_cpu_affinity(int cpu)1745 SWITCH_DECLARE(switch_status_t) switch_core_thread_set_cpu_affinity(int cpu)
1746 {
1747 	switch_status_t status = SWITCH_STATUS_FALSE;
1748 
1749 	if (cpu > -1) {
1750 
1751 #ifdef HAVE_CPU_SET_MACROS
1752 		cpu_set_t set;
1753 
1754 		CPU_ZERO(&set);
1755 		CPU_SET(cpu, &set);
1756 
1757 		if (!sched_setaffinity(0, sizeof(set), &set)) {
1758 			status = SWITCH_STATUS_SUCCESS;
1759 		}
1760 
1761 #else
1762 #if WIN32
1763 		if (SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR) cpu)) {
1764 			status = SWITCH_STATUS_SUCCESS;
1765 		}
1766 #endif
1767 #endif
1768 	}
1769 
1770 	return status;
1771 }
1772 
1773 
1774 #ifdef ENABLE_ZRTP
switch_core_set_serial(void)1775 static void switch_core_set_serial(void)
1776 {
1777 	char buf[13] = "";
1778 	char path[256];
1779 
1780 	int fd = -1, write_fd = -1;
1781 	switch_ssize_t bytes = 0;
1782 
1783 	switch_snprintf(path, sizeof(path), "%s%sfreeswitch.serial", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR);
1784 
1785 
1786 	if ((fd = open(path, O_RDONLY, 0)) < 0) {
1787 		char *ip = switch_core_get_variable_dup("local_ip_v4");
1788 		uint32_t ipi = 0;
1789 		switch_byte_t *byte;
1790 		int i = 0;
1791 
1792 		if (ip) {
1793 			switch_inet_pton(AF_INET, ip, &ipi);
1794 			free(ip);
1795 			ip = NULL;
1796 		}
1797 
1798 
1799 		byte = (switch_byte_t *) & ipi;
1800 
1801 		for (i = 0; i < 8; i += 2) {
1802 			switch_snprintf(buf + i, sizeof(buf) - i, "%0.2x", *byte);
1803 			byte++;
1804 		}
1805 
1806 		switch_stun_random_string(buf + 8, 4, "0123456789abcdef");
1807 
1808 		if ((write_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) >= 0) {
1809 			bytes = write(write_fd, buf, sizeof(buf));
1810 			bytes++;
1811 			close(write_fd);
1812 		}
1813 	} else {
1814 		bytes = read(fd, buf, sizeof(buf) - 1);
1815 		close(fd);
1816 	}
1817 
1818 	switch_core_set_variable("switch_serial", buf);
1819 }
1820 #endif
1821 
switch_core_test_flag(int flag)1822 SWITCH_DECLARE(int) switch_core_test_flag(int flag)
1823 {
1824 	return switch_test_flag((&runtime), flag);
1825 }
1826 
1827 
switch_core_init(switch_core_flag_t flags,switch_bool_t console,const char ** err)1828 SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err)
1829 {
1830 	switch_uuid_t uuid;
1831 	char guess_ip[256];
1832 	int mask = 0;
1833 	struct in_addr in;
1834 
1835 
1836 	if (runtime.runlevel > 0) {
1837 		/* one per customer */
1838 		return SWITCH_STATUS_SUCCESS;
1839 	}
1840 
1841 	memset(&runtime, 0, sizeof(runtime));
1842 	gethostname(runtime.hostname, sizeof(runtime.hostname));
1843 
1844 	runtime.max_db_handles = 50;
1845 	runtime.db_handle_timeout = 5000000;
1846 	runtime.event_heartbeat_interval = 20;
1847 
1848 	runtime.runlevel++;
1849 	runtime.dummy_cng_frame.data = runtime.dummy_data;
1850 	runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data);
1851 	runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data);
1852 	runtime.dbname = "core";
1853 	switch_set_flag((&runtime.dummy_cng_frame), SFF_CNG);
1854 	switch_set_flag((&runtime), SCF_AUTO_SCHEMAS);
1855 	switch_set_flag((&runtime), SCF_CLEAR_SQL);
1856 	switch_set_flag((&runtime), SCF_API_EXPANSION);
1857 	switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL);
1858 #ifdef WIN32
1859 	switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
1860 #endif
1861 	switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
1862 	runtime.hard_log_level = SWITCH_LOG_DEBUG;
1863 	runtime.mailer_app = "sendmail";
1864 	runtime.mailer_app_args = "-t";
1865 	runtime.max_dtmf_duration = SWITCH_MAX_DTMF_DURATION;
1866 	runtime.default_dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION;
1867 	runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION;
1868 	runtime.odbc_dbtype = DBTYPE_DEFAULT;
1869 	runtime.dbname = NULL;
1870 #ifndef WIN32
1871 	runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN);
1872 #else
1873 	{
1874 		SYSTEM_INFO sysinfo;
1875 		GetSystemInfo( &sysinfo );
1876 		runtime.cpu_count = sysinfo.dwNumberOfProcessors;
1877 	}
1878 #endif
1879 
1880 	if (!runtime.cpu_count) runtime.cpu_count = 1;
1881 
1882 	if (sqlite3_initialize() != SQLITE_OK) {
1883 		*err = "FATAL ERROR! Could not initialize SQLite\n";
1884 		return SWITCH_STATUS_MEMERR;
1885 	}
1886 
1887 	/* INIT APR and Create the pool context */
1888 	if (apr_initialize() != SWITCH_STATUS_SUCCESS) {
1889 		*err = "FATAL ERROR! Could not initialize APR\n";
1890 		return SWITCH_STATUS_MEMERR;
1891 	}
1892 
1893 	if (!(runtime.memory_pool = switch_core_memory_init())) {
1894 		*err = "FATAL ERROR! Could not allocate memory pool\n";
1895 		return SWITCH_STATUS_MEMERR;
1896 	}
1897 	switch_assert(runtime.memory_pool != NULL);
1898 
1899 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.base_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1900 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.mod_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1901 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.conf_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1902 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.log_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1903 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1904 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.db_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1905 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.script_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1906 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.htdocs_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1907 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1908 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.fonts_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1909 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.images_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1910 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.recordings_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1911 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.sounds_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1912 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.temp_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1913 	switch_dir_make_recursive(SWITCH_GLOBAL_dirs.certs_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
1914 
1915 	switch_mutex_init(&runtime.uuid_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
1916 
1917 	switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
1918 
1919 	switch_mutex_init(&runtime.session_hash_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
1920 	switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
1921 
1922 	switch_thread_rwlock_create(&runtime.global_var_rwlock, runtime.memory_pool);
1923 	switch_core_set_globals();
1924 	switch_core_session_init(runtime.memory_pool);
1925 	switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA);
1926 	switch_core_hash_init_case(&runtime.mime_types, SWITCH_FALSE);
1927 	switch_core_hash_init_case(&runtime.mime_type_exts, SWITCH_FALSE);
1928 	switch_core_hash_init_case(&runtime.ptimes, SWITCH_FALSE);
1929 	load_mime_types();
1930 	runtime.flags |= flags;
1931 	runtime.sps_total = 30;
1932 
1933 	*err = NULL;
1934 
1935 	if (console) {
1936 		runtime.console = stdout;
1937 	}
1938 
1939 	SSL_library_init();
1940 	switch_ssl_init_ssl_locks();
1941 	switch_curl_init();
1942 
1943 	switch_core_set_variable("hostname", runtime.hostname);
1944 	switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET);
1945 	switch_core_set_variable("local_ip_v4", guess_ip);
1946 	in.s_addr = mask;
1947 	switch_core_set_variable("local_mask_v4", inet_ntoa(in));
1948 
1949 
1950 	switch_find_local_ip(guess_ip, sizeof(guess_ip), NULL, AF_INET6);
1951 	switch_core_set_variable("local_ip_v6", guess_ip);
1952 	switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir);
1953 	switch_core_set_variable("recordings_dir", SWITCH_GLOBAL_dirs.recordings_dir);
1954 	switch_core_set_variable("sound_prefix", SWITCH_GLOBAL_dirs.sounds_dir);
1955 	switch_core_set_variable("sounds_dir", SWITCH_GLOBAL_dirs.sounds_dir);
1956 	switch_core_set_variable("conf_dir", SWITCH_GLOBAL_dirs.conf_dir);
1957 	switch_core_set_variable("log_dir", SWITCH_GLOBAL_dirs.log_dir);
1958 	switch_core_set_variable("run_dir", SWITCH_GLOBAL_dirs.run_dir);
1959 	switch_core_set_variable("db_dir", SWITCH_GLOBAL_dirs.db_dir);
1960 	switch_core_set_variable("mod_dir", SWITCH_GLOBAL_dirs.mod_dir);
1961 	switch_core_set_variable("htdocs_dir", SWITCH_GLOBAL_dirs.htdocs_dir);
1962 	switch_core_set_variable("script_dir", SWITCH_GLOBAL_dirs.script_dir);
1963 	switch_core_set_variable("temp_dir", SWITCH_GLOBAL_dirs.temp_dir);
1964 	switch_core_set_variable("grammar_dir", SWITCH_GLOBAL_dirs.grammar_dir);
1965 	switch_core_set_variable("fonts_dir", SWITCH_GLOBAL_dirs.fonts_dir);
1966 	switch_core_set_variable("images_dir", SWITCH_GLOBAL_dirs.images_dir);
1967 	switch_core_set_variable("certs_dir", SWITCH_GLOBAL_dirs.certs_dir);
1968 	switch_core_set_variable("storage_dir", SWITCH_GLOBAL_dirs.storage_dir);
1969 	switch_core_set_variable("cache_dir", SWITCH_GLOBAL_dirs.cache_dir);
1970 	switch_core_set_variable("data_dir", SWITCH_GLOBAL_dirs.data_dir);
1971 	switch_core_set_variable("localstate_dir", SWITCH_GLOBAL_dirs.localstate_dir);
1972 #ifdef ENABLE_ZRTP
1973 	switch_core_set_serial();
1974 #endif
1975 	switch_console_init(runtime.memory_pool);
1976 	switch_event_init(runtime.memory_pool);
1977 	switch_channel_global_init(runtime.memory_pool);
1978 
1979 	if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) {
1980 		/* allow missing configuration if MINIMAL */
1981 		if (!(flags & SCF_MINIMAL)) {
1982 			apr_terminate();
1983 			return SWITCH_STATUS_MEMERR;
1984 		}
1985 	}
1986 
1987 	if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {
1988 		switch_nat_init(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_NAT_MAPPING));
1989 	}
1990 
1991 	switch_log_init(runtime.memory_pool, runtime.colorize_console);
1992 
1993 	runtime.tipping_point = 0;
1994 	runtime.timer_affinity = -1;
1995 	runtime.microseconds_per_tick = 20000;
1996 
1997 	if (flags & SCF_MINIMAL) return SWITCH_STATUS_SUCCESS;
1998 
1999 	switch_load_core_config("switch.conf");
2000 
2001 	switch_core_state_machine_init(runtime.memory_pool);
2002 
2003 	switch_core_media_init();
2004 	switch_scheduler_task_thread_start();
2005 
2006 	switch_nat_late_init();
2007 
2008 	switch_rtp_init(runtime.memory_pool);
2009 
2010 	runtime.running = 1;
2011 	runtime.initiated = switch_mono_micro_time_now();
2012 
2013 	switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL);
2014 
2015 	switch_scheduler_add_task(switch_epoch_time_now(NULL), check_ip_callback, "check_ip", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL | SSHF_OWN_THREAD);
2016 
2017 	switch_uuid_get(&uuid);
2018 	switch_uuid_format(runtime.uuid_str, &uuid);
2019 	switch_core_set_variable("core_uuid", runtime.uuid_str);
2020 
2021 
2022 	return SWITCH_STATUS_SUCCESS;
2023 }
2024 
2025 
2026 #ifdef TRAP_BUS
handle_SIGBUS(int sig)2027 static void handle_SIGBUS(int sig)
2028 {
2029 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Sig BUS!\n");
2030 	return;
2031 }
2032 #endif
2033 
handle_SIGHUP(int sig)2034 static void handle_SIGHUP(int sig)
2035 {
2036 	if (sig) {
2037 		switch_event_t *event;
2038 
2039 		if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
2040 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Trapped-Signal", "HUP");
2041 			switch_event_fire(&event);
2042 		}
2043 	}
2044 	return;
2045 }
2046 
2047 
switch_default_ptime(const char * name,uint32_t number)2048 SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number)
2049 {
2050 	uint32_t *p;
2051 
2052 	if ((p = switch_core_hash_find(runtime.ptimes, name))) {
2053 		return *p;
2054 	}
2055 
2056 	return 20;
2057 }
2058 
switch_default_rate(const char * name,uint32_t number)2059 SWITCH_DECLARE(uint32_t) switch_default_rate(const char *name, uint32_t number)
2060 {
2061 
2062 	if (!strcasecmp(name, "opus")) {
2063 		return 48000;
2064 	} else if (!strncasecmp(name, "h26", 3)) { // h26x
2065 		return 90000;
2066 	} else if (!strncasecmp(name, "vp", 2)) {  // vp8, vp9
2067 		return 90000;
2068 	}
2069 
2070 	return 8000;
2071 }
2072 
2073 static uint32_t d_30 = 30;
2074 
switch_load_core_config(const char * file)2075 static void switch_load_core_config(const char *file)
2076 {
2077 	switch_xml_t xml = NULL, cfg = NULL;
2078 
2079 	switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30);
2080 	switch_core_hash_insert(runtime.ptimes, "isac", &d_30);
2081 	switch_core_hash_insert(runtime.ptimes, "G723", &d_30);
2082 
2083 
2084 	if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) {
2085 		switch_xml_t settings, param;
2086 
2087 		if ((settings = switch_xml_child(cfg, "default-ptimes"))) {
2088 			for (param = switch_xml_child(settings, "codec"); param; param = param->next) {
2089 				const char *var = switch_xml_attr_soft(param, "name");
2090 				const char *val = switch_xml_attr_soft(param, "ptime");
2091 
2092 				if (!zstr(var) && !zstr(val)) {
2093 					uint32_t *p;
2094 					uint32_t v = switch_atoul(val);
2095 
2096 					if (!strcasecmp(var, "G723") || !strcasecmp(var, "iLBC")) {
2097 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, defaults cannot be changed\n", var);
2098 						continue;
2099 					}
2100 
2101 					if (v == 0) {
2102 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, invalid ptime\n", var);
2103 						continue;
2104 					}
2105 
2106 					p = switch_core_alloc(runtime.memory_pool, sizeof(*p));
2107 					*p = v;
2108 					switch_core_hash_insert(runtime.ptimes, var, p);
2109 				}
2110 
2111 			}
2112 		}
2113 
2114 		if ((settings = switch_xml_child(cfg, "settings"))) {
2115 			for (param = switch_xml_child(settings, "param"); param; param = param->next) {
2116 				const char *var = switch_xml_attr_soft(param, "name");
2117 				const char *val = switch_xml_attr_soft(param, "value");
2118 
2119 				if (!strcasecmp(var, "loglevel")) {
2120 					int level;
2121 					if (*val > 47 && *val < 58) {
2122 						level = atoi(val);
2123 					} else {
2124 						level = switch_log_str2level(val);
2125 					}
2126 
2127 					if (level != SWITCH_LOG_INVALID) {
2128 						switch_core_session_ctl(SCSC_LOGLEVEL, &level);
2129 					}
2130 #ifdef HAVE_SETRLIMIT
2131 				} else if (!strcasecmp(var, "dump-cores") && switch_true(val)) {
2132 					struct rlimit rlp;
2133 					memset(&rlp, 0, sizeof(rlp));
2134 					rlp.rlim_cur = RLIM_INFINITY;
2135 					rlp.rlim_max = RLIM_INFINITY;
2136 					setrlimit(RLIMIT_CORE, &rlp);
2137 #endif
2138 				} else if (!strcasecmp(var, "debug-level")) {
2139 					int tmp = atoi(val);
2140 					if (tmp > -1 && tmp < 11) {
2141 						switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp);
2142 					}
2143 				} else if (!strcasecmp(var, "max-db-handles")) {
2144 					long tmp = atol(val);
2145 
2146 					if (tmp > 4 && tmp < 5001) {
2147 						runtime.max_db_handles = (uint32_t) tmp;
2148 					} else {
2149 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-db-handles must be between 5 and 5000\n");
2150 					}
2151 				} else if (!strcasecmp(var, "db-handle-timeout")) {
2152 					long tmp = atol(val);
2153 
2154 					if (tmp > 0 && tmp < 5001) {
2155 						runtime.db_handle_timeout = (uint32_t) tmp * 1000000;
2156 					} else {
2157 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "db-handle-timeout must be between 1 and 5000\n");
2158 					}
2159 
2160 				} else if (!strcasecmp(var, "event-heartbeat-interval")) {
2161 					long tmp = atol(val);
2162 
2163 					if (tmp > 0) {
2164 						runtime.event_heartbeat_interval = (uint32_t) tmp;
2165 					} else {
2166 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "heartbeat-interval must be a greater than 0\n");
2167 					}
2168 
2169 				} else if (!strcasecmp(var, "multiple-registrations")) {
2170 					runtime.multiple_registrations = switch_true(val);
2171 				} else if (!strcasecmp(var, "auto-create-schemas")) {
2172 					if (switch_true(val)) {
2173 						switch_set_flag((&runtime), SCF_AUTO_SCHEMAS);
2174 					} else {
2175 						switch_clear_flag((&runtime), SCF_AUTO_SCHEMAS);
2176 					}
2177 				} else if (!strcasecmp(var, "session-thread-pool")) {
2178 					if (switch_true(val)) {
2179 						switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL);
2180 					} else {
2181 						switch_clear_flag((&runtime), SCF_SESSION_THREAD_POOL);
2182 					}
2183 				} else if (!strcasecmp(var, "auto-clear-sql")) {
2184 					if (switch_true(val)) {
2185 						switch_set_flag((&runtime), SCF_CLEAR_SQL);
2186 					} else {
2187 						switch_clear_flag((&runtime), SCF_CLEAR_SQL);
2188 					}
2189 				} else if (!strcasecmp(var, "api-expansion")) {
2190 					if (switch_true(val)) {
2191 						switch_set_flag((&runtime), SCF_API_EXPANSION);
2192 					} else {
2193 						switch_clear_flag((&runtime), SCF_API_EXPANSION);
2194 					}
2195 				} else if (!strcasecmp(var, "enable-early-hangup") && switch_true(val)) {
2196 					switch_set_flag((&runtime), SCF_EARLY_HANGUP);
2197 				} else if (!strcasecmp(var, "colorize-console") && switch_true(val)) {
2198 					runtime.colorize_console = SWITCH_TRUE;
2199 				} else if (!strcasecmp(var, "core-db-pre-trans-execute") && !zstr(val)) {
2200 					runtime.core_db_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val);
2201 				} else if (!strcasecmp(var, "core-db-post-trans-execute") && !zstr(val)) {
2202 					runtime.core_db_post_trans_execute = switch_core_strdup(runtime.memory_pool, val);
2203 				} else if (!strcasecmp(var, "core-db-inner-pre-trans-execute") && !zstr(val)) {
2204 					runtime.core_db_inner_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val);
2205 				} else if (!strcasecmp(var, "core-db-inner-post-trans-execute") && !zstr(val)) {
2206 					runtime.core_db_inner_post_trans_execute = switch_core_strdup(runtime.memory_pool, val);
2207 				} else if (!strcasecmp(var, "dialplan-timestamps")) {
2208 					if (switch_true(val)) {
2209 						switch_set_flag((&runtime), SCF_DIALPLAN_TIMESTAMPS);
2210 					} else {
2211 						switch_clear_flag((&runtime), SCF_DIALPLAN_TIMESTAMPS);
2212 					}
2213 				} else if (!strcasecmp(var, "mailer-app") && !zstr(val)) {
2214 					runtime.mailer_app = switch_core_strdup(runtime.memory_pool, val);
2215 				} else if (!strcasecmp(var, "mailer-app-args") && val) {
2216 					runtime.mailer_app_args = switch_core_strdup(runtime.memory_pool, val);
2217 				} else if (!strcasecmp(var, "sessions-per-second") && !zstr(val)) {
2218 					switch_core_sessions_per_second(atoi(val));
2219 				} else if (!strcasecmp(var, "max-dtmf-duration") && !zstr(val)) {
2220 					int tmp = atoi(val);
2221 					if (tmp > 0) {
2222 						switch_core_max_dtmf_duration((uint32_t) tmp);
2223 					}
2224 				} else if (!strcasecmp(var, "min-dtmf-duration") && !zstr(val)) {
2225 					int tmp = atoi(val);
2226 					if (tmp > 0) {
2227 						switch_core_min_dtmf_duration((uint32_t) tmp);
2228 					}
2229 				} else if (!strcasecmp(var, "default-dtmf-duration") && !zstr(val)) {
2230 					int tmp = atoi(val);
2231 					if (tmp > 0) {
2232 						switch_core_default_dtmf_duration((uint32_t) tmp);
2233 					}
2234 				} else if (!strcasecmp(var, "enable-use-system-time")) {
2235 					switch_time_set_use_system_time(switch_true(val));
2236 				} else if (!strcasecmp(var, "enable-monotonic-timing")) {
2237 					switch_time_set_monotonic(switch_true(val));
2238 				} else if (!strcasecmp(var, "enable-softtimer-timerfd")) {
2239 					int ival = 0;
2240 					if (val) {
2241 						if (switch_true(val)) {
2242 							ival = 2;
2243 						} else {
2244 							if (strcasecmp(val, "broadcast")) {
2245 								ival = 1;
2246 							} else if (strcasecmp(val, "fd-per-timer")) {
2247 								ival = 2;
2248 							}
2249 						}
2250 					}
2251 					switch_time_set_timerfd(ival);
2252 				} else if (!strcasecmp(var, "enable-clock-nanosleep")) {
2253 					switch_time_set_nanosleep(switch_true(val));
2254 				} else if (!strcasecmp(var, "enable-cond-yield")) {
2255 					switch_time_set_cond_yield(switch_true(val));
2256 				} else if (!strcasecmp(var, "enable-timer-matrix")) {
2257 					switch_time_set_matrix(switch_true(val));
2258 				} else if (!strcasecmp(var, "max-sessions") && !zstr(val)) {
2259 					switch_core_session_limit(atoi(val));
2260 				} else if (!strcasecmp(var, "verbose-channel-events") && !zstr(val)) {
2261 					int v = switch_true(val);
2262 					if (v) {
2263 						switch_set_flag((&runtime), SCF_VERBOSE_EVENTS);
2264 					} else {
2265 						switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS);
2266 					}
2267 				} else if (!strcasecmp(var, "threaded-system-exec") && !zstr(val)) {
2268 #ifdef WIN32
2269 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "threaded-system-exec is not implemented on this platform\n");
2270 #else
2271 					int v = switch_true(val);
2272 					if (v) {
2273 						switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
2274 					} else {
2275 						switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
2276 					}
2277 #endif
2278 				} else if (!strcasecmp(var, "min-idle-cpu") && !zstr(val)) {
2279 					switch_core_min_idle_cpu(atof(val));
2280 				} else if (!strcasecmp(var, "tipping-point") && !zstr(val)) {
2281 					runtime.tipping_point = atoi(val);
2282 				} else if (!strcasecmp(var, "cpu-idle-smoothing-depth") && !zstr(val)) {
2283 					runtime.cpu_idle_smoothing_depth = atoi(val);
2284 				} else if (!strcasecmp(var, "events-use-dispatch") && !zstr(val)) {
2285 					runtime.events_use_dispatch = switch_true(val);
2286 				} else if (!strcasecmp(var, "initial-event-threads") && !zstr(val)) {
2287 					int tmp;
2288 
2289 					if (!runtime.events_use_dispatch) {
2290 						runtime.events_use_dispatch = 1;
2291 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
2292 										  "Implicitly setting events-use-dispatch based on usage of this initial-event-threads parameter.\n");
2293 					}
2294 
2295 					tmp = atoi(val);
2296 
2297 					if (tmp > runtime.cpu_count / 2) {
2298 						tmp = runtime.cpu_count / 2;
2299 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be higher than %d so setting it to that value\n",
2300 										  runtime.cpu_count / 2);
2301 					}
2302 
2303 					if (tmp < 1) {
2304 						tmp = 1;
2305 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be lower than 1 so setting it to that level\n");
2306 					}
2307 
2308 					switch_event_launch_dispatch_threads(tmp);
2309 
2310 				} else if (!strcasecmp(var, "1ms-timer") && switch_true(val)) {
2311 					runtime.microseconds_per_tick = 1000;
2312 				} else if (!strcasecmp(var, "timer-affinity") && !zstr(val)) {
2313 					if (!strcasecmp(val, "disabled")) {
2314 						runtime.timer_affinity = -1;
2315 					} else {
2316 						runtime.timer_affinity = atoi(val);
2317 					}
2318 				} else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) {
2319 					switch_rtp_set_start_port((switch_port_t) atoi(val));
2320 				} else if (!strcasecmp(var, "rtp-end-port") && !zstr(val)) {
2321 					switch_rtp_set_end_port((switch_port_t) atoi(val));
2322 				} else if (!strcasecmp(var, "rtp-port-usage-robustness") && switch_true(val)) {
2323 					runtime.port_alloc_flags |= SPF_ROBUST_UDP;
2324 				} else if (!strcasecmp(var, "core-db-name") && !zstr(val)) {
2325 					runtime.dbname = switch_core_strdup(runtime.memory_pool, val);
2326 				} else if (!strcasecmp(var, "core-db-dsn") && !zstr(val)) {
2327 					runtime.odbc_dsn = switch_core_strdup(runtime.memory_pool, val);
2328 				} else if (!strcasecmp(var, "core-non-sqlite-db-required") && !zstr(val)) {
2329 					switch_set_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ);
2330 				} else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) {
2331 					if (!strcasecmp(val, "MSSQL")) {
2332 						runtime.odbc_dbtype = DBTYPE_MSSQL;
2333 					} else {
2334 						runtime.odbc_dbtype = DBTYPE_DEFAULT;
2335 					}
2336 #ifdef ENABLE_ZRTP
2337 				} else if (!strcasecmp(var, "rtp-enable-zrtp")) {
2338 					switch_core_set_variable("zrtp_enabled", val);
2339 #endif
2340 				} else if (!strcasecmp(var, "switchname") && !zstr(val)) {
2341 					runtime.switchname = switch_core_strdup(runtime.memory_pool, val);
2342 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Set switchname to %s\n", runtime.switchname);
2343 				} else if (!strcasecmp(var, "rtp-retain-crypto-keys")) {
2344 					if (switch_true(val)) {
2345 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
2346 										  "rtp-retain-crypto-keys enabled. Could be used to decrypt secure media.\n");
2347 					}
2348 					switch_core_set_variable("rtp_retain_crypto_keys", val);
2349 				} else if (!strcasecmp(var, "caller-profile-soft-variables-uses-prefix") && !zstr(val)) {
2350 					int v = switch_true(val);
2351 					if (v) {
2352 						switch_set_flag((&runtime), SCF_CPF_SOFT_PREFIX);
2353 					} else {
2354 						switch_clear_flag((&runtime), SCF_CPF_SOFT_PREFIX);
2355 					}
2356 				} else if (!strcasecmp(var, "caller-profile-soft-lookup-values") && !zstr(val)) {
2357 					int v = switch_true(val);
2358 					if (v) {
2359 						switch_set_flag((&runtime), SCF_CPF_SOFT_LOOKUP);
2360 					} else {
2361 						switch_clear_flag((&runtime), SCF_CPF_SOFT_LOOKUP);
2362 					}
2363 				} else if (!strcasecmp(var, "event-channel-key-separator") && !zstr(val)) {
2364 					runtime.event_channel_key_separator = switch_core_strdup(runtime.memory_pool, val);
2365 				} else if (!strcasecmp(var, "event-channel-enable-hierarchy-deliver") && !zstr(val)) {
2366 					int v = switch_true(val);
2367 					if (v) {
2368 						switch_set_flag((&runtime), SCF_EVENT_CHANNEL_ENABLE_HIERARCHY_DELIVERY);
2369 					} else {
2370 						switch_clear_flag((&runtime), SCF_EVENT_CHANNEL_ENABLE_HIERARCHY_DELIVERY);
2371 					}
2372 				} else if (!strcasecmp(var, "event-channel-hierarchy-deliver-once") && !zstr(val)) {
2373 					int v = switch_true(val);
2374 					if (v) {
2375 						switch_set_flag((&runtime), SCF_EVENT_CHANNEL_HIERARCHY_DELIVERY_ONCE);
2376 					} else {
2377 						switch_clear_flag((&runtime), SCF_EVENT_CHANNEL_HIERARCHY_DELIVERY_ONCE);
2378 					}
2379 				} else if (!strcasecmp(var, "event-channel-log-undeliverable-json") && !zstr(val)) {
2380 					int v = switch_true(val);
2381 					if (v) {
2382 						switch_set_flag((&runtime), SCF_EVENT_CHANNEL_LOG_UNDELIVERABLE_JSON);
2383 					} else {
2384 						switch_clear_flag((&runtime), SCF_EVENT_CHANNEL_LOG_UNDELIVERABLE_JSON);
2385 					}
2386 				} else if (!strcasecmp(var, "max-audio-channels") && !zstr(val)) {
2387 					switch_core_max_audio_channels(atoi(val));
2388 				}
2389 			}
2390 		}
2391 
2392 		if (runtime.event_channel_key_separator == NULL) {
2393 			runtime.event_channel_key_separator = switch_core_strdup(runtime.memory_pool, ".");
2394 		}
2395 
2396 		if ((settings = switch_xml_child(cfg, "variables"))) {
2397 			for (param = switch_xml_child(settings, "variable"); param; param = param->next) {
2398 				const char *var = switch_xml_attr_soft(param, "name");
2399 				const char *val = switch_xml_attr_soft(param, "value");
2400 				if (var && val) {
2401 					switch_core_set_variable(var, val);
2402 				}
2403 			}
2404 		}
2405 
2406 		switch_xml_free(xml);
2407 	}
2408 
2409 
2410 }
2411 
switch_core_banner(void)2412 SWITCH_DECLARE(const char *) switch_core_banner(void)
2413 {
2414 
2415 	return ("\n"
2416 			".=============================================================.\n"
2417 			"|   _____              ______        _____ _____ ____ _   _   |\n"
2418 			"|  |  ___| __ ___  ___/ ___\\ \\      / /_ _|_   _/ ___| | | |  |\n"
2419 			"|  | |_ | '__/ _ \\/ _ \\___ \\\\ \\ /\\ / / | |  | || |   | |_| |  |\n"
2420 			"|  |  _|| | |  __/  __/___) |\\ V  V /  | |  | || |___|  _  |  |\n"
2421 			"|  |_|  |_|  \\___|\\___|____/  \\_/\\_/  |___| |_| \\____|_| |_|  |\n"
2422 			"|                                                             |\n"
2423 			".=============================================================."
2424 			"\n"
2425 
2426 			"|   Anthony Minessale II, Michael Jerris, Brian West, Others  |\n"
2427 			"|   FreeSWITCH (http://www.freeswitch.org)                    |\n"
2428 			"|   Paypal Donations Appreciated: paypal@freeswitch.org       |\n"
2429 			"|   Brought to you by ClueCon http://www.cluecon.com/         |\n"
2430 			".=============================================================.\n"
2431 			"\n");
2432 }
2433 
switch_core_sqldb_init(const char ** err)2434 switch_status_t switch_core_sqldb_init(const char **err)
2435 {
2436 	if (switch_core_check_core_db_dsn() != SWITCH_STATUS_SUCCESS) {
2437 		*err = "NO SUITABLE DATABASE INTERFACE IS AVAILABLE TO SERVE 'core-db-dsn'!\n";
2438 		return SWITCH_STATUS_GENERR;
2439 	}
2440 
2441 	if (switch_core_sqldb_start(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_SQL) ? SWITCH_TRUE : SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
2442 		*err = "Error activating database";
2443 		return SWITCH_STATUS_GENERR;
2444 	}
2445 
2446 	return SWITCH_STATUS_SUCCESS;
2447 }
2448 
switch_core_init_and_modload(switch_core_flag_t flags,switch_bool_t console,const char ** err)2449 SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t flags, switch_bool_t console, const char **err)
2450 {
2451 	switch_event_t *event;
2452 	char *cmd;
2453 	int x = 0;
2454 	const char *use = NULL;
2455 #include "cc.h"
2456 
2457 
2458 	if (switch_core_init(flags, console, err) != SWITCH_STATUS_SUCCESS) {
2459 		return SWITCH_STATUS_GENERR;
2460 	}
2461 
2462 	if (runtime.runlevel > 1) {
2463 		/* one per customer */
2464 		return SWITCH_STATUS_SUCCESS;
2465 	}
2466 
2467 	runtime.runlevel++;
2468 	runtime.events_use_dispatch = 1;
2469 
2470 	switch_core_set_signal_handlers();
2471 	switch_load_network_lists(SWITCH_FALSE);
2472 
2473 	switch_msrp_init();
2474 
2475 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Bringing up environment.\n");
2476 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Loading Modules.\n");
2477 	if (switch_loadable_module_init(SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
2478 		*err = "Cannot load modules";
2479 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error: %s\n", *err);
2480 		return SWITCH_STATUS_GENERR;
2481 	}
2482 
2483 	switch_load_network_lists(SWITCH_FALSE);
2484 
2485 	switch_load_core_config("post_load_switch.conf");
2486 
2487 	switch_core_set_signal_handlers();
2488 
2489 	if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {
2490 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");
2491 		switch_event_fire(&event);
2492 	}
2493 
2494 	switch_core_screen_size(&x, NULL);
2495 
2496 	use = (x > 100) ? cc : cc_s;
2497 
2498 #ifdef WIN32
2499 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), use);
2500 #else
2501 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n",
2502 					  SWITCH_SEQ_DEFAULT_COLOR,
2503 					  SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE,
2504 					  switch_core_banner(),
2505 					  use, SWITCH_SEQ_DEFAULT_COLOR);
2506 
2507 #endif
2508 
2509 
2510 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
2511 					  "\nFreeSWITCH Version %s (%s)\n\nFreeSWITCH Started\nMax Sessions [%u]\nSession Rate [%d]\nSQL [%s]\n",
2512 					  switch_version_full(), switch_version_revision_human(),
2513 					  switch_core_session_limit(0),
2514 					  switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled");
2515 
2516 
2517 	if (x < 160) {
2518 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\n[This app Best viewed at 160x60 or more..]\n");
2519 	}
2520 
2521 	switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);
2522 
2523 	if ((cmd = switch_core_get_variable_dup("api_on_startup"))) {
2524 		switch_stream_handle_t stream = { 0 };
2525 		SWITCH_STANDARD_STREAM(stream);
2526 		switch_console_execute(cmd, 0, &stream);
2527 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Startup command [%s] executed. Output:\n%s\n", cmd, (char *)stream.data);
2528 		free(stream.data);
2529 		free(cmd);
2530 	}
2531 
2532 	return SWITCH_STATUS_SUCCESS;
2533 
2534 }
2535 
switch_core_measure_time(switch_time_t total_ms,switch_core_time_duration_t * duration)2536 SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration)
2537 {
2538 	switch_time_t temp = total_ms / 1000;
2539 	memset(duration, 0, sizeof(*duration));
2540 	duration->mms = (uint32_t) (total_ms % 1000);
2541 	duration->ms = (uint32_t) (temp % 1000);
2542 	temp = temp / 1000;
2543 	duration->sec = (uint32_t) (temp % 60);
2544 	temp = temp / 60;
2545 	duration->min = (uint32_t) (temp % 60);
2546 	temp = temp / 60;
2547 	duration->hr = (uint32_t) (temp % 24);
2548 	temp = temp / 24;
2549 	duration->day = (uint32_t) (temp % 365);
2550 	duration->yr = (uint32_t) (temp / 365);
2551 }
2552 
switch_core_uptime(void)2553 SWITCH_DECLARE(switch_time_t) switch_core_uptime(void)
2554 {
2555 	return switch_mono_micro_time_now() - runtime.initiated;
2556 }
2557 
2558 
2559 #ifdef _MSC_VER
win_shutdown(void)2560 static void win_shutdown(void)
2561 {
2562 
2563 	HANDLE shutdown_event;
2564 	char path[512];
2565 	/* for windows we need the event to signal for shutting down a background FreeSWITCH */
2566 	snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid());
2567 
2568 	/* open the event so we can signal it */
2569 	shutdown_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, path);
2570 
2571 	if (shutdown_event) {
2572 		/* signal the event to shutdown */
2573 		SetEvent(shutdown_event);
2574 		/* cleanup */
2575 		CloseHandle(shutdown_event);
2576 	}
2577 }
2578 #endif
2579 
switch_core_set_signal_handlers(void)2580 SWITCH_DECLARE(void) switch_core_set_signal_handlers(void)
2581 {
2582 	/* set signal handlers */
2583 	signal(SIGINT, SIG_IGN);
2584 #ifdef SIGPIPE
2585 	signal(SIGPIPE, SIG_IGN);
2586 #endif
2587 #ifdef SIGALRM
2588 	signal(SIGALRM, SIG_IGN);
2589 #endif
2590 #ifdef SIGQUIT
2591 	signal(SIGQUIT, SIG_IGN);
2592 #endif
2593 #ifdef SIGPOLL
2594 	signal(SIGPOLL, SIG_IGN);
2595 #endif
2596 #ifdef SIGIO
2597 	signal(SIGIO, SIG_IGN);
2598 #endif
2599 #ifdef TRAP_BUS
2600 	signal(SIGBUS, handle_SIGBUS);
2601 #endif
2602 #ifdef SIGUSR1
2603 	signal(SIGUSR1, handle_SIGHUP);
2604 #endif
2605 	signal(SIGHUP, handle_SIGHUP);
2606 }
2607 
switch_core_debug_level(void)2608 SWITCH_DECLARE(uint32_t) switch_core_debug_level(void)
2609 {
2610 	return runtime.debug_level;
2611 }
2612 
switch_core_sps(void)2613 SWITCH_DECLARE(int32_t) switch_core_sps(void)
2614 {
2615 	return runtime.sps;
2616 }
2617 
switch_core_sps_last(void)2618 SWITCH_DECLARE(int32_t) switch_core_sps_last(void)
2619 {
2620 	return runtime.sps_last;
2621 }
2622 
switch_core_sps_peak(void)2623 SWITCH_DECLARE(int32_t) switch_core_sps_peak(void)
2624 {
2625 	return runtime.sps_peak;
2626 }
2627 
switch_core_sps_peak_fivemin(void)2628 SWITCH_DECLARE(int32_t) switch_core_sps_peak_fivemin(void)
2629 {
2630 	return runtime.sps_peak_fivemin;
2631 }
2632 
switch_core_sessions_peak(void)2633 SWITCH_DECLARE(int32_t) switch_core_sessions_peak(void)
2634 {
2635 	return runtime.sessions_peak;
2636 }
2637 
switch_core_sessions_peak_fivemin(void)2638 SWITCH_DECLARE(int32_t) switch_core_sessions_peak_fivemin(void)
2639 {
2640 	return runtime.sessions_peak_fivemin;
2641 }
2642 
switch_core_max_audio_channels(uint32_t limit)2643 SWITCH_DECLARE(uint32_t) switch_core_max_audio_channels(uint32_t limit)
2644 {
2645 	if (limit) {
2646 		runtime.max_audio_channels = limit;
2647 	}
2648 
2649 	return runtime.max_audio_channels;
2650 }
2651 
switch_core_session_ctl(switch_session_ctl_t cmd,void * val)2652 SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void *val)
2653 {
2654 	int *intval = (int *) val;
2655 	int oldintval = 0, newintval = 0;
2656 
2657 	if (intval) {
2658 		oldintval = *intval;
2659 	}
2660 
2661 	if (switch_test_flag((&runtime), SCF_SHUTTING_DOWN)) {
2662 		return -1;
2663 	}
2664 
2665 	switch (cmd) {
2666 	case SCSC_RECOVER:
2667 		{
2668 			char *arg = (char *) val;
2669 			char *tech = NULL, *prof = NULL;
2670 			int r, flush = 0;
2671 
2672 			if (!zstr(arg)) {
2673 				tech = strdup(arg);
2674 				switch_assert(tech);
2675 
2676 				if ((prof = strchr(tech, ':'))) {
2677 					*prof++ = '\0';
2678 				}
2679 
2680 				if (!strcasecmp(tech, "flush")) {
2681 					flush++;
2682 
2683 					if (prof) {
2684 						char *tech = prof;
2685 						if ((prof = strchr(tech, ':'))) {
2686 							*prof++ = '\0';
2687 						}
2688 					}
2689 				}
2690 
2691 			}
2692 
2693 			if (flush) {
2694 				switch_core_recovery_flush(tech, prof);
2695 				r = -1;
2696 			} else {
2697 				r = switch_core_recovery_recover(tech, prof);
2698 			}
2699 
2700 			switch_safe_free(tech);
2701 			return r;
2702 
2703 		}
2704 		break;
2705 	case SCSC_DEBUG_SQL:
2706 		{
2707 			if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) {
2708 				switch_clear_flag((&runtime), SCF_DEBUG_SQL);
2709 				newintval = 0;
2710 			} else {
2711 				switch_set_flag((&runtime), SCF_DEBUG_SQL);
2712 				newintval = 1;
2713 			}
2714 		}
2715 		break;
2716 	case SCSC_VERBOSE_EVENTS:
2717 		if (intval) {
2718 			if (oldintval > -1) {
2719 				if (oldintval) {
2720 					switch_set_flag((&runtime), SCF_VERBOSE_EVENTS);
2721 				} else {
2722 					switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS);
2723 				}
2724 			}
2725 			newintval = switch_test_flag((&runtime), SCF_VERBOSE_EVENTS);
2726 		}
2727 		break;
2728 	case SCSC_API_EXPANSION:
2729 		if (intval) {
2730 			if (oldintval > -1) {
2731 				if (oldintval) {
2732 					switch_set_flag((&runtime), SCF_API_EXPANSION);
2733 				} else {
2734 					switch_clear_flag((&runtime), SCF_API_EXPANSION);
2735 				}
2736 			}
2737 			newintval = switch_test_flag((&runtime), SCF_API_EXPANSION);
2738 		}
2739 		break;
2740 	case SCSC_THREADED_SYSTEM_EXEC:
2741 		if (intval) {
2742 			if (oldintval > -1) {
2743 				if (oldintval) {
2744 					switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
2745 				} else {
2746 					switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
2747 				}
2748 			}
2749 			newintval = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);
2750 		}
2751 		break;
2752 	case SCSC_CALIBRATE_CLOCK:
2753 		switch_time_calibrate_clock();
2754 		break;
2755 	case SCSC_FLUSH_DB_HANDLES:
2756 		switch_cache_db_flush_handles();
2757 		break;
2758 	case SCSC_SEND_SIGHUP:
2759 		handle_SIGHUP(1);
2760 		break;
2761 	case SCSC_SYNC_CLOCK:
2762 		switch_time_sync();
2763 		newintval = 0;
2764 		break;
2765 	case SCSC_SYNC_CLOCK_WHEN_IDLE:
2766 		newintval = switch_core_session_sync_clock();
2767 		break;
2768 	case SCSC_SQL:
2769 		if (oldintval) {
2770 			switch_core_sqldb_resume();
2771 		} else {
2772 			switch_core_sqldb_pause();
2773 		}
2774 		break;
2775 	case SCSC_PAUSE_ALL:
2776 		if (oldintval) {
2777 			switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
2778 		} else {
2779 			switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);
2780 		}
2781 		break;
2782 	case SCSC_PAUSE_INBOUND:
2783 		if (oldintval) {
2784 			switch_set_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS);
2785 		} else {
2786 			switch_clear_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS);
2787 		}
2788 		break;
2789 	case SCSC_PAUSE_OUTBOUND:
2790 		if (oldintval) {
2791 			switch_set_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS);
2792 		} else {
2793 			switch_clear_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS);
2794 		}
2795 		break;
2796 	case SCSC_HUPALL:
2797 		switch_core_session_hupall(SWITCH_CAUSE_MANAGER_REQUEST);
2798 		break;
2799 	case SCSC_CANCEL_SHUTDOWN:
2800 		switch_clear_flag((&runtime), SCF_SHUTDOWN_REQUESTED);
2801 		break;
2802 	case SCSC_SAVE_HISTORY:
2803 		switch_console_save_history();
2804 		break;
2805 	case SCSC_CRASH:
2806 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Declinatio Mortuus Obfirmo!\n");
2807 		switch_console_save_history();
2808 		abort();
2809 		break;
2810 	case SCSC_SHUTDOWN_NOW:
2811 		switch_console_save_history();
2812 		exit(0);
2813 		break;
2814 	case SCSC_REINCARNATE_NOW:
2815 		switch_console_save_history();
2816 		exit(SWITCH_STATUS_RESTART);
2817 		break;
2818 	case SCSC_SHUTDOWN_ELEGANT:
2819 	case SCSC_SHUTDOWN_ASAP:
2820 		{
2821 			int x = 19;
2822 			uint32_t count;
2823 			switch_event_t *shutdown_requested_event = NULL;
2824 			if (switch_event_create(&shutdown_requested_event, SWITCH_EVENT_SHUTDOWN_REQUESTED) == SWITCH_STATUS_SUCCESS) {
2825 				switch_event_add_header(shutdown_requested_event, SWITCH_STACK_BOTTOM, "Event-Info", "%s", cmd == SCSC_SHUTDOWN_ASAP ? "ASAP" : "elegant");
2826 				switch_event_fire(&shutdown_requested_event);
2827 			}
2828 			switch_set_flag((&runtime), SCF_SHUTDOWN_REQUESTED);
2829 			if (cmd == SCSC_SHUTDOWN_ASAP) {
2830 				switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
2831 			}
2832 
2833 			while (runtime.running && switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED) && (count = switch_core_session_count())) {
2834 				switch_yield(500000);
2835 				if (++x == 20) {
2836 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
2837 									  "Shutdown in progress, %u session(s) remain.\nShutting down %s\n",
2838 									  count, cmd == SCSC_SHUTDOWN_ASAP ? "ASAP" : "once there are no active calls.");
2839 					x = 0;
2840 				}
2841 			}
2842 
2843 			if (switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED)) {
2844 				switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
2845 #ifdef _MSC_VER
2846 				win_shutdown();
2847 #endif
2848 
2849 				if (oldintval) {
2850 					switch_set_flag((&runtime), SCF_RESTART);
2851 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n");
2852 				} else {
2853 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n");
2854 #ifdef _MSC_VER
2855 					fclose(stdin);
2856 #endif
2857 				}
2858 				runtime.running = 0;
2859 			} else {
2860 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutdown Cancelled\n");
2861 				switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);
2862 			}
2863 		}
2864 		break;
2865 	case SCSC_PAUSE_CHECK:
2866 		newintval = !!(switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS);
2867 		break;
2868 	case SCSC_PAUSE_INBOUND_CHECK:
2869 		newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS);
2870 		break;
2871 	case SCSC_PAUSE_OUTBOUND_CHECK:
2872 		newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS);
2873 		break;
2874 	case SCSC_READY_CHECK:
2875 		newintval = switch_core_ready();
2876 		break;
2877 	case SCSC_SHUTDOWN_CHECK:
2878 		newintval = !!switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED);
2879 		break;
2880 	case SCSC_SHUTDOWN:
2881 
2882 #ifdef _MSC_VER
2883 		win_shutdown();
2884 #endif
2885 
2886 		if (oldintval) {
2887 			switch_set_flag((&runtime), SCF_RESTART);
2888 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n");
2889 		} else {
2890 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n");
2891 #ifdef _MSC_VER
2892 			fclose(stdin);
2893 #endif
2894 		}
2895 		runtime.running = 0;
2896 		break;
2897 	case SCSC_CHECK_RUNNING:
2898 		newintval = runtime.running;
2899 		break;
2900 	case SCSC_LOGLEVEL:
2901 		if (oldintval > -1) {
2902 			runtime.hard_log_level = oldintval;
2903 		}
2904 
2905 		if (runtime.hard_log_level > SWITCH_LOG_DEBUG) {
2906 			runtime.hard_log_level = SWITCH_LOG_DEBUG;
2907 		}
2908 		newintval = runtime.hard_log_level;
2909 		break;
2910 	case SCSC_DEBUG_LEVEL:
2911 		if (oldintval > -1) {
2912 			if (oldintval > 10)
2913 				oldintval = 10;
2914 			runtime.debug_level = oldintval;
2915 		}
2916 		newintval = runtime.debug_level;
2917 		break;
2918 	case SCSC_MIN_IDLE_CPU:
2919 		{
2920 			double *dval = (double *) val;
2921 			if (dval) {
2922 				*dval = switch_core_min_idle_cpu(*dval);
2923 			}
2924 			intval = NULL;
2925 		}
2926 		break;
2927 	case SCSC_MAX_SESSIONS:
2928 		newintval = switch_core_session_limit(oldintval);
2929 		break;
2930 	case SCSC_LAST_SPS:
2931 		newintval = runtime.sps_last;
2932 		break;
2933 	case SCSC_SPS_PEAK:
2934 		if (oldintval == -1) {
2935 			runtime.sps_peak = 0;
2936 		}
2937 		newintval = runtime.sps_peak;
2938 		break;
2939 	case SCSC_SPS_PEAK_FIVEMIN:
2940 		newintval = runtime.sps_peak_fivemin;
2941 		break;
2942 	case SCSC_SESSIONS_PEAK:
2943 		newintval = runtime.sessions_peak;
2944 		break;
2945 	case SCSC_SESSIONS_PEAK_FIVEMIN:
2946 		newintval = runtime.sessions_peak_fivemin;
2947 		break;
2948 	case SCSC_MAX_DTMF_DURATION:
2949 		newintval = switch_core_max_dtmf_duration(oldintval);
2950 		break;
2951 	case SCSC_MIN_DTMF_DURATION:
2952 		newintval = switch_core_min_dtmf_duration(oldintval);
2953 		break;
2954 	case SCSC_DEFAULT_DTMF_DURATION:
2955 		newintval = switch_core_default_dtmf_duration(oldintval);
2956 		break;
2957 	case SCSC_SPS:
2958 		switch_mutex_lock(runtime.throttle_mutex);
2959 		if (oldintval > 0) {
2960 			runtime.sps_total = oldintval;
2961 		}
2962 		newintval = runtime.sps_total;
2963 		switch_mutex_unlock(runtime.throttle_mutex);
2964 		break;
2965 
2966 	case SCSC_RECLAIM:
2967 		switch_core_memory_reclaim_all();
2968 		newintval = 0;
2969 		break;
2970 	}
2971 
2972 	if (intval) {
2973 		*intval = newintval;
2974 	}
2975 
2976 
2977 	return 0;
2978 }
2979 
switch_core_flags(void)2980 SWITCH_DECLARE(switch_core_flag_t) switch_core_flags(void)
2981 {
2982 	return runtime.flags;
2983 }
2984 
switch_core_running(void)2985 SWITCH_DECLARE(switch_bool_t) switch_core_running(void)
2986 {
2987 	return runtime.running ? SWITCH_TRUE : SWITCH_FALSE;
2988 }
2989 
switch_core_ready(void)2990 SWITCH_DECLARE(switch_bool_t) switch_core_ready(void)
2991 {
2992 	return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS) ? SWITCH_FALSE : SWITCH_TRUE;
2993 }
2994 
switch_core_ready_inbound(void)2995 SWITCH_DECLARE(switch_bool_t) switch_core_ready_inbound(void)
2996 {
2997 	return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE;
2998 }
2999 
switch_core_ready_outbound(void)3000 SWITCH_DECLARE(switch_bool_t) switch_core_ready_outbound(void)
3001 {
3002 	return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE;
3003 }
3004 
switch_core_sqldb_destroy()3005 void switch_core_sqldb_destroy()
3006 {
3007 	if (switch_test_flag((&runtime), SCF_USE_SQL)) {
3008 		switch_core_sqldb_stop();
3009 	}
3010 }
3011 
switch_core_destroy(void)3012 SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
3013 {
3014 	switch_event_t *event;
3015 
3016 	if (switch_event_create(&event, SWITCH_EVENT_SHUTDOWN) == SWITCH_STATUS_SUCCESS) {
3017 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down");
3018 		switch_event_fire(&event);
3019 	}
3020 
3021 	switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
3022 	switch_set_flag((&runtime), SCF_SHUTTING_DOWN);
3023 
3024 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n");
3025 	switch_core_session_hupall(SWITCH_CAUSE_SYSTEM_SHUTDOWN);
3026 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n");
3027 
3028 	switch_loadable_module_shutdown();
3029 
3030 	switch_curl_destroy();
3031 
3032 	switch_ssl_destroy_ssl_locks();
3033 
3034 	switch_scheduler_task_thread_stop();
3035 
3036 	switch_rtp_shutdown();
3037 	switch_msrp_destroy();
3038 
3039 	if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {
3040 		switch_nat_shutdown();
3041 	}
3042 	switch_xml_destroy();
3043 	switch_console_shutdown();
3044 	switch_channel_global_uninit();
3045 
3046 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n");
3047 	switch_event_shutdown();
3048 
3049 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n");
3050 	switch_log_shutdown();
3051 
3052 	switch_core_session_uninit();
3053 	switch_core_unset_variables();
3054 	switch_core_memory_stop();
3055 
3056 	if (runtime.console && runtime.console != stdout && runtime.console != stderr) {
3057 		fclose(runtime.console);
3058 		runtime.console = NULL;
3059 	}
3060 
3061 	switch_safe_free(SWITCH_GLOBAL_dirs.base_dir);
3062 	switch_safe_free(SWITCH_GLOBAL_dirs.mod_dir);
3063 	switch_safe_free(SWITCH_GLOBAL_dirs.conf_dir);
3064 	switch_safe_free(SWITCH_GLOBAL_dirs.log_dir);
3065 	switch_safe_free(SWITCH_GLOBAL_dirs.db_dir);
3066 	switch_safe_free(SWITCH_GLOBAL_dirs.script_dir);
3067 	switch_safe_free(SWITCH_GLOBAL_dirs.htdocs_dir);
3068 	switch_safe_free(SWITCH_GLOBAL_dirs.grammar_dir);
3069 	switch_safe_free(SWITCH_GLOBAL_dirs.fonts_dir);
3070 	switch_safe_free(SWITCH_GLOBAL_dirs.images_dir);
3071 	switch_safe_free(SWITCH_GLOBAL_dirs.storage_dir);
3072 	switch_safe_free(SWITCH_GLOBAL_dirs.cache_dir);
3073 	switch_safe_free(SWITCH_GLOBAL_dirs.recordings_dir);
3074 	switch_safe_free(SWITCH_GLOBAL_dirs.sounds_dir);
3075 	switch_safe_free(SWITCH_GLOBAL_dirs.run_dir);
3076 	switch_safe_free(SWITCH_GLOBAL_dirs.temp_dir);
3077 	switch_safe_free(SWITCH_GLOBAL_dirs.data_dir);
3078 	switch_safe_free(SWITCH_GLOBAL_dirs.localstate_dir);
3079 	switch_safe_free(SWITCH_GLOBAL_dirs.certs_dir);
3080 	switch_safe_free(SWITCH_GLOBAL_dirs.lib_dir);
3081 
3082 	switch_safe_free(SWITCH_GLOBAL_filenames.conf_name);
3083 
3084 	switch_event_destroy(&runtime.global_vars);
3085 	switch_core_hash_destroy(&runtime.ptimes);
3086 	switch_core_hash_destroy(&runtime.mime_types);
3087 	switch_core_hash_destroy(&runtime.mime_type_exts);
3088 
3089 	if (IP_LIST.hash) {
3090 		switch_core_hash_destroy(&IP_LIST.hash);
3091 	}
3092 
3093 	if (IP_LIST.pool) {
3094 		switch_core_destroy_memory_pool(&IP_LIST.pool);
3095 	}
3096 
3097 	switch_core_media_deinit();
3098 
3099 	if (runtime.memory_pool) {
3100 		apr_pool_destroy(runtime.memory_pool);
3101 		apr_terminate();
3102 	}
3103 
3104 	sqlite3_shutdown();
3105 
3106 	return switch_test_flag((&runtime), SCF_RESTART) ? SWITCH_STATUS_RESTART : SWITCH_STATUS_SUCCESS;
3107 }
3108 
switch_core_management_exec(char * relative_oid,switch_management_action_t action,char * data,switch_size_t datalen)3109 SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen)
3110 {
3111 	const switch_management_interface_t *ptr;
3112 	switch_status_t status = SWITCH_STATUS_FALSE;
3113 
3114 	if ((ptr = switch_loadable_module_get_management_interface(relative_oid))) {
3115 		status = ptr->management_function(relative_oid, action, data, datalen);
3116 	}
3117 
3118 	return status;
3119 }
3120 
switch_core_memory_reclaim_all(void)3121 SWITCH_DECLARE(void) switch_core_memory_reclaim_all(void)
3122 {
3123 	switch_core_memory_reclaim_logger();
3124 	switch_core_memory_reclaim_events();
3125 	switch_core_memory_reclaim();
3126 }
3127 
3128 
3129 struct system_thread_handle {
3130 	const char *cmd;
3131 	switch_thread_cond_t *cond;
3132 	switch_mutex_t *mutex;
3133 	switch_memory_pool_t *pool;
3134 	int ret;
3135 	int *fds;
3136 };
3137 
system_thread(switch_thread_t * thread,void * obj)3138 static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj)
3139 {
3140 	struct system_thread_handle *sth = (struct system_thread_handle *) obj;
3141 
3142 #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)
3143 	struct rlimit rlim;
3144 	struct rlimit rlim_save;
3145 
3146 	memset(&rlim, 0, sizeof(rlim));
3147 	getrlimit(RLIMIT_STACK, &rlim);
3148 
3149 	memset(&rlim_save, 0, sizeof(rlim_save));
3150 	getrlimit(RLIMIT_STACK, &rlim_save);
3151 
3152 	rlim.rlim_cur = rlim.rlim_max;
3153 	if (setrlimit(RLIMIT_STACK, &rlim) < 0) {
3154 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno));
3155 	}
3156 #endif
3157 
3158 	if (sth->fds) {
3159 		dup2(sth->fds[1], STDOUT_FILENO);
3160 	}
3161 
3162 	sth->ret = system(sth->cmd);
3163 
3164 #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)
3165 	if (setrlimit(RLIMIT_STACK, &rlim_save) < 0) {
3166 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno));
3167 	}
3168 #endif
3169 
3170 	switch_mutex_lock(sth->mutex);
3171 	switch_thread_cond_signal(sth->cond);
3172 	switch_mutex_unlock(sth->mutex);
3173 
3174 	switch_core_destroy_memory_pool(&sth->pool);
3175 
3176 	return NULL;
3177 }
3178 
3179 
switch_system_thread(const char * cmd,switch_bool_t wait)3180 static int switch_system_thread(const char *cmd, switch_bool_t wait)
3181 {
3182 	switch_thread_t *thread;
3183 	switch_threadattr_t *thd_attr;
3184 	int ret = 0;
3185 	struct system_thread_handle *sth;
3186 	switch_memory_pool_t *pool;
3187 
3188 	if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
3189 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n");
3190 		return 1;
3191 	}
3192 
3193 	if (!(sth = switch_core_alloc(pool, sizeof(struct system_thread_handle)))) {
3194 		switch_core_destroy_memory_pool(&pool);
3195 		return 1;
3196 	}
3197 
3198 	sth->pool = pool;
3199 	sth->cmd = switch_core_strdup(pool, cmd);
3200 
3201 	switch_thread_cond_create(&sth->cond, sth->pool);
3202 	switch_mutex_init(&sth->mutex, SWITCH_MUTEX_NESTED, sth->pool);
3203 	switch_mutex_lock(sth->mutex);
3204 
3205 	switch_threadattr_create(&thd_attr, sth->pool);
3206 	switch_threadattr_stacksize_set(thd_attr, SWITCH_SYSTEM_THREAD_STACKSIZE);
3207 	switch_threadattr_detach_set(thd_attr, 1);
3208 	switch_thread_create(&thread, thd_attr, system_thread, sth, sth->pool);
3209 
3210 	if (wait) {
3211 		switch_thread_cond_wait(sth->cond, sth->mutex);
3212 		ret = sth->ret;
3213 	}
3214 	switch_mutex_unlock(sth->mutex);
3215 
3216 	return ret;
3217 }
3218 
switch_max_file_desc(void)3219 SWITCH_DECLARE(int) switch_max_file_desc(void)
3220 {
3221 	int max = 0;
3222 
3223 #ifndef WIN32
3224 #if defined(HAVE_GETDTABLESIZE)
3225 	max = getdtablesize();
3226 #else
3227 	max = sysconf(_SC_OPEN_MAX);
3228 #endif
3229 #endif
3230 
3231 	return max;
3232 
3233 }
3234 
switch_close_extra_files(int * keep,int keep_ttl)3235 SWITCH_DECLARE(void) switch_close_extra_files(int *keep, int keep_ttl)
3236 {
3237 	int open_max = switch_max_file_desc();
3238 	int i, j;
3239 
3240 	for (i = 3; i < open_max; i++) {
3241 		if (keep) {
3242 			for (j = 0; j < keep_ttl; j++) {
3243 				if (i == keep[j]) {
3244 					goto skip;
3245 				}
3246 			}
3247 		}
3248 
3249 		close(i);
3250 
3251 	skip:
3252 
3253 		continue;
3254 
3255 	}
3256 }
3257 
3258 
3259 #ifdef WIN32
switch_system_fork(const char * cmd,switch_bool_t wait)3260 static int switch_system_fork(const char *cmd, switch_bool_t wait)
3261 {
3262 	return switch_system_thread(cmd, wait);
3263 }
3264 
switch_fork(void)3265 SWITCH_DECLARE(pid_t) switch_fork(void)
3266 {
3267 	return -1;
3268 }
3269 
3270 
3271 #else
3272 
switch_fork(void)3273 SWITCH_DECLARE(pid_t) switch_fork(void)
3274 {
3275 	int i = fork();
3276 
3277 	if (!i) {
3278 		set_low_priority();
3279 	}
3280 
3281 	return i;
3282 }
3283 
3284 
3285 
switch_system_fork(const char * cmd,switch_bool_t wait)3286 static int switch_system_fork(const char *cmd, switch_bool_t wait)
3287 {
3288 	int pid;
3289 	char *dcmd = strdup(cmd);
3290 #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)
3291 	struct rlimit rlim;
3292 	struct rlimit rlim_save;
3293 #endif
3294 
3295 	switch_core_set_signal_handlers();
3296 
3297 	pid = switch_fork();
3298 
3299 	if (pid) {
3300 		if (wait) {
3301 			waitpid(pid, NULL, 0);
3302 		}
3303 		free(dcmd);
3304 	} else {
3305 		switch_close_extra_files(NULL, 0);
3306 
3307 #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)
3308 		memset(&rlim, 0, sizeof(rlim));
3309 		getrlimit(RLIMIT_STACK, &rlim);
3310 
3311 		memset(&rlim_save, 0, sizeof(rlim_save));
3312 		getrlimit(RLIMIT_STACK, &rlim_save);
3313 
3314 		rlim.rlim_cur = rlim.rlim_max;
3315 		if (setrlimit(RLIMIT_STACK, &rlim) < 0) {
3316 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno));
3317 		}
3318 #endif
3319 
3320 		if (system(dcmd) == -1) {
3321 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute because of a command error : %s\n", dcmd);
3322 		}
3323 		free(dcmd);
3324 		exit(0);
3325 	}
3326 
3327 	return 0;
3328 }
3329 #endif
3330 
3331 
3332 
switch_system(const char * cmd,switch_bool_t wait)3333 SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait)
3334 {
3335 	int (*sys_p)(const char *cmd, switch_bool_t wait);
3336 
3337 	sys_p = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork;
3338 
3339 	return sys_p(cmd, wait);
3340 
3341 }
3342 
3343 
3344 
switch_stream_system_fork(const char * cmd,switch_stream_handle_t * stream)3345 SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream)
3346 {
3347 	return switch_stream_system(cmd, stream);
3348 }
3349 
switch_core_get_stacksizes(switch_size_t * cur,switch_size_t * max)3350 SWITCH_DECLARE(switch_status_t) switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max)
3351 {
3352 #ifdef HAVE_SETRLIMIT
3353 	struct rlimit rlp;
3354 
3355 	memset(&rlp, 0, sizeof(rlp));
3356 	getrlimit(RLIMIT_STACK, &rlp);
3357 
3358 	*cur = rlp.rlim_cur;
3359 	*max = rlp.rlim_max;
3360 
3361 	return SWITCH_STATUS_SUCCESS;
3362 
3363 #else
3364 
3365 	return SWITCH_STATUS_FALSE;
3366 
3367 #endif
3368 
3369 
3370 
3371 }
3372 
3373 
switch_stream_system(const char * cmd,switch_stream_handle_t * stream)3374 SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t *stream)
3375 {
3376 	char buffer[128];
3377 	size_t bytes;
3378 	FILE* pipe = popen(cmd, "r");
3379 	if (!pipe) return 1;
3380 
3381 	while (!feof(pipe)) {
3382 		while ((bytes = fread(buffer, 1, 128, pipe)) > 0) {
3383 			if (stream != NULL) {
3384 				stream->raw_write_function(stream, (unsigned char *)buffer, bytes);
3385 			}
3386 		}
3387 	}
3388 
3389 	if (ferror(pipe)) {
3390 		pclose(pipe);
3391 		return 1;
3392 	}
3393 
3394 	pclose(pipe);
3395 	return 0;
3396 }
3397 
switch_core_get_rtp_port_range_start_port()3398 SWITCH_DECLARE(uint16_t) switch_core_get_rtp_port_range_start_port()
3399 {
3400 	uint16_t start_port = 0;
3401 
3402 	/* By default pass rtp port range start value as zero in order to get actual
3403 	 * RTP port range start value as configured */
3404 	start_port = (uint16_t)switch_rtp_set_start_port((switch_port_t)start_port);
3405 
3406 	return start_port;
3407 }
3408 
switch_core_get_rtp_port_range_end_port()3409 SWITCH_DECLARE(uint16_t) switch_core_get_rtp_port_range_end_port()
3410 {
3411 	uint16_t end_port = 0;
3412 
3413 	/* By default pass rtp port range end value as zero in order to get actual
3414 	 * RTP port range end value as configured */
3415 	end_port = (uint16_t)switch_rtp_set_end_port((switch_port_t)end_port);
3416 
3417 	return end_port;
3418 }
3419 
switch_core_get_event_channel_key_separator(void)3420 SWITCH_DECLARE(const char *) switch_core_get_event_channel_key_separator(void)
3421 {
3422 	return runtime.event_channel_key_separator;
3423 }
3424 
3425 /* For Emacs:
3426  * Local Variables:
3427  * mode:c
3428  * indent-tabs-mode:t
3429  * tab-width:4
3430  * c-basic-offset:4
3431  * End:
3432  * For VIM:
3433  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3434  */
3435