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