Bug Summary

File:src/switch_xml.c
Warning:line 2105, column 2
Potential leak of memory pointed to by 'expires_val'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name switch_xml.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fno-trapping-math -ffp-contract=fast -ffast-math -ffinite-math-only -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -resource-dir /usr/lib/llvm-7/lib/clang/7.0.1 -D HAVE_CONFIG_H -I . -I ./src/include -I ./libs/esl/src/include -I ./libs/xmlrpc-c -I /drone/src/libs/libvpx -I /drone/src/src/include -I /drone/src/src/include -I /drone/src/libs/libteletone/src -D SWITCH_API_VISIBILITY=1 -D CJSON_API_VISIBILITY=1 -D HAVE_VISIBILITY=1 -D _REENTRANT -D _GNU_SOURCE -I /drone/src/libs/apr/include -I /drone/src/libs/apr-util/include -I /drone/src/libs/apr-util/xml/expat/lib -I /drone/src/libs/srtp/include -I /drone/src/libs/libyuv/include -D SWITCH_HAVE_YUV -I /drone/src/libs/srtp/crypto/include -I libs/srtp/crypto/include -D SWITCH_HAVE_VPX -D ENABLE_SRTP -D SWITCH_HAVE_ODBC -I /usr/include -D SWITCH_HAVE_PNG -I /usr/include/libpng16 -D SWITCH_HAVE_FREETYPE -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/x86_64-linux-gnu -I /usr/include/editline -D HAVE_OPENSSL -I /usr/include/sofia-sip-1.13 -I /usr/include/uuid -I /drone/src/src/include -I /drone/src/src/include -I /drone/src/libs/libteletone/src -D SWITCH_API_VISIBILITY=1 -D CJSON_API_VISIBILITY=1 -D HAVE_VISIBILITY=1 -D HAVE_OPENSSL -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-result -Wno-misleading-indentation -std=c99 -fdebug-compilation-dir /drone/src -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -o /drone/src/scan-build/2021-10-18-163402-401-1 -x c src/switch_xml.c -faddrsig

src/switch_xml.c

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 * Simon Capper <skyjunky@sbcglobal.net>
28 * Marc Olivier Chouinard <mochouinard@moctel.com>
29 * Raymond Chandler <intralanman@freeswitch.org>
30 *
31 * switch_xml.c -- XML PARSER
32 *
33 * Derived from ezxml http://ezxml.sourceforge.net
34 * Original Copyright
35 *
36 * Copyright 2004, 2006 Aaron Voisine <aaron@voisine.org>
37 *
38 * Permission is hereby granted, free of charge, to any person obtaining
39 * a copy of this software and associated documentation files (the
40 * "Software"), to deal in the Software without restriction, including
41 * without limitation the rights to use, copy, modify, merge, publish,
42 * distribute, sublicense, and/or sell copies of the Software, and to
43 * permit persons to whom the Software is furnished to do so, subject to
44 * the following conditions:
45 *
46 * The above copyright notice and this permission notice shall be included
47 * in all copies or substantial portions of the Software.
48 *
49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
52 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
53 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
54 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
55 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56 */
57
58#include <switch.h>
59#include <switch_stun.h>
60#ifndef WIN32
61#include <sys/wait.h>
62#include <switch_private.h>
63#include <glob.h>
64#else /* we're on windoze :( */
65/* glob functions at end of this file */
66#include <apr_file_io.h>
67
68typedef struct {
69 size_t gl_pathc; /* Count of total paths so far. */
70 size_t gl_matchc; /* Count of paths matching pattern. */
71 size_t gl_offs; /* Reserved at beginning of gl_pathv. */
72 int gl_flags; /* Copy of flags parameter to glob. */
73 char **gl_pathv; /* List of paths matching pattern. */
74 /* Copy of errfunc parameter to glob. */
75 int (*gl_errfunc) (const char *, int);
76} glob_t;
77
78/* Believed to have been introduced in 1003.2-1992 */
79#define GLOB_APPEND(1 << 5) 0x0001 /* Append to output from previous call. */
80#define GLOB_DOOFFS(1 << 3) 0x0002 /* Use gl_offs. */
81#define GLOB_ERR(1 << 0) 0x0004 /* Return on error. */
82#define GLOB_MARK(1 << 1) 0x0008 /* Append / to matching directories. */
83#define GLOB_NOCHECK(1 << 4) 0x0010 /* Return pattern itself if nothing matches. */
84#define GLOB_NOSORT(1 << 2) 0x0020 /* Don't sort. */
85
86/* Error values returned by glob(3) */
87#define GLOB_NOSPACE1 (-1) /* Malloc call failed. */
88#define GLOB_ABORTED2 (-2) /* Unignored error. */
89#define GLOB_NOMATCH3 (-3) /* No match and GLOB_NOCHECK was not set. */
90#define GLOB_NOSYS4 (-4) /* Obsolete: source comptability only. */
91
92#define GLOB_ALTDIRFUNC(1 << 9) 0x0040 /* Use alternately specified directory funcs. */
93#define GLOB_MAGCHAR(1 << 8) 0x0100 /* Pattern had globbing characters. */
94#define GLOB_NOMAGIC(1 << 11) 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
95#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
96#define GLOB_LIMIT 0x1000 /* limit number of returned paths */
97
98int glob(const char *, int, int (*)(const char *, int), glob_t *);
99void globfree(glob_t *);
100
101#endif
102
103#define SWITCH_XML_WS"\t\r\n " "\t\r\n " /* whitespace */
104#define SWITCH_XML_ERRL128 128 /* maximum error string length */
105
106static void preprocess_exec_set(char *keyval)
107{
108 char *key = keyval;
109 char *val = strchr(keyval, '=');
110
111 if (val) {
112 char *ve = val++;
113 while (*val && *val == ' ') {
114 val++;
115 }
116 *ve-- = '\0';
117 while (*ve && *ve == ' ') {
118 *ve-- = '\0';
119 }
120 }
121
122 if (key && val) {
123 switch_stream_handle_t exec_result = { 0 };
124 SWITCH_STANDARD_STREAM(exec_result)memset(&exec_result, 0, sizeof(exec_result)); exec_result
.data = malloc(1024); ((exec_result.data) ? (void) (0) : __assert_fail
("exec_result.data", "src/switch_xml.c", 124, __extension__ __PRETTY_FUNCTION__
)); memset(exec_result.data, 0, 1024); exec_result.end = exec_result
.data; exec_result.data_size = 1024; exec_result.write_function
= switch_console_stream_write; exec_result.raw_write_function
= switch_console_stream_raw_write; exec_result.alloc_len = 1024
; exec_result.alloc_chunk = 1024
;
125 if (switch_stream_system(val, &exec_result) == 0) {
126 if (!zstr(exec_result.data)_zstr(exec_result.data)) {
127 char *tmp = (char *) exec_result.data;
128 tmp = &tmp[strlen(tmp)-1];
129 while (tmp >= (char *) exec_result.data && ( tmp[0] == ' ' || tmp[0] == '\n') ) {
130 tmp[0] = '\0'; /* remove trailing spaces and newlines */
131 tmp--;
132 }
133 switch_core_set_variable(key, exec_result.data);
134 }
135 } else {
136 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 136, ((void*)0)
, SWITCH_LOG_ERROR, "Error while executing command: %s\n", val);
137 }
138 switch_safe_free(exec_result.data)if (exec_result.data) {free(exec_result.data);exec_result.data
=((void*)0);}
;
139 }
140}
141
142static void preprocess_stun_set(char *keyval)
143{
144 char *key = keyval;
145 char *val = strchr(keyval, '=');
146
147 if (val) {
148 char *ve = val++;
149 while (*val && *val == ' ') {
150 val++;
151 }
152 *ve-- = '\0';
153 while (*ve && *ve == ' ') {
154 *ve-- = '\0';
155 }
156 }
157
158 if (key && val) {
159 char *external_ip = NULL((void*)0);
160 switch_memory_pool_t *pool;
161
162 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "src/switch_xml.c"
, (const char *)__func__, 162)
;
163
164 if (switch_stun_ip_lookup(&external_ip, val, pool) == SWITCH_STATUS_SUCCESS) {
165 if (!zstr(external_ip)_zstr(external_ip)) {
166 char *tmp = external_ip;
167 tmp = &tmp[strlen(tmp) - 1];
168 while (tmp >= external_ip && (tmp[0] == ' ' || tmp[0] == '\n')) {
169 tmp[0] = '\0'; /* remove trailing spaces and newlines */
170 tmp--;
171 }
172 switch_core_set_variable(key, external_ip);
173 }
174 } else {
175 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 175, ((void*)0)
, SWITCH_LOG_ERROR, "stun-set failed.\n");
176 }
177
178 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_xml.c"
, (const char *)__func__, 178)
;
179 }
180}
181
182static void preprocess_env_set(char *keyval)
183{
184 char *key = keyval;
185 char *val = strchr(keyval, '=');
186
187 if (key && val) {
188 *val++ = '\0';
189
190 if (*val++ == '$') {
191 char *data = getenv(val);
192
193 if (data) {
194 switch_core_set_variable(key, data);
195 }
196 }
197 }
198}
199
200static int preprocess(const char *cwd, const char *file, FILE *write_fd, int rlevel);
201
202typedef struct switch_xml_root *switch_xml_root_t;
203struct switch_xml_root { /* additional data for the root tag */
204 struct switch_xml xml; /* is a super-struct built on top of switch_xml struct */
205 switch_xml_t cur; /* current xml tree insertion point */
206 char *m; /* original xml string */
207 switch_size_t len; /* length of allocated memory */
208 uint8_t dynamic; /* Free the original string when calling switch_xml_free */
209 char *u; /* UTF-8 conversion of string if original was UTF-16 */
210 char *s; /* start of work area */
211 char *e; /* end of work area */
212 char **ent; /* general entities (ampersand sequences) */
213 char ***attr; /* default attributes */
214 char ***pi; /* processing instructions */
215 short standalone; /* non-zero if <?xml standalone="yes"?> */
216 char err[SWITCH_XML_ERRL128]; /* error string */
217};
218
219char *SWITCH_XML_NIL[] = { NULL((void*)0) }; /* empty, null terminated array of strings */
220
221struct switch_xml_binding {
222 switch_xml_search_function_t function;
223 switch_xml_section_t sections;
224 void *user_data;
225 struct switch_xml_binding *next;
226};
227
228
229static switch_xml_binding_t *BINDINGS = NULL((void*)0);
230static switch_xml_t MAIN_XML_ROOT = NULL((void*)0);
231static switch_memory_pool_t *XML_MEMORY_POOL = NULL((void*)0);
232
233static switch_thread_rwlock_t *B_RWLOCK = NULL((void*)0);
234static switch_mutex_t *XML_LOCK = NULL((void*)0);
235static switch_mutex_t *CACHE_MUTEX = NULL((void*)0);
236static switch_mutex_t *REFLOCK = NULL((void*)0);
237static switch_mutex_t *FILE_LOCK = NULL((void*)0);
238
239SWITCH_DECLARE_NONSTD(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t __switch_xml_open_root(uint8_t reload, const char **err, void *user_data);
240
241static switch_xml_open_root_function_t XML_OPEN_ROOT_FUNCTION = (switch_xml_open_root_function_t)__switch_xml_open_root;
242static void *XML_OPEN_ROOT_FUNCTION_USER_DATA = NULL((void*)0);
243
244static switch_hash_t *CACHE_HASH = NULL((void*)0);
245static switch_hash_t *CACHE_EXPIRES_HASH = NULL((void*)0);
246
247struct xml_section_t {
248 const char *name;
249 /* switch_xml_section_t section; */
250 uint32_t section;
251};
252
253static struct xml_section_t SECTIONS[] = {
254 {"result", SWITCH_XML_SECTION_RESULT},
255 {"config", SWITCH_XML_SECTION_CONFIG},
256 {"directory", SWITCH_XML_SECTION_DIRECTORY},
257 {"dialplan", SWITCH_XML_SECTION_DIALPLAN},
258 {"languages", SWITCH_XML_SECTION_LANGUAGES},
259 {"chatplan", SWITCH_XML_SECTION_CHATPLAN},
260 {"channels", SWITCH_XML_SECTION_CHANNELS},
261 {NULL((void*)0), 0}
262};
263
264SWITCH_DECLARE(switch_xml_section_t)__attribute__((visibility("default"))) switch_xml_section_t switch_xml_parse_section_string(const char *str)
265{
266 size_t x;
267 char buf[1024] = "";
268 /*switch_xml_section_t sections = SWITCH_XML_SECTION_RESULT; */
269 uint32_t sections = SWITCH_XML_SECTION_RESULT;
270
271 if (str) {
272 for (x = 0; x < strlen(str); x++) {
273 buf[x] = (char) tolower((int) str[x])(__extension__ ({ int __res; if (sizeof ((int) str[x]) > 1
) { if (__builtin_constant_p ((int) str[x])) { int __c = ((int
) str[x]); __res = __c < -128 || __c > 255 ? __c : (*__ctype_tolower_loc
())[__c]; } else __res = tolower ((int) str[x]); } else __res
= (*__ctype_tolower_loc ())[(int) ((int) str[x])]; __res; })
)
;
274 }
275 for (x = 0;; x++) {
276 if (!SECTIONS[x].name) {
277 break;
278 }
279 if (strstr(buf, SECTIONS[x].name)) {
280 sections |= SECTIONS[x].section;
281 }
282 }
283 }
284 return (switch_xml_section_t) sections;
285}
286
287SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_unbind_search_function(switch_xml_binding_t **binding)
288{
289 switch_xml_binding_t *ptr, *last = NULL((void*)0);
290 switch_status_t status = SWITCH_STATUS_FALSE;
291
292
293 switch_thread_rwlock_wrlock(B_RWLOCK);
294 for (ptr = BINDINGS; ptr; ptr = ptr->next) {
295 if (ptr == *binding) {
296 if (last) {
297 last->next = (*binding)->next;
298 } else {
299 BINDINGS = (*binding)->next;
300 }
301 status = SWITCH_STATUS_SUCCESS;
302 break;
303 }
304 last = ptr;
305 }
306 switch_thread_rwlock_unlock(B_RWLOCK);
307
308 return status;
309}
310
311SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_unbind_search_function_ptr(switch_xml_search_function_t function)
312{
313 switch_xml_binding_t *ptr, *last = NULL((void*)0);
314 switch_status_t status = SWITCH_STATUS_FALSE;
315
316 switch_thread_rwlock_wrlock(B_RWLOCK);
317 for (ptr = BINDINGS; ptr; ptr = ptr->next) {
318 if (ptr->function == function) {
319 status = SWITCH_STATUS_SUCCESS;
320
321 if (last) {
322 last->next = ptr->next;
323 } else {
324 BINDINGS = ptr->next;
325 last = NULL((void*)0);
326 continue;
327 }
328 }
329 last = ptr;
330 }
331 switch_thread_rwlock_unlock(B_RWLOCK);
332
333 return status;
334}
335
336SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_xml_set_binding_sections(switch_xml_binding_t *binding, switch_xml_section_t sections)
337{
338 switch_assert(binding)((binding) ? (void) (0) : __assert_fail ("binding", "src/switch_xml.c"
, 338, __extension__ __PRETTY_FUNCTION__))
;
339 binding->sections = sections;
340}
341
342SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_xml_set_binding_user_data(switch_xml_binding_t *binding, void *user_data)
343{
344 switch_assert(binding)((binding) ? (void) (0) : __assert_fail ("binding", "src/switch_xml.c"
, 344, __extension__ __PRETTY_FUNCTION__))
;
345 binding->user_data = user_data;
346}
347
348SWITCH_DECLARE(switch_xml_section_t)__attribute__((visibility("default"))) switch_xml_section_t switch_xml_get_binding_sections(switch_xml_binding_t *binding)
349{
350 return binding->sections;
351}
352
353SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_xml_get_binding_user_data(switch_xml_binding_t *binding)
354{
355 return binding->user_data;
356}
357
358SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_bind_search_function_ret(switch_xml_search_function_t function,
359 switch_xml_section_t sections, void *user_data, switch_xml_binding_t **ret_binding)
360{
361 switch_xml_binding_t *binding = NULL((void*)0), *ptr = NULL((void*)0);
362 assert(function != NULL)((function != ((void*)0)) ? (void) (0) : __assert_fail ("function != NULL"
, "src/switch_xml.c", 362, __extension__ __PRETTY_FUNCTION__)
)
;
363
364 if (!(binding = (switch_xml_binding_t *) switch_core_alloc(XML_MEMORY_POOL, sizeof(*binding))switch_core_perform_alloc(XML_MEMORY_POOL, sizeof(*binding), "src/switch_xml.c"
, (const char *)__func__, 364)
)) {
365 return SWITCH_STATUS_MEMERR;
366 }
367
368 binding->function = function;
369 binding->sections = sections;
370 binding->user_data = user_data;
371
372 switch_thread_rwlock_wrlock(B_RWLOCK);
373 for (ptr = BINDINGS; ptr && ptr->next; ptr = ptr->next);
374
375 if (ptr) {
376 ptr->next = binding;
377 } else {
378 BINDINGS = binding;
379 }
380
381 if (ret_binding) {
382 *ret_binding = binding;
383 }
384
385 switch_thread_rwlock_unlock(B_RWLOCK);
386
387 return SWITCH_STATUS_SUCCESS;
388}
389
390SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_find_child(switch_xml_t node, const char *childname, const char *attrname, const char *value)
391{
392 switch_xml_t p = NULL((void*)0);
393
394 if (!(childname && attrname && value)) {
395 return node;
396 }
397
398 for (p = switch_xml_child(node, childname); p; p = p->next) {
399 const char *aname = switch_xml_attr(p, attrname);
400 if (aname && !strcasecmp(aname, value)) {
401 break;
402 }
403 }
404
405 return p;
406}
407
408SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_find_child_multi(switch_xml_t node, const char *childname,...)
409{
410 switch_xml_t p = NULL((void*)0);
411 const char *names[256] = { 0 };
412 const char *vals[256] = { 0 };
413 int x, i = 0;
414 va_list ap;
415 const char *attrname, *value = NULL((void*)0);
416
417 va_start(ap, childname)__builtin_va_start(ap, childname);
418
419 while (i < 255) {
420 if ((attrname = va_arg(ap, const char *)__builtin_va_arg(ap, const char *))) {
421 value = va_arg(ap, const char *)__builtin_va_arg(ap, const char *);
422 }
423 if (attrname && value) {
424 names[i] = attrname;
425 vals[i] = value;
426 } else {
427 break;
428 }
429 i++;
430 }
431
432 va_end(ap)__builtin_va_end(ap);
433
434 if (!(childname && i)) {
435 return node;
436 }
437
438 for (p = switch_xml_child(node, childname); p; p = p->next) {
439 for (x = 0; x < i; x++) {
440 if (names[x] && vals[x]) {
441 const char *aname = switch_xml_attr(p, names[x]);
442
443 if (aname) {
444 if (*vals[x] == '!') {
445 const char *sval = vals[x] + 1;
446 if (strcasecmp(aname, sval)) {
447 goto done;
448 }
449 } else {
450 if (!strcasecmp(aname, vals[x])) {
451 goto done;
452 }
453 }
454 }
455 }
456 }
457 }
458
459 done:
460
461 return p;
462}
463
464/* returns the first child tag with the given name or NULL if not found */
465SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_child(switch_xml_t xml, const char *name)
466{
467 xml = (xml) ? xml->child : NULL((void*)0);
468 while (xml && strcmp(name, xml->name))
469 xml = xml->sibling;
470 return xml;
471}
472
473/* returns the Nth tag with the same name in the same subsection or NULL if not found */
474switch_xml_t switch_xml_idx(switch_xml_t xml, int idx)
475{
476 for (; xml && idx; idx--)
477 xml = xml->next;
478 return xml;
479}
480
481/* returns the value of the requested tag attribute or "" if not found */
482SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_xml_attr_soft(switch_xml_t xml, const char *attr)
483{
484 const char *ret = switch_xml_attr(xml, attr);
485
486 return ret ? ret : "";
487}
488
489/* returns the value of the requested tag attribute or NULL if not found */
490SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_xml_attr(switch_xml_t xml, const char *attr)
491{
492 int i = 0, j = 1;
493 switch_xml_root_t root = (switch_xml_root_t) xml;
494
495 if (!xml || !xml->attr)
496 return NULL((void*)0);
497 while (xml->attr[i] && attr && strcmp(attr, xml->attr[i]))
498 i += 2;
499 if (xml->attr[i])
500 return xml->attr[i + 1]; /* found attribute */
501
502 while (root->xml.parent)
503 root = (switch_xml_root_t) root->xml.parent; /* root tag */
504
505 if (!root->attr) {
506 return NULL((void*)0);
507 }
508
509 for (i = 0; root->attr[i] && xml->name && strcmp(xml->name, root->attr[i][0]); i++);
510 if (!root->attr[i])
511 return NULL((void*)0); /* no matching default attributes */
512 while (root->attr[i][j] && attr && strcmp(attr, root->attr[i][j]))
513 j += 3;
514 return (root->attr[i][j]) ? root->attr[i][j + 1] : NULL((void*)0); /* found default */
515}
516
517/* same as switch_xml_get but takes an already initialized va_list */
518static switch_xml_t switch_xml_vget(switch_xml_t xml, va_list ap)
519{
520 char *name = va_arg(ap, char *)__builtin_va_arg(ap, char *);
521 int idx = -1;
522
523 if (name && *name) {
524 idx = va_arg(ap, int)__builtin_va_arg(ap, int);
525 xml = switch_xml_child(xml, name);
526 }
527 return (idx < 0) ? xml : switch_xml_vget(switch_xml_idx(xml, idx), ap);
528}
529
530/* Traverses the xml tree to retrieve a specific subtag. Takes a variable
531 length list of tag names and indexes. The argument list must be terminated
532 by either an index of -1 or an empty string tag name. Example:
533 title = switch_xml_get(library, "shelf", 0, "book", 2, "title", -1);
534 This retrieves the title of the 3rd book on the 1st shelf of library.
535 Returns NULL if not found. */
536SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_get(switch_xml_t xml,...)
537{
538 va_list ap;
539 switch_xml_t r;
540
541 va_start(ap, xml)__builtin_va_start(ap, xml);
542 r = switch_xml_vget(xml, ap);
543 va_end(ap)__builtin_va_end(ap);
544 return r;
545}
546
547/* returns a null terminated array of processing instructions for the given target */
548SWITCH_DECLARE(const char **)__attribute__((visibility("default"))) const char ** switch_xml_pi(switch_xml_t xml, const char *target)
549{
550 switch_xml_root_t root = (switch_xml_root_t) xml;
551 int i = 0;
552
553 if (!root)
554 return (const char **) SWITCH_XML_NIL;
555 while (root->xml.parent)
556 root = (switch_xml_root_t) root->xml.parent; /* root tag */
557 if (!root || !root->pi) {
558 return (const char **) SWITCH_XML_NIL;
559 }
560 while (root->pi[i] && strcmp(target, root->pi[i][0]))
561 i++; /* find target */
562 return (const char **) ((root->pi[i]) ? root->pi[i] + 1 : SWITCH_XML_NIL);
563}
564
565/* set an error string and return root */
566static switch_xml_t switch_xml_err(switch_xml_root_t root, char *s, const char *err, ...)
567{
568 va_list ap;
569 int line = 1;
570 char *t, fmt[SWITCH_XML_ERRL128];
571
572 if (!root || !root->s) {
573 return NULL((void*)0);
574 }
575
576 for (t = root->s; t && t < s; t++)
577 if (*t == '\n')
578 line++;
579 switch_snprintf(fmt, SWITCH_XML_ERRL128, "[error near line %d]: %s", line, err);
580
581 va_start(ap, err)__builtin_va_start(ap, err);
582 vsnprintf(root->err, SWITCH_XML_ERRL128, fmt, ap);
583 va_end(ap)__builtin_va_end(ap);
584
585 return &root->xml;
586}
587
588/* Recursively decodes entity and character references and normalizes new lines
589 ent is a null terminated array of alternating entity names and values. set t
590 to '&' for general entity decoding, '%' for parameter entity decoding, 'c'
591 for cdata sections, ' ' for attribute normalization, or '*' for non-cdata
592 attribute normalization. Returns s, or if the decoded string is longer than
593 s, returns a malloced string that must be freed. */
594static char *switch_xml_decode(char *s, char **ent, char t)
595{
596 char *e, *r = s, *m = s;
597 unsigned long b, c, d, l;
598
599 for (; *s; s++) { /* normalize line endings */
600 while (*s == '\r') {
601 *(s++) = '\n';
602 if (*s == '\n')
603 memmove(s, (s + 1), strlen(s));
604 }
605 }
606
607 for (s = r;;) {
608 while (*s && *s != '&' && (*s != '%' || t != '%') && !isspace((unsigned char) (*s))((*__ctype_b_loc ())[(int) (((unsigned char) (*s)))] & (unsigned
short int) _ISspace)
)
609 s++;
610
611 if (!*s)
612 break;
613 else if (t != 'c' && !strncmp(s, "&#", 2)) { /* character reference */
614 char *code = s + 2;
615 int base = 10;
616 if (*code == 'x') {
617 code++;
618 base = 16;
619 }
620 if (!isxdigit((int)*code)((*__ctype_b_loc ())[(int) (((int)*code))] & (unsigned short
int) _ISxdigit)
) { /* "&# 1;" and "&#-1;" are invalid */
621 s++;
622 continue;
623 }
624 c = strtoul(code, &e, base);
625 if (!c || *e != ';') {
626 s++;
627 continue;
628 }
629 /* not a character ref */
630 if (c < 0x80)
631 *(s++) = (char) c; /* US-ASCII subset */
632 else if (c > 0x7FFFFFFF) { /* out of UTF-8 range */
633 s++;
634 continue;
635 } else { /* multi-byte UTF-8 sequence */
636 for (b = 0, d = c; d; d /= 2)
637 b++; /* number of bits in c */
638 b = (b - 2) / 5; /* number of bytes in payload */
639 assert(b < 7)((b < 7) ? (void) (0) : __assert_fail ("b < 7", "src/switch_xml.c"
, 639, __extension__ __PRETTY_FUNCTION__))
; /* because c <= 0x7FFFFFFF */
640 *(s++) = (char) ((0xFF << (7 - b)) | (c >> (6 * b))); /* head */
641 while (b)
642 *(s++) = (char) (0x80 | ((c >> (6 * --b)) & 0x3F)); /* payload */
643 }
644
645 memmove(s, strchr(s, ';') + 1, strlen(strchr(s, ';')));
646 } else if ((*s == '&' && (t == '&' || t == ' ' || t == '*')) || (*s == '%' && t == '%')) { /* entity reference */
647 for (b = 0; ent[b] && strncmp(s + 1, ent[b], strlen(ent[b])); b += 2); /* find entity in entity list */
648
649 if (ent[b++]) { /* found a match */
650 if ((c = (unsigned long) strlen(ent[b])) - 1 > (e = strchr(s, ';')) - s) {
651 l = (d = (unsigned long) (s - r)) + c + (unsigned long) strlen(e); /* new length */
652 if (l) {
653 if (r == m) {
654 char *tmp = (char *) switch_must_malloc(l);
655 r = strcpy(tmp, r);
656 } else {
657 r = (char *) switch_must_realloc(r, l);
658 }
659 }
660 e = strchr((s = r + d), ';'); /* fix up pointers */
661 }
662
663 memmove(s + c, e + 1, strlen(e)); /* shift rest of string */
664 strncpy(s, ent[b], c); /* copy in replacement text */
665 } else
666 s++; /* not a known entity */
667 } else if ((t == ' ' || t == '*') && isspace((int) (*s))((*__ctype_b_loc ())[(int) (((int) (*s)))] & (unsigned short
int) _ISspace)
)
668 *(s++) = ' ';
669 else
670 s++; /* no decoding needed */
671 }
672
673 if (t == '*') { /* normalize spaces for non-cdata attributes */
674 for (s = r; *s; s++) {
675 if ((l = (unsigned long) strspn(s, " ")))
676 memmove(s, s + l, strlen(s + l) + 1);
677 while (*s && *s != ' ')
678 s++;
679 }
680 if (--s >= r && *s == ' ')
681 *s = '\0'; /* trim any trailing space */
682 }
683 return r;
684}
685
686/* called when parser finds start of new tag */
687static void switch_xml_open_tag(switch_xml_root_t root, char *name, char **attr)
688{
689 switch_xml_t xml;
690
691 if (!root || !root->cur) {
692 return;
693 }
694
695 xml = root->cur;
696
697 if (xml->name)
698 xml = switch_xml_add_child(xml, name, strlen(xml->txt));
699 else
700 xml->name = name; /* first open tag */
701
702 xml->attr = attr;
703 root->cur = xml; /* update tag insertion point */
704}
705
706/* called when parser finds character content between open and closing tag */
707static void switch_xml_char_content(switch_xml_root_t root, char *s, switch_size_t len, char t)
708{
709 switch_xml_t xml;
710 char *m = s;
711 switch_size_t l;
712
713 if (!root || !root->cur) {
714 return;
715 }
716
717 xml = root->cur;
718
719 if (!xml || !xml->name || !len)
720 return; /* sanity check */
721
722 s[len] = '\0'; /* null terminate text (calling functions anticipate this) */
723 len = strlen(s = switch_xml_decode(s, root->ent, t)) + 1;
724
725 if (!*(xml->txt))
726 xml->txt = s; /* initial character content */
727 else { /* allocate our own memory and make a copy */
728 if ((xml->flags & SWITCH_XML_TXTM)) { /* allocate some space */
729 xml->txt = (char *) switch_must_realloc(xml->txt, (l = strlen(xml->txt)) + len);
730 } else {
731 char *tmp = (char *) switch_must_malloc((l = strlen(xml->txt)) + len);
732
733 xml->txt = strcpy(tmp, xml->txt);
734 }
735 strcpy(xml->txt + l, s); /* add new char content */
736 if (s != m)
737 free(s); /* free s if it was malloced by switch_xml_decode() */
738 }
739
740 if (xml->txt != m)
741 switch_xml_set_flag(xml, SWITCH_XML_TXTM);
742}
743
744/* called when parser finds closing tag */
745static switch_xml_t switch_xml_close_tag(switch_xml_root_t root, char *name, char *s)
746{
747 if (!root || !root->cur || !root->cur->name || strcmp(name, root->cur->name))
748 return switch_xml_err(root, s, "unexpected closing tag </%s>", name);
749
750 root->cur = root->cur->parent;
751 return NULL((void*)0);
752}
753
754/* checks for circular entity references, returns non-zero if no circular
755 references are found, zero otherwise */
756static int switch_xml_ent_ok(char *name, char *s, char **ent)
757{
758 int i;
759
760 for (;; s++) {
761 while (*s && *s != '&')
762 s++; /* find next entity reference */
763 if (!*s)
764 return 1;
765 if (!strncmp(s + 1, name, strlen(name)))
766 return 0; /* circular ref. */
767 for (i = 0; ent[i] && strncmp(ent[i], s + 1, strlen(ent[i])); i += 2);
768 if (ent[i] && !switch_xml_ent_ok(name, ent[i + 1], ent))
769 return 0;
770 }
771}
772
773/* called when the parser finds a processing instruction */
774static void switch_xml_proc_inst(switch_xml_root_t root, char *s, switch_size_t len)
775{
776 int i = 0, j = 1;
777 char *target = s;
778 char **sstmp;
779 char *stmp;
780
781 s[len] = '\0'; /* null terminate instruction */
782 if (*(s += strcspn(s, SWITCH_XML_WS"\t\r\n "))) {
783 *s = '\0'; /* null terminate target */
784 s += strspn(s + 1, SWITCH_XML_WS"\t\r\n ") + 1; /* skip whitespace after target */
785 }
786
787 if (!root)
788 return;
789
790 if (!strcmp(target, "xml")) { /* <?xml ... ?> */
791 if ((s = strstr(s, "standalone")) && !strncmp(s + strspn(s + 10, SWITCH_XML_WS"\t\r\n " "='\"") + 10, "yes", 3))
792 root->standalone = 1;
793 return;
794 }
795
796 if (!root->pi || !root->pi[0]) {
797 root->pi = (char ***) switch_must_malloc(sizeof(char **));
798 *(root->pi) = NULL((void*)0); /* first pi */
799 }
800
801 while (root->pi[i] && strcmp(target, root->pi[i][0]))
802 i++; /* find target */
803 if (!root->pi[i]) { /* new target */
804 char ***ssstmp = (char ***) switch_must_realloc(root->pi, sizeof(char **) * (i + 2));
805
806 root->pi = ssstmp;
807 if (!root->pi)
808 return;
809 root->pi[i] = (char **) switch_must_malloc(sizeof(char *) * 3);
810 root->pi[i][0] = target;
811 root->pi[i][1] = (char *) (root->pi[i + 1] = NULL((void*)0)); /* terminate pi list */
812 root->pi[i][2] = switch_must_strdup(""); /* empty document position list */
813 }
814
815 while (root->pi[i][j])
816 j++; /* find end of instruction list for this target */
817 sstmp = (char **) switch_must_realloc(root->pi[i], sizeof(char *) * (j + 3));
818 root->pi[i] = sstmp;
819 stmp = (char *) switch_must_realloc(root->pi[i][j + 1], j + 1);
820 root->pi[i][j + 2] = stmp;
821 strcpy(root->pi[i][j + 2] + j - 1, (root->xml.name) ? ">" : "<");
822 root->pi[i][j + 1] = NULL((void*)0); /* null terminate pi list for this target */
823 root->pi[i][j] = s; /* set instruction */
824}
825
826/* called when the parser finds an internal doctype subset */
827static short switch_xml_internal_dtd(switch_xml_root_t root, char *s, switch_size_t len)
828{
829 char q, *c, *t, *n = NULL((void*)0), *v, **ent, **pe;
830 int i, j;
831 char **sstmp;
832
833 pe = (char **) memcpy(switch_must_malloc(sizeof(SWITCH_XML_NIL)), SWITCH_XML_NIL, sizeof(SWITCH_XML_NIL));
834
835 for (s[len] = '\0'; s;) {
836 while (*s && *s != '<' && *s != '%')
837 s++; /* find next declaration */
838
839 if (!*s)
840 break;
841 else if (!strncmp(s, "<!ENTITY", 8)) { /* parse entity definitions */
842 int use_pe;
843
844 c = s += strspn(s + 8, SWITCH_XML_WS"\t\r\n ") + 8; /* skip white space separator */
845 n = s + strspn(s, SWITCH_XML_WS"\t\r\n " "%"); /* find name */
846 *(s = n + strcspn(n, SWITCH_XML_WS"\t\r\n ")) = ';'; /* append ; to name */
847
848 v = s + strspn(s + 1, SWITCH_XML_WS"\t\r\n ") + 1; /* find value */
849 if ((q = *(v++)) != '"' && q != '\'') { /* skip externals */
850 s = strchr(s, '>');
851 continue;
852 }
853
854 use_pe = (*c == '%');
855 for (i = 0, ent = (use_pe) ? pe : root->ent; ent[i]; i++);
856 sstmp = (char **) switch_must_realloc(ent, (i + 3) * sizeof(char *)); /* space for next ent */
857 ent = sstmp;
858 if (use_pe)
859 pe = ent;
860 else
861 root->ent = ent;
862
863 *(++s) = '\0'; /* null terminate name */
864 if ((s = strchr(v, q)))
865 *(s++) = '\0'; /* null terminate value */
866 ent[i + 1] = switch_xml_decode(v, pe, '%'); /* set value */
867 ent[i + 2] = NULL((void*)0); /* null terminate entity list */
868 if (!switch_xml_ent_ok(n, ent[i + 1], ent)) { /* circular reference */
869 if (ent[i + 1] != v)
870 free(ent[i + 1]);
871 switch_xml_err(root, v, "circular entity declaration &%s", n);
872 break;
873 } else
874 ent[i] = n; /* set entity name */
875 } else if (!strncmp(s, "<!ATTLIST", 9)) { /* parse default attributes */
876 t = s + strspn(s + 9, SWITCH_XML_WS"\t\r\n ") + 9; /* skip whitespace separator */
877 if (!*t) {
878 switch_xml_err(root, t, "unclosed <!ATTLIST");
879 break;
880 }
881 if (*(s = t + strcspn(t, SWITCH_XML_WS"\t\r\n " ">")) == '>')
882 continue;
883 else
884 *s = '\0'; /* null terminate tag name */
885 for (i = 0; root->attr[i] && strcmp(n, root->attr[i][0]); i++);
886
887 //while (*(n = ++s + strspn(s, SWITCH_XML_WS)) && *n != '>') {
888 // gcc 4.4 you are a creep
889 for (;;) {
890 s++;
891 if (!(*(n = s + strspn(s, SWITCH_XML_WS"\t\r\n ")) && *n != '>')) {
892 break;
893 }
894 if (*(s = n + strcspn(n, SWITCH_XML_WS"\t\r\n ")))
895 *s = '\0'; /* attr name */
896 else {
897 switch_xml_err(root, t, "malformed <!ATTLIST");
898 break;
899 }
900
901 s += strspn(s + 1, SWITCH_XML_WS"\t\r\n ") + 1; /* find next token */
902 c = (strncmp(s, "CDATA", 5)) ? (char *) "*" : (char *) " "; /* is it cdata? */
903 if (!strncmp(s, "NOTATION", 8))
904 s += strspn(s + 8, SWITCH_XML_WS"\t\r\n ") + 8;
905 s = (*s == '(') ? strchr(s, ')') : s + strcspn(s, SWITCH_XML_WS"\t\r\n ");
906 if (!s) {
907 switch_xml_err(root, t, "malformed <!ATTLIST");
908 break;
909 }
910
911 s += strspn(s, SWITCH_XML_WS"\t\r\n " ")"); /* skip white space separator */
912 if (!strncmp(s, "#FIXED", 6))
913 s += strspn(s + 6, SWITCH_XML_WS"\t\r\n ") + 6;
914 if (*s == '#') { /* no default value */
915 s += strcspn(s, SWITCH_XML_WS"\t\r\n " ">") - 1;
916 if (*c == ' ')
917 continue; /* cdata is default, nothing to do */
918 v = NULL((void*)0);
919 } else if ((*s == '"' || *s == '\'') && /* default value */
920 (s = strchr(v = s + 1, *s)))
921 *s = '\0';
922 else {
923 switch_xml_err(root, t, "malformed <!ATTLIST");
924 break;
925 }
926
927 if (!root->attr[i]) { /* new tag name */
928 root->attr = (!i) ? (char ***) switch_must_malloc(2 * sizeof(char **))
929 : (char ***) switch_must_realloc(root->attr, (i + 2) * sizeof(char **));
930 root->attr[i] = (char **) switch_must_malloc(2 * sizeof(char *));
931 root->attr[i][0] = t; /* set tag name */
932 root->attr[i][1] = (char *) (root->attr[i + 1] = NULL((void*)0));
933 }
934
935 for (j = 1; root->attr[i][j]; j += 3); /* find end of list */
936 sstmp = (char **) switch_must_realloc(root->attr[i], (j + 4) * sizeof(char *));
937
938 root->attr[i] = sstmp;
939 root->attr[i][j + 3] = NULL((void*)0); /* null terminate list */
940 root->attr[i][j + 2] = c; /* is it cdata? */
941 root->attr[i][j + 1] = (v) ? switch_xml_decode(v, root->ent, *c) : NULL((void*)0);
942 root->attr[i][j] = n; /* attribute name */
943 }
944 } else if (!strncmp(s, "<!--", 4))
945 s = strstr(s + 4, "-->"); /* comments */
946 else if (!strncmp(s, "<?", 2)) { /* processing instructions */
947 if ((s = strstr(c = s + 2, "?>")))
948 switch_xml_proc_inst(root, c, s++ - c);
949 } else if (*s == '<')
950 s = strchr(s, '>'); /* skip other declarations */
951 else if (*(s++) == '%' && !root->standalone)
952 break;
953 }
954
955 free(pe);
956 return !*root->err;
957}
958
959/* Converts a UTF-16 string to UTF-8. Returns a new string that must be freed
960 or NULL if no conversion was needed. */
961static char *switch_xml_str2utf8(char **s, switch_size_t *len)
962{
963 char *u;
964 switch_size_t l = 0, sl, max = *len;
965 long c, d;
966 int b, be = (**s == '\xFE') ? 1 : (**s == '\xFF') ? 0 : -1;
967
968 if (be == -1)
969 return NULL((void*)0); /* not UTF-16 */
970
971 u = (char *) switch_must_malloc(max);
972 for (sl = 2; sl < *len - 1; sl += 2) {
973 c = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF) /* UTF-16BE */
974 : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF); /* UTF-16LE */
975 if (c >= 0xD800 && c <= 0xDFFF && (sl += 2) < *len - 1) { /* high-half */
976 d = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF)
977 : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF);
978 c = (((c & 0x3FF) << 10) | (d & 0x3FF)) + 0x10000;
979 }
980
981 while (l + 6 > max) {
982 char *tmp;
983 tmp = (char *) switch_must_realloc(u, max += SWITCH_XML_BUFSIZE1024);
984 u = tmp;
985 }
986 if (c < 0x80)
987 u[l++] = (char) c; /* US-ASCII subset */
988 else { /* multi-byte UTF-8 sequence */
989 for (b = 0, d = c; d; d /= 2)
990 b++; /* bits in c */
991 b = (b - 2) / 5; /* bytes in payload */
992 u[l++] = (char) ((0xFF << (7 - b)) | (c >> (6 * b))); /* head */
993 while (b)
994 u[l++] = (char) (0x80 | ((c >> (6 * --b)) & 0x3F)); /* payload */
995 }
996 }
997 return *s = (char *) switch_must_realloc(u, *len = l);
998}
999
1000/* frees a tag attribute list */
1001static void switch_xml_free_attr(char **attr)
1002{
1003 int i, c = 0;
1004 char *m;
1005
1006 if (!attr || attr == SWITCH_XML_NIL)
1007 return; /* nothing to free */
1008 while (attr[c])
1009 c += 2; /* find end of attribute list */
1010 m = attr[c + 1]; /* list of which names and values are malloced */
1011 for (i = c / 2 - 1; i >= 0 ; i--) {
1012 if (m[i] & SWITCH_XML_NAMEM)
1013 free(attr[i * 2]);
1014 if (m[i] & SWITCH_XML_TXTM)
1015 free(attr[(i * 2) + 1]);
1016 }
1017 free(m);
1018 free(attr);
1019}
1020
1021SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_str_dynamic(char *s, switch_bool_t dup)
1022{
1023 switch_xml_root_t root;
1024 char *data;
1025
1026 switch_assert(s)((s) ? (void) (0) : __assert_fail ("s", "src/switch_xml.c", 1026
, __extension__ __PRETTY_FUNCTION__))
;
1027 data = dup ? switch_must_strdup(s) : s;
1028
1029 if ((root = (switch_xml_root_t) switch_xml_parse_str(data, strlen(data)))) {
1030 root->dynamic = 1; /* Make sure we free the memory is switch_xml_free() */
1031 return &root->xml;
1032 } else {
1033 if (dup) {
1034 free(data);
1035 }
1036 return NULL((void*)0);
1037 }
1038}
1039
1040/* parse the given xml string and return a switch_xml structure */
1041SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_str(char *s, switch_size_t len)
1042{
1043 switch_xml_root_t root = (switch_xml_root_t) switch_xml_new(NULL((void*)0));
1044 char q, e, *d, **attr, **a = NULL((void*)0); /* initialize a to avoid compile warning */
1045 int l, i, j;
1046
1047 root->m = s;
1048 if (!len)
1049 return switch_xml_err(root, s, "root tag missing");
1050 root->u = switch_xml_str2utf8(&s, &len); /* convert utf-16 to utf-8 */
1051 root->e = (root->s = s) + len; /* record start and end of work area */
1052
1053 e = s[len - 1]; /* save end char */
1054 s[len - 1] = '\0'; /* turn end char into null terminator */
1055
1056 while (*s && *s != '<')
1057 s++; /* find first tag */
1058 if (!*s)
1059 return switch_xml_err(root, s, "root tag missing");
1060
1061 for (;;) {
1062 attr = (char **) SWITCH_XML_NIL;
1063 d = ++s;
1064
1065 if (isalpha((int) (*s))((*__ctype_b_loc ())[(int) (((int) (*s)))] & (unsigned short
int) _ISalpha)
|| *s == '_' || *s == ':' || (int8_t) * s < '\0') { /* new tag */
1066 if (!root->cur)
1067 return switch_xml_err(root, d, "markup outside of root element");
1068
1069 s += strcspn(s, SWITCH_XML_WS"\t\r\n " "/>");
1070 while (isspace((int) (*s))((*__ctype_b_loc ())[(int) (((int) (*s)))] & (unsigned short
int) _ISspace)
)
1071 *(s++) = '\0'; /* null terminate tag name */
1072
1073 if (*s && *s != '/' && *s != '>') /* find tag in default attr list */
1074 for (i = 0; (a = root->attr[i]) && strcmp(a[0], d); i++);
1075
1076 for (l = 0; *s && *s != '/' && *s != '>'; l += 2) { /* new attrib */
1077 attr = (l) ? (char **) switch_must_realloc(attr, (l + 4) * sizeof(char *))
1078 : (char **) switch_must_malloc(4 * sizeof(char *)); /* allocate space */
1079 attr[l + 3] = (l) ? (char *) switch_must_realloc(attr[l + 1], (l / 2) + 2)
1080 : (char *) switch_must_malloc(2); /* mem for list of maloced vals */
1081 strcpy(attr[l + 3] + (l / 2), " "); /* value is not malloced */
1082 attr[l + 2] = NULL((void*)0); /* null terminate list */
1083 attr[l + 1] = (char *) ""; /* temporary attribute value */
1084 attr[l] = s; /* set attribute name */
1085
1086 s += strcspn(s, SWITCH_XML_WS"\t\r\n " "=/>");
1087 if (*s == '=' || isspace((int) (*s))((*__ctype_b_loc ())[(int) (((int) (*s)))] & (unsigned short
int) _ISspace)
) {
1088 *(s++) = '\0'; /* null terminate tag attribute name */
1089 q = *(s += strspn(s, SWITCH_XML_WS"\t\r\n " "="));
1090 if (q == '"' || q == '\'') { /* attribute value */
1091 attr[l + 1] = ++s;
1092 while (*s && *s != q)
1093 s++;
1094 if (*s)
1095 *(s++) = '\0'; /* null terminate attribute val */
1096 else {
1097 switch_xml_free_attr(attr);
1098 return switch_xml_err(root, d, "missing %c", q);
1099 }
1100
1101 for (j = 1; a && a[j] && strcmp(a[j], attr[l]); j += 3);
1102 attr[l + 1] = switch_xml_decode(attr[l + 1], root->ent, (a && a[j]) ? *a[j + 2] : ' ');
1103 if (attr[l + 1] < d || attr[l + 1] > s)
1104 attr[l + 3][l / 2] = SWITCH_XML_TXTM; /* value malloced */
1105 }
1106 }
1107 while (isspace((int) (*s))((*__ctype_b_loc ())[(int) (((int) (*s)))] & (unsigned short
int) _ISspace)
)
1108 s++;
1109 }
1110
1111 if (*s == '/') { /* self closing tag */
1112 *(s++) = '\0';
1113 if ((*s && *s != '>') || (!*s && e != '>')) {
1114 if (l)
1115 switch_xml_free_attr(attr);
1116 return switch_xml_err(root, d, "missing >");
1117 }
1118 switch_xml_open_tag(root, d, attr);
1119 switch_xml_close_tag(root, d, s);
1120 } else if ((q = *s) == '>' || (!*s && e == '>')) { /* open tag */
1121 *s = '\0'; /* temporarily null terminate tag name */
1122 switch_xml_open_tag(root, d, attr);
1123 *s = q;
1124 } else {
1125 if (l)
1126 switch_xml_free_attr(attr);
1127 return switch_xml_err(root, d, "missing >");
1128 }
1129 } else if (*s == '/') { /* close tag */
1130 s += strcspn(d = s + 1, SWITCH_XML_WS"\t\r\n " ">") + 1;
1131 if (!(q = *s) && e != '>')
1132 return switch_xml_err(root, d, "missing >");
1133 *s = '\0'; /* temporarily null terminate tag name */
1134 if (switch_xml_close_tag(root, d, s))
1135 return &root->xml;
1136 if (isspace((int) (*s = q))((*__ctype_b_loc ())[(int) (((int) (*s = q)))] & (unsigned
short int) _ISspace)
)
1137 s += strspn(s, SWITCH_XML_WS"\t\r\n ");
1138 } else if (!strncmp(s, "!--", 3)) { /* xml comment */
1139 if (!(s = strstr(s + 3, "--")) || (*(s += 2) != '>' && *s) || (!*s && e != '>'))
1140 return switch_xml_err(root, d, "unclosed <!--");
1141 } else if (!strncmp(s, "![CDATA[", 8)) { /* cdata */
1142 if ((s = strstr(s, "]]>"))) {
1143 if (root && root->cur) {
1144 root->cur->flags |= SWITCH_XML_CDATA;
1145 }
1146 switch_xml_char_content(root, d + 8, (s += 2) - d - 10, 'c');
1147 } else {
1148 return switch_xml_err(root, d, "unclosed <![CDATA[");
1149 }
1150 } else if (!strncmp(s, "!DOCTYPE", 8)) { /* dtd */
1151 for (l = 0; *s && ((!l && *s != '>') || (l && (*s != ']' || *(s + strspn(s + 1, SWITCH_XML_WS"\t\r\n ") + 1) != '>'))); l = (*s == '[') ? 1 : l)
1152 s += strcspn(s + 1, "[]>") + 1;
1153 if (!*s && e != '>')
1154 return switch_xml_err(root, d, "unclosed <!DOCTYPE");
1155 d = (l) ? strchr(d, '[') + 1 : d;
1156 if (l && !switch_xml_internal_dtd(root, d, s++ - d))
1157 return &root->xml;
1158 } else if (*s == '?') { /* <?...?> processing instructions */
1159 do {
1160 s = strchr(s, '?');
1161 } while (s && *(++s) && *s != '>');
1162 if (!s || (!*s && e != '>'))
1163 return switch_xml_err(root, d, "unclosed <?");
1164 else
1165 switch_xml_proc_inst(root, d + 1, s - d - 2);
1166 } else
1167 return switch_xml_err(root, d, "unexpected <");
1168
1169 if (!s || !*s)
1170 break;
1171 *s = '\0';
1172 d = ++s;
1173 if (*s && *s != '<') { /* tag character content */
1174 while (*s && *s != '<')
1175 s++;
1176 if (*s)
1177 switch_xml_char_content(root, d, s - d, '&');
1178 else
1179 break;
1180 } else if (!*s)
1181 break;
1182 }
1183
1184 if (!root->cur)
1185 return &root->xml;
1186 else if (!root->cur->name)
1187 return switch_xml_err(root, d, "root tag missing");
1188 else
1189 return switch_xml_err(root, d, "unclosed tag <%s>", root->cur->name);
1190}
1191
1192/* Wrapper for switch_xml_parse_str() that accepts a file stream. Reads the entire
1193 stream into memory and then parses it. For xml files, use switch_xml_parse_file()
1194 or switch_xml_parse_fd() */
1195SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_fp(FILE * fp)
1196{
1197 switch_xml_root_t root;
1198 switch_size_t l, len = 0;
1199 char *s;
1200
1201 s = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
1202
1203 do {
1204 len += (l = fread((s + len), 1, SWITCH_XML_BUFSIZE1024, fp));
1205 if (l == SWITCH_XML_BUFSIZE1024) {
1206 s = (char *) switch_must_realloc(s, len + SWITCH_XML_BUFSIZE1024);
1207 }
1208 } while (s && l == SWITCH_XML_BUFSIZE1024);
1209
1210 if (!s)
1211 return NULL((void*)0);
1212 root = (switch_xml_root_t) switch_xml_parse_str(s, len);
1213 root->dynamic = 1; /* so we know to free s in switch_xml_free() */
1214 return &root->xml;
1215}
1216
1217/* A wrapper for switch_xml_parse_str() that accepts a file descriptor. First
1218 attempts to mem map the file. Failing that, reads the file into memory.
1219 Returns NULL on failure. */
1220SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_fd(int fd)
1221{
1222 switch_xml_root_t root;
1223 struct stat st;
1224 switch_ssize_t l;
1225 void *m;
1226
1227 if (fd < 0)
1228 return NULL((void*)0);
1229 fstat(fd, &st);
1230
1231 if (!st.st_size) {
1232 return NULL((void*)0);
1233 }
1234
1235 m = switch_must_malloc(st.st_size);
1236
1237 if (!(0<(l = read(fd, m, st.st_size)))
1238 || !(root = (switch_xml_root_t) switch_xml_parse_str((char *) m, l))) {
1239 free(m);
1240 return NULL((void*)0);
1241 }
1242 root->dynamic = 1; /* so we know to free s in switch_xml_free() */
1243
1244 return &root->xml;
1245}
1246
1247static char *expand_vars(char *buf, char *ebuf, switch_size_t elen, switch_size_t *newlen, const char **err)
1248{
1249 char *var, *val;
1250 char *rp = buf;
1251 char *wp = ebuf;
1252 char *ep = ebuf + elen - 1;
1253
1254 if (!(var = strstr(rp, "$${"))) {
1255 *newlen = strlen(buf);
1256 return buf;
1257 }
1258
1259 while (*rp && wp < ep) {
1260
1261 if (*rp == '$' && *(rp + 1) == '$' && *(rp + 2) == '{') {
1262 char *e = switch_find_end_paren(rp + 2, '{', '}');
1263
1264 if (e) {
1265 rp += 3;
1266 var = rp;
1267 *e++ = '\0';
1268 rp = e;
1269 if ((val = switch_core_get_variable_dup(var))) {
1270 char *p;
1271 for (p = val; p && *p && wp <= ep; p++) {
1272 *wp++ = *p;
1273 }
1274 free(val);
1275 }
1276 continue;
1277 } else if (err) {
1278 *err = "unterminated ${var}";
1279 }
1280 }
1281
1282 *wp++ = *rp++;
1283 }
1284
1285 if (wp == ep) {
1286 return NULL((void*)0);
1287 }
1288
1289 *wp++ = '\0';
1290 *newlen = strlen(ebuf);
1291
1292 return ebuf;
1293}
1294
1295static FILE *preprocess_exec(const char *cwd, const char *command, FILE *write_fd, int rlevel)
1296{
1297#ifdef WIN32
1298 FILE *fp = NULL((void*)0);
1299 char buffer[1024];
1300
1301 if (!command || !strlen(command)) goto end;
1302
1303 if ((fp = _popen(command, "r"))) {
1304 while (fgets(buffer, sizeof(buffer), fp) != NULL((void*)0)) {
1305 if (fwrite(buffer, 1, strlen(buffer), write_fd) <= 0) {
1306 break;
1307 }
1308 }
1309
1310 if(feof(fp)) {
1311 _pclose(fp);
1312 } else {
1313 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1313, ((void*)0)
, SWITCH_LOG_ERROR, "Exec failed to read the pipe of [%s] to the end\n", command);
1314 }
1315 } else {
1316 switch_snprintf(buffer, sizeof(buffer), "<!-- exec can not execute [%s] -->", command);
1317 fwrite( buffer, 1, strlen(buffer), write_fd);
1318 }
1319#else
1320 int fds[2], pid = 0;
1321
1322 if (pipe(fds)) {
1323 goto end;
1324 } else { /* good to go */
1325 pid = switch_fork();
1326
1327 if (pid < 0) { /* ok maybe not */
1328 close(fds[0]);
1329 close(fds[1]);
1330 goto end;
1331 } else if (pid) { /* parent */
1332 char buf[1024] = "";
1333 int bytes;
1334 close(fds[1]);
1335 while ((bytes = read(fds[0], buf, sizeof(buf))) > 0) {
1336 if (fwrite(buf, 1, bytes, write_fd) <= 0) {
1337 break;
1338 }
1339 }
1340 close(fds[0]);
1341 waitpid(pid, NULL((void*)0), 0);
1342 } else { /* child */
1343 switch_close_extra_files(fds, 2);
1344 close(fds[0]);
1345 dup2(fds[1], STDOUT_FILENO1);
1346 switch_system(command, SWITCH_TRUE);
1347 close(fds[1]);
1348 exit(0);
1349 }
1350 }
1351#endif
1352 end:
1353
1354 return write_fd;
1355
1356}
1357
1358static FILE *preprocess_glob(const char *cwd, const char *pattern, FILE *write_fd, int rlevel)
1359{
1360 char *full_path = NULL((void*)0);
1361 char *dir_path = NULL((void*)0), *e = NULL((void*)0);
1362 glob_t glob_data;
1363 size_t n;
1364 int glob_return;
1365
1366 if (!switch_is_file_path(pattern)) {
1367 full_path = switch_mprintf("%s%s%s", cwd, SWITCH_PATH_SEPARATOR"/", pattern);
1368 pattern = full_path;
1369 }
1370
1371 glob_return = glob(pattern, GLOB_ERR(1 << 0), NULL((void*)0), &glob_data);
1372 if (glob_return == GLOB_NOSPACE1 || glob_return == GLOB_ABORTED2) {
1373 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1373, ((void*)0)
, SWITCH_LOG_ERROR, "Error including %s\n", pattern);
1374 goto end;
1375 } else if (glob_return == GLOB_NOMATCH3) {
1376 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1376, ((void*)0)
, SWITCH_LOG_INFO, "No files to include at %s\n", pattern);
1377 goto end;
1378 }
1379
1380 for (n = 0; n < glob_data.gl_pathc; ++n) {
1381 dir_path = switch_must_strdup(glob_data.gl_pathv[n]);
1382
1383 if ((e = strrchr(dir_path, *SWITCH_PATH_SEPARATOR"/"))) {
1384 *e = '\0';
1385 }
1386 if (preprocess(dir_path, glob_data.gl_pathv[n], write_fd, rlevel) < 0) {
1387 if (rlevel > 100) {
1388 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1388, ((void*)0)
, SWITCH_LOG_ERROR, "Error including %s (Maximum recursion limit reached)\n", pattern);
1389 }
1390 }
1391 free(dir_path);
1392 }
1393 globfree(&glob_data);
1394
1395 end:
1396
1397 switch_safe_free(full_path)if (full_path) {free(full_path);full_path=((void*)0);};
1398
1399 return write_fd;
1400}
1401
1402static int preprocess(const char *cwd, const char *file, FILE *write_fd, int rlevel)
1403{
1404 FILE *read_fd = NULL((void*)0);
1405 switch_size_t cur = 0, ml = 0;
1406 char *q, *cmd, *buf = NULL((void*)0), *ebuf = NULL((void*)0);
1407 char *tcmd, *targ;
1408 int line = 0;
1409 switch_size_t len = 0, eblen = 0;
1410
1411 if (rlevel > 100) {
1412 return -1;
1413 }
1414
1415 if (!(read_fd = fopen(file, "r"))) {
1416 const char *reason = strerror(errno(*__errno_location ()));
1417 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1417, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't open %s (%s)\n", file, reason);
1418 return -1;
1419 }
1420
1421 setvbuf(read_fd, (char *) NULL((void*)0), _IOFBF0, 65536);
1422
1423 for(;;) {
1424 char *arg, *e;
1425 const char *err = NULL((void*)0);
1426 char *bp;
1427
1428 switch_safe_free(ebuf)if (ebuf) {free(ebuf);ebuf=((void*)0);};
1429
1430 if ((cur = switch_fp_read_dline(read_fd, &buf, &len)) <= 0) {
1431 break;
1432 }
1433
1434 eblen = len * 2;
1435 ebuf = switch_must_malloc(eblen);
1436 memset(ebuf, 0, eblen);
1437
1438 while (!(bp = expand_vars(buf, ebuf, eblen, &cur, &err))) {
1439 eblen *= 2;
1440 ebuf = switch_must_realloc(ebuf, eblen);
1441 memset(ebuf, 0, eblen);
1442 }
1443
1444 line++;
1445
1446 if (err) {
1447 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1447, ((void*)0)
, SWITCH_LOG_ERROR, "Error [%s] in file %s line %d\n", err, file, line);
1448 }
1449
1450 /* we ignore <include> or </include> for the sake of validators as well as <?xml version="1.0"?> type stuff */
1451 if (strstr(buf, "<include>") || strstr(buf, "</include>") || strstr(buf, "<?")) {
1452 continue;
1453 }
1454
1455 if (ml) {
1456 if ((e = strstr(buf, "-->"))) {
1457 ml = 0;
1458 bp = e + 3;
1459 cur = strlen(bp);
1460 } else {
1461 continue;
1462 }
1463 }
1464
1465 if ((tcmd = (char *) switch_stristr("X-pre-process", bp))) {
1466 if (*(tcmd - 1) != '<') {
1467 continue;
1468 }
1469 if ((e = strstr(tcmd, "/>"))) {
1470 e += 2;
1471 *e = '\0';
1472 if (fwrite(e, 1, (unsigned) strlen(e), write_fd) != (int) strlen(e)) {
1473 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1473, ((void*)0)
, SWITCH_LOG_ERROR, "Short write!\n");
1474 }
1475 }
1476
1477 if (!(tcmd = (char *) switch_stristr("cmd", tcmd))) {
1478 continue;
1479 }
1480
1481 if (!(tcmd = (char *) switch_stristr("=", tcmd))) {
1482 continue;
1483 }
1484
1485 if (!(tcmd = (char *) switch_stristr("\"", tcmd))) {
1486 continue;
1487 }
1488
1489 tcmd++;
1490
1491
1492 if ((e = strchr(tcmd, '"'))) {
1493 *e++ = '\0';
1494 }
1495
1496 if (!(targ = (char *) switch_stristr("data", e))) {
1497 continue;
1498 }
1499
1500 if (!(targ = (char *) switch_stristr("=", targ))) {
1501 continue;
1502 }
1503
1504 if (!(targ = (char *) switch_stristr("\"", targ))) {
1505 continue;
1506 }
1507
1508 targ++;
1509
1510 if ((e = strchr(targ, '"'))) {
1511 *e++ = '\0';
1512 }
1513
1514 if (!strcasecmp(tcmd, "set")) {
1515 char *name = (char *) targ;
1516 char *val = strchr(name, '=');
1517
1518 if (val) {
1519 char *ve = val++;
1520 while (*val && *val == ' ') {
1521 val++;
1522 }
1523 *ve-- = '\0';
1524 while (*ve && *ve == ' ') {
1525 *ve-- = '\0';
1526 }
1527 }
1528
1529 if (val) {
1530 switch_core_set_variable(name, val);
1531 }
1532
1533 } else if (!strcasecmp(tcmd, "exec-set")) {
1534 preprocess_exec_set(targ);
1535 } else if (!strcasecmp(tcmd, "stun-set")) {
1536 preprocess_stun_set(targ);
1537 } else if (!strcasecmp(tcmd, "env-set")) {
1538 preprocess_env_set(targ);
1539 } else if (!strcasecmp(tcmd, "include")) {
1540 preprocess_glob(cwd, targ, write_fd, rlevel + 1);
1541 } else if (!strcasecmp(tcmd, "exec")) {
1542 preprocess_exec(cwd, targ, write_fd, rlevel + 1);
1543 }
1544
1545 continue;
1546 }
1547
1548 if ((cmd = strstr(bp, "<!--#"))) {
1549 if (fwrite(bp, 1, (unsigned) (cmd - bp), write_fd) != (unsigned) (cmd - bp)) {
1550 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1550, ((void*)0)
, SWITCH_LOG_ERROR, "Short write!\n");
1551 }
1552 if ((e = strstr(cmd, "-->"))) {
1553 *e = '\0';
1554 e += 3;
1555 if (fwrite(e, 1, (unsigned) strlen(e), write_fd) != (int) strlen(e)) {
1556 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1556, ((void*)0)
, SWITCH_LOG_ERROR, "Short write!\n");
1557 }
1558 } else {
1559 ml++;
1560 }
1561
1562 cmd += 5;
1563 if ((e = strchr(cmd, '\r')) || (e = strchr(cmd, '\n'))) {
1564 *e = '\0';
1565 }
1566
1567 if ((arg = strchr(cmd, ' '))) {
1568 *arg++ = '\0';
1569 if ((q = strchr(arg, '"'))) {
1570 char *qq = q + 1;
1571
1572 if ((qq = strchr(qq, '"'))) {
1573 *qq = '\0';
1574 arg = q + 1;
1575 }
1576 }
1577
1578 if (!strcasecmp(cmd, "set")) {
1579 char *name = arg;
1580 char *val = strchr(name, '=');
1581
1582 if (val) {
1583 char *ve = val++;
1584 while (*val && *val == ' ') {
1585 val++;
1586 }
1587 *ve-- = '\0';
1588 while (*ve && *ve == ' ') {
1589 *ve-- = '\0';
1590 }
1591 }
1592
1593 if (val) {
1594 switch_core_set_variable(name, val);
1595 }
1596
1597 } else if (!strcasecmp(cmd, "exec-set")) {
1598 preprocess_exec_set(arg);
1599 } else if (!strcasecmp(cmd, "stun-set")) {
1600 preprocess_stun_set(arg);
1601 } else if (!strcasecmp(cmd, "include")) {
1602 preprocess_glob(cwd, arg, write_fd, rlevel + 1);
1603 } else if (!strcasecmp(cmd, "exec")) {
1604 preprocess_exec(cwd, arg, write_fd, rlevel + 1);
1605 }
1606 }
1607
1608 continue;
1609 }
1610
1611 if (fwrite(bp, 1, (unsigned) cur, write_fd) != (int) cur) {
1612 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1612, ((void*)0)
, SWITCH_LOG_ERROR, "Short write!\n");
1613 }
1614
1615 }
1616
1617 switch_safe_free(buf)if (buf) {free(buf);buf=((void*)0);};
1618 switch_safe_free(ebuf)if (ebuf) {free(ebuf);ebuf=((void*)0);};
1619
1620 fclose(read_fd);
1621
1622 return 0;
1623}
1624
1625SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_file_simple(const char *file)
1626{
1627 int fd = -1;
1628 struct stat st;
1629 switch_ssize_t l;
1630 void *m;
1631 switch_xml_root_t root;
1632
1633 if ((fd = open(file, O_RDONLY00, 0)) > -1) {
1634 fstat(fd, &st);
1635 if (!st.st_size) goto error;
1636 m = switch_must_malloc(st.st_size);
1637
1638 if (!(0<(l = read(fd, m, st.st_size)))) goto error;
1639 if (!(root = (switch_xml_root_t) switch_xml_parse_str((char *) m, l))) goto error;
1640 root->dynamic = 1;
1641 close(fd);
1642 return &root->xml;
1643 }
1644
1645 error:
1646
1647 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1647, ((void*)0)
, SWITCH_LOG_ERROR, "Error Parsing File [%s]\n", file);
1648
1649 return NULL((void*)0);
1650}
1651
1652SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_file(const char *file)
1653{
1654 int fd = -1;
1655 FILE *write_fd = NULL((void*)0);
1656 switch_xml_t xml = NULL((void*)0);
1657 char *new_file = NULL((void*)0);
1658 char *new_file_tmp = NULL((void*)0);
1659 const char *abs, *absw;
1660
1661 abs = strrchr(file, '/');
1662 absw = strrchr(file, '\\');
1663 if (abs || absw) {
1664 abs > absw ? abs++ : (abs = ++absw);
1665 } else {
1666 abs = file;
1667 }
1668
1669 switch_mutex_lock(FILE_LOCK);
1670
1671 if (!(new_file = switch_mprintf("%s%s%s.fsxml", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR"/", abs))) {
1672 goto done;
1673 }
1674
1675 if (!(new_file_tmp = switch_mprintf("%s%s%s.fsxml.tmp", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR"/", abs))) {
1676 goto done;
1677 }
1678
1679 if ((write_fd = fopen(new_file_tmp, "w+")) == NULL((void*)0)) {
1680 goto done;
1681 }
1682
1683 setvbuf(write_fd, (char *) NULL((void*)0), _IOFBF0, 65536);
1684
1685 if (preprocess(SWITCH_GLOBAL_dirs.conf_dir, file, write_fd, 0) > -1) {
1686 fclose(write_fd);
1687 write_fd = NULL((void*)0);
1688 unlink (new_file);
1689
1690 if ( rename(new_file_tmp,new_file) ) {
1691 goto done;
1692 }
1693 if ((fd = open(new_file, O_RDONLY00, 0)) > -1) {
1694 if ((xml = switch_xml_parse_fd(fd))) {
1695 if (strcmp(abs, SWITCH_GLOBAL_filenames.conf_name)) {
1696 xml->free_path = new_file;
1697 new_file = NULL((void*)0);
1698 }
1699 }
1700 close(fd);
1701 fd = -1;
1702 }
1703 }
1704
1705 done:
1706
1707 switch_mutex_unlock(FILE_LOCK);
1708
1709 if (write_fd) {
1710 fclose(write_fd);
1711 write_fd = NULL((void*)0);
1712 }
1713
1714 if (fd > -1) {
1715 close(fd);
1716 }
1717
1718 switch_safe_free(new_file_tmp)if (new_file_tmp) {free(new_file_tmp);new_file_tmp=((void*)0)
;}
;
1719 switch_safe_free(new_file)if (new_file) {free(new_file);new_file=((void*)0);};
1720
1721 return xml;
1722}
1723
1724SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate(const char *section,
1725 const char *tag_name,
1726 const char *key_name,
1727 const char *key_value,
1728 switch_xml_t *root, switch_xml_t *node, switch_event_t *params, switch_bool_t clone)
1729{
1730 switch_xml_t conf = NULL((void*)0);
1731 switch_xml_t tag = NULL((void*)0);
1732 switch_xml_t xml = NULL((void*)0);
1733 switch_xml_binding_t *binding;
1734 uint8_t loops = 0;
1735 switch_xml_section_t sections = BINDINGS ? switch_xml_parse_section_string(section) : 0;
1736
1737 switch_thread_rwlock_rdlock(B_RWLOCK);
1738
1739 for (binding = BINDINGS; binding; binding = binding->next) {
1740 if (binding->sections && !(sections & binding->sections)) {
1741 continue;
1742 }
1743
1744 if ((xml = binding->function(section, tag_name, key_name, key_value, params, binding->user_data))) {
1745 const char *err = NULL((void*)0);
1746
1747 err = switch_xml_error(xml);
1748 if (zstr(err)_zstr(err)) {
1749 if ((conf = switch_xml_find_child(xml, "section", "name", "result"))) {
1750 switch_xml_t p;
1751 const char *aname;
1752
1753 if ((p = switch_xml_child(conf, "result"))) {
1754 aname = switch_xml_attr(p, "status");
1755 if (aname && !strcasecmp(aname, "not found")) {
1756 switch_xml_free(xml);
1757 xml = NULL((void*)0);
1758 continue;
1759 }
1760 }
1761 }
1762 break;
1763 } else {
1764 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1764, ((void*)0)
, SWITCH_LOG_ERROR, "Error[%s]\n", err);
1765 switch_xml_free(xml);
1766 xml = NULL((void*)0);
1767 }
1768 }
1769 }
1770 switch_thread_rwlock_unlock(B_RWLOCK);
1771
1772 for (;;) {
1773 if (!xml) {
1774 if (!(xml = switch_xml_root())) {
1775 *node = NULL((void*)0);
1776 *root = NULL((void*)0);
1777 return SWITCH_STATUS_FALSE;
1778 }
1779 }
1780
1781 if ((conf = switch_xml_find_child(xml, "section", "name", section)) && (tag = switch_xml_find_child(conf, tag_name, key_name, key_value))) {
1782 if (clone) {
1783 char *x = switch_xml_toxml(tag, SWITCH_FALSE)switch_xml_toxml_ex(tag, SWITCH_FALSE, SWITCH_TRUE);
1784 switch_assert(x)((x) ? (void) (0) : __assert_fail ("x", "src/switch_xml.c", 1784
, __extension__ __PRETTY_FUNCTION__))
;
1785 *node = *root = switch_xml_parse_str_dynamic(x, SWITCH_FALSE); /* x will be free()'d in switch_xml_free() */
1786 switch_xml_free(xml);
1787 } else {
1788 *node = tag;
1789 *root = xml;
1790 }
1791 return SWITCH_STATUS_SUCCESS;
1792 } else {
1793 switch_xml_free(xml);
1794 xml = NULL((void*)0);
1795 *node = NULL((void*)0);
1796 *root = NULL((void*)0);
1797 if (loops++ > 1) {
1798 break;
1799 }
1800 }
1801 }
1802
1803 return SWITCH_STATUS_FALSE;
1804}
1805
1806SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate_domain(const char *domain_name, switch_event_t *params, switch_xml_t *root, switch_xml_t *domain)
1807{
1808 switch_event_t *my_params = NULL((void*)0);
1809 switch_status_t status;
1810 *domain = NULL((void*)0);
1811
1812 if (!params) {
1813 switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("src/switch_xml.c", (const
char * )(const char *)__func__, 1813, &my_params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
1814 switch_assert(my_params)((my_params) ? (void) (0) : __assert_fail ("my_params", "src/switch_xml.c"
, 1814, __extension__ __PRETTY_FUNCTION__))
;
1815 switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain_name);
1816 params = my_params;
1817 }
1818
1819 status = switch_xml_locate("directory", "domain", "name", domain_name, root, domain, params, SWITCH_FALSE);
1820 if (my_params) {
1821 switch_event_destroy(&my_params);
1822 }
1823 return status;
1824}
1825
1826SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate_group(const char *group_name,
1827 const char *domain_name,
1828 switch_xml_t *root, switch_xml_t *domain, switch_xml_t *group, switch_event_t *params)
1829{
1830 switch_status_t status = SWITCH_STATUS_FALSE;
1831 switch_event_t *my_params = NULL((void*)0);
1832 switch_xml_t groups = NULL((void*)0);
1833
1834 *root = NULL((void*)0);
1835 *group = NULL((void*)0);
1836 *domain = NULL((void*)0);
1837
1838 if (!params) {
1839 switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("src/switch_xml.c", (const
char * )(const char *)__func__, 1839, &my_params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
1840 switch_assert(my_params)((my_params) ? (void) (0) : __assert_fail ("my_params", "src/switch_xml.c"
, 1840, __extension__ __PRETTY_FUNCTION__))
;
1841 params = my_params;
1842 }
1843
1844 if (group_name) {
1845 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "group_name", group_name);
1846 }
1847
1848 if (domain_name) {
1849 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain_name);
1850 }
1851
1852 if ((status = switch_xml_locate_domain(domain_name, params, root, domain)) != SWITCH_STATUS_SUCCESS) {
1853 goto end;
1854 }
1855
1856 status = SWITCH_STATUS_FALSE;
1857
1858 if ((groups = switch_xml_child(*domain, "groups"))) {
1859 if ((*group = switch_xml_find_child(groups, "group", "name", group_name))) {
1860 status = SWITCH_STATUS_SUCCESS;
1861 }
1862 }
1863
1864 end:
1865
1866 if (my_params) {
1867 switch_event_destroy(&my_params);
1868 }
1869
1870 return status;
1871}
1872
1873static switch_status_t find_user_in_tag(switch_xml_t tag, const char *ip, const char *user_name,
1874 const char *key, switch_event_t *params, switch_xml_t *user)
1875{
1876 const char *type = "!pointer";
1877 const char *val;
1878
1879 if (params && (val = switch_event_get_header(params, "user_type")switch_event_get_header_idx(params, "user_type", -1))) {
1880 if (!strcasecmp(val, "any")) {
1881 type = NULL((void*)0);
1882 } else {
1883 type = val;
1884 }
1885 }
1886
1887 if (ip) {
1888 if ((*user = switch_xml_find_child_multi(tag, "user", "ip", ip, "type", type, NULL((void*)0)))) {
1889 return SWITCH_STATUS_SUCCESS;
1890 }
1891 }
1892
1893 if (user_name) {
1894 if (!strcasecmp(key, "id")) {
1895 if ((*user = switch_xml_find_child_multi(tag, "user", key, user_name, "number-alias", user_name, "type", type, NULL((void*)0)))) {
1896 return SWITCH_STATUS_SUCCESS;
1897 }
1898 } else {
1899 if ((*user = switch_xml_find_child_multi(tag, "user", key, user_name, "type", type, NULL((void*)0)))) {
1900 return SWITCH_STATUS_SUCCESS;
1901 }
1902 }
1903 }
1904
1905 return SWITCH_STATUS_FALSE;
1906
1907}
1908
1909SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate_user_in_domain(const char *user_name, switch_xml_t domain, switch_xml_t *user, switch_xml_t *ingroup)
1910{
1911 switch_xml_t group = NULL((void*)0), groups = NULL((void*)0), users = NULL((void*)0);
1912 switch_status_t status = SWITCH_STATUS_FALSE;
1913
1914 if ((groups = switch_xml_child(domain, "groups"))) {
1915 for (group = switch_xml_child(groups, "group"); group; group = group->next) {
1916 if ((users = switch_xml_child(group, "users"))) {
1917 if ((status = find_user_in_tag(users, NULL((void*)0), user_name, "id", NULL((void*)0), user)) == SWITCH_STATUS_SUCCESS) {
1918 if (ingroup) {
1919 *ingroup = group;
1920 }
1921 break;
1922 }
1923 }
1924 }
1925 } else {
1926 if ((users = switch_xml_child(domain, "users"))) {
1927 status = find_user_in_tag(users, NULL((void*)0), user_name, "id", NULL((void*)0), user);
1928 } else {
1929 status = find_user_in_tag(domain, NULL((void*)0), user_name, "id", NULL((void*)0), user);
1930 }
1931 }
1932
1933 return status;
1934}
1935
1936
1937SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_dup(switch_xml_t xml)
1938{
1939 char *x = switch_xml_toxml(xml, SWITCH_FALSE)switch_xml_toxml_ex(xml, SWITCH_FALSE, SWITCH_TRUE);
1940 return switch_xml_parse_str_dynamic(x, SWITCH_FALSE);
1941}
1942
1943
1944static void do_merge(switch_xml_t in, switch_xml_t src, const char *container, const char *tag_name)
1945{
1946 switch_xml_t itag, tag, param, iparam, iitag;
1947
1948 if (!(itag = switch_xml_child(in, container))) {
1949 itag = switch_xml_add_child_d(in, container, 0);
1950 }
1951
1952 if ((tag = switch_xml_child(src, container))) {
1953 for (param = switch_xml_child(tag, tag_name); param; param = param->next) {
1954 const char *var = switch_xml_attr(param, "name");
1955 const char *val = switch_xml_attr(param, "value");
1956
1957 switch_bool_t add_child = SWITCH_TRUE;
1958
1959 for (iparam = switch_xml_child(itag, tag_name); iparam; iparam = iparam->next) {
1960 const char *ivar = switch_xml_attr(iparam, "name");
1961
1962 if (var && ivar && !strcasecmp(var, ivar)) {
1963 add_child = SWITCH_FALSE;
1964 break;
1965 }
1966 }
1967
1968 if (add_child) {
1969 iitag = switch_xml_add_child_d(itag, tag_name, 0);
1970 switch_xml_set_attr_d(iitag, "name", var);
1971 switch_xml_set_attr_d(iitag, "value", val);
1972 }
1973 }
1974 }
1975
1976}
1977
1978
1979SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_xml_merge_user(switch_xml_t user, switch_xml_t domain, switch_xml_t group)
1980{
1981 const char *domain_name = switch_xml_attr(domain, "name");
1982
1983 do_merge(user, group, "params", "param");
1984 do_merge(user, group, "variables", "variable");
1985 do_merge(user, group, "profile-variables", "variable");
1986 do_merge(user, domain, "params", "param");
1987 do_merge(user, domain, "variables", "variable");
1988 do_merge(user, domain, "profile-variables", "variable");
1989
1990 if (!zstr(domain_name)_zstr(domain_name)) {
1991 switch_xml_set_attr_d(user, "domain-name", domain_name);
1992 }
1993}
1994
1995SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_xml_clear_user_cache(const char *key, const char *user_name, const char *domain_name)
1996{
1997 switch_hash_index_t *hi = NULL((void*)0);
1998 void *val;
1999 const void *var;
2000 char mega_key[1024];
2001 int r = 0;
2002 switch_xml_t lookup;
2003 char *expires_val = NULL((void*)0);
2004
2005 switch_mutex_lock(CACHE_MUTEX);
2006
2007 if (key && user_name && domain_name) {
2008 switch_snprintf(mega_key, sizeof(mega_key), "%s%s%s", key, user_name, domain_name);
2009
2010 if ((lookup = switch_core_hash_find(CACHE_HASH, mega_key))) {
2011 switch_core_hash_delete(CACHE_HASH, mega_key);
2012 if ((expires_val = switch_core_hash_find(CACHE_EXPIRES_HASH, mega_key))) {
2013 switch_core_hash_delete(CACHE_EXPIRES_HASH, mega_key);
2014 free(expires_val);
2015 expires_val = NULL((void*)0);
2016 }
2017 switch_xml_free(lookup);
2018 r++;
2019 }
2020
2021 } else {
2022
2023 while ((hi = switch_core_hash_first_iter( CACHE_HASH, hi))) {
2024 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
2025 switch_xml_free(val);
2026 switch_core_hash_delete(CACHE_HASH, var);
2027 r++;
2028 }
2029
2030 while ((hi = switch_core_hash_first_iter( CACHE_EXPIRES_HASH, hi))) {
2031 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
2032 switch_safe_free(val)if (val) {free(val);val=((void*)0);};
2033 switch_core_hash_delete(CACHE_EXPIRES_HASH, var);
2034 }
2035
2036 switch_safe_free(hi)if (hi) {free(hi);hi=((void*)0);};
2037 }
2038
2039 switch_mutex_unlock(CACHE_MUTEX);
2040
2041 return r;
2042
2043}
2044
2045static switch_status_t switch_xml_locate_user_cache(const char *key, const char *user_name, const char *domain_name, switch_xml_t *user)
2046{
2047 char mega_key[1024];
2048 switch_status_t status = SWITCH_STATUS_FALSE;
2049 switch_xml_t lookup;
2050
2051 switch_snprintf(mega_key, sizeof(mega_key), "%s%s%s", key, user_name, domain_name);
2052
2053 switch_mutex_lock(CACHE_MUTEX);
2054 if ((lookup = switch_core_hash_find(CACHE_HASH, mega_key))) {
2055 char *expires_lookup = NULL((void*)0);
2056
2057 if ((expires_lookup = switch_core_hash_find(CACHE_EXPIRES_HASH, mega_key))) {
2058 switch_time_t time_expires = 0;
2059 switch_time_t time_now = 0;
2060
2061 time_now = switch_micro_time_now();
2062 time_expires = atol(expires_lookup);
2063 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2063, ((void*)0)
, SWITCH_LOG_DEBUG, "Cache Info\nTime Now:\t%ld\nExpires:\t%ld\n", (long)time_now, (long)time_expires);
2064 if (time_expires < time_now) {
2065 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2065, ((void*)0)
, SWITCH_LOG_DEBUG, "Cache expired for %s@%s, doing fresh lookup\n", user_name, domain_name);
2066 } else {
2067 *user = switch_xml_dup(lookup);
2068 status = SWITCH_STATUS_SUCCESS;
2069 }
2070 } else {
2071 *user = switch_xml_dup(lookup);
2072 status = SWITCH_STATUS_SUCCESS;
2073 }
2074 }
2075 switch_mutex_unlock(CACHE_MUTEX);
2076
2077 return status;
2078}
2079
2080static void switch_xml_user_cache(const char *key, const char *user_name, const char *domain_name, switch_xml_t user, switch_time_t expires)
2081{
2082 char mega_key[1024];
2083 switch_xml_t lookup;
2084 char *expires_lookup;
2085
2086 switch_snprintf(mega_key, sizeof(mega_key), "%s%s%s", key, user_name, domain_name);
2087
2088 switch_mutex_lock(CACHE_MUTEX);
2089 if ((lookup = switch_core_hash_find(CACHE_HASH, mega_key))) {
11
Assuming 'lookup' is null
12
Taking false branch
2090 switch_core_hash_delete(CACHE_HASH, mega_key);
2091 switch_xml_free(lookup);
2092 }
2093 if ((expires_lookup = switch_core_hash_find(CACHE_EXPIRES_HASH, mega_key))) {
13
Assuming 'expires_lookup' is null
14
Taking false branch
2094 switch_core_hash_delete(CACHE_EXPIRES_HASH, mega_key);
2095 switch_safe_free(expires_lookup)if (expires_lookup) {free(expires_lookup);expires_lookup=((void
*)0);}
;
2096 }
2097 if (expires) {
15
Assuming 'expires' is not equal to 0
16
Taking true branch
2098 char *expires_val = switch_must_malloc(1024);
17
Calling 'switch_must_malloc'
20
Returned allocated memory
2099 if (sprintf(expires_val, "%ld", (long)expires)) {
21
Assuming the condition is true
22
Taking true branch
2100 switch_core_hash_insert(CACHE_EXPIRES_HASH, mega_key, expires_val)switch_core_hash_insert_destructor(CACHE_EXPIRES_HASH, mega_key
, expires_val, ((void*)0))
;
2101 } else {
2102 switch_safe_free(expires_val)if (expires_val) {free(expires_val);expires_val=((void*)0);};
2103 }
2104 }
2105 switch_core_hash_insert(CACHE_HASH, mega_key, switch_xml_dup(user))switch_core_hash_insert_destructor(CACHE_HASH, mega_key, switch_xml_dup
(user), ((void*)0))
;
23
Within the expansion of the macro 'switch_core_hash_insert':
a
Potential leak of memory pointed to by 'expires_val'
2106 switch_mutex_unlock(CACHE_MUTEX);
2107}
2108
2109SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate_user_merged(const char *key, const char *user_name, const char *domain_name,
2110 const char *ip, switch_xml_t *user, switch_event_t *params)
2111{
2112 switch_xml_t xml, domain, group, x_user, x_user_dup;
2113 switch_status_t status = SWITCH_STATUS_FALSE;
2114 char *kdup = NULL((void*)0);
2115 char *keys[10] = {0};
2116 int i, nkeys;
2117
2118 if (strchr(key, ':')) {
1
Assuming the condition is false
2
Taking false branch
2119 kdup = switch_must_strdup(key);
2120 nkeys = switch_split(kdup, ':', keys)switch_separate_string(kdup, ':', keys, (sizeof(keys) / sizeof
(keys[0])))
;
2121 } else {
2122 keys[0] = (char *)key;
2123 nkeys = 1;
2124 }
2125
2126 for(i = 0; i < nkeys; i++) {
3
Loop condition is true. Entering loop body
2127 if ((status = switch_xml_locate_user_cache(keys[i], user_name, domain_name, &x_user)) == SWITCH_STATUS_SUCCESS) {
4
Taking false branch
2128 *user = x_user;
2129 break;
2130 } else if ((status = switch_xml_locate_user(keys[i], user_name, domain_name, ip, &xml, &domain, &x_user, &group, params)) == SWITCH_STATUS_SUCCESS) {
5
Assuming the condition is true
6
Taking true branch
2131 const char *cacheable = NULL((void*)0);
2132
2133 x_user_dup = switch_xml_dup(x_user);
2134 switch_xml_merge_user(x_user_dup, domain, group);
2135
2136 cacheable = switch_xml_attr(x_user_dup, "cacheable");
2137 if (!zstr(cacheable)_zstr(cacheable)) {
7
Taking true branch
2138 switch_time_t expires = 0;
2139 switch_time_t time_now = 0;
2140
2141 if (switch_is_number(cacheable)) {
8
Assuming the condition is true
9
Taking true branch
2142 int cache_ms = atol(cacheable);
2143 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2143, ((void*)0)
, SWITCH_LOG_DEBUG, "caching lookup for user %s@%s for %d milliseconds\n",
2144 user_name, domain_name, cache_ms);
2145 time_now = switch_micro_time_now();
2146 expires = time_now + (cache_ms * 1000);
2147 } else {
2148 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2148, ((void*)0)
, SWITCH_LOG_DEBUG, "caching lookup for user %s@%s indefinitely\n", user_name, domain_name);
2149 }
2150 switch_xml_user_cache(keys[i], user_name, domain_name, x_user_dup, expires);
10
Calling 'switch_xml_user_cache'
2151 }
2152 *user = x_user_dup;
2153 switch_xml_free(xml);
2154 break;
2155 }
2156 }
2157
2158 switch_safe_free(kdup)if (kdup) {free(kdup);kdup=((void*)0);};
2159
2160 return status;
2161
2162}
2163
2164SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate_user(const char *key,
2165 const char *user_name,
2166 const char *domain_name,
2167 const char *ip,
2168 switch_xml_t *root,
2169 switch_xml_t *domain, switch_xml_t *user, switch_xml_t *ingroup, switch_event_t *params)
2170{
2171 switch_status_t status = SWITCH_STATUS_FALSE;
2172 switch_event_t *my_params = NULL((void*)0);
2173 switch_xml_t group = NULL((void*)0), groups = NULL((void*)0), users = NULL((void*)0);
2174
2175 *root = NULL((void*)0);
2176 *user = NULL((void*)0);
2177 *domain = NULL((void*)0);
2178
2179 if (ingroup) {
2180 *ingroup = NULL((void*)0);
2181 }
2182
2183 if (!params) {
2184 switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("src/switch_xml.c", (const
char * )(const char *)__func__, 2184, &my_params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
2185 switch_assert(my_params)((my_params) ? (void) (0) : __assert_fail ("my_params", "src/switch_xml.c"
, 2185, __extension__ __PRETTY_FUNCTION__))
;
2186 params = my_params;
2187 }
2188
2189 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "key", key);
2190
2191 if (user_name) {
2192 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "user", user_name);
2193 }
2194
2195 if (domain_name) {
2196 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain_name);
2197 }
2198
2199 if (ip) {
2200 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "ip", ip);
2201 }
2202
2203 if ((status = switch_xml_locate_domain(domain_name, params, root, domain)) != SWITCH_STATUS_SUCCESS) {
2204 goto end;
2205 }
2206
2207 status = SWITCH_STATUS_FALSE;
2208
2209 if ((groups = switch_xml_child(*domain, "groups"))) {
2210 for (group = switch_xml_child(groups, "group"); group; group = group->next) {
2211 if ((users = switch_xml_child(group, "users"))) {
2212 if ((status = find_user_in_tag(users, ip, user_name, key, params, user)) == SWITCH_STATUS_SUCCESS) {
2213 if (ingroup) {
2214 *ingroup = group;
2215 }
2216 break;
2217 }
2218 }
2219 }
2220 }
2221
2222 if (status != SWITCH_STATUS_SUCCESS) {
2223 if ((users = switch_xml_child(*domain, "users"))) {
2224 status = find_user_in_tag(users, ip, user_name, key, params, user);
2225 } else {
2226 status = find_user_in_tag(*domain, ip, user_name, key, params, user);
2227 }
2228 }
2229
2230 end:
2231
2232 if (my_params) {
2233 switch_event_destroy(&my_params);
2234 }
2235
2236 if (status != SWITCH_STATUS_SUCCESS && root && *root) {
2237 switch_xml_free(*root);
2238 *root = NULL((void*)0);
2239 *domain = NULL((void*)0);
2240 }
2241
2242 return status;
2243}
2244
2245SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_root(void)
2246{
2247 switch_xml_t xml;
2248
2249 switch_mutex_lock(REFLOCK);
2250 xml = MAIN_XML_ROOT;
2251 xml->refs++;
2252 switch_mutex_unlock(REFLOCK);
2253
2254 return xml;
2255}
2256
2257struct destroy_xml {
2258 switch_xml_t xml;
2259 switch_memory_pool_t *pool;
2260};
2261
2262static void *SWITCH_THREAD_FUNC destroy_thread(switch_thread_t *thread, void *obj)
2263{
2264 struct destroy_xml *dx = (struct destroy_xml *) obj;
2265 switch_memory_pool_t *pool = dx->pool;
2266 switch_xml_free(dx->xml);
2267 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_xml.c"
, (const char *)__func__, 2267)
;
2268 return NULL((void*)0);
2269}
2270
2271SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_xml_free_in_thread(switch_xml_t xml, int stacksize)
2272{
2273 switch_thread_t *thread;
2274 switch_threadattr_t *thd_attr;
2275 switch_memory_pool_t *pool = NULL((void*)0);
2276 struct destroy_xml *dx;
2277
2278 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "src/switch_xml.c"
, (const char *)__func__, 2278)
;
2279
2280 switch_threadattr_create(&thd_attr, pool);
2281 switch_threadattr_detach_set(thd_attr, 1);
2282 /* TBD figure out how much space we need by looking at the xml_t when stacksize == 0 */
2283 switch_threadattr_stacksize_set(thd_attr, stacksize);
2284
2285 dx = switch_core_alloc(pool, sizeof(*dx))switch_core_perform_alloc(pool, sizeof(*dx), "src/switch_xml.c"
, (const char *)__func__, 2285)
;
2286 dx->pool = pool;
2287 dx->xml = xml;
2288
2289 switch_thread_create(&thread, thd_attr, destroy_thread, dx, pool);
2290}
2291
2292static char not_so_threadsafe_error_buffer[256] = "";
2293
2294SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_set_root(switch_xml_t new_main)
2295{
2296 switch_xml_t old_root = NULL((void*)0);
2297
2298 switch_mutex_lock(REFLOCK);
2299
2300 old_root = MAIN_XML_ROOT;
2301 MAIN_XML_ROOT = new_main;
2302 switch_set_flag(MAIN_XML_ROOT, SWITCH_XML_ROOT)(MAIN_XML_ROOT)->flags |= (SWITCH_XML_ROOT);
2303 MAIN_XML_ROOT->refs++;
2304
2305 if (old_root) {
2306 if (old_root->refs) {
2307 old_root->refs--;
2308 }
2309
2310 if (!old_root->refs) {
2311 switch_xml_free(old_root);
2312 }
2313 }
2314
2315 switch_mutex_unlock(REFLOCK);
2316
2317 return SWITCH_STATUS_SUCCESS;
2318}
2319
2320SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_set_open_root_function(switch_xml_open_root_function_t func, void *user_data)
2321{
2322 if (XML_LOCK) {
2323 switch_mutex_lock(XML_LOCK);
2324 }
2325
2326 XML_OPEN_ROOT_FUNCTION = func;
2327 XML_OPEN_ROOT_FUNCTION_USER_DATA = user_data;
2328
2329 if (XML_LOCK) {
2330 switch_mutex_unlock(XML_LOCK);
2331 }
2332 return SWITCH_STATUS_SUCCESS;
2333}
2334
2335SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_open_root(uint8_t reload, const char **err)
2336{
2337 switch_xml_t root = NULL((void*)0);
2338 switch_event_t *event;
2339
2340 switch_mutex_lock(XML_LOCK);
2341
2342 if (XML_OPEN_ROOT_FUNCTION) {
2343 root = XML_OPEN_ROOT_FUNCTION(reload, err, XML_OPEN_ROOT_FUNCTION_USER_DATA);
2344 }
2345 switch_mutex_unlock(XML_LOCK);
2346
2347
2348 if (root) {
2349 if (switch_event_create(&event, SWITCH_EVENT_RELOADXML)switch_event_create_subclass_detailed("src/switch_xml.c", (const
char * )(const char *)__func__, 2349, &event, SWITCH_EVENT_RELOADXML
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2350 if (switch_event_fire(&event)switch_event_fire_detailed("src/switch_xml.c", (const char * )
(const char *)__func__, 2350, &event, ((void*)0))
!= SWITCH_STATUS_SUCCESS) {
2351 switch_event_destroy(&event);
2352 }
2353 }
2354 }
2355
2356 return root;
2357}
2358
2359SWITCH_DECLARE_NONSTD(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t __switch_xml_open_root(uint8_t reload, const char **err, void *user_data)
2360{
2361 char path_buf[1024];
2362 uint8_t errcnt = 0;
2363 switch_xml_t new_main, r = NULL((void*)0);
2364
2365 if (MAIN_XML_ROOT) {
2366 if (!reload) {
2367 r = switch_xml_root();
2368 goto done;
2369 }
2370 }
2371
2372 switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR"/", SWITCH_GLOBAL_filenames.conf_name);
2373 if ((new_main = switch_xml_parse_file(path_buf))) {
2374 *err = switch_xml_error(new_main);
2375 switch_copy_string(not_so_threadsafe_error_buffer, *err, sizeof(not_so_threadsafe_error_buffer));
2376 *err = not_so_threadsafe_error_buffer;
2377 if (!zstr(*err)_zstr(*err)) {
2378 switch_xml_free(new_main);
2379 new_main = NULL((void*)0);
2380 errcnt++;
2381 } else {
2382 *err = "Success";
2383 switch_xml_set_root(new_main);
2384
2385 }
2386 } else {
2387 *err = "Cannot Open log directory or XML Root!";
2388 errcnt++;
2389 }
2390
2391 if (errcnt == 0) {
2392 r = switch_xml_root();
2393 }
2394
2395 done:
2396
2397 return r;
2398}
2399
2400SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_reload(const char **err)
2401{
2402 switch_xml_t xml_root;
2403
2404 if ((xml_root = switch_xml_open_root(1, err))) {
2405 switch_xml_free(xml_root);
2406 return SWITCH_STATUS_SUCCESS;
2407 }
2408
2409 return SWITCH_STATUS_GENERR;
2410}
2411
2412SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_init(switch_memory_pool_t *pool, const char **err)
2413{
2414 switch_xml_t xml;
2415 XML_MEMORY_POOL = pool;
2416 *err = "Success";
2417
2418 switch_mutex_init(&CACHE_MUTEX, SWITCH_MUTEX_NESTED0x1, XML_MEMORY_POOL);
2419 switch_mutex_init(&XML_LOCK, SWITCH_MUTEX_NESTED0x1, XML_MEMORY_POOL);
2420 switch_mutex_init(&REFLOCK, SWITCH_MUTEX_NESTED0x1, XML_MEMORY_POOL);
2421 switch_mutex_init(&FILE_LOCK, SWITCH_MUTEX_NESTED0x1, XML_MEMORY_POOL);
2422 switch_core_hash_init(&CACHE_HASH)switch_core_hash_init_case(&CACHE_HASH, SWITCH_TRUE);
2423 switch_core_hash_init(&CACHE_EXPIRES_HASH)switch_core_hash_init_case(&CACHE_EXPIRES_HASH, SWITCH_TRUE
)
;
2424
2425 switch_thread_rwlock_create(&B_RWLOCK, XML_MEMORY_POOL);
2426
2427 assert(pool != NULL)((pool != ((void*)0)) ? (void) (0) : __assert_fail ("pool != NULL"
, "src/switch_xml.c", 2427, __extension__ __PRETTY_FUNCTION__
))
;
2428
2429 if ((xml = switch_xml_open_root(FALSE0, err))) {
2430 switch_xml_free(xml);
2431 return SWITCH_STATUS_SUCCESS;
2432 } else {
2433 return SWITCH_STATUS_FALSE;
2434 }
2435}
2436
2437SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_destroy(void)
2438{
2439 switch_status_t status = SWITCH_STATUS_FALSE;
2440
2441
2442 switch_mutex_lock(XML_LOCK);
2443 switch_mutex_lock(REFLOCK);
2444
2445 if (MAIN_XML_ROOT) {
2446 switch_xml_t xml = MAIN_XML_ROOT;
2447 MAIN_XML_ROOT = NULL((void*)0);
2448 switch_xml_free(xml);
2449 status = SWITCH_STATUS_SUCCESS;
2450 }
2451
2452 switch_mutex_unlock(XML_LOCK);
2453 switch_mutex_unlock(REFLOCK);
2454
2455 switch_xml_clear_user_cache(NULL((void*)0), NULL((void*)0), NULL((void*)0));
2456
2457 switch_core_hash_destroy(&CACHE_HASH);
2458 switch_core_hash_destroy(&CACHE_EXPIRES_HASH);
2459
2460 return status;
2461}
2462
2463SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_open_cfg(const char *file_path, switch_xml_t *node, switch_event_t *params)
2464{
2465 switch_xml_t xml = NULL((void*)0), cfg = NULL((void*)0);
2466
2467 *node = NULL((void*)0);
2468
2469 assert(MAIN_XML_ROOT != NULL)((MAIN_XML_ROOT != ((void*)0)) ? (void) (0) : __assert_fail (
"MAIN_XML_ROOT != NULL", "src/switch_xml.c", 2469, __extension__
__PRETTY_FUNCTION__))
;
2470
2471 if (switch_xml_locate("configuration", "configuration", "name", file_path, &xml, &cfg, params, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
2472 *node = cfg;
2473 }
2474
2475 return xml;
2476
2477}
2478
2479/* Encodes ampersand sequences appending the results to *dst, reallocating *dst
2480 if length exceeds max. a is non-zero for attribute encoding. Returns *dst */
2481static char *switch_xml_ampencode(const char *s, switch_size_t len, char **dst, switch_size_t *dlen, switch_size_t *max, short a, switch_bool_t use_utf8_encoding)
2482{
2483 const char *e = NULL((void*)0);
2484 int immune = 0;
2485 int expecting_x_utf_8_char = 0;
2486 int unicode_char = 0x000000;
2487
2488 if (!(s && *s))
2489 return *dst;
2490
2491 if (len) {
2492 e = s + len;
2493 }
2494
2495 while (s != e) {
2496 while (*dlen + 10 > *max) {
2497 *dst = (char *) switch_must_realloc(*dst, *max += SWITCH_XML_BUFSIZE1024);
2498 }
2499
2500 if (immune) {
2501 if (*s == '\0') {
2502 return *dst;
2503 }
2504 (*dst)[(*dlen)++] = *s;
2505 } else
2506 switch (*s) {
2507 case '\0':
2508 return *dst;
2509 case '&':
2510 *dlen += sprintf(*dst + *dlen, "&amp;");
2511 break;
2512 case '<':
2513 if (*(s + 1) == '!') {
2514 (*dst)[(*dlen)++] = *s;
2515 immune++;
2516 break;
2517 }
2518 *dlen += sprintf(*dst + *dlen, "&lt;");
2519 break;
2520 case '>':
2521 *dlen += sprintf(*dst + *dlen, "&gt;");
2522 break;
2523 case '"':
2524 *dlen += sprintf(*dst + *dlen, (a) ? "&quot;" : "\"");
2525 break;
2526 case '\n':
2527 *dlen += sprintf(*dst + *dlen, (a) ? "&#xA;" : "\n");
2528 break;
2529 case '\t':
2530 *dlen += sprintf(*dst + *dlen, (a) ? "&#x9;" : "\t");
2531 break;
2532 case '\r':
2533 *dlen += sprintf(*dst + *dlen, "&#xD;");
2534 break;
2535 default:
2536 if (use_utf8_encoding && expecting_x_utf_8_char == 0 && ((*s >> 8) & 0x01)) {
2537 int num = 1;
2538 for (;num<4;num++) {
2539 if (! ((*s >> (7-num)) & 0x01)) {
2540 break;
2541 }
2542 }
2543 switch (num) {
2544 case 2:
2545 unicode_char = *s & 0x1f;
2546 break;
2547 case 3:
2548 unicode_char = *s & 0x0f;
2549 break;
2550 case 4:
2551 unicode_char = *s & 0x07;
2552 break;
2553 default:
2554 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2554, ((void*)0)
, SWITCH_LOG_WARNING, "Invalid UTF-8 Initial charactere, skip it\n");
2555 /* ERROR HERE */
2556 break;
2557 }
2558 expecting_x_utf_8_char = num - 1;
2559
2560 } else if (use_utf8_encoding && expecting_x_utf_8_char > 0) {
2561 if (((*s >> 6) & 0x03) == 0x2) {
2562
2563 unicode_char = unicode_char << 6;
2564 unicode_char = unicode_char | (*s & 0x3f);
2565 } else {
2566 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2566, ((void*)0)
, SWITCH_LOG_WARNING, "Invalid UTF-8 character to ampersand, skip it\n");
2567 expecting_x_utf_8_char = 0;
2568 break;
2569 }
2570 expecting_x_utf_8_char--;
2571 if (expecting_x_utf_8_char == 0) {
2572 *dlen += sprintf(*dst + *dlen, "&#x%X;", unicode_char);
2573 }
2574 } else {
2575 (*dst)[(*dlen)++] = *s;
2576 }
2577 }
2578 s++;
2579 }
2580 return *dst;
2581}
2582
2583#define XML_INDENT" " " "
2584/* Recursively converts each tag to xml appending it to *s. Reallocates *s if
2585 its length exceeds max. start is the location of the previous tag in the
2586 parent tag's character content. Returns *s. */
2587static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len, switch_size_t *max, switch_size_t start, char ***attr, uint32_t *count, int isroot, switch_bool_t use_utf8_encoding)
2588{
2589 int i, j;
2590 char *txt;
2591 switch_size_t off;
2592 uint32_t lcount;
2593 uint32_t loops = 0;
2594
2595 tailrecurse:
2596 off = 0;
2597 txt = "";
2598
2599 if (loops++) {
2600 isroot = 0;
2601 }
2602
2603 if (!isroot && xml->parent) {
2604 txt = (char *) xml->parent->txt;
2605 }
2606
2607 /* parent character content up to this tag */
2608 *s = switch_xml_ampencode(txt + start, xml->off - start, s, len, max, 0, use_utf8_encoding);
2609
2610 while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT" ") * (*count)) + 1 > *max) { /* reallocate s */
2611 *s = (char *) switch_must_realloc(*s, *max += SWITCH_XML_BUFSIZE1024);
2612 }
2613
2614 if (*len && *(*s + (*len) - 1) == '>') {
2615 *len += sprintf(*s + *len, "\n"); /* indent */
2616 }
2617 for (lcount = 0; lcount < *count; lcount++) {
2618 *len += sprintf(*s + *len, "%s", XML_INDENT" "); /* indent */
2619 }
2620
2621 *len += sprintf(*s + *len, "<%s", xml->name); /* open tag */
2622 for (i = 0; xml->attr[i]; i += 2) { /* tag attributes */
2623 if (switch_xml_attr(xml, xml->attr[i]) != xml->attr[i + 1])
2624 continue;
2625 while (*len + strlen(xml->attr[i]) + 7 + (strlen(XML_INDENT" ") * (*count)) > *max) { /* reallocate s */
2626 *s = (char *) switch_must_realloc(*s, *max += SWITCH_XML_BUFSIZE1024);
2627 }
2628
2629 *len += sprintf(*s + *len, " %s=\"", xml->attr[i]);
2630 switch_xml_ampencode(xml->attr[i + 1], 0, s, len, max, 1, use_utf8_encoding);
2631 *len += sprintf(*s + *len, "\"");
2632 }
2633
2634 for (i = 0; attr[i] && strcmp(attr[i][0], xml->name); i++);
2635 for (j = 1; attr[i] && attr[i][j]; j += 3) { /* default attributes */
2636 if (!attr[i][j + 1] || switch_xml_attr(xml, attr[i][j]) != attr[i][j + 1])
2637 continue; /* skip duplicates and non-values */
2638 while (*len + strlen(attr[i][j]) + 8 + (strlen(XML_INDENT" ") * (*count)) > *max) { /* reallocate s */
2639 *s = (char *) switch_must_realloc(*s, *max += SWITCH_XML_BUFSIZE1024);
2640 }
2641
2642 *len += sprintf(*s + *len, " %s=\"", attr[i][j]);
2643 switch_xml_ampencode(attr[i][j + 1], 0, s, len, max, 1, use_utf8_encoding);
2644 *len += sprintf(*s + *len, "\"");
2645 }
2646
2647 *len += sprintf(*s + *len, (xml->child || xml->txt) ? ">" : "/>\n");
2648
2649 if (xml->child) {
2650 (*count)++;
2651 *s = switch_xml_toxml_r(xml->child, s, len, max, 0, attr, count, 0, use_utf8_encoding);
2652
2653 } else {
2654 *s = switch_xml_ampencode(xml->txt, 0, s, len, max, 0, use_utf8_encoding); /* data */
2655 }
2656
2657 while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT" ") * (*count)) > *max) { /* reallocate s */
2658 *s = (char *) switch_must_realloc(*s, *max += SWITCH_XML_BUFSIZE1024);
2659 }
2660
2661 if (xml->child || xml->txt) {
2662 if (*(*s + (*len) - 1) == '\n') {
2663 for (lcount = 0; lcount < *count; lcount++) {
2664 *len += sprintf(*s + *len, "%s", XML_INDENT" "); /* indent */
2665 }
2666 }
2667 *len += sprintf(*s + (*len), "</%s>\n", xml->name); /* close tag */
2668 }
2669
2670 while (txt[off] && off < xml->off)
2671 off++; /* make sure off is within bounds */
2672
2673 if (!isroot && xml->ordered) {
2674 xml = xml->ordered;
2675 start = off;
2676 goto tailrecurse;
2677/*
2678 return switch_xml_toxml_r(xml->ordered, s, len, max, off, attr, count, use_utf8_encoding);
2679*/
2680 } else {
2681 if (*count > 0)
2682 (*count)--;
2683 return switch_xml_ampencode(txt + off, 0, s, len, max, 0, use_utf8_encoding);
2684 }
2685}
2686
2687SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_xml_toxml_nolock_ex(switch_xml_t xml, switch_bool_t prn_header, switch_bool_t use_utf8_encoding)
2688{
2689 char *s = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
2690
2691 return switch_xml_toxml_buf_ex(xml, s, SWITCH_XML_BUFSIZE1024, 0, prn_header, use_utf8_encoding);
2692}
2693
2694SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_xml_toxml_ex(switch_xml_t xml, switch_bool_t prn_header, switch_bool_t use_utf8_encoding)
2695{
2696 char *r, *s;
2697
2698 s = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
2699
2700 r = switch_xml_toxml_buf_ex(xml, s, SWITCH_XML_BUFSIZE1024, 0, prn_header, use_utf8_encoding);
2701
2702 return r;
2703}
2704
2705SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_xml_tohtml_ex(switch_xml_t xml, switch_bool_t prn_header, switch_bool_t use_utf8_encoding)
2706{
2707 char *r, *s, *h;
2708 switch_size_t rlen = 0;
2709 switch_size_t len = SWITCH_XML_BUFSIZE1024;
2710
2711 s = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
2712 h = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
2713
2714 r = switch_xml_toxml_buf_ex(xml, s, SWITCH_XML_BUFSIZE1024, 0, prn_header, use_utf8_encoding);
2715 h = switch_xml_ampencode(r, 0, &h, &rlen, &len, 1, use_utf8_encoding);
2716 switch_safe_free(r)if (r) {free(r);r=((void*)0);};
2717 return h;
2718}
2719
2720/* converts a switch_xml structure back to xml, returning a string of xml data that
2721 must be freed */
2722SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_xml_toxml_buf_ex(switch_xml_t xml, char *buf, switch_size_t buflen, switch_size_t offset, switch_bool_t prn_header, switch_bool_t use_utf8_encoding)
2723{
2724 switch_xml_t p = (xml) ? xml->parent : NULL((void*)0);
2725 switch_xml_root_t root = (switch_xml_root_t) xml;
2726 switch_size_t len = 0, max = buflen;
2727 char *s, *t, *n;
2728 int i, j, k;
2729 uint32_t count = 0;
2730
2731 s = buf;
2732 assert(s != NULL)((s != ((void*)0)) ? (void) (0) : __assert_fail ("s != NULL",
"src/switch_xml.c", 2732, __extension__ __PRETTY_FUNCTION__)
)
;
2733 memset(s, 0, max);
2734 len += offset;
2735 if (prn_header) {
2736 len += sprintf(s + len, "<?xml version=\"1.0\"?>\n");
2737 }
2738
2739 if (!xml || !xml->name) {
2740 return (char *) switch_must_realloc(s, len + 1);
2741 }
2742
2743 while (root->xml.parent) {
2744 root = (switch_xml_root_t) root->xml.parent; /* root tag */
2745 }
2746
2747 for (i = 0; !p && root->pi[i]; i++) { /* pre-root processing instructions */
2748 for (k = 2; root->pi[i][k - 1]; k++);
2749 for (j = 1; (n = root->pi[i][j]); j++) {
2750 if (root->pi[i][k][j - 1] == '>') {
2751 continue; /* not pre-root */
2752 }
2753 while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max) {
2754 s = (char *) switch_must_realloc(s, max += SWITCH_XML_BUFSIZE1024);
2755 }
2756 len += sprintf(s + len, "<?%s%s%s?>", t, *n ? " " : "", n);
2757 }
2758 }
2759
2760 s = switch_xml_toxml_r(xml, &s, &len, &max, 0, root->attr, &count, 1, use_utf8_encoding);
2761
2762 for (i = 0; !p && root->pi[i]; i++) { /* post-root processing instructions */
2763 for (k = 2; root->pi[i][k - 1]; k++);
2764 for (j = 1; (n = root->pi[i][j]); j++) {
2765 if (root->pi[i][k][j - 1] == '<') {
2766 continue; /* not post-root */
2767 }
2768 while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max) {
2769 s = (char *) switch_must_realloc(s, max += SWITCH_XML_BUFSIZE1024);
2770 }
2771 len += sprintf(s + len, "\n<?%s%s%s?>", t, *n ? " " : "", n);
2772 }
2773 }
2774
2775 return (char *) switch_must_realloc(s, len + 1);
2776}
2777
2778/* free the memory allocated for the switch_xml structure */
2779SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_xml_free(switch_xml_t xml)
2780{
2781 switch_xml_root_t root;
2782 int i, j;
2783 char **a, *s;
2784 switch_xml_t orig_xml;
2785 int refs = 0;
2786
2787 tailrecurse:
2788 root = (switch_xml_root_t) xml;
2789 if (!xml) {
2790 return;
2791 }
2792
2793 if (switch_test_flag(xml, SWITCH_XML_ROOT)((xml)->flags & SWITCH_XML_ROOT)) {
2794 switch_mutex_lock(REFLOCK);
2795
2796 if (xml->refs) {
2797 xml->refs--;
2798 refs = xml->refs;
2799 }
2800 switch_mutex_unlock(REFLOCK);
2801 }
2802
2803 if (refs) {
2804 return;
2805 }
2806
2807 if (xml->free_path) {
2808 if (unlink(xml->free_path) != 0) {
2809 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2809, ((void*)0)
, SWITCH_LOG_WARNING, "Failed to delete file [%s]\n", xml->free_path);
2810 }
2811 switch_safe_free(xml->free_path)if (xml->free_path) {free(xml->free_path);xml->free_path
=((void*)0);}
;
2812 }
2813
2814 switch_xml_free(xml->child);
2815 /*switch_xml_free(xml->ordered); */
2816
2817 if (!xml->parent) { /* free root tag allocations */
2818#if (_MSC_VER >= 1400) // VC8+
2819 __analysis_assume(sizeof(root->ent) > 44); /* tail recursion confuses code analysis */
2820#endif
2821 for (i = 10; root->ent[i]; i += 2) /* 0 - 9 are default entities (<>&"') */
2822 if ((s = root->ent[i + 1]) < root->s || s > root->e)
2823 free(s);
2824 free(root->ent); /* free list of general entities */
2825
2826 for (i = 0; (a = root->attr[i]); i++) {
2827 for (j = 1; a[j++]; j += 2) /* free malloced attribute values */
2828 if (a[j] && (a[j] < root->s || a[j] > root->e))
2829 free(a[j]);
2830 free(a);
2831 }
2832 if (root->attr[0])
2833 free(root->attr); /* free default attribute list */
2834
2835 for (i = 0; root->pi[i]; i++) {
2836 for (j = 1; root->pi[i][j]; j++);
2837 free(root->pi[i][j + 1]);
2838 free(root->pi[i]);
2839 }
2840 if (root->pi[0])
2841 free(root->pi); /* free processing instructions */
2842
2843 if (root->dynamic == 1)
2844 free(root->m); /* malloced xml data */
2845 if (root->u)
2846 free(root->u); /* utf8 conversion */
2847 }
2848
2849 switch_xml_free_attr(xml->attr); /* tag attributes */
2850 if ((xml->flags & SWITCH_XML_TXTM))
2851 free(xml->txt); /* character content */
2852 if ((xml->flags & SWITCH_XML_NAMEM))
2853 free(xml->name); /* tag name */
2854 if (xml->ordered) {
2855 orig_xml = xml;
2856 xml = xml->ordered;
2857 free(orig_xml);
2858 goto tailrecurse;
2859 }
2860 free(xml);
2861}
2862
2863/* return parser error message or empty string if none */
2864SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_xml_error(switch_xml_t xml)
2865{
2866 while (xml && xml->parent)
2867 xml = xml->parent; /* find root tag */
2868 return (xml) ? ((switch_xml_root_t) xml)->err : "";
2869}
2870
2871/* returns a new empty switch_xml structure with the given root tag name */
2872SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_new(const char *name)
2873{
2874 static const char *ent[] = { "lt;", "&#60;", "gt;", "&#62;", "quot;", "&#34;",
2875 "apos;", "&#39;", "amp;", "&#38;", NULL((void*)0)
2876 };
2877 switch_xml_root_t root = (switch_xml_root_t) switch_must_malloc(sizeof(struct switch_xml_root));
2878
2879 memset(root, '\0', sizeof(struct switch_xml_root));
2880 root->xml.name = (char *) name;
2881 root->cur = &root->xml;
2882 strcpy(root->err, root->xml.txt = (char *) "");
2883 root->ent = (char **) memcpy(switch_must_malloc(sizeof(ent)), ent, sizeof(ent));
2884 root->attr = root->pi = (char ***) (root->xml.attr = SWITCH_XML_NIL);
2885 return &root->xml;
2886}
2887
2888/* inserts an existing tag into a switch_xml structure */
2889SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_insert(switch_xml_t xml, switch_xml_t dest, switch_size_t off)
2890{
2891 switch_xml_t cur, prev, head;
2892
2893 xml->next = xml->sibling = xml->ordered = NULL((void*)0);
2894 xml->off = off;
2895 xml->parent = dest;
2896
2897 if ((head = dest->child)) { /* already have sub tags */
2898 if (head->off <= off) { /* not first subtag */
2899 for (cur = head; cur->ordered && cur->ordered->off <= off; cur = cur->ordered);
2900 xml->ordered = cur->ordered;
2901 cur->ordered = xml;
2902 } else { /* first subtag */
2903 xml->ordered = head;
2904 dest->child = xml;
2905 }
2906
2907 for (cur = head, prev = NULL((void*)0); cur && strcmp(cur->name, xml->name); prev = cur, cur = cur->sibling); /* find tag type */
2908 if (cur && cur->off <= off) { /* not first of type */
2909 while (cur->next && cur->next->off <= off)
2910 cur = cur->next;
2911 xml->next = cur->next;
2912 cur->next = xml;
2913 } else { /* first tag of this type */
2914 if (prev && cur)
2915 prev->sibling = cur->sibling; /* remove old first */
2916 xml->next = cur; /* old first tag is now next */
2917 for (cur = head, prev = NULL((void*)0); cur && cur->off <= off; prev = cur, cur = cur->sibling); /* new sibling insert point */
2918 xml->sibling = cur;
2919 if (prev)
2920 prev->sibling = xml;
2921 }
2922 } else
2923 dest->child = xml; /* only sub tag */
2924
2925 return xml;
2926}
2927
2928/* Adds a child tag. off is the offset of the child tag relative to the start
2929 of the parent tag's character content. Returns the child tag */
2930SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_add_child(switch_xml_t xml, const char *name, switch_size_t off)
2931{
2932 switch_xml_t child;
2933
2934 if (!xml)
2935 return NULL((void*)0);
2936 child = (switch_xml_t) switch_must_malloc(sizeof(struct switch_xml));
2937
2938 memset(child, '\0', sizeof(struct switch_xml));
2939 child->name = (char *) name;
2940 child->attr = SWITCH_XML_NIL;
2941 child->off = off;
2942 child->parent = xml;
2943 child->txt = (char *) "";
2944
2945 return switch_xml_insert(child, xml, off);
2946}
2947
2948/* Adds a child tag. off is the offset of the child tag relative to the start
2949 of the parent tag's character content. Returns the child tag */
2950SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_add_child_d(switch_xml_t xml, const char *name, switch_size_t off)
2951{
2952 if (!xml) return NULL((void*)0);
2953 return switch_xml_set_flag(switch_xml_add_child(xml, strdup(name), off), SWITCH_XML_NAMEM);
2954}
2955
2956/* sets the character content for the given tag and returns the tag */
2957SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_txt(switch_xml_t xml, const char *txt)
2958{
2959 if (!xml)
2960 return NULL((void*)0);
2961 if (xml->flags & SWITCH_XML_TXTM)
2962 free(xml->txt); /* existing txt was malloced */
2963 xml->flags &= ~SWITCH_XML_TXTM;
2964 xml->txt = (char *) txt;
2965 return xml;
2966}
2967
2968/* sets the character content for the given tag and returns the tag */
2969SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_txt_d(switch_xml_t xml, const char *txt)
2970{
2971 if (!xml) return NULL((void*)0);
2972 return switch_xml_set_flag(switch_xml_set_txt(xml, strdup(txt)), SWITCH_XML_TXTM);
2973}
2974
2975/* Sets the given tag attribute or adds a new attribute if not found. A value
2976 of NULL will remove the specified attribute. Returns the tag given */
2977SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_attr(switch_xml_t xml, const char *name, const char *value)
2978{
2979 int l = 0, c;
2980
2981 if (!xml)
2982 return NULL((void*)0);
2983 while (xml->attr[l] && strcmp(xml->attr[l], name))
2984 l += 2;
2985 if (!xml->attr[l]) { /* not found, add as new attribute */
2986 if (!value)
2987 return xml; /* nothing to do */
2988 if (xml->attr == SWITCH_XML_NIL) { /* first attribute */
2989 xml->attr = (char **) switch_must_malloc(4 * sizeof(char *));
2990 xml->attr[l + 1] = switch_must_strdup(""); /* empty list of malloced names/vals */
2991 } else {
2992 xml->attr = (char **) switch_must_realloc(xml->attr, (l + 4) * sizeof(char *));
2993 }
2994
2995 xml->attr[l] = (char *) name; /* set attribute name */
2996 xml->attr[l + 2] = NULL((void*)0); /* null terminate attribute list */
2997 xml->attr[l + 3] = (char *) switch_must_realloc(xml->attr[l + 1], (c = (int) strlen(xml->attr[l + 1])) + 2);
2998 strcpy(xml->attr[l + 3] + c, " "); /* set name/value as not malloced */
2999 if (xml->flags & SWITCH_XML_DUP)
3000 xml->attr[l + 3][c] = SWITCH_XML_NAMEM;
3001 c = l + 2; /* end of attribute list */
3002 } else {
3003 for (c = l; xml->attr[c]; c += 2); /* find end of attribute list */
3004
3005 if (xml->flags & SWITCH_XML_DUP)
3006 free((char*)name); /* name was strduped */
3007 if (xml->attr[c + 1][l / 2] & SWITCH_XML_TXTM)
3008 free(xml->attr[l + 1]); /* old val */
3009 }
3010
3011 if (xml->flags & SWITCH_XML_DUP)
3012 xml->attr[c + 1][l / 2] |= SWITCH_XML_TXTM;
3013 else
3014 xml->attr[c + 1][l / 2] &= ~SWITCH_XML_TXTM;
3015
3016 if (value)
3017 xml->attr[l + 1] = (char *) value; /* set attribute value */
3018 else { /* remove attribute */
3019 if (xml->attr[c + 1][l / 2] & SWITCH_XML_NAMEM)
3020 free(xml->attr[l]);
3021 c -= 2;
3022 if (c > 0) {
3023 memmove(xml->attr + l, xml->attr + l + 2, (c - l + 2) * sizeof(char*));
3024 xml->attr = (char**)switch_must_realloc(xml->attr, (c + 2) * sizeof(char*));
3025 memmove(xml->attr[c + 1] + (l / 2), xml->attr[c + 1] + (l / 2) + 1, (c / 2) - (l / 2)); /* fix list of which name/vals are malloced */
3026 xml->attr[c + 1][c / 2] = '\0';
3027 } else {
3028 /* last attribute removed, reset attribute list */
3029 free(xml->attr[3]);
3030 free(xml->attr);
3031 xml->attr = SWITCH_XML_NIL;
3032 }
3033 }
3034 xml->flags &= ~SWITCH_XML_DUP; /* clear strdup() flag */
3035
3036 return xml;
3037}
3038
3039/* Sets the given tag attribute or adds a new attribute if not found. A value
3040 of NULL will remove the specified attribute. Returns the tag given */
3041SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_attr_d(switch_xml_t xml, const char *name, const char *value)
3042{
3043 if (!xml) return NULL((void*)0);
3044 return switch_xml_set_attr(switch_xml_set_flag(xml, SWITCH_XML_DUP), strdup(name), strdup(switch_str_nil(value)(value ? value : "")));
3045}
3046
3047/* Sets the given tag attribute or adds a new attribute if not found. A value
3048 of NULL will remove the specified attribute. Returns the tag given */
3049SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_attr_d_buf(switch_xml_t xml, const char *name, const char *value)
3050{
3051 if (!xml) return NULL((void*)0);
3052 return switch_xml_set_attr(switch_xml_set_flag(xml, SWITCH_XML_DUP), strdup(name), strdup(value));
3053}
3054
3055/* sets a flag for the given tag and returns the tag */
3056SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_flag(switch_xml_t xml, switch_xml_flag_t flag)
3057{
3058 if (xml)
3059 xml->flags |= flag;
3060 return xml;
3061}
3062
3063/* removes a tag along with its subtags without freeing its memory */
3064SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_cut(switch_xml_t xml)
3065{
3066 switch_xml_t cur;
3067
3068 if (!xml)
3069 return NULL((void*)0); /* nothing to do */
3070 if (xml->next)
3071 xml->next->sibling = xml->sibling; /* patch sibling list */
3072
3073 if (xml->parent) { /* not root tag */
3074 cur = xml->parent->child; /* find head of subtag list */
3075 if (cur == xml)
3076 xml->parent->child = xml->ordered; /* first subtag */
3077 else { /* not first subtag */
3078 while (cur->ordered != xml)
3079 cur = cur->ordered;
3080 cur->ordered = cur->ordered->ordered; /* patch ordered list */
3081
3082 cur = xml->parent->child; /* go back to head of subtag list */
3083 if (strcmp(cur->name, xml->name)) { /* not in first sibling list */
3084 while (strcmp(cur->sibling->name, xml->name))
3085 cur = cur->sibling;
3086 if (cur->sibling == xml) { /* first of a sibling list */
3087 cur->sibling = (xml->next) ? xml->next : cur->sibling->sibling;
3088 } else
3089 cur = cur->sibling; /* not first of a sibling list */
3090 }
3091
3092 while (cur->next && cur->next != xml)
3093 cur = cur->next;
3094 if (cur->next)
3095 cur->next = cur->next->next; /* patch next list */
3096 }
3097 }
3098 xml->ordered = xml->sibling = xml->next = NULL((void*)0); /* prevent switch_xml_free() from clobbering ordered list */
3099 return xml;
3100}
3101
3102SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_xml_std_datetime_check(switch_xml_t xcond, int *offset, const char *tzname)
3103{
3104
3105 const char *xdt = switch_xml_attr(xcond, "date-time");
3106 const char *xyear = switch_xml_attr(xcond, "year");
3107 const char *xyday = switch_xml_attr(xcond, "yday");
3108 const char *xmon = switch_xml_attr(xcond, "mon");
3109 const char *xmday = switch_xml_attr(xcond, "mday");
3110 const char *xweek = switch_xml_attr(xcond, "week");
3111 const char *xmweek = switch_xml_attr(xcond, "mweek");
3112 const char *xwday = switch_xml_attr(xcond, "wday");
3113 const char *xhour = switch_xml_attr(xcond, "hour");
3114 const char *xminute = switch_xml_attr(xcond, "minute");
3115 const char *xminday = switch_xml_attr(xcond, "minute-of-day");
3116 const char *xtod = switch_xml_attr(xcond, "time-of-day");
3117 const char *tzoff = switch_xml_attr(xcond, "tz-offset");
3118 const char *isdst = switch_xml_attr(xcond, "dst");
3119
3120 int loffset = -1000;
3121 int eoffset = -1000;
3122 int dst = -1000;
3123 switch_time_t ts = switch_micro_time_now();
3124 int time_match = -1;
3125 switch_time_exp_t tm, tm2;
3126
3127 if (!zstr(isdst)_zstr(isdst)) {
3128 dst = switch_true(isdst);
3129 }
3130
3131 if (!zstr(tzoff)_zstr(tzoff) && switch_is_number(tzoff)) {
3132 loffset = atoi(tzoff);
3133 }
3134
3135 switch_time_exp_lt(&tm2, ts);
3136
3137 if (offset) {
3138 eoffset = *offset;
3139 switch_time_exp_tz(&tm, ts, *offset * 3600);
3140 } else if (!zstr(tzname)_zstr(tzname)) {
3141 switch_time_exp_tz_name(tzname, &tm, ts);
3142 } else {
3143 tm = tm2;
3144 }
3145
3146 if (eoffset == -1000) {
3147 eoffset = tm.tm_gmtoff / 3600;
3148 }
3149
3150 if (loffset == -1000) {
3151 loffset = eoffset;
3152 }
3153
3154
3155 if (time_match && tzoff) {
3156 time_match = loffset == eoffset;
3157 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3157, ((void*)0)
, SWITCH_LOG_DEBUG9,
3158 "XML DateTime Check: TZOFFSET[%d] == %d (%s)\n", eoffset, loffset, time_match ? "PASS" : "FAIL");
3159
3160 }
3161
3162 if (time_match && dst > -1) {
3163 time_match = (tm2.tm_isdst > 0 && dst > 0);
3164 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3164, ((void*)0)
, SWITCH_LOG_DEBUG9,
3165 "XML DateTime Check: DST[%s] == %s (%s)\n",
3166 tm2.tm_isdst > 0 ? "true" : "false", dst > 0 ? "true" : "false", time_match ? "PASS" : "FAIL");
3167
3168 }
3169
3170 if (time_match && xdt) {
3171 char tmpdate[80];
3172 switch_size_t retsize;
3173 switch_strftime(tmpdate, &retsize, sizeof(tmpdate), "%Y-%m-%d %H:%M:%S", &tm);
3174 time_match = switch_fulldate_cmp(xdt, &ts);
3175 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3175, ((void*)0)
, SWITCH_LOG_DEBUG,
3176 "XML DateTime Check: date time[%s] =~ %s (%s)\n", tmpdate, xdt, time_match ? "PASS" : "FAIL");
3177 }
3178
3179 if (time_match && xyear) {
3180 int test = tm.tm_year + 1900;
3181 time_match = switch_number_cmp(xyear, test);
3182 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3182, ((void*)0)
, SWITCH_LOG_DEBUG9,
3183 "XML DateTime Check: year[%d] =~ %s (%s)\n", test, xyear, time_match ? "PASS" : "FAIL");
3184 }
3185
3186 if (time_match && xyday) {
3187 int test = tm.tm_yday + 1;
3188 time_match = switch_number_cmp(xyday, test);
3189 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3189, ((void*)0)
, SWITCH_LOG_DEBUG9,
3190 "XML DateTime Check: day of year[%d] =~ %s (%s)\n", test, xyday, time_match ? "PASS" : "FAIL");
3191 }
3192
3193 if (time_match && xmon) {
3194 int test = tm.tm_mon + 1;
3195 time_match = switch_number_cmp(xmon, test);
3196 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3196, ((void*)0)
, SWITCH_LOG_DEBUG9,
3197 "XML DateTime Check: month[%d] =~ %s (%s)\n", test, xmon, time_match ? "PASS" : "FAIL");
3198 }
3199
3200 if (time_match && xmday) {
3201 int test = tm.tm_mday;
3202 time_match = switch_number_cmp(xmday, test);
3203 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3203, ((void*)0)
, SWITCH_LOG_DEBUG9,
3204 "XML DateTime Check: day of month[%d] =~ %s (%s)\n", test, xmday, time_match ? "PASS" : "FAIL");
3205 }
3206
3207 if (time_match && xweek) {
3208 int test = (int) (tm.tm_yday / 7 + 1);
3209 time_match = switch_number_cmp(xweek, test);
3210 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3210, ((void*)0)
, SWITCH_LOG_DEBUG9,
3211 "XML DateTime Check: week of year[%d] =~ %s (%s)\n", test, xweek, time_match ? "PASS" : "FAIL");
3212 }
3213
3214 if (time_match && xmweek) {
3215 /* calculate the day of the week of the first of the month (0-6) */
3216 int firstdow = (int) (7 - (tm.tm_mday - (tm.tm_wday + 1)) % 7) % 7;
3217 /* calculate the week of the month (1-6)*/
3218 int test = (int) ceil((tm.tm_mday + firstdow) / 7.0);
3219 time_match = switch_number_cmp(xmweek, test);
3220 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3220, ((void*)0)
, SWITCH_LOG_DEBUG9,
3221 "XML DateTime: week of month[%d] =~ %s (%s)\n", test, xmweek, time_match ? "PASS" : "FAIL");
3222 }
3223
3224 if (time_match && xwday) {
3225 int test = tm.tm_wday + 1;
3226 time_match = switch_dow_cmp(xwday, test);
3227 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3227, ((void*)0)
, SWITCH_LOG_DEBUG9,
3228 "XML DateTime Check: day of week[%s] =~ %s (%s)\n", switch_dow_int2str(test), xwday, time_match ? "PASS" : "FAIL");
3229 }
3230 if (time_match && xhour) {
3231 int test = tm.tm_hour;
3232 time_match = switch_number_cmp(xhour, test);
3233 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3233, ((void*)0)
, SWITCH_LOG_DEBUG9,
3234 "XML DateTime Check: hour[%d] =~ %s (%s)\n", test, xhour, time_match ? "PASS" : "FAIL");
3235 }
3236
3237 if (time_match && xminute) {
3238 int test = tm.tm_min;
3239 time_match = switch_number_cmp(xminute, test);
3240 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3240, ((void*)0)
, SWITCH_LOG_DEBUG9,
3241 "XML DateTime Check: minute[%d] =~ %s (%s)\n", test, xminute, time_match ? "PASS" : "FAIL");
3242 }
3243
3244 if (time_match && xminday) {
3245 int test = (tm.tm_hour * 60) + (tm.tm_min + 1);
3246 time_match = switch_number_cmp(xminday, test);
3247 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3247, ((void*)0)
, SWITCH_LOG_DEBUG9,
3248 "XML DateTime Check: minute of day[%d] =~ %s (%s)\n", test, xminday, time_match ? "PASS" : "FAIL");
3249 }
3250
3251 if (time_match && xtod) {
3252 int test = (tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec;
3253 char tmpdate[10];
3254 switch_snprintf(tmpdate, 10, "%d:%d:%d", tm.tm_hour, tm.tm_min, tm.tm_sec);
3255 time_match = switch_tod_cmp(xtod, test);
3256 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3256, ((void*)0)
, SWITCH_LOG_DEBUG9,
3257 "XML DateTime Check: time of day[%s] =~ %s (%s)\n", tmpdate, xtod, time_match ? "PASS" : "FAIL");
3258 }
3259
3260 return time_match;
3261}
3262
3263SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate_language_ex(switch_xml_t *root, switch_xml_t *node, switch_event_t *params, switch_xml_t *language, switch_xml_t *phrases, switch_xml_t *macros, const char *str_language) {
3264 switch_status_t status = SWITCH_STATUS_FALSE;
3265
3266 if (switch_xml_locate("languages", NULL((void*)0), NULL((void*)0), NULL((void*)0), root, node, params, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
3267 switch_xml_t sub_macros;
3268
3269 if (switch_xml_locate("phrases", NULL((void*)0), NULL((void*)0), NULL((void*)0), root, node, params, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
3270 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3270, ((void*)0)
, SWITCH_LOG_ERROR, "Open of languages and phrases failed.\n");
3271 goto done;
3272 }
3273 if (!(sub_macros = switch_xml_child(*node, "macros"))) {
3274 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3274, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find macros tag.\n");
3275 switch_xml_free(*root);
3276 *root = NULL((void*)0);
3277 *node = NULL((void*)0);
3278 goto done;
3279 }
3280 if (!(*language = switch_xml_find_child(sub_macros, "language", "name", str_language))) {
3281 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3281, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find language %s.\n", str_language);
3282 switch_xml_free(*root);
3283 *root = NULL((void*)0);
3284 *node = NULL((void*)0);
3285 goto done;
3286 }
3287 *macros = *language;
3288 } else {
3289 if (!(*language = switch_xml_find_child(*node, "language", "name", str_language))) {
3290 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3290, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find language %s.\n", str_language);
3291 switch_xml_free(*root);
3292 *root = NULL((void*)0);
3293 goto done;
3294 }
3295 if (!(*phrases = switch_xml_child(*language, "phrases"))) {
3296 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3296, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find phrases tag.\n");
3297 switch_xml_free(*root);
3298 *root = NULL((void*)0);
3299 *node = NULL((void*)0);
3300 *language = NULL((void*)0);
3301 goto done;
3302 }
3303
3304 if (!(*macros = switch_xml_child(*phrases, "macros"))) {
3305 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3305, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find macros tag.\n");
3306 switch_xml_free(*root);
3307 *root = NULL((void*)0);
3308 *node = NULL((void*)0);
3309 *language = NULL((void*)0);
3310 *phrases = NULL((void*)0);
3311 goto done;
3312 }
3313 }
3314 status = SWITCH_STATUS_SUCCESS;
3315
3316done:
3317 return status;
3318}
3319
3320SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate_language(switch_xml_t *root, switch_xml_t *node, switch_event_t *params, switch_xml_t *language, switch_xml_t *phrases, switch_xml_t *macros, const char *str_language) {
3321 switch_status_t status;
3322
3323 if ((status = switch_xml_locate_language_ex(root, node, params, language, phrases, macros, str_language)) != SWITCH_STATUS_SUCCESS) {
3324 char *str_language_dup = strdup(str_language);
3325 char *secondary;
3326 switch_assert(str_language_dup)((str_language_dup) ? (void) (0) : __assert_fail ("str_language_dup"
, "src/switch_xml.c", 3326, __extension__ __PRETTY_FUNCTION__
))
;
3327 if ((secondary = strchr(str_language_dup, '-'))) {
3328 *secondary++ = '\0';
3329 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3329, ((void*)0)
, SWITCH_LOG_WARNING,
3330 "language %s not found. trying %s by removing %s\n", str_language, str_language_dup, secondary);
3331 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "lang", str_language_dup);
3332 status = switch_xml_locate_language_ex(root, node, params, language, phrases, macros, str_language_dup);
3333 }
3334 switch_safe_free(str_language_dup)if (str_language_dup) {free(str_language_dup);str_language_dup
=((void*)0);}
;
3335 }
3336
3337 return status;
3338}
3339
3340#ifdef WIN32
3341/*
3342 * globbing functions for windows, part of libc on unix, this code was cut and paste from
3343 * freebsd lib and distilled a bit to work with windows
3344 */
3345
3346/*
3347 * Copyright (c) 1989, 1993
3348 * The Regents of the University of California. All rights reserved.
3349 *
3350 * This code is derived from software contributed to Berkeley by
3351 * Guido van Rossum.
3352 *
3353 * Redistribution and use in source and binary forms, with or without
3354 * modification, are permitted provided that the following conditions
3355 * are met:
3356 * 1. Redistributions of source code must retain the above copyright
3357 * notice, this list of conditions and the following disclaimer.
3358 * 2. Redistributions in binary form must reproduce the above copyright
3359 * notice, this list of conditions and the following disclaimer in the
3360 * documentation and/or other materials provided with the distribution.
3361 * 4. Neither the name of the University nor the names of its contributors
3362 * may be used to endorse or promote products derived from this software
3363 * without specific prior written permission.
3364 *
3365 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
3366 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3367 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3368 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3369 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3370 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3371 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3372 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3373 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3374 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3375 * SUCH DAMAGE.
3376 */
3377
3378#define DOLLAR '$'
3379#define DOT '.'
3380#define EOS '\0'
3381#define LBRACKET '['
3382#define NOT '!'
3383#define QUESTION '?'
3384#define RANGE '-'
3385#define RBRACKET ']'
3386#define SEP '/'
3387#define WIN_SEP '/'
3388#define STAR '*'
3389#define TILDE '~'
3390#define UNDERSCORE '_'
3391#define LBRACE '{'
3392#define RBRACE '}'
3393#define SLASH '/'
3394#define COMMA ','
3395
3396#define M_QUOTE (char)0x80
3397#define M_PROTECT (char)0x40
3398#define M_MASK (char)0xff
3399#define M_ASCII (char)0x7f
3400
3401#define CHAR(c) ((char)((c)&M_ASCII))
3402#define META(c) ((char)((c)|M_QUOTE))
3403#define M_ALL META('*')
3404#define M_END META(']')
3405#define M_NOT META('!')
3406#define M_ONE META('?')
3407#define M_RNG META('-')
3408#define M_SET META('[')
3409#define ismeta(c) (((c)&M_QUOTE) != 0)
3410
3411#ifndef MAXPATHLEN
3412#define MAXPATHLEN 256
3413#endif
3414
3415static int compare(const void *, const void *);
3416static int glob0(const char *, glob_t *, size_t *);
3417static int glob1(char *, glob_t *, size_t *);
3418static int glob2(char *, char *, char *, char *, glob_t *, size_t *);
3419static int glob3(char *, char *, char *, char *, char *, glob_t *, size_t *);
3420static int globextend(const char *, glob_t *, size_t *);
3421static int match(char *, char *, char *);
3422
3423#pragma warning(push)
3424#pragma warning(disable:4310)
3425
3426int glob(const char *pattern, int flags, int (*errfunc) (const char *, int), glob_t *pglob)
3427{
3428 const unsigned char *patnext;
3429 size_t limit;
3430 char c;
3431 char *bufnext, *bufend, patbuf[MAXPATHLEN];
3432
3433 patnext = (unsigned char *) pattern;
3434 if (!(flags & GLOB_APPEND(1 << 5))) {
3435 pglob->gl_pathc = 0;
3436 pglob->gl_pathv = NULL((void*)0);
3437 if (!(flags & GLOB_DOOFFS(1 << 3)))
3438 pglob->gl_offs = 0;
3439 }
3440 if (flags & GLOB_LIMIT) {
3441 limit = pglob->gl_matchc;
3442 if (limit == 0)
3443 limit = 9999999;
3444 } else
3445 limit = 0;
3446 pglob->gl_flags = flags & ~GLOB_MAGCHAR(1 << 8);
3447 pglob->gl_errfunc = errfunc;
3448 pglob->gl_matchc = 0;
3449
3450 bufnext = patbuf;
3451 bufend = bufnext + MAXPATHLEN - 1;
3452 while (bufnext < bufend && (c = *patnext++) != EOS)
3453 *bufnext++ = c;
3454 *bufnext = EOS;
3455
3456 return glob0(patbuf, pglob, &limit);
3457}
3458
3459/*
3460 * The main glob() routine: compiles the pattern (optionally processing
3461 * quotes), calls glob1() to do the real pattern matching, and finally
3462 * sorts the list (unless unsorted operation is requested). Returns 0
3463 * if things went well, nonzero if errors occurred.
3464 */
3465static int glob0(const char *pattern, glob_t *pglob, size_t *limit)
3466{
3467 const char *qpatnext;
3468 int c, err;
3469 size_t oldpathc;
3470 char *bufnext, patbuf[MAXPATHLEN];
3471
3472 qpatnext = pattern;
3473 oldpathc = pglob->gl_pathc;
3474 bufnext = patbuf;
3475
3476 /* We don't need to check for buffer overflow any more. */
3477 while ((c = *qpatnext++) != EOS) {
3478 switch (c) {
3479 case SEP:
3480 *bufnext++ = WIN_SEP;
3481 break;
3482 case LBRACKET:
3483 c = *qpatnext;
3484 if (c == NOT)
3485 ++qpatnext;
3486 if (*qpatnext == EOS || strchr((char *) qpatnext + 1, RBRACKET) == NULL((void*)0)) {
3487 *bufnext++ = LBRACKET;
3488 if (c == NOT)
3489 --qpatnext;
3490 break;
3491 }
3492 *bufnext++ = M_SET;
3493 if (c == NOT)
3494 *bufnext++ = M_NOT;
3495 c = *qpatnext++;
3496 do {
3497 *bufnext++ = CHAR(c);
3498 if (*qpatnext == RANGE && (c = qpatnext[1]) != RBRACKET) {
3499 *bufnext++ = M_RNG;
3500 *bufnext++ = CHAR(c);
3501 qpatnext += 2;
3502 }
3503 } while ((c = *qpatnext++) != RBRACKET);
3504 pglob->gl_flags |= GLOB_MAGCHAR(1 << 8);
3505 *bufnext++ = M_END;
3506 break;
3507 case QUESTION:
3508 pglob->gl_flags |= GLOB_MAGCHAR(1 << 8);
3509 *bufnext++ = M_ONE;
3510 break;
3511 case STAR:
3512 pglob->gl_flags |= GLOB_MAGCHAR(1 << 8);
3513 /* collapse adjacent stars to one,
3514 * to avoid exponential behavior
3515 */
3516 if (bufnext == patbuf || bufnext[-1] != M_ALL)
3517 *bufnext++ = M_ALL;
3518 break;
3519 default:
3520 *bufnext++ = CHAR(c);
3521 break;
3522 }
3523 }
3524 *bufnext = EOS;
3525
3526 if ((err = glob1(patbuf, pglob, limit)) != 0)
3527 return (err);
3528
3529 /*
3530 * If there was no match we are going to append the pattern
3531 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
3532 * and the pattern did not contain any magic characters
3533 * GLOB_NOMAGIC is there just for compatibility with csh.
3534 */
3535 if (pglob->gl_pathc == oldpathc) {
3536 if (((pglob->gl_flags & GLOB_NOCHECK(1 << 4)) || ((pglob->gl_flags & GLOB_NOMAGIC(1 << 11)) && !(pglob->gl_flags & GLOB_MAGCHAR(1 << 8)))))
3537 return (globextend(pattern, pglob, limit));
3538 else
3539 return (GLOB_NOMATCH3);
3540 }
3541 if (!(pglob->gl_flags & GLOB_NOSORT(1 << 2)))
3542 qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, pglob->gl_pathc - oldpathc, sizeof(char *), compare);
3543 return (0);
3544}
3545
3546static int compare(const void *p, const void *q)
3547{
3548 return (strcmp(*(char **) p, *(char **) q));
3549}
3550
3551static int glob1(char *pattern, glob_t *pglob, size_t *limit)
3552{
3553 char pathbuf[MAXPATHLEN];
3554
3555 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
3556 if (*pattern == EOS)
3557 return (0);
3558 return (glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1, pattern, pglob, limit));
3559}
3560
3561/*
3562 * The functions glob2 and glob3 are mutually recursive; there is one level
3563 * of recursion for each segment in the pattern that contains one or more
3564 * meta characters.
3565 */
3566static int glob2(char *pathbuf, char *pathend, char *pathend_last, char *pattern, glob_t *pglob, size_t *limit)
3567{
3568 struct stat sb;
3569 char *p, *q;
3570 int anymeta;
3571
3572 /*
3573 * Loop over pattern segments until end of pattern or until
3574 * segment with meta character found.
3575 */
3576 for (anymeta = 0;;) {
3577 if (*pattern == EOS) { /* End of pattern? */
3578 *pathend = EOS;
3579 if (stat(pathbuf, &sb))
3580 return (0);
3581
3582 if (((pglob->gl_flags & GLOB_MARK(1 << 1)) && pathend[-1] != SEP && pathend[-1] != WIN_SEP) && (_S_IFDIR & sb.st_mode)) {
3583 if (pathend + 1 > pathend_last)
3584 return (GLOB_ABORTED2);
3585 *pathend++ = WIN_SEP;
3586 *pathend = EOS;
3587 }
3588 ++pglob->gl_matchc;
3589 return (globextend(pathbuf, pglob, limit));
3590 }
3591
3592 /* Find end of next segment, copy tentatively to pathend. */
3593 q = pathend;
3594 p = pattern;
3595 while (*p != EOS && *p != SEP && *p != WIN_SEP) {
3596 if (ismeta(*p))
3597 anymeta = 1;
3598 if (q + 1 > pathend_last)
3599 return (GLOB_ABORTED2);
3600 *q++ = *p++;
3601 }
3602
3603 if (!anymeta) { /* No expansion, do next segment. */
3604 pathend = q;
3605 pattern = p;
3606 while (*pattern == SEP || *pattern == WIN_SEP) {
3607 if (pathend + 1 > pathend_last)
3608 return (GLOB_ABORTED2);
3609 *pathend++ = *pattern++;
3610 }
3611 } else /* Need expansion, recurse. */
3612 return (glob3(pathbuf, pathend, pathend_last, pattern, p, pglob, limit));
3613 }
3614 /* NOTREACHED */
3615}
3616
3617static int glob3(char *pathbuf, char *pathend, char *pathend_last, char *pattern, char *restpattern, glob_t *pglob, size_t *limit)
3618{
3619 int err;
3620 apr_dir_t *dirp;
3621 apr_pool_t *pool;
3622
3623 apr_pool_create(&pool, NULL((void*)0));
3624
3625 if (pathend > pathend_last)
3626 return (GLOB_ABORTED2);
3627 *pathend = EOS;
3628 errno(*__errno_location ()) = 0;
3629
3630 if (apr_dir_open(&dirp, pathbuf, pool) != APR_SUCCESS) {
3631 /* TODO: don't call for ENOENT or ENOTDIR? */
3632 apr_pool_destroy(pool);
3633 if (pglob->gl_errfunc) {
3634 if (pglob->gl_errfunc(pathbuf, errno(*__errno_location ())) || pglob->gl_flags & GLOB_ERR(1 << 0))
3635 return (GLOB_ABORTED2);
3636 }
3637 return (0);
3638 }
3639
3640 err = 0;
3641
3642 /* Search directory for matching names. */
3643 while (dirp) {
3644 apr_finfo_t dp;
3645 unsigned char *sc;
3646 char *dc;
3647
3648 if (apr_dir_read(&dp, APR_FINFO_NAME, dirp) != APR_SUCCESS)
3649 break;
3650 if (!(dp.valid & APR_FINFO_NAME) || !(dp.name) || !strlen(dp.name))
3651 break;
3652
3653 /* Initial DOT must be matched literally. */
3654 if (dp.name[0] == DOT && *pattern != DOT)
3655 continue;
3656 dc = pathend;
3657 sc = (unsigned char *) dp.name;
3658
3659 while (dc < pathend_last && (*dc++ = *sc++) != EOS);
3660
3661 if (!match(pathend, pattern, restpattern)) {
3662 *pathend = EOS;
3663 continue;
3664 }
3665 err = glob2(pathbuf, --dc, pathend_last, restpattern, pglob, limit);
3666 if (err)
3667 break;
3668 }
3669
3670 if (dirp)
3671 apr_dir_close(dirp);
3672 apr_pool_destroy(pool);
3673 return (err);
3674}
3675
3676
3677/*
3678 * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
3679 * add the new item, and update gl_pathc.
3680 *
3681 * This assumes the BSD realloc, which only copies the block when its size
3682 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
3683 * behavior.
3684 *
3685 * Return 0 if new item added, error code if memory couldn't be allocated.
3686 *
3687 * Invariant of the glob_t structure:
3688 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
3689 * gl_pathv points to (gl_offs + gl_pathc + 1) items.
3690 */
3691static int globextend(const char *path, glob_t *pglob, size_t *limit)
3692{
3693 char **pathv;
3694 char *copy;
3695 size_t i;
3696 size_t newsize, len;
3697 const char *p;
3698
3699 if (*limit && pglob->gl_pathc > *limit) {
3700 errno(*__errno_location ()) = 0;
3701 return (GLOB_NOSPACE1);
3702 }
3703
3704 newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
3705 pathv = pglob->gl_pathv ? switch_must_realloc((char *) pglob->gl_pathv, newsize) : switch_must_malloc(newsize);
3706
3707 if (pglob->gl_pathv == NULL((void*)0) && pglob->gl_offs > 0) {
3708 /* first time around -- clear initial gl_offs items */
3709 pathv += pglob->gl_offs;
3710 for (i = pglob->gl_offs; i-- > 0;)
3711 *--pathv = NULL((void*)0);
3712 }
3713 pglob->gl_pathv = pathv;
3714
3715 for (p = path; *p++;)
3716 continue;
3717 len = (size_t) (p - path);
3718 copy = switch_must_malloc(len);
3719 memcpy(copy, path, len);
3720 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
3721 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL((void*)0);
3722 return (copy == NULL((void*)0) ? GLOB_NOSPACE1 : 0);
3723}
3724
3725/*
3726 * pattern matching function for filenames. Each occurrence of the *
3727 * pattern causes a recursion level.
3728 */
3729static int match(char *name, char *pat, char *patend)
3730{
3731 int ok, negate_range;
3732 char c, k;
3733 char s1[6];
3734
3735 while (pat < patend) {
3736 c = *pat++;
3737 switch (c & M_MASK) {
3738 case M_ALL:
3739 if (pat == patend)
3740 return (1);
3741 do
3742 if (match(name, pat, patend))
3743 return (1);
3744 while (*name++ != EOS);
3745 return (0);
3746 case M_ONE:
3747 if (*name++ == EOS)
3748 return (0);
3749 break;
3750 case M_SET:
3751 ok = 0;
3752 if ((k = *name++) == EOS)
3753 return (0);
3754 if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
3755 ++pat;
3756 while (((c = *pat++) & M_MASK) != M_END)
3757 if ((*pat & M_MASK) == M_RNG) {
3758 memset(s1, 0, sizeof(s1));
3759 s1[0] = c;
3760 s1[2] = k;
3761 s1[4] = pat[1];
3762 if (strcoll(&s1[0], &s1[2]) <= 0 && strcoll(&s1[2], &s1[4]) <= 0)
3763 ok = 1;
3764 pat += 2;
3765 } else if (c == k)
3766 ok = 1;
3767 if (ok == negate_range)
3768 return (0);
3769 break;
3770 default:
3771 if (*name++ != c)
3772 return (0);
3773 break;
3774 }
3775 }
3776 return (*name == EOS);
3777}
3778
3779/* Free allocated data belonging to a glob_t structure. */
3780void globfree(glob_t *pglob)
3781{
3782 size_t i;
3783 char **pp;
3784
3785 if (pglob->gl_pathv != NULL((void*)0)) {
3786 pp = pglob->gl_pathv + pglob->gl_offs;
3787 for (i = pglob->gl_pathc; i--; ++pp)
3788 if (*pp)
3789 free(*pp);
3790 free(pglob->gl_pathv);
3791 pglob->gl_pathv = NULL((void*)0);
3792 }
3793}
3794
3795#pragma warning(pop)
3796#endif
3797
3798/* For Emacs:
3799 * Local Variables:
3800 * mode:c
3801 * indent-tabs-mode:t
3802 * tab-width:4
3803 * c-basic-offset:4
3804 * End:
3805 * For VIM:
3806 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3807 */

./src/include/switch_core.h

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 * Luke Dashjr <luke@openmethods.com> (OpenMethods, LLC)
28 * Joseph Sullivan <jossulli@amazon.com>
29 * Emmanuel Schmidbauer <eschmidbauer@gmail.com>
30 * Andrey Volk <andywolk@gmail.com>
31 *
32 * switch_core.h -- Core Library
33 *
34 */
35/*! \file switch_core.h
36 \brief Core Library
37
38 This module is the main core library and is the intended location of all fundamental operations.
39*/
40
41#ifndef SWITCH_CORE_H
42#define SWITCH_CORE_H
43
44#include <switch.h>
45
46SWITCH_BEGIN_EXTERN_C
47#define SWITCH_MAX_CORE_THREAD_SESSION_OBJS128 128
48#define SWITCH_MAX_STREAMS128 128
49 struct switch_core_time_duration {
50 uint32_t mms;
51 uint32_t ms;
52 uint32_t sec;
53 uint32_t min;
54 uint32_t hr;
55 uint32_t day;
56 uint32_t yr;
57};
58
59struct switch_app_log {
60 char *app;
61 char *arg;
62 switch_time_t stamp;
63 struct switch_app_log *next;
64};
65
66typedef struct switch_thread_data_s {
67 switch_thread_start_t func;
68 void *obj;
69 int alloc;
70 switch_memory_pool_t *pool;
71} switch_thread_data_t;
72
73typedef struct switch_hold_record_s {
74 switch_time_t on;
75 switch_time_t off;
76 char *uuid;
77 struct switch_hold_record_s *next;
78} switch_hold_record_t;
79
80typedef struct device_uuid_node_s {
81 char *uuid;
82 switch_xml_t xml_cdr;
83 switch_event_t *event;
84 switch_channel_callstate_t callstate;
85 switch_hold_record_t *hold_record;
86 switch_caller_profile_t *hup_profile;
87 switch_call_direction_t direction;
88 struct switch_device_record_s *parent;
89 struct device_uuid_node_s *next;
90} switch_device_node_t;
91
92typedef struct switch_device_stats_s {
93 uint32_t total;
94 uint32_t total_in;
95 uint32_t total_out;
96 uint32_t offhook;
97 uint32_t offhook_in;
98 uint32_t offhook_out;
99 uint32_t active;
100 uint32_t active_in;
101 uint32_t active_out;
102 uint32_t held;
103 uint32_t held_in;
104 uint32_t held_out;
105 uint32_t unheld;
106 uint32_t unheld_in;
107 uint32_t unheld_out;
108 uint32_t hup;
109 uint32_t hup_in;
110 uint32_t hup_out;
111 uint32_t ringing;
112 uint32_t ringing_in;
113 uint32_t ringing_out;
114 uint32_t early;
115 uint32_t early_in;
116 uint32_t early_out;
117 uint32_t ring_wait;
118} switch_device_stats_t;
119
120
121typedef struct switch_device_record_s {
122 char *device_id;
123 char *uuid;
124 int refs;
125 switch_device_stats_t stats;
126 switch_device_stats_t last_stats;
127 switch_device_state_t state;
128 switch_device_state_t last_state;
129 switch_time_t active_start;
130 switch_time_t active_stop;
131 switch_time_t last_call_time;
132 switch_time_t ring_start;
133 switch_time_t ring_stop;
134 switch_time_t hold_start;
135 switch_time_t hold_stop;
136 switch_time_t call_start;
137 struct device_uuid_node_s *uuid_list;
138 struct device_uuid_node_s *uuid_tail;
139 switch_mutex_t *mutex;
140 switch_memory_pool_t *pool;
141 void *user_data;
142} switch_device_record_t;
143
144typedef void(*switch_device_state_function_t)(switch_core_session_t *session, switch_channel_callstate_t callstate, switch_device_record_t *drec);
145
146
147#define DTLS_SRTP_FNAME"dtls-srtp" "dtls-srtp"
148#define MAX_FPLEN64 64
149#define MAX_FPSTRLEN192 192
150
151typedef struct dtls_fp_s {
152 uint32_t len;
153 uint8_t data[MAX_FPLEN64+1];
154 char *type;
155 char str[MAX_FPSTRLEN192];
156} dtls_fingerprint_t;
157
158typedef enum {
159 DTLS_TYPE_CLIENT = (1 << 0),
160 DTLS_TYPE_SERVER = (1 << 1),
161 DTLS_TYPE_RTP = (1 << 2),
162 DTLS_TYPE_RTCP = (1 << 3)
163} dtls_type_t;
164
165typedef enum {
166 DS_OFF,
167 DS_HANDSHAKE,
168 DS_SETUP,
169 DS_READY,
170 DS_FAIL,
171 DS_INVALID,
172} dtls_state_t;
173
174#define MESSAGE_STAMP_FFL(_m)_m->_file = "./src/include/switch_core.h"; _m->_func = (
const char *)__func__; _m->_line = 174
_m->_file = __FILE__"./src/include/switch_core.h"; _m->_func = __SWITCH_FUNC__(const char *)__func__; _m->_line = __LINE__174
175
176#define MESSAGE_STRING_ARG_MAX10 10
177/*! \brief A message object designed to allow unlike technologies to exchange data */
178struct switch_core_session_message {
179 /*! uuid of the sender (for replies) */
180 char *from;
181 /*! enumeration of the type of message */
182 switch_core_session_message_types_t message_id;
183
184 /*! optional numeric arg */
185 int numeric_arg;
186 /*! optional string arg */
187 const char *string_arg;
188 /*! optional string arg */
189 switch_size_t string_arg_size;
190 /*! optional arbitrary pointer arg */
191 void *pointer_arg;
192 /*! optional arbitrary pointer arg's size */
193 switch_size_t pointer_arg_size;
194
195 /*! optional numeric reply */
196 int numeric_reply;
197 /*! optional string reply */
198 char *string_reply;
199 /*! optional string reply */
200 switch_size_t string_reply_size;
201 /*! optional arbitrary pointer reply */
202 void *pointer_reply;
203 /*! optional arbitrary pointer reply's size */
204 switch_size_t pointer_reply_size;
205 /*! message flags */
206 switch_core_session_message_flag_t flags;
207 const char *_file;
208 const char *_func;
209 int _line;
210 const char *string_array_arg[MESSAGE_STRING_ARG_MAX10];
211 time_t delivery_time;
212};
213
214/*! \brief A generic object to pass as a thread's session object to allow mutiple arguements and a pool */
215struct switch_core_thread_session {
216 /*! status of the thread */
217 int running;
218 /*! mutex */
219 switch_mutex_t *mutex;
220 /*! array of void pointers to pass mutiple data objects */
221 void *objs[SWITCH_MAX_CORE_THREAD_SESSION_OBJS128];
222 /*! a pointer to a memory pool if the thread has it's own pool */
223 switch_input_callback_function_t input_callback;
224 switch_memory_pool_t *pool;
225};
226
227struct switch_core_session;
228struct switch_core_runtime;
229struct switch_core_port_allocator;
230
231
232static inline void *switch_must_malloc(size_t _b)
233{
234 void *m = malloc(_b);
18
Memory is allocated
235 switch_assert(m)((m) ? (void) (0) : __assert_fail ("m", "./src/include/switch_core.h"
, 235, __extension__ __PRETTY_FUNCTION__))
;
19
Within the expansion of the macro 'switch_assert':
a
Assuming 'm' is non-null
236 return m;
237}
238
239static inline void *switch_must_realloc(void *_b, size_t _z)
240{
241 void *m = realloc(_b, _z);
242 switch_assert(m)((m) ? (void) (0) : __assert_fail ("m", "./src/include/switch_core.h"
, 242, __extension__ __PRETTY_FUNCTION__))
;
243 return m;
244}
245
246static inline char *switch_must_strdup(const char *_s)
247{
248 char *s = strdup(_s);
249 switch_assert(s)((s) ? (void) (0) : __assert_fail ("s", "./src/include/switch_core.h"
, 249, __extension__ __PRETTY_FUNCTION__))
;
250 return s;
251}
252
253
254/*!
255 \defgroup core1 Core Library
256 \ingroup FREESWITCH
257 \{
258*/
259
260///\defgroup mb1 Media Bugs
261///\ingroup core1
262///\{
263
264
265SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_screen_size(int *x, int *y);
266SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_sched_heartbeat(switch_core_session_t *session, uint32_t seconds);
267SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_unsched_heartbeat(switch_core_session_t *session);
268
269SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_enable_heartbeat(switch_core_session_t *session, uint32_t seconds);
270SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_disable_heartbeat(switch_core_session_t *session);
271
272#define switch_core_session_get_name(_s)switch_channel_get_name(switch_core_session_get_channel(_s)) switch_channel_get_name(switch_core_session_get_channel(_s))
273
274SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_pop(switch_core_session_t *orig_session, const char *function, switch_media_bug_t **pop);
275
276SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_exec_all(switch_core_session_t *orig_session,
277 const char *function, switch_media_bug_exec_cb_t cb, void *user_data);
278SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_media_bug_patch_video(switch_core_session_t *orig_session, switch_frame_t *frame);
279SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_media_bug_count(switch_core_session_t *orig_session, const char *function);
280SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_media_bug_set_spy_fmt(switch_media_bug_t *bug, switch_vid_spy_fmt_t spy_fmt);
281SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_push_spy_frame(switch_media_bug_t *bug, switch_frame_t *frame, switch_rw_t rw);
282SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_patch_spy_frame(switch_media_bug_t *bug, switch_image_t *img, switch_rw_t rw);
283SWITCH_DECLARE(switch_vid_spy_fmt_t)__attribute__((visibility("default"))) switch_vid_spy_fmt_t switch_media_bug_parse_spy_fmt(const char *name);
284
285/*!
286 \brief Add a media bug to the session
287 \param session the session to add the bug to
288 \param function user defined module/function/reason identifying this bug
289 \param target user defined identification of the target of the bug
290 \param callback a callback for events
291 \param user_data arbitrary user data
292 \param stop_time absolute time at which the bug is automatically removed (or 0)
293 \param flags flags to choose the stream
294 \param new_bug pointer to assign new bug to
295 \return SWITCH_STATUS_SUCCESS if the operation was a success
296*/
297SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_add(_In_ switch_core_session_t *session,
298 _In_ const char *function,
299 _In_ const char *target,
300 _In_ switch_media_bug_callback_t callback,
301 _In_opt_ void *user_data,
302 _In_ time_t stop_time, _In_ switch_media_bug_flag_t flags, _Out_ switch_media_bug_t **new_bug);
303
304/*!
305 \brief Pause a media bug on the session
306 \param session the session to pause the bug on sets CF_PAUSE_BUGS flag
307*/
308SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_media_bug_pause(switch_core_session_t *session);
309
310/*!
311 \brief Resume a media bug on the session
312 \param session the session to resume the bug on, clears CF_PAUSE_BUGS flag
313*/
314SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_media_bug_resume(switch_core_session_t *session);
315
316SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_media_bug_inuse(switch_media_bug_t *bug, switch_size_t *readp, switch_size_t *writep);
317
318/*!
319 \brief Obtain private data from a media bug
320 \param bug the bug to get the data from
321 \return the private data
322*/
323SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_media_bug_get_user_data(_In_ switch_media_bug_t *bug);
324
325/*!
326 \brief Obtain a replace frame from a media bug
327 \param bug the bug to get the data from
328*/
329SWITCH_DECLARE(switch_frame_t *)__attribute__((visibility("default"))) switch_frame_t * switch_core_media_bug_get_write_replace_frame(_In_ switch_media_bug_t *bug);
330
331
332SWITCH_DECLARE(switch_frame_t *)__attribute__((visibility("default"))) switch_frame_t * switch_core_media_bug_get_native_read_frame(switch_media_bug_t *bug);
333SWITCH_DECLARE(switch_frame_t *)__attribute__((visibility("default"))) switch_frame_t * switch_core_media_bug_get_native_write_frame(switch_media_bug_t *bug);
334
335
336SWITCH_DECLARE(switch_frame_t *)__attribute__((visibility("default"))) switch_frame_t * switch_core_media_bug_get_video_ping_frame(switch_media_bug_t *bug);
337
338/*!
339 \brief Set a return replace frame
340 \param bug the bug to set the frame on
341 \param frame the frame to set
342*/
343SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_media_bug_set_write_replace_frame(_In_ switch_media_bug_t *bug, _In_ switch_frame_t *frame);
344
345/*!
346 \brief Obtain a replace frame from a media bug
347 \param bug the bug to get the data from
348*/
349SWITCH_DECLARE(switch_frame_t *)__attribute__((visibility("default"))) switch_frame_t * switch_core_media_bug_get_read_replace_frame(_In_ switch_media_bug_t *bug);
350SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_media_bug_set_read_demux_frame(_In_ switch_media_bug_t *bug, _In_ switch_frame_t *frame);
351/*!
352 \brief Obtain the session from a media bug
353 \param bug the bug to get the data from
354*/
355SWITCH_DECLARE(switch_core_session_t *)__attribute__((visibility("default"))) switch_core_session_t * switch_core_media_bug_get_session(_In_ switch_media_bug_t *bug);
356
357SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_media_bug_set_media_params(switch_media_bug_t *bug, switch_mm_t *mm);
358SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_media_bug_get_media_params(switch_media_bug_t *bug, switch_mm_t *mm);
359
360SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_media_bug_get_text(switch_media_bug_t *bug);
361
362/*!
363 \brief Test for the existance of a flag on an media bug
364 \param bug the object to test
365 \param flag the or'd list of flags to test
366 \return true value if the object has the flags defined
367*/
368SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_media_bug_test_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag);
369SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_media_bug_set_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag);
370SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_media_bug_clear_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag);
371
372/*!
373 \brief Set a return replace frame
374 \param bug the bug to set the frame on
375 \param frame the frame to set
376*/
377SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_media_bug_set_read_replace_frame(_In_ switch_media_bug_t *bug, _In_ switch_frame_t *frame);
378
379SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_cpu_count(void);
380
381/*!
382 \brief Remove a media bug from the session
383 \param session the session to remove the bug from
384 \param bug bug to remove
385 \return SWITCH_STATUS_SUCCESS if the operation was a success
386*/
387
388SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_remove(_In_ switch_core_session_t *session, _Inout_ switch_media_bug_t **bug);
389SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_media_bug_prune(switch_core_session_t *session);
390
391/*!
392 \brief Remove media bug callback
393 \param bug bug to remove
394 \param callback callback to remove
395 \return SWITCH_STATUS_SUCCESS if the operation was a success
396*/
397SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_remove_callback(switch_core_session_t *session, switch_media_bug_callback_t callback);
398
399/*!
400 \brief Close and destroy a media bug
401 \param bug bug to remove
402 \return SWITCH_STATUS_SUCCESS if the operation was a success
403*/
404SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_close(_Inout_ switch_media_bug_t **bug, switch_bool_t destroy);
405/*!
406 \brief Remove all media bugs from the session
407 \param session the session to remove the bugs from
408 \return SWITCH_STATUS_SUCCESS if the operation was a success
409*/
410SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_remove_all_function(_In_ switch_core_session_t *session, const char *function);
411
412#define switch_core_media_bug_remove_all(_s)switch_core_media_bug_remove_all_function(_s, ((void*)0)) switch_core_media_bug_remove_all_function(_s, NULL((void*)0))
413
414SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_enumerate(switch_core_session_t *session, switch_stream_handle_t *stream);
415
416SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_transfer_callback(switch_core_session_t *orig_session, switch_core_session_t *new_session,
417 switch_media_bug_callback_t callback, void * (*user_data_dup_func) (switch_core_session_t *, void *));
418
419
420/*!
421 \brief Read a frame from the bug
422 \param bug the bug to read from
423 \param frame the frame to write the data to
424 \return SWITCH_STATUS_SUCCESS if the operation was a success
425*/
426SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_read(_In_ switch_media_bug_t *bug, _In_ switch_frame_t *frame, switch_bool_t fill);
427
428/*!
429 \brief Flush the read and write buffers for the bug
430 \param bug the bug to flush the read and write buffers on
431*/
432SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_media_bug_flush(_In_ switch_media_bug_t *bug);
433
434/*!
435 \brief Flush the read/write buffers for all media bugs on the session
436 \param session the session to flush the read/write buffers for all media bugs on the session
437*/
438SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_flush_all(_In_ switch_core_session_t *session);
439
440SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_media_bug_set_pre_buffer_framecount(switch_media_bug_t *bug, uint32_t framecount);
441
442///\}
443
444///\defgroup pa1 Port Allocation
445///\ingroup core1
446///\{
447
448/*!
449 \brief Initilize the port allocator
450 \param start the starting port
451 \param end the ending port
452 \param flags flags to change allocator behaviour (e.g. only even/odd portnumbers)
453 \param new_allocator new pointer for the return value
454 \return SWITCH_STATUS_SUCCESS if the operation was a success
455*/
456SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_port_allocator_new(_In_ const char *ip,
457 _In_ switch_port_t start,
458 _In_ switch_port_t end,
459 _In_ switch_port_flag_t flags, _Out_ switch_core_port_allocator_t **new_allocator);
460
461/*!
462 \brief Get a port from the port allocator
463 \param alloc the allocator object
464 \param port_ptr a pointer to the port
465 \return SUCCESS
466*/
467SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_port_allocator_request_port(_In_ switch_core_port_allocator_t *alloc, _Out_ switch_port_t *port_ptr);
468
469/*!
470 \brief Return unused port to the port allocator
471 \param alloc the allocator object
472 \param port the port
473 \return SUCCESS
474*/
475SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_port_allocator_free_port(_In_ switch_core_port_allocator_t *alloc, _In_ switch_port_t port);
476
477/*!
478 \brief destroythe port allocator
479 \param alloc the allocator object
480*/
481SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_port_allocator_destroy(_Inout_ switch_core_port_allocator_t **alloc);
482///\}
483
484
485SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_test_flag(int flag);
486
487///\defgroup ss Startup/Shutdown
488///\ingroup core1
489///\{
490/*!
491 \brief Initilize the core
492 \param console optional FILE stream for output
493 \param flags core flags
494 \param err a pointer to set any errors to
495 \note to be called at application startup
496*/
497SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_init(_In_ switch_core_flag_t flags, _In_ switch_bool_t console, _Out_ const char **err);
498
499/*!
500 \brief Initilize the core and load modules
501 \param console optional FILE stream for output
502 \param flags core flags
503 \param err a pointer to set any errors to
504 \note to be called at application startup instead of switch_core_init. Includes module loading.
505*/
506SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_init_and_modload(_In_ switch_core_flag_t flags, _In_ switch_bool_t console, _Out_ const char **err);
507
508/*!
509 \brief Set/Get Session Limit
510 \param new_limit new value (if > 0)
511 \return the current session limit
512*/
513SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_session_limit(_In_ uint32_t new_limit);
514
515/*!
516 \brief Set/Get Session Rate Limit
517 \param new_limit new value (if > 0)
518 \return the current session rate limit
519*/
520SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_sessions_per_second(_In_ uint32_t new_limit);
521
522/*!
523 \brief Destroy the core
524 \note to be called at application shutdown
525*/
526SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_destroy(void);
527///\}
528
529
530///\defgroup rwl Read/Write Locking
531///\ingroup core1
532///\{
533
534
535SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_io_read_lock(switch_core_session_t *session);
536SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_io_write_lock(switch_core_session_t *session);
537SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_io_rwunlock(switch_core_session_t *session);
538
539#ifdef SWITCH_DEBUG_RWLOCKS
540SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_perform_read_lock(_In_ switch_core_session_t *session, const char *file, const char *func, int line);
541#endif
542
543/*!
544 \brief Acquire a read lock on the session
545 \param session the session to acquire from
546 \return success if it is safe to read from the session
547*/
548#ifdef SWITCH_DEBUG_RWLOCKS
549#define switch_core_session_read_lock(session) switch_core_session_perform_read_lock(session, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__549)
550#else
551SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_read_lock(_In_ switch_core_session_t *session);
552#endif
553
554
555#ifdef SWITCH_DEBUG_RWLOCKS
556SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_perform_read_lock_hangup(_In_ switch_core_session_t *session, const char *file, const char *func,
557 int line);
558#endif
559
560/*!
561 \brief Acquire a read lock on the session
562 \param session the session to acquire from
563 \return success if it is safe to read from the session
564*/
565#ifdef SWITCH_DEBUG_RWLOCKS
566#define switch_core_session_read_lock_hangup(session) switch_core_session_perform_read_lock_hangup(session, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__566)
567#else
568SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_read_lock_hangup(_In_ switch_core_session_t *session);
569#endif
570
571
572#ifdef SWITCH_DEBUG_RWLOCKS
573SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_perform_write_lock(_In_ switch_core_session_t *session, const char *file, const char *func, int line);
574#endif
575
576/*!
577 \brief Acquire a write lock on the session
578 \param session the session to acquire from
579*/
580#ifdef SWITCH_DEBUG_RWLOCKS
581#define switch_core_session_write_lock(session) switch_core_session_perform_write_lock(session, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__581)
582#else
583SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_write_lock(_In_ switch_core_session_t *session);
584#endif
585
586#ifdef SWITCH_DEBUG_RWLOCKS
587SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_perform_rwunlock(_In_ switch_core_session_t *session, const char *file, const char *func, int line);
588#endif
589
590/*!
591 \brief Unlock a read or write lock on as given session
592 \param session the session
593*/
594#ifdef SWITCH_DEBUG_RWLOCKS
595#define switch_core_session_rwunlock(session) switch_core_session_perform_rwunlock(session, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__595)
596#else
597SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_rwunlock(_In_ switch_core_session_t *session);
598#endif
599
600///\}
601
602///\defgroup sh State Handlers
603///\ingroup core1
604///\{
605/*!
606 \brief Add a global state handler
607 \param state_handler a state handler to add
608 \return the current index/priority of this handler
609*/
610SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_add_state_handler(_In_ const switch_state_handler_table_t *state_handler);
611
612/*!
613 \brief Remove a global state handler
614 \param state_handler the state handler to remove
615*/
616SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_remove_state_handler(_In_ const switch_state_handler_table_t *state_handler);
617
618/*!
619 \brief Access a state handler
620 \param index the desired index to access
621 \return the desired state handler table or NULL when it does not exist.
622*/
623SWITCH_DECLARE(const switch_state_handler_table_t *)__attribute__((visibility("default"))) const switch_state_handler_table_t
*
switch_core_get_state_handler(_In_ int index);
624///\}
625
626SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_pool_tag(switch_memory_pool_t *pool, const char *tag);
627
628SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_pool_stats(switch_stream_handle_t *stream);
629
630SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_perform_new_memory_pool(_Out_ switch_memory_pool_t **pool,
631 _In_z_ const char *file, _In_z_ const char *func, _In_ int line);
632
633///\defgroup memp Memory Pooling/Allocation
634///\ingroup core1
635///\{
636/*!
637 \brief Create a new sub memory pool from the core's master pool
638 \return SWITCH_STATUS_SUCCESS on success
639*/
640#define switch_core_new_memory_pool(p)switch_core_perform_new_memory_pool(p, "./src/include/switch_core.h"
, (const char *)__func__, 640)
switch_core_perform_new_memory_pool(p, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__640)
641
642SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_session_sync_clock(void);
643SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_perform_destroy_memory_pool(_Inout_ switch_memory_pool_t **pool,
644 _In_z_ const char *file, _In_z_ const char *func, _In_ int line);
645/*!
646 \brief Returns a subpool back to the main pool
647 \return SWITCH_STATUS_SUCCESS on success
648*/
649#define switch_core_destroy_memory_pool(p)switch_core_perform_destroy_memory_pool(p, "./src/include/switch_core.h"
, (const char *)__func__, 649)
switch_core_perform_destroy_memory_pool(p, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__649)
650
651
652SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_pool_set_data(switch_memory_pool_t *pool, const char *key, void *data);
653SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_memory_pool_get_data(switch_memory_pool_t *pool, const char *key);
654
655
656/*!
657 \brief Start the session's state machine
658 \param session the session on which to start the state machine
659*/
660SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_run(_In_ switch_core_session_t *session);
661
662/*!
663 \brief determine if the session's state machine is running
664 \param session the session on which to check
665*/
666SWITCH_DECLARE(unsigned int)__attribute__((visibility("default"))) unsigned int switch_core_session_running(_In_ switch_core_session_t *session);
667SWITCH_DECLARE(unsigned int)__attribute__((visibility("default"))) unsigned int switch_core_session_started(_In_ switch_core_session_t *session);
668
669SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_perform_permanent_alloc(_In_ switch_size_t memory, _In_z_ const char *file, _In_z_ const char *func, _In_ int line);
670
671
672/*!
673 \brief Allocate memory from the main pool with no intention of returning it
674 \param _memory the number of bytes to allocate
675 \return a void pointer to the allocated memory
676 \note this memory never goes out of scope until the core is destroyed
677*/
678#define switch_core_permanent_alloc(_memory)switch_core_perform_permanent_alloc(_memory, "./src/include/switch_core.h"
, (const char *)__func__, 678)
switch_core_perform_permanent_alloc(_memory, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__678)
679
680
681SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_perform_alloc(_In_ switch_memory_pool_t *pool, _In_ switch_size_t memory, _In_z_ const char *file,
682 _In_z_ const char *func, _In_ int line);
683
684/*!
685 \brief Allocate memory directly from a memory pool
686 \param _pool the memory pool to allocate from
687 \param _mem the number of bytes to allocate
688 \remark the memory returned has been memset to zero
689 \return a void pointer to the allocated memory
690*/
691#define switch_core_alloc(_pool, _mem)switch_core_perform_alloc(_pool, _mem, "./src/include/switch_core.h"
, (const char *)__func__, 691)
switch_core_perform_alloc(_pool, _mem, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__691)
692
693 _Ret_ SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_perform_session_alloc(_In_ switch_core_session_t *session, _In_ switch_size_t memory, const char *file,
694 const char *func, int line);
695
696/*!
697 \brief Allocate memory from a session's pool
698 \param _session the session to request memory from
699 \param _memory the amount of memory to allocate
700 \return a void pointer to the newly allocated memory
701 \note the memory will be in scope as long as the session exists
702*/
703#define switch_core_session_alloc(_session, _memory)switch_core_perform_session_alloc(_session, _memory, "./src/include/switch_core.h"
, (const char *)__func__, 703)
switch_core_perform_session_alloc(_session, _memory, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__703)
704
705
706
707SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_perform_permanent_strdup(_In_z_ const char *todup, _In_z_ const char *file, _In_z_ const char *func, _In_ int line);
708
709/*!
710 \brief Copy a string using permanent memory allocation
711 \param _todup the string to duplicate
712 \return a pointer to the newly duplicated string
713*/
714#define switch_core_permanent_strdup(_todup)switch_core_perform_permanent_strdup(_todup, "./src/include/switch_core.h"
, (const char *)__func__, 714)
switch_core_perform_permanent_strdup(_todup, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__714)
715
716
717SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_perform_session_strdup(_In_ switch_core_session_t *session, _In_z_ const char *todup, _In_z_ const char *file,
718 _In_z_ const char *func, _In_ int line);
719
720/*!
721 \brief Copy a string using memory allocation from a session's pool
722 \param _session a session to use for allocation
723 \param _todup the string to duplicate
724 \return a pointer to the newly duplicated string
725*/
726#define switch_core_session_strdup(_session, _todup)switch_core_perform_session_strdup(_session, _todup, "./src/include/switch_core.h"
, (const char *)__func__, 726)
switch_core_perform_session_strdup(_session, _todup, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__726)
727
728
729SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_perform_strdup(_In_ switch_memory_pool_t *pool, _In_z_ const char *todup, _In_z_ const char *file,
730 _In_z_ const char *func, _In_ int line);
731SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_perform_strndup(_In_ switch_memory_pool_t *pool, _In_z_ const char *todup, size_t len, _In_z_ const char *file,
732 _In_z_ const char *func, _In_ int line);
733
734/*!
735 \brief Copy a string using memory allocation from a given pool
736 \param _pool the pool to use for allocation
737 \param _todup the string to duplicate
738 \return a pointer to the newly duplicated string
739*/
740#define switch_core_strdup(_pool, _todup)switch_core_perform_strdup(_pool, _todup, "./src/include/switch_core.h"
, (const char *)__func__, 740)
switch_core_perform_strdup(_pool, _todup, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__740)
741
742#define switch_core_strndup(_pool, _todup, _len)switch_core_perform_strndup(_pool, _todup, _len, "./src/include/switch_core.h"
, (const char *)__func__, 742)
switch_core_perform_strndup(_pool, _todup, _len, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__742)
743
744/*!
745 \brief printf-style style printing routine. The data is output to a string allocated from the session
746 \param session a session to use for allocation
747 \param fmt The format of the string
748 \param ... The arguments to use while printing the data
749 \return The new string
750*/
751SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_session_sprintf(_In_ switch_core_session_t *session, _In_z_ _Printf_format_string_ const char *fmt, ...);
752
753/*!
754 \brief printf-style style printing routine. The data is output to a string allocated from the session
755 \param session a session to use for allocation
756 \param fmt The format of the string
757 \param ap The arguments to use while printing the data
758 \return The new string
759*/
760#ifndef SWIG
761SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_session_vsprintf(switch_core_session_t *session, const char *fmt, va_list ap);
762#endif
763
764/*!
765 \brief printf-style style printing routine. The data is output to a string allocated from the pool
766 \param pool a pool to use for allocation
767 \param fmt The format of the string
768 \param ... The arguments to use while printing the data
769 \return The new string
770*/
771SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_sprintf(_In_ switch_memory_pool_t *pool, _In_z_ _Printf_format_string_ const char *fmt, ...);
772
773/*!
774 \brief printf-style style printing routine. The data is output to a string allocated from the pool
775 \param pool a pool to use for allocation
776 \param fmt The format of the string
777 \param ap The arguments to use while printing the data
778 \return The new string
779*/
780#ifndef SWIG
781SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_vsprintf(switch_memory_pool_t *pool, _In_z_ _Printf_format_string_ const char *fmt, va_list ap);
782#endif
783
784/*!
785 \brief Retrieve the memory pool from a session
786 \param session the session to retrieve the pool from
787 \return the session's pool
788 \note to be used sparingly
789*/
790SWITCH_DECLARE(switch_memory_pool_t *)__attribute__((visibility("default"))) switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session);
791///\}
792
793SWITCH_DECLARE(switch_core_session_t *)__attribute__((visibility("default"))) switch_core_session_t * switch_core_session_request_xml(switch_endpoint_interface_t *endpoint_interface,
794 switch_memory_pool_t **pool, switch_xml_t xml);
795
796///\defgroup sessm Session Creation / Management
797///\ingroup core1
798///\{
799/*!
800 \brief Allocate and return a new session from the core
801 \param endpoint_interface the endpoint interface the session is to be based on
802 \param pool the pool to use for the allocation (a new one will be used if NULL)
803 \return the newly created session
804*/
805SWITCH_DECLARE(switch_core_session_t *)__attribute__((visibility("default"))) switch_core_session_t * switch_core_session_request_uuid(_In_ switch_endpoint_interface_t *endpoint_interface,
806 _In_ switch_call_direction_t direction,
807 switch_originate_flag_t originate_flags,
808 _Inout_opt_ switch_memory_pool_t **pool,
809 _In_opt_z_ const char *use_uuid);
810#define switch_core_session_request(_ep, _d, _f, _p)switch_core_session_request_uuid(_ep, _d, _f, _p, ((void*)0)) switch_core_session_request_uuid(_ep, _d, _f, _p, NULL((void*)0))
811
812SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_uuid(_In_ switch_core_session_t *session, _In_z_ const char *use_uuid);
813
814SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_perform_destroy(_Inout_ switch_core_session_t **session,
815 _In_z_ const char *file, _In_z_ const char *func, _In_ int line);
816
817/*!
818 \brief Destroy a session and return the memory pool to the core
819 \param session pointer to a pointer of the session to destroy
820 \return
821*/
822#define switch_core_session_destroy(session)switch_core_session_perform_destroy(session, "./src/include/switch_core.h"
, (const char *)__func__, 822)
switch_core_session_perform_destroy(session, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__822)
823
824SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_destroy_state(switch_core_session_t *session);
825SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_reporting_state(switch_core_session_t *session);
826SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_hangup_state(switch_core_session_t *session, switch_bool_t force);
827
828/*!
829 \brief Provide the total number of sessions
830 \return the total number of allocated sessions
831*/
832SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_session_count(void);
833
834SWITCH_DECLARE(switch_size_t)__attribute__((visibility("default"))) switch_size_t switch_core_session_get_id(_In_ switch_core_session_t *session);
835
836/*!
837 \brief Provide the current session_id
838 \return the total number of allocated sessions since core startup
839*/
840SWITCH_DECLARE(switch_size_t)__attribute__((visibility("default"))) switch_size_t switch_core_session_id(void);
841SWITCH_DECLARE(switch_size_t)__attribute__((visibility("default"))) switch_size_t switch_core_session_id_dec(void);
842
843/*!
844 \brief Allocate and return a new session from the core based on a given endpoint module name
845 \param endpoint_name the name of the endpoint module
846 \param pool the pool to use
847 \return the newly created session
848*/
849SWITCH_DECLARE(switch_core_session_t *)__attribute__((visibility("default"))) switch_core_session_t * switch_core_session_request_by_name(_In_z_ const char *endpoint_name,
850 _In_ switch_call_direction_t direction, _Inout_ switch_memory_pool_t **pool);
851
852/*!
853 \brief Launch the session thread (state machine) on a given session
854 \param session the session to activate the state machine on
855 \return SWITCH_STATUS_SUCCESS if the thread was launched
856*/
857SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_thread_launch(_In_ switch_core_session_t *session);
858
859
860SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_thread_pool_launch_thread(switch_thread_data_t **tdp);
861SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_thread_pool_launch(switch_core_session_t *session);
862
863/*!
864 \brief Retrieve a pointer to the channel object associated with a given session
865 \param session the session to retrieve from
866 \return a pointer to the channel object
867*/
868 _Ret_ SWITCH_DECLARE(switch_channel_t *)__attribute__((visibility("default"))) switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session);
869
870/*!
871 \brief Signal a session's state machine thread that a state change has occured
872*/
873SWITCH_DECLARE(switch_mutex_t *)__attribute__((visibility("default"))) switch_mutex_t * switch_core_session_get_mutex(switch_core_session_t *session);
874SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_wake_session_thread(_In_ switch_core_session_t *session);
875SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_signal_state_change(_In_ switch_core_session_t *session);
876
877/*!
878 \brief Retrieve the unique identifier from a session
879 \param session the session to retrieve the uuid from
880 \return a string representing the uuid
881*/
882SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_session_get_uuid(_In_ switch_core_session_t *session);
883
884
885/*!
886 \brief Sets the log level for a session
887 \param session the session to set the log level on
888 \return SWITCH_STATUS_SUCCESS
889*/
890SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_loglevel(switch_core_session_t *session, switch_log_level_t loglevel);
891
892
893/*!
894 \brief Get the log level for a session
895 \param session the session to get the log level from
896 \return the log level
897*/
898SWITCH_DECLARE(switch_log_level_t)__attribute__((visibility("default"))) switch_log_level_t switch_core_session_get_loglevel(switch_core_session_t *session);
899
900SWITCH_DECLARE(switch_jb_t *)__attribute__((visibility("default"))) switch_jb_t * switch_core_session_get_jb(switch_core_session_t *session, switch_media_type_t type);
901SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec);
902SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_soft_unlock(switch_core_session_t *session);
903SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target);
904SWITCH_DECLARE(switch_ivr_dmachine_t *)__attribute__((visibility("default"))) switch_ivr_dmachine_t * switch_core_session_get_dmachine(switch_core_session_t *session, switch_digit_action_target_t target);
905SWITCH_DECLARE(switch_digit_action_target_t)__attribute__((visibility("default"))) switch_digit_action_target_t switch_ivr_dmachine_get_target(switch_ivr_dmachine_t *dmachine);
906SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_ivr_dmachine_set_target(switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target);
907SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_dmachine_set_terminators(switch_ivr_dmachine_t *dmachine, const char *terminators);
908SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data);
909SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_raw_read(switch_core_session_t *session);
910
911/*!
912 \brief Retrieve the unique identifier from the core
913 \return a string representing the uuid
914*/
915SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_get_uuid(void);
916
917
918SWITCH_DECLARE(switch_core_session_t *)__attribute__((visibility("default"))) switch_core_session_t * switch_core_session_perform_locate(const char *uuid_str, const char *file, const char *func, int line);
919SWITCH_DECLARE(switch_core_session_t *)__attribute__((visibility("default"))) switch_core_session_t * switch_core_session_perform_force_locate(const char *uuid_str, const char *file, const char *func, int line);
920
921
922/*!
923 \brief Locate a session based on it's uuid
924 \param uuid_str the unique id of the session you want to find
925 \return the session or NULL
926 \note if the session was located it will have a read lock obtained which will need to be released with switch_core_session_rwunlock()
927*/
928
929#define switch_core_session_locate(uuid_str)switch_core_session_perform_locate(uuid_str, "./src/include/switch_core.h"
, (const char *)__func__, 929)
switch_core_session_perform_locate(uuid_str, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__929)
930
931/*!
932 \brief Locate a session based on it's uuid even if the channel is not ready
933 \param uuid_str the unique id of the session you want to find
934 \return the session or NULL
935 \note if the session was located it will have a read lock obtained which will need to be released with switch_core_session_rwunlock()
936*/
937
938#define switch_core_session_force_locate(uuid_str)switch_core_session_perform_force_locate(uuid_str, "./src/include/switch_core.h"
, (const char *)__func__, 938)
switch_core_session_perform_force_locate(uuid_str, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__938)
939
940
941/*!
942 \brief Retrieve a global variable from the core
943 \param varname the name of the variable
944 \return the value of the desired variable
945*/
946SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_get_variable(_In_z_ const char *varname);
947SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_get_variable_dup(_In_z_ const char *varname);
948SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_get_variable_pdup(_In_z_ const char *varname, switch_memory_pool_t *pool);
949SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_get_hostname(void);
950SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_get_switchname(void);
951
952SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_core_get_domain(switch_bool_t dup);
953
954/*!
955 \brief Add a global variable to the core
956 \param varname the name of the variable
957 \param value the value of the variable
958 \ If \p value is NULL, then \p varname is deleted.
959*/
960SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_set_variable(_In_z_ const char *varname, _In_opt_z_ const char *value);
961SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_get_variables(switch_event_t **event);
962
963/*!
964 \brief Conditionally add a global variable to the core
965 \param varname the name of the variable
966 \param value the value of the variable
967 \param val2 the value of the variable to verify against
968 \ If the global did not exist and val2=="", add global with value, return true
969 \ If the global exists with the value of val2, replace it, return true
970 \ If the global exists with a value other than val2, return false
971*/
972SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_set_var_conditional(_In_z_ const char *varname, _In_opt_z_ const char *value, _In_opt_z_ const char *val2);
973
974SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_dump_variables(_In_ switch_stream_handle_t *stream);
975
976/*!
977 \brief Hangup all sessions
978 \param cause the hangup cause to apply to the hungup channels
979*/
980SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_hupall(_In_ switch_call_cause_t cause);
981
982typedef enum {
983 SHT_NONE = 0,
984 SHT_UNANSWERED = (1 << 0),
985 SHT_ANSWERED = (1 << 1)
986} switch_hup_type_t;
987
988/*!
989 \brief Hangup all sessions which match a specific channel variable
990 \param var_name The variable name to look for
991 \param var_val The value to look for
992 \param cause the hangup cause to apply to the hungup channels
993*/
994SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_session_hupall_matching_var_ans(_In_ const char *var_name, _In_ const char *var_val, _In_
995 switch_call_cause_t cause, switch_hup_type_t type);
996SWITCH_DECLARE(switch_console_callback_match_t *)__attribute__((visibility("default"))) switch_console_callback_match_t
*
switch_core_session_findall_matching_var(const char *var_name, const char *var_val);
997#define switch_core_session_hupall_matching_var(_vn, _vv, _c)switch_core_session_hupall_matching_var_ans(_vn, _vv, _c, SHT_UNANSWERED
| SHT_ANSWERED)
switch_core_session_hupall_matching_var_ans(_vn, _vv, _c, SHT_UNANSWERED | SHT_ANSWERED)
998SWITCH_DECLARE(switch_console_callback_match_t *)__attribute__((visibility("default"))) switch_console_callback_match_t
*
switch_core_session_findall(void);
999/*!
1000 \brief Hangup all sessions which match specific channel variable(s)
1001 \param var_name The variable name to look for
1002 \param var_val The value to look for
1003 \param cause the hangup cause to apply to the hungup channels
1004*/
1005SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_session_hupall_matching_vars_ans(_In_ switch_event_t *vars, _In_
1006 switch_call_cause_t cause, switch_hup_type_t type);
1007#define switch_core_session_hupall_matching_vars(_vs, _c)switch_core_session_hupall_matching_vars_ans(_vs, _c, SHT_UNANSWERED
| SHT_ANSWERED)
switch_core_session_hupall_matching_vars_ans(_vs, _c, SHT_UNANSWERED | SHT_ANSWERED)
1008
1009/*!
1010 \brief Hangup all sessions that belong to an endpoint
1011 \param endpoint_interface The endpoint interface
1012 \param cause the hangup cause to apply to the hungup channels
1013*/
1014SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_hupall_endpoint(const switch_endpoint_interface_t *endpoint_interface, switch_call_cause_t cause);
1015
1016/*!
1017 \brief Get the session's partner (the session its bridged to)
1018 \param session The session we're searching with
1019 \param partner [out] The session's partner, or NULL if it wasnt found
1020 \return SWITCH_STATUS_SUCCESS or SWITCH_STATUS_FALSE if this session isn't bridged
1021*/
1022SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_perform_get_partner(switch_core_session_t *session, switch_core_session_t **partner,
1023 const char *file, const char *func, int line);
1024
1025#define switch_core_session_get_partner(_session, _partner)switch_core_session_perform_get_partner(_session, _partner, "./src/include/switch_core.h"
, (const char *)__func__, 1025)
switch_core_session_perform_get_partner(_session, _partner, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__1025)
1026
1027/*!
1028 \brief Send a message to another session using it's uuid
1029 \param uuid_str the unique id of the session you want to send a message to
1030 \param message the switch_core_session_message_t object to send
1031 \return the status returned by the message handler
1032*/
1033SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_message_send(_In_z_ const char *uuid_str, _In_ switch_core_session_message_t *message);
1034
1035/*!
1036 \brief Queue a message on a session
1037 \param session the session to queue the message to
1038 \param message the message to queue
1039 \return SWITCH_STATUS_SUCCESS if the message was queued
1040*/
1041SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_queue_message(_In_ switch_core_session_t *session, _In_ switch_core_session_message_t *message);
1042
1043SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_free_message(switch_core_session_message_t **message);
1044
1045
1046SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_queue_signal_data(switch_core_session_t *session, void *signal_data);
1047SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_dequeue_signal_data(switch_core_session_t *session, void **signal_data);
1048
1049/*!
1050 \brief pass an indication message on a session
1051 \param session the session to pass the message across
1052 \param indication the indication message to pass
1053 \return SWITCH_STATUS_SUCCESS if the message was passed
1054*/
1055SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_pass_indication(_In_ switch_core_session_t *session,
1056 _In_ switch_core_session_message_types_t indication);
1057
1058/*!
1059 \brief Queue an indication message on a session
1060 \param session the session to queue the message to
1061 \param indication the indication message to queue
1062 \return SWITCH_STATUS_SUCCESS if the message was queued
1063*/
1064SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_queue_indication(_In_ switch_core_session_t *session,
1065 _In_ switch_core_session_message_types_t indication);
1066
1067/*!
1068 \brief DE-Queue an message on a given session
1069 \param session the session to de-queue the message on
1070 \param message the de-queued message
1071 \return SWITCH_STATUS_SUCCESS if the message was de-queued
1072*/
1073SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_dequeue_message(_In_ switch_core_session_t *session, _Out_ switch_core_session_message_t **message);
1074
1075/*!
1076 \brief Flush a message queue on a given session
1077 \param session the session to de-queue the message on
1078 \return SWITCH_STATUS_SUCCESS if the message was de-queued
1079*/
1080SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_flush_message(_In_ switch_core_session_t *session);
1081
1082/*!
1083 \brief Queue an event on another session using its uuid
1084 \param uuid_str the unique id of the session you want to send a message to
1085 \param event the event to send
1086 \return the status returned by the message handler
1087*/
1088SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_event_send(_In_z_ const char *uuid_str, _Inout_ switch_event_t **event);
1089
1090SWITCH_DECLARE(switch_app_log_t *)__attribute__((visibility("default"))) switch_app_log_t * switch_core_session_get_app_log(_In_ switch_core_session_t *session);
1091
1092/*!
1093 \brief Execute an application on a session
1094 \param session the current session
1095 \param application_interface the interface of the application to execute
1096 \param arg application arguments
1097 \warning Has to be called from the session's thread
1098 \return the application's return value
1099*/
1100SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_exec(_In_ switch_core_session_t *session,
1101 _In_ const switch_application_interface_t *application_interface, _In_opt_z_ const char *arg);
1102
1103SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_video_reset(switch_core_session_t *session);
1104/*!
1105 \brief Execute an application on a session
1106 \param session the current session
1107 \param app the application's name
1108 \param arg application arguments
1109 \param flags pointer to a flags variable to set the applications flags to
1110 \return the application's return value
1111*/
1112SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_execute_application_get_flags(_In_ switch_core_session_t *session,
1113 _In_ const char *app, _In_opt_z_ const char *arg, _Out_opt_ int32_t *flags);
1114
1115SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg);
1116
1117SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_get_app_flags(const char *app, int32_t *flags);
1118
1119/*!
1120 \brief Execute an application on a session
1121 \param session the current session
1122 \param app the application's name
1123 \param arg application arguments
1124 \return the application's return value
1125*/
1126#define switch_core_session_execute_application(_a, _b, _c)switch_core_session_execute_application_get_flags(_a, _b, _c,
((void*)0))
switch_core_session_execute_application_get_flags(_a, _b, _c, NULL((void*)0))
1127
1128SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_session_stack_count(switch_core_session_t *session, int x);
1129
1130/*!
1131 \brief Run a dialplan and execute an extension
1132 \param session the current session
1133 \param exten the interface of the application to execute
1134 \param arg application arguments
1135 \note It does not change the channel back to CS_ROUTING, it manually calls the dialplan and executes the applications
1136 \warning Has to be called from the session's thread
1137 \return the application's return value
1138*/
1139SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_execute_exten(_In_ switch_core_session_t *session,
1140 _In_z_ const char *exten,
1141 _In_opt_z_ const char *dialplan, _In_opt_z_ const char *context);
1142
1143/*!
1144 \brief Send an event to a session translating it to it's native message format
1145 \param session the session to receive the event
1146 \param event the event to receive
1147 \return the status returned by the handler
1148*/
1149SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_receive_event(_In_ switch_core_session_t *session, _Inout_ switch_event_t **event);
1150
1151/*!
1152 \brief Retrieve private user data from a session
1153 \param session the session to retrieve from
1154 \return a pointer to the private data
1155*/
1156SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_session_get_private_class(_In_ switch_core_session_t *session, _In_ switch_pvt_class_t index);
1157#define switch_core_session_get_private(_s)switch_core_session_get_private_class(_s, SWITCH_PVT_PRIMARY) switch_core_session_get_private_class(_s, SWITCH_PVT_PRIMARY)
1158
1159/*!
1160 \brief Add private user data to a session
1161 \param session the session to add used data to
1162 \param private_info the used data to add
1163 \return SWITCH_STATUS_SUCCESS if data is added
1164*/
1165SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_private_class(_In_ switch_core_session_t *session, _In_ void *private_info, _In_ switch_pvt_class_t index);
1166#define switch_core_session_set_private(_s, _p)switch_core_session_set_private_class(_s, _p, SWITCH_PVT_PRIMARY
)
switch_core_session_set_private_class(_s, _p, SWITCH_PVT_PRIMARY)
1167
1168/*!
1169 \brief Add a logical stream to a session
1170 \param session the session to add the stream to
1171 \param private_info an optional pointer to private data for the new stream
1172 \return the stream id of the new stream
1173*/
1174SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_session_add_stream(_In_ switch_core_session_t *session, _In_opt_ void *private_info);
1175
1176/*!
1177 \brief Retreive a logical stream from a session
1178 \param session the session to add the stream to
1179 \param index the index to retrieve
1180 \return the stream
1181*/
1182SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_session_get_stream(_In_ switch_core_session_t *session, _In_ int index);
1183
1184/*!
1185 \brief Determine the number of logical streams a session has
1186 \param session the session to query
1187 \return the total number of logical streams
1188*/
1189SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_session_get_stream_count(_In_ switch_core_session_t *session);
1190
1191SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_session_get_text_buffer(switch_core_session_t *session);
1192
1193/*!
1194 \brief Launch a thread designed to exist within the scope of a given session
1195 \param session a session to allocate the thread from
1196 \param func a function to execute in the thread
1197 \param obj an arguement
1198*/
1199SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_launch_thread(_In_ switch_core_session_t *session,
1200 _In_ void *(*func) (switch_thread_t *, void *), _In_opt_ void *obj);
1201
1202/*!
1203 \brief Signal a thread using a thread session to terminate
1204 \param session the session to indicate to
1205*/
1206SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_thread_session_end(_In_ switch_core_session_t *session);
1207
1208/*!
1209 \brief Launch a service thread on a session to drop inbound data
1210 \param session the session the launch thread on
1211*/
1212SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_service_session_av(_In_ switch_core_session_t *session, switch_bool_t audio, switch_bool_t video);
1213#define switch_core_service_session(_s)switch_core_service_session_av(_s, SWITCH_TRUE, SWITCH_FALSE) switch_core_service_session_av(_s, SWITCH_TRUE, SWITCH_FALSE)
1214
1215
1216/*!
1217 \brief Request an outgoing session spawned from an existing session using a desired endpoing module
1218 \param session the originating session
1219 \param var_event switch_event_t containing paramaters
1220 \param endpoint_name the name of the module to use for the new session
1221 \param caller_profile the originator's caller profile
1222 \param new_session a NULL pointer to aim at the newly created session
1223 \param pool optional existing memory pool to donate to the session
1224 \param flags flags to use
1225 \return the cause code of the attempted call
1226*/
1227SWITCH_DECLARE(switch_call_cause_t)__attribute__((visibility("default"))) switch_call_cause_t switch_core_session_outgoing_channel(_In_opt_ switch_core_session_t *session,
1228 _In_opt_ switch_event_t *var_event,
1229 _In_z_ const char *endpoint_name,
1230 _In_ switch_caller_profile_t *caller_profile,
1231 _Inout_ switch_core_session_t **new_session,
1232 _Inout_ switch_memory_pool_t **pool, _In_ switch_originate_flag_t flags,
1233 switch_call_cause_t *cancel_cause);
1234
1235/*!
1236 \brief Receive a message on a given session
1237 \param session the session to receive the message from
1238 \param message the message to recieve
1239 \return the status returned by the message handler
1240*/
1241SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_perform_receive_message(_In_ switch_core_session_t *session,
1242 _In_ switch_core_session_message_t *message,
1243 const char *file, const char *func, int line);
1244#define switch_core_session_receive_message(_session, _message)switch_core_session_perform_receive_message(_session, _message
, "./src/include/switch_core.h", (const char *)__func__, 1244
)
switch_core_session_perform_receive_message(_session, _message, \
1245 __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__1245)
1246
1247/*!
1248 \brief Queue an event on a given session
1249 \param session the session to queue the message on
1250 \param event the event to queue
1251 \return the status returned by the message handler
1252*/
1253SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_queue_event(_In_ switch_core_session_t *session, _Inout_ switch_event_t **event);
1254
1255
1256/*!
1257 \brief Indicate the number of waiting events on a session
1258 \param session the session to check
1259 \return the number of events
1260*/
1261SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_session_event_count(_In_ switch_core_session_t *session);
1262
1263/*
1264 Number of parsable messages waiting on the session.
1265 */
1266SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_session_messages_waiting(switch_core_session_t *session);
1267
1268/*!
1269 \brief DE-Queue an event on a given session
1270 \param session the session to de-queue the message on
1271 \param event the de-queued event
1272 \param force force the dequeue
1273 \return the SWITCH_STATUS_SUCCESS if the event was de-queued
1274*/
1275SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_dequeue_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event, switch_bool_t force);
1276
1277/*!
1278 \brief Queue a private event on a given session
1279 \param session the session to queue the message on
1280 \param event the event to queue
1281 \param priority event has high priority
1282 \return the status returned by the message handler
1283*/
1284SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_queue_private_event(_In_ switch_core_session_t *session, _Inout_ switch_event_t **event,
1285 switch_bool_t priority);
1286
1287
1288/*!
1289 \brief Indicate the number of waiting private events on a session
1290 \param session the session to check
1291 \return the number of events
1292*/
1293SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_session_private_event_count(_In_ switch_core_session_t *session);
1294
1295/*!
1296 \brief DE-Queue a private event on a given session
1297 \param session the session to de-queue the message on
1298 \param event the de-queued event
1299 \return the SWITCH_STATUS_SUCCESS if the event was de-queued
1300*/
1301SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_dequeue_private_event(_In_ switch_core_session_t *session, _Out_ switch_event_t **event);
1302
1303
1304/*!
1305 \brief Flush the private event queue of a session
1306 \param session the session to flush
1307 \return SWITCH_STATUS_SUCCESS if the events have been flushed
1308*/
1309SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_session_flush_private_events(switch_core_session_t *session);
1310
1311
1312/*!
1313 \brief Read a frame from a session
1314 \param session the session to read from
1315 \param frame a NULL pointer to a frame to aim at the newly read frame
1316 \param flags I/O flags to modify behavior (i.e. non blocking)
1317 \param stream_id which logical media channel to use
1318 \return SWITCH_STATUS_SUCCESS a the frame was read
1319*/
1320SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
1321 int stream_id);
1322
1323SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_session_transcoding(switch_core_session_t *session_a, switch_core_session_t *session_b, switch_media_type_t type);
1324SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_passthru(switch_core_session_t *session, switch_media_type_t type, switch_bool_t on);
1325
1326/*!
1327 \brief Read a video frame from a session
1328 \param session the session to read from
1329 \param frame a NULL pointer to a frame to aim at the newly read frame
1330 \param flags I/O flags to modify behavior (i.e. non blocking)
1331 \param stream_id which logical media channel to use
1332 \return SWITCH_STATUS_SUCCESS a if the frame was read
1333*/
1334SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_read_video_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags,
1335 int stream_id);
1336/*!
1337 \brief Write a video frame to a session
1338 \param session the session to write to
1339 \param frame a pointer to a frame to write
1340 \param flags I/O flags to modify behavior (i.e. non blocking)
1341 \param stream_id which logical media channel to use
1342 \return SWITCH_STATUS_SUCCESS a if the frame was written
1343*/
1344SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_write_video_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags,
1345 int stream_id);
1346
1347SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_write_encoded_video_frame(switch_core_session_t *session,
1348 switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
1349
1350SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_read_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp);
1351SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_write_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp);
1352SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_video_read_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp);
1353SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_video_write_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp);
1354
1355/*!
1356 \brief Reset the buffers and resampler on a session
1357 \param session the session to reset
1358 \param flush_dtmf flush all queued dtmf events too
1359*/
1360SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec);
1361
1362/*!
1363 \brief Reset the buffers and resampler on a session, fail if can not lock codec mutexes
1364 \param session the session to reset
1365 \param flush_dtmf flush all queued dtmf events too
1366 \return SWITCH_STATUS_SUCCESS if the session was reset
1367*/
1368SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_try_reset(switch_core_session_t* session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec);
1369
1370/*!
1371 \brief Write a frame to a session
1372 \param session the session to write to
1373 \param frame the frame to write
1374 \param flags I/O flags to modify behavior (i.e. non blocking)
1375 \param stream_id which logical media channel to use
1376 \return SWITCH_STATUS_SUCCESS a the frame was written
1377*/
1378SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_write_frame(_In_ switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags,
1379 int stream_id);
1380
1381
1382SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_perform_kill_channel(_In_ switch_core_session_t *session,
1383 const char *file, const char *func, int line, switch_signal_t sig);
1384/*!
1385 \brief Send a signal to a channel
1386 \param session session to send signal to
1387 \param sig signal to send
1388 \return status returned by the session's signal handler
1389*/
1390#define switch_core_session_kill_channel(session, sig)switch_core_session_perform_kill_channel(session, "./src/include/switch_core.h"
, (const char *)__func__, 1390, sig)
switch_core_session_perform_kill_channel(session, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__1390, sig)
1391
1392/*!
1393 \brief Send DTMF to a session
1394 \param session session to send DTMF to
1395 \param dtmf dtmf to send to the session
1396 \return SWITCH_STATUS_SUCCESS if the dtmf was written
1397*/
1398SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_send_dtmf(_In_ switch_core_session_t *session, const switch_dtmf_t *dtmf);
1399/*!
1400 \brief Send DTMF to a session
1401 \param session session to send DTMF to
1402 \param dtmf_string string to send to the session
1403 \return SWITCH_STATUS_SUCCESS if the dtmf was written
1404*/
1405SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_send_dtmf_string(switch_core_session_t *session, const char *dtmf_string);
1406
1407/*!
1408 \brief RECV DTMF on a session
1409 \param session session to recv DTMF from
1410 \param dtmf string to recv from the session
1411 \return SWITCH_STATUS_SUCCESS if the dtmf is ok to queue
1412*/
1413SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_recv_dtmf(_In_ switch_core_session_t *session, const switch_dtmf_t *dtmf);
1414
1415///\}
1416
1417
1418///\defgroup hashf Hash Functions
1419///\ingroup core1
1420///\{
1421/*!
1422 \brief Initialize a hash table
1423 \param hash a NULL pointer to a hash table to aim at the new hash
1424 \param pool the pool to use for the new hash
1425 \return SWITCH_STATUS_SUCCESS if the hash is created
1426*/
1427SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_hash_init_case(_Out_ switch_hash_t **hash, switch_bool_t case_sensitive);
1428#define switch_core_hash_init(_hash)switch_core_hash_init_case(_hash, SWITCH_TRUE) switch_core_hash_init_case(_hash, SWITCH_TRUE)
1429#define switch_core_hash_init_nocase(_hash)switch_core_hash_init_case(_hash, SWITCH_FALSE) switch_core_hash_init_case(_hash, SWITCH_FALSE)
1430
1431
1432/*!
1433 \brief Destroy an existing hash table
1434 \param hash the hash to destroy
1435 \return SWITCH_STATUS_SUCCESS if the hash is destroyed
1436*/
1437SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_hash_destroy(_Inout_ switch_hash_t **hash);
1438
1439/*!
1440 \brief Insert data into a hash and set flags so the value is automatically freed on delete
1441 \param hash the hash to add data to
1442 \param key the name of the key to add the data to
1443 \param data the data to add
1444 \return SWITCH_STATUS_SUCCESS if the data is added
1445 \note the string key must be a constant or a dynamic string
1446*/
1447SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_hash_insert_auto_free(switch_hash_t *hash, const char *key, const void *data);
1448
1449/*!
1450 \brief Insert data into a hash
1451 \param hash the hash to add data to
1452 \param key the name of the key to add the data to
1453 \param data the data to add
1454 \return SWITCH_STATUS_SUCCESS if the data is added
1455 \note the string key must be a constant or a dynamic string
1456*/
1457SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_hash_insert_destructor(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ const void *data, hashtable_destructor_t destructor);
1458#define switch_core_hash_insert(_h, _k, _d)switch_core_hash_insert_destructor(_h, _k, _d, ((void*)0)) switch_core_hash_insert_destructor(_h, _k, _d, NULL((void*)0))
1459
1460/*!
1461 \brief Allocate memory and insert into a hash
1462 \param hash the hash to add data to
1463 \param key the name of the key to add the data to
1464 \param size the size in bytes to allocate
1465 \return pointer to the allocated memory
1466 \note the string key must be a constant or a dynamic string
1467*/
1468SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_hash_insert_alloc_destructor(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ size_t size, hashtable_destructor_t destructor);
1469#define switch_core_hash_insert_alloc(_h, _k, _s)switch_core_hash_insert_alloc_destructor(_h, _k, _s, ((void*)
0))
switch_core_hash_insert_alloc_destructor(_h, _k, _s, NULL((void*)0))
1470
1471/*!
1472 \brief Insert strdup(data) into a hash
1473 \param hash the hash to add data to
1474 \param key the name of the key to add the data to
1475 \param data string to strdup and add
1476 \return SWITCH_STATUS_SUCCESS if the data is added
1477 \note the string key must be a constant or a dynamic string
1478*/
1479SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_hash_insert_dup_destructor(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ const char *str, hashtable_destructor_t destructor);
1480#define switch_core_hash_insert_dup(_h, _k, _d)switch_core_hash_insert_dup_destructor(_h, _k, _d, ((void*)0)
)
switch_core_hash_insert_dup_destructor(_h, _k, _d, NULL((void*)0))
1481
1482
1483/*!
1484 \brief Insert data into a hash
1485 \param hash the hash to add data to
1486 \param key the name of the key to add the data to
1487 \param data the data to add
1488 \param mutex optional mutex to lock
1489 \return SWITCH_STATUS_SUCCESS if the data is added
1490 \note the string key must be a constant or a dynamic string
1491*/
1492SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_hash_insert_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ const void *data,
1493 _In_opt_ switch_mutex_t *mutex);
1494/*!
1495 \brief Retrieve data from a given hash
1496 \param hash the hash to retrieve from
1497 \param key the key to retrieve
1498 \param mutex optional rwlock to wrlock
1499 \return a pointer to the data held in the key
1500*/
1501SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_hash_insert_wrlock(switch_hash_t *hash, const char *key, const void *data, switch_thread_rwlock_t *rwlock);
1502
1503/*!
1504 \brief Delete data from a hash based on desired key
1505 \param hash the hash to delete from
1506 \param key the key from which to delete the data
1507 \return The value stored if the data is deleted otherwise NULL
1508*/
1509SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_hash_delete(_In_ switch_hash_t *hash, _In_z_ const char *key);
1510
1511/*!
1512 \brief Delete data from a hash based on desired key
1513 \param hash the hash to delete from
1514 \param key the key from which to delete the data
1515 \param mutex optional mutex to lock
1516 \return a pointer to the deleted data
1517*/
1518SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_hash_delete_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ switch_mutex_t *mutex);
1519
1520/*!
1521 \brief Delete data from a hash based on desired key
1522 \param hash the hash to delete from
1523 \param key the key from which to delete the data
1524 \param mutex optional rwlock to wrlock
1525 \return a pointer to the deleted data
1526*/
1527SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_hash_delete_wrlock(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ switch_thread_rwlock_t *rwlock);
1528
1529/*!
1530 \brief Delete data from a hash based on callback function
1531 \param hash the hash to delete from
1532 \param callback the function to call which returns SWITCH_TRUE to delete, SWITCH_FALSE to preserve
1533 \return SWITCH_STATUS_SUCCESS if any data is deleted
1534*/
1535SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_hash_delete_multi(_In_ switch_hash_t *hash, _In_ switch_hash_delete_callback_t callback, _In_opt_ void *pData);
1536
1537/*!
1538 \brief Retrieve data from a given hash
1539 \param hash the hash to retrieve from
1540 \param key the key to retrieve
1541 \return a pointer to the data held in the key
1542*/
1543SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_hash_find(_In_ switch_hash_t *hash, _In_z_ const char *key);
1544
1545
1546/*!
1547 \brief Retrieve data from a given hash
1548 \param hash the hash to retrieve from
1549 \param key the key to retrieve
1550 \param mutex optional mutex to lock
1551 \return a pointer to the data held in the key
1552*/
1553SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_hash_find_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_mutex_t *mutex);
1554
1555/*!
1556 \brief Retrieve data from a given hash
1557 \param hash the hash to retrieve from
1558 \param key the key to retrieve
1559 \param mutex optional rwlock to rdlock
1560 \return a pointer to the data held in the key
1561*/
1562SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_hash_find_rdlock(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_thread_rwlock_t *rwlock);
1563
1564/*!
1565 \brief Gets the first element of a hashtable
1566 \param deprecate_me [deprecated] NULL
1567 \param hash the hashtable to use
1568 \return The element, or NULL if it wasn't found
1569*/
1570SWITCH_DECLARE(switch_hash_index_t *)__attribute__((visibility("default"))) switch_hash_index_t * switch_core_hash_first_iter(_In_ switch_hash_t *hash, switch_hash_index_t *hi);
1571#define switch_core_hash_first(_h)switch_core_hash_first_iter(_h, ((void*)0)) switch_core_hash_first_iter(_h, NULL((void*)0))
1572
1573/*!
1574 \brief tells if a hash is empty
1575 \param hash the hashtable
1576 \return TRUE or FALSE depending on if the hash is empty
1577*/
1578SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_hash_empty(switch_hash_t *hash);
1579
1580/*!
1581 \brief Gets the next element of a hashtable
1582 \param hi The current element
1583 \return The next element, or NULL if there are no more
1584*/
1585SWITCH_DECLARE(switch_hash_index_t *)__attribute__((visibility("default"))) switch_hash_index_t * switch_core_hash_next(_In_ switch_hash_index_t **hi);
1586
1587/*!
1588 \brief Gets the key and value of the current hash element
1589 \param hi The current element
1590 \param key [out] the key
1591 \param klen [out] the key's size
1592 \param val [out] the value
1593*/
1594SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_hash_this(_In_ switch_hash_index_t *hi, _Out_opt_ptrdiff_cap_(klen)
1595 const void **key, _Out_opt_ switch_ssize_t *klen, _Out_ void **val);
1596
1597SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_hash_this_val(switch_hash_index_t *hi, void *val);
1598
1599SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_inthash_init(switch_inthash_t **hash);
1600SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_inthash_destroy(switch_inthash_t **hash);
1601SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_inthash_insert(switch_inthash_t *hash, uint32_t key, const void *data);
1602SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_inthash_delete(switch_inthash_t *hash, uint32_t key);
1603SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_inthash_find(switch_inthash_t *hash, uint32_t key);
1604
1605///\}
1606
1607///\defgroup timer Timer Functions
1608///\ingroup core1
1609///\{
1610/*!
1611 \brief Request a timer handle using given time module
1612 \param timer a timer object to allocate to
1613 \param timer_name the name of the timer module to use
1614 \param interval desired interval
1615 \param samples the number of samples to increment on each cycle
1616 \param pool the memory pool to use for allocation
1617 \return
1618*/
1619SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_init(switch_timer_t *timer, const char *timer_name, int interval, int samples,
1620 switch_memory_pool_t *pool);
1621
1622SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_calibrate_clock(void);
1623
1624/*!
1625 \brief Wait for one cycle on an existing timer
1626 \param timer the timer to wait on
1627 \return the newest sample count
1628*/
1629SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_next(switch_timer_t *timer);
1630
1631/*!
1632 \brief Step the timer one step
1633 \param timer the timer to wait on
1634 \return the newest sample count
1635*/
1636SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_step(switch_timer_t *timer);
1637
1638SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_sync(switch_timer_t *timer);
1639
1640/*!
1641 \brief Check if the current step has been exceeded
1642 \param timer the timer to wait on
1643 \param step increment timer if a tick was detected
1644 \return the newest sample count
1645*/
1646SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_check(switch_timer_t *timer, switch_bool_t step);
1647
1648/*!
1649 \brief Destroy an allocated timer
1650 \param timer timer to destroy
1651 \return SWITCH_STATUS_SUCCESS after destruction
1652*/
1653SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_destroy(switch_timer_t *timer);
1654///\}
1655
1656///\defgroup codecs Codec Functions
1657///\ingroup core1
1658///\{
1659/*!
1660 \brief Initialize a codec handle
1661 \param codec the handle to initilize
1662 \param codec_name the name of the codec module to use
1663 \param fmtp codec parameters to send
1664 \param rate the desired rate (0 for any)
1665 \param ms the desired number of milliseconds (0 for any)
1666 \param channels the desired number of channels (0 for any)
1667 \param flags flags to alter behaviour
1668 \param codec_settings desired codec settings
1669 \param pool the memory pool to use
1670 \return SWITCH_STATUS_SUCCESS if the handle is allocated
1671*/
1672#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)switch_core_codec_init_with_bitrate(_codec, _codec_name, _modname
, _fmtp, _rate, _ms, _channels, 0, _flags, _codec_settings, _pool
)
\
1673 switch_core_codec_init_with_bitrate(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, 0, _flags, _codec_settings, _pool)
1674SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_init_with_bitrate(switch_codec_t *codec,
1675 const char *codec_name,
1676 const char *fmtp,
1677 const char *modname,
1678 uint32_t rate,
1679 int ms,
1680 int channels,
1681 uint32_t bitrate,
1682 uint32_t flags,
1683 const switch_codec_settings_t *codec_settings,
1684 switch_memory_pool_t *pool);
1685
1686SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_copy(switch_codec_t *codec, switch_codec_t *new_codec,
1687 const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool);
1688SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_parse_fmtp(const char *codec_name, const char *fmtp, uint32_t rate, switch_codec_fmtp_t *codec_fmtp);
1689SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_reset(switch_codec_t *codec);
1690
1691/*!
1692 \brief Encode data using a codec handle
1693 \param codec the codec handle to use
1694 \param other_codec the codec handle of the last codec used
1695 \param decoded_data the raw data
1696 \param decoded_data_len then length of the raw buffer
1697 \param decoded_rate the rate of the decoded data
1698 \param encoded_data the buffer to write the encoded data to
1699 \param encoded_data_len the size of the encoded_data buffer
1700 \param encoded_rate the new rate of the encoded data
1701 \param flag flags to exchange
1702 \return SWITCH_STATUS_SUCCESS if the data was encoded
1703 \note encoded_data_len will be rewritten to the in-use size of encoded_data
1704*/
1705SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_encode(switch_codec_t *codec,
1706 switch_codec_t *other_codec,
1707 void *decoded_data,
1708 uint32_t decoded_data_len,
1709 uint32_t decoded_rate,
1710 void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag);
1711
1712/*!
1713 \brief Decode data using a codec handle
1714 \param codec the codec handle to use
1715 \param other_codec the codec handle of the last codec used
1716 \param encoded_data the buffer to read the encoded data from
1717 \param encoded_data_len the size of the encoded_data buffer
1718 \param encoded_rate the rate of the encoded data
1719 \param decoded_data the raw data buffer
1720 \param decoded_data_len then length of the raw buffer
1721 \param decoded_rate the new rate of the decoded data
1722 \param flag flags to exchange
1723 \return SWITCH_STATUS_SUCCESS if the data was decoded
1724 \note decoded_data_len will be rewritten to the in-use size of decoded_data
1725*/
1726SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_decode(switch_codec_t *codec,
1727 switch_codec_t *other_codec,
1728 void *encoded_data,
1729 uint32_t encoded_data_len,
1730 uint32_t encoded_rate,
1731 void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag);
1732
1733/*!
1734 \brief Encode video data using a codec handle
1735 \param codec the codec handle to use
1736 \param frame the frame to encode
1737*/
1738SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_encode_video(switch_codec_t *codec, switch_frame_t *frame);
1739
1740
1741/*!
1742 \brief send control data using a codec handle
1743 \param codec the codec handle to use
1744 \param cmd the command to send
1745 \param ctype the type of the arguement
1746 \param cmd_data a void pointer to the data matching the passed type
1747 \param atype the type of the extra arguement
1748 \param cmd_arg a void pointer to the data matching the passed type
1749 \param rtype the type of the response if any
1750 \param ret_data a void pointer to a pointer of return data
1751 \return SWITCH_STATUS_SUCCESS if the command was received
1752*/
1753SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_control(switch_codec_t *codec,
1754 switch_codec_control_command_t cmd,
1755 switch_codec_control_type_t ctype,
1756 void *cmd_data,
1757 switch_codec_control_type_t atype,
1758 void *cmd_arg,
1759 switch_codec_control_type_t *rtype,
1760 void **ret_data);
1761
1762/*!
1763 \brief Decode video data using a codec handle
1764 \param codec the codec handle to use
1765 \param frame the frame to be decoded
1766 \param img the new image in I420 format, allocated by the codec
1767 \param flag flags to exchange
1768 \return SWITCH_STATUS_SUCCESS if the data was decoded, and a non-NULL img
1769*/
1770SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_decode_video(switch_codec_t *codec, switch_frame_t *frame);
1771
1772/*!
1773 \brief Destroy an initalized codec handle
1774 \param codec the codec handle to destroy
1775 \return SWITCH_STATUS_SUCCESS if the codec was destroyed
1776*/
1777SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_destroy(switch_codec_t *codec);
1778
1779/*!
1780 \brief Assign the read codec to a given session
1781 \param session session to add the codec to
1782 \param codec the codec to add
1783 \return SWITCH_STATUS_SUCCESS if successful
1784*/
1785SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_read_codec(_In_ switch_core_session_t *session, switch_codec_t *codec);
1786
1787/*!
1788 \brief Assign the original read codec to a given session. This is the read codec used by an endpoint.
1789 \param session session to add the codec to
1790 \param codec the codec to add
1791 \return SWITCH_STATUS_SUCCESS if successful
1792*/
1793SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_real_read_codec(_In_ switch_core_session_t *session, switch_codec_t *codec);
1794
1795SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_unset_read_codec(_In_ switch_core_session_t *session);
1796SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_unset_write_codec(_In_ switch_core_session_t *session);
1797
1798
1799SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_lock_codec_write(_In_ switch_core_session_t *session);
1800SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_unlock_codec_write(_In_ switch_core_session_t *session);
1801SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_lock_codec_read(_In_ switch_core_session_t *session);
1802SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_unlock_codec_read(_In_ switch_core_session_t *session);
1803
1804
1805SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp);
1806SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_get_real_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp);
1807SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_get_write_impl(switch_core_session_t *session, switch_codec_implementation_t *impp);
1808SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_get_video_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp);
1809SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_get_video_write_impl(switch_core_session_t *session, switch_codec_implementation_t *impp);
1810
1811
1812/*!
1813 \brief Retrieve the read codec from a given session
1814 \param session session to retrieve from
1815 \return a pointer to the codec
1816*/
1817SWITCH_DECLARE(switch_codec_t *)__attribute__((visibility("default"))) switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session);
1818
1819/*!
1820 \brief Retrieve the effevtive read codec from a given session
1821 \param session session to retrieve from
1822 \return a pointer to the codec
1823*/
1824SWITCH_DECLARE(switch_codec_t *)__attribute__((visibility("default"))) switch_codec_t * switch_core_session_get_effective_read_codec(_In_ switch_core_session_t *session);
1825
1826/*!
1827 \brief Assign the write codec to a given session
1828 \param session session to add the codec to
1829 \param codec the codec to add
1830 \return SWITCH_STATUS_SUCCESS if successful
1831*/
1832SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_write_codec(_In_ switch_core_session_t *session, switch_codec_t *codec);
1833
1834/*!
1835 \brief Retrieve the write codec from a given session
1836 \param session session to retrieve from
1837 \return a pointer to the codec
1838*/
1839SWITCH_DECLARE(switch_codec_t *)__attribute__((visibility("default"))) switch_codec_t * switch_core_session_get_write_codec(_In_ switch_core_session_t *session);
1840
1841/*!
1842 \brief Retrieve the effevtive write codec from a given session
1843 \param session session to retrieve from
1844 \return a pointer to the codec
1845*/
1846SWITCH_DECLARE(switch_codec_t *)__attribute__((visibility("default"))) switch_codec_t * switch_core_session_get_effective_write_codec(_In_ switch_core_session_t *session);
1847
1848/*!
1849 \brief Assign the video_read codec to a given session
1850 \param session session to add the codec to
1851 \param codec the codec to add
1852 \return SWITCH_STATUS_SUCCESS if successful
1853*/
1854SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_video_read_codec(_In_ switch_core_session_t *session, switch_codec_t *codec);
1855
1856/*!
1857 \brief Retrieve the video_read codec from a given session
1858 \param session session to retrieve from
1859 \return a pointer to the codec
1860*/
1861SWITCH_DECLARE(switch_codec_t *)__attribute__((visibility("default"))) switch_codec_t * switch_core_session_get_video_read_codec(_In_ switch_core_session_t *session);
1862
1863/*!
1864 \brief Assign the video_write codec to a given session
1865 \param session session to add the codec to
1866 \param codec the codec to add
1867 \return SWITCH_STATUS_SUCCESS if successful
1868*/
1869SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_video_write_codec(_In_ switch_core_session_t *session, switch_codec_t *codec);
1870
1871/*!
1872 \brief Retrieve the video_write codec from a given session
1873 \param session session to retrieve from
1874 \return a pointer to the codec
1875*/
1876SWITCH_DECLARE(switch_codec_t *)__attribute__((visibility("default"))) switch_codec_t * switch_core_session_get_video_write_codec(_In_ switch_core_session_t *session);
1877
1878///\}
1879///\defgroup db Database Functions
1880///\ingroup core1
1881///\{
1882/*!
1883 \brief Open a core db (SQLite) file
1884 \param filename the path to the db file to open
1885 \return the db handle
1886*/
1887SWITCH_DECLARE(switch_core_db_t *)__attribute__((visibility("default"))) switch_core_db_t * switch_core_db_open_file(const char *filename);
1888
1889/*!
1890 \brief Open a core db (SQLite) in-memory
1891 \param uri to the db to open
1892 \return the db handle
1893*/
1894SWITCH_DECLARE(switch_core_db_t *)__attribute__((visibility("default"))) switch_core_db_t * switch_core_db_open_in_memory(const char *uri);
1895
1896/*!
1897 \brief Execute a sql stmt until it is accepted
1898 \param db the db handle
1899 \param sql the sql to execute
1900 \param retries the number of retries to use
1901 \return SWITCH_STATUS_SUCCESS if successful
1902
1903*/
1904SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_db_persistant_execute(switch_core_db_t *db, char *sql, uint32_t retries);
1905SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_db_persistant_execute_trans(switch_core_db_t *db, char *sql, uint32_t retries);
1906SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_db_persistant_execute_trans(switch_core_db_t *db, char *sql, uint32_t retries);
1907
1908
1909
1910/*!
1911 \brief perform a test query then perform a reactive query if the first one fails
1912 \param db the db handle
1913 \param test_sql the test sql
1914 \param drop_sql the drop sql
1915 \param reactive_sql the reactive sql
1916*/
1917SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_db_test_reactive(switch_core_db_t *db, char *test_sql, char *drop_sql, char *reactive_sql);
1918
1919///\}
1920
1921///\defgroup Media File Functions
1922///\ingroup core1
1923///\{
1924
1925SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_perform_file_open(const char *file, const char *func, int line,
1926 _In_ switch_file_handle_t *fh,
1927 _In_opt_z_ const char *file_path,
1928 _In_ uint32_t channels,
1929 _In_ uint32_t rate, _In_ unsigned int flags, _In_opt_ switch_memory_pool_t *pool);
1930
1931/*!
1932 \brief Open a media file using file format modules
1933 \param _fh a file handle to use
1934 \param _file_path the path to the file
1935 \param _channels the number of channels
1936 \param _rate the sample rate
1937 \param _flags read/write flags
1938 \param _pool the pool to use (NULL for new pool)
1939 \return SWITCH_STATUS_SUCCESS if the file is opened
1940 \note the loadable module used is chosen based on the file extension
1941*/
1942#define switch_core_file_open(_fh, _file_path, _channels, _rate, _flags, _pool)switch_core_perform_file_open("./src/include/switch_core.h", (
const char *)__func__, 1942, _fh, _file_path, _channels, _rate
, _flags, _pool)
\
1943 switch_core_perform_file_open(__FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__1943, _fh, _file_path, _channels, _rate, _flags, _pool)
1944
1945/*!
1946 \brief Read media from a file handle
1947 \param fh the file handle to read from (must be initilized by you memset all 0 for read, fill in channels and rate for write)
1948 \param data the buffer to read the data to
1949 \param len the max size of the buffer
1950 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes read if successful
1951*/
1952SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_read(_In_ switch_file_handle_t *fh, void *data, switch_size_t *len);
1953
1954/*!
1955 \brief Write media to a file handle
1956 \param fh the file handle to write to
1957 \param data the buffer to write
1958 \param len the amount of data to write from the buffer
1959 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes written if successful
1960*/
1961SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_write(_In_ switch_file_handle_t *fh, void *data, switch_size_t *len);
1962
1963/*!
1964 \brief Write media to a file handle
1965 \param fh the file handle to write to
1966 \param data the buffer to write
1967 \param len the amount of data to write from the buffer
1968 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes written if successful
1969*/
1970SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_write_video(_In_ switch_file_handle_t *fh, switch_frame_t *frame);
1971SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_read_video(switch_file_handle_t *fh, switch_frame_t *frame, switch_video_read_flag_t flags);
1972
1973/*!
1974 \brief Seek a position in a file
1975 \param fh the file handle to seek
1976 \param cur_pos the current position in the file
1977 \param samples the amount of samples to seek from the beginning of the file
1978 \param whence the indicator (see traditional seek)
1979 \return SWITCH_STATUS_SUCCESS with cur_pos adjusted to new position
1980*/
1981SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_seek(_In_ switch_file_handle_t *fh, unsigned int *cur_pos, int64_t samples, int whence);
1982
1983/*!
1984 \brief Set metadata to the desired string
1985 \param fh the file handle to set data to
1986 \param col the enum of the col name
1987 \param string the string to add
1988 \return SWITCH_STATUS_SUCCESS with cur_pos adjusted to new position
1989*/
1990SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_set_string(_In_ switch_file_handle_t *fh, switch_audio_col_t col, const char *string);
1991
1992/*!
1993 \brief get metadata of the desired string
1994 \param fh the file handle to get data from
1995 \param col the enum of the col name
1996 \param string pointer to the string to fetch
1997 \return SWITCH_STATUS_SUCCESS with cur_pos adjusted to new position
1998*/
1999SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_get_string(_In_ switch_file_handle_t *fh, switch_audio_col_t col, const char **string);
2000
2001/*!
2002 \brief Pre close an open file handle, then can get file size etc., no more wirte to the file
2003 \param fh the file handle to close
2004 \return SWITCH_STATUS_SUCCESS if the file handle was pre closed
2005*/
2006SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_pre_close(_In_ switch_file_handle_t *fh);
2007
2008/*!
2009 \brief Duplicates a file handle using another pool
2010 \param oldfh the file handle to duplicate
2011 \param newfh pointer to assign new file handle to
2012 \param pool the pool to use (NULL for new pool)
2013 \return SWITCH_STATUS_SUCCESS if the file handle was duplicated
2014*/
2015
2016SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_handle_dup(switch_file_handle_t *oldfh, switch_file_handle_t **newfh, switch_memory_pool_t *pool);
2017
2018/*!
2019 \brief Close an open file handle
2020 \param fh the file handle to close
2021 \return SWITCH_STATUS_SUCCESS if the file handle was closed
2022*/
2023SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_close(_In_ switch_file_handle_t *fh);
2024
2025SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_command(switch_file_handle_t *fh, switch_file_command_t command);
2026
2027SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_truncate(switch_file_handle_t *fh, int64_t offset);
2028SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_file_has_video(switch_file_handle_t *fh, switch_bool_t CHECK_OPEN);
2029
2030
2031///\}
2032
2033///\defgroup speech ASR/TTS Functions
2034///\ingroup core1
2035///\{
2036/*!
2037 \brief Open a speech handle
2038 \param sh a speech handle to use
2039 \param module_name the speech module to use
2040 \param voice_name the desired voice name
2041 \param rate the sampling rate
2042 \param interval the sampling interval
2043 \param flags tts flags
2044 \param pool the pool to use (NULL for new pool)
2045 \return SWITCH_STATUS_SUCCESS if the handle is opened
2046*/
2047SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_speech_open(_In_ switch_speech_handle_t *sh,
2048 const char *module_name,
2049 const char *voice_name,
2050 _In_ unsigned int rate,
2051 _In_ unsigned int interval,
2052 _In_ unsigned int channels,
2053 switch_speech_flag_t *flags, _In_opt_ switch_memory_pool_t *pool);
2054/*!
2055 \brief Feed text to the TTS module
2056 \param sh the speech handle to feed
2057 \param text the buffer to write
2058 \param flags flags in/out for fine tuning
2059 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes written if successful
2060*/
2061SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_speech_feed_tts(switch_speech_handle_t *sh, const char *text, switch_speech_flag_t *flags);
2062
2063/*!
2064 \brief Flush TTS audio on a given handle
2065 \param sh the speech handle
2066*/
2067SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_speech_flush_tts(switch_speech_handle_t *sh);
2068
2069/*!
2070 \brief Set a text parameter on a TTS handle
2071 \param sh the speech handle
2072 \param param the parameter
2073 \param val the value
2074*/
2075SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_speech_text_param_tts(switch_speech_handle_t *sh, char *param, const char *val);
2076
2077/*!
2078 \brief Set a numeric parameter on a TTS handle
2079 \param sh the speech handle
2080 \param param the parameter
2081 \param val the value
2082*/
2083SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_speech_numeric_param_tts(switch_speech_handle_t *sh, char *param, int val);
2084
2085/*!
2086 \brief Set a float parameter on a TTS handle
2087 \param sh the speech handle
2088 \param param the parameter
2089 \param val the value
2090*/
2091SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_speech_float_param_tts(switch_speech_handle_t *sh, char *param, double val);
2092
2093/*!
2094 \brief Read rendered audio from the TTS module
2095 \param sh the speech handle to read
2096 \param data the buffer to read to
2097 \param datalen the max size / written size of the data
2098 \param rate the rate of the read audio
2099 \param flags flags in/out for fine tuning
2100 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes written if successful
2101*/
2102SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_speech_read_tts(switch_speech_handle_t *sh, void *data, switch_size_t *datalen, switch_speech_flag_t *flags);
2103/*!
2104 \brief Close an open speech handle
2105 \param sh the speech handle to close
2106 \param flags flags in/out for fine tuning
2107 \return SWITCH_STATUS_SUCCESS if the file handle was closed
2108*/
2109SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags);
2110
2111
2112/*!
2113 \brief Open an asr handle
2114 \param ah the asr handle to open
2115 \param module_name the name of the asr module
2116 \param codec the preferred codec
2117 \param rate the preferred rate
2118 \param dest the destination address
2119 \param flags flags to influence behaviour
2120 \param pool the pool to use (NULL for new pool)
2121 \return SWITCH_STATUS_SUCCESS if the asr handle was opened
2122*/
2123SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_open(switch_asr_handle_t *ah,
2124 const char *module_name,
2125 const char *codec, int rate, const char *dest, switch_asr_flag_t *flags, switch_memory_pool_t *pool);
2126
2127/*!
2128 \brief Close an asr handle
2129 \param ah the handle to close
2130 \param flags flags to influence behaviour
2131 \return SWITCH_STATUS_SUCCESS
2132*/
2133SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
2134
2135/*!
2136 \brief Feed audio data to an asr handle
2137 \param ah the handle to feed data to
2138 \param data a pointer to the data
2139 \param len the size in bytes of the data
2140 \param flags flags to influence behaviour
2141 \return SWITCH_STATUS_SUCCESS
2142*/
2143SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags);
2144
2145/*!
2146 \brief Feed DTMF to an asr handle
2147 \param ah the handle to feed data to
2148 \param dtmf a string of DTMF digits
2149 \param flags flags to influence behaviour
2150 \return SWITCH_STATUS_SUCCESS
2151*/
2152SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_feed_dtmf(switch_asr_handle_t *ah, const switch_dtmf_t *dtmf, switch_asr_flag_t *flags);
2153
2154/*!
2155 \brief Check an asr handle for results
2156 \param ah the handle to check
2157 \param flags flags to influence behaviour
2158 \return SWITCH_STATUS_SUCCESS
2159*/
2160SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
2161
2162/*!
2163 \brief Get results from an asr handle
2164 \param ah the handle to get results from
2165 \param xmlstr a pointer to dynamically allocate an xml result string to
2166 \param flags flags to influence behaviour
2167 \return SWITCH_STATUS_SUCCESS
2168*/
2169SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_get_results(switch_asr_handle_t *ah, char **xmlstr, switch_asr_flag_t *flags);
2170
2171/*!
2172 \brief Get result headers from an asr handle
2173 \param ah the handle to get results from
2174 \param headers a pointer to dynamically allocate an switch_event_t result to
2175 \param flags flags to influence behaviour
2176 \return SWITCH_STATUS_SUCCESS
2177*/
2178SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_get_result_headers(switch_asr_handle_t *ah, switch_event_t **headers, switch_asr_flag_t *flags);
2179
2180/*!
2181 \brief Load a grammar to an asr handle
2182 \param ah the handle to load to
2183 \param grammar the grammar text, file path, or URI
2184 \param name the grammar name
2185 \return SWITCH_STATUS_SUCCESS
2186*/
2187SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_load_grammar(switch_asr_handle_t *ah, const char *grammar, const char *name);
2188
2189/*!
2190 \brief Unload a grammar from an asr handle
2191 \param ah the handle to unload the grammar from
2192 \param name the name of the grammar to unload
2193 \return SWITCH_STATUS_SUCCESS
2194*/
2195SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name);
2196
2197/*!
2198 \brief Enable a grammar from an asr handle
2199 \param ah the handle to enable the grammar from
2200 \param name the name of the grammar to enable
2201 \return SWITCH_STATUS_SUCCESS
2202*/
2203SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_enable_grammar(switch_asr_handle_t *ah, const char *name);
2204
2205/*!
2206 \brief Disable a grammar from an asr handle
2207 \param ah the handle to disable the grammar from
2208 \param name the name of the grammar to disable
2209 \return SWITCH_STATUS_SUCCESS
2210*/
2211SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_disable_grammar(switch_asr_handle_t *ah, const char *name);
2212
2213/*!
2214 \brief Disable all grammars from an asr handle
2215 \param ah the handle to disable the grammars from
2216 \return SWITCH_STATUS_SUCCESS
2217*/
2218SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_disable_all_grammars(switch_asr_handle_t *ah);
2219
2220/*!
2221 \brief Pause detection on an asr handle
2222 \param ah the handle to pause
2223 \return SWITCH_STATUS_SUCCESS
2224*/
2225SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_pause(switch_asr_handle_t *ah);
2226
2227/*!
2228 \brief Resume detection on an asr handle
2229 \param ah the handle to resume
2230 \return SWITCH_STATUS_SUCCESS
2231*/
2232SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_resume(switch_asr_handle_t *ah);
2233
2234/*!
2235 \brief Start input timers on an asr handle
2236 \param ah the handle to start timers on
2237 \return SWITCH_STATUS_SUCCESS
2238*/
2239SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_start_input_timers(switch_asr_handle_t *ah);
2240
2241/*!
2242 \brief Set a text parameter on an asr handle
2243 \param sh the asr handle
2244 \param param the parameter
2245 \param val the value
2246*/
2247SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val);
2248
2249/*!
2250 \brief Set a numeric parameter on an asr handle
2251 \param sh the asr handle
2252 \param param the parameter
2253 \param val the value
2254*/
2255SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val);
2256
2257/*!
2258 \brief Set a float parameter on an asr handle
2259 \param sh the asr handle
2260 \param param the parameter
2261 \param val the value
2262*/
2263SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_asr_float_param(switch_asr_handle_t *ah, char *param, double val);
2264
2265///\}
2266
2267
2268///\defgroup dir Directory Service Functions
2269///\ingroup core1
2270///\{
2271/*!
2272 \brief Open a directory handle
2273 \param dh a directory handle to use
2274 \param module_name the directory module to use
2275 \param source the source of the db (ip, hostname, path etc)
2276 \param dsn the username or designation of the lookup
2277 \param passwd the password
2278 \param pool the pool to use (NULL for new pool)
2279 \return SWITCH_STATUS_SUCCESS if the handle is opened
2280*/
2281SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_open(switch_directory_handle_t *dh,
2282 char *module_name, char *source, char *dsn, char *passwd, switch_memory_pool_t *pool);
2283
2284/*!
2285 \brief Query a directory handle
2286 \param dh a directory handle to use
2287 \param base the base to query against
2288 \param query a string of filters or query data
2289 \return SWITCH_STATUS_SUCCESS if the query is successful
2290*/
2291SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_query(switch_directory_handle_t *dh, char *base, char *query);
2292
2293/*!
2294 \brief Obtain the next record in a lookup
2295 \param dh a directory handle to use
2296 \return SWITCH_STATUS_SUCCESS if another record exists
2297*/
2298SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_next(switch_directory_handle_t *dh);
2299
2300/*!
2301 \brief Obtain the next name/value pair in the current record
2302 \param dh a directory handle to use
2303 \param var a pointer to pointer of the name to fill in
2304 \param val a pointer to pointer of the value to fill in
2305 \return SWITCH_STATUS_SUCCESS if an item exists
2306*/
2307SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_next_pair(switch_directory_handle_t *dh, char **var, char **val);
2308
2309/*!
2310 \brief Close an open directory handle
2311 \param dh a directory handle to close
2312 \return SWITCH_STATUS_SUCCESS if handle was closed
2313*/
2314SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_close(switch_directory_handle_t *dh);
2315///\}
2316
2317
2318///\defgroup misc Misc
2319///\ingroup core1
2320///\{
2321/*!
2322 \brief Retrieve a FILE stream of a given text channel name
2323 \param channel text channel enumeration
2324 \return a FILE stream
2325*/
2326SWITCH_DECLARE(FILE *)__attribute__((visibility("default"))) FILE * switch_core_data_channel(switch_text_channel_t channel);
2327
2328/*!
2329 \brief Determines if the core is ready to take calls
2330 \return SWITCH_TRUE or SWITCH_FALSE
2331*/
2332SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_ready(void);
2333
2334SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_running(void);
2335
2336/*!
2337 \brief Determines if the core is ready to take inbound calls
2338 \return SWITCH_TRUE or SWITCH_FALSE
2339*/
2340SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_ready_inbound(void);
2341
2342/*!
2343 \brief Determines if the core is ready to place outbound calls
2344 \return SWITCH_TRUE or SWITCH_FALSE
2345*/
2346SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_ready_outbound(void);
2347
2348/*!
2349 \brief return core flags
2350 \return core flags
2351*/
2352SWITCH_DECLARE(switch_core_flag_t)__attribute__((visibility("default"))) switch_core_flag_t switch_core_flags(void);
2353
2354/*!
2355 \brief Execute a management operation.
2356 \param relative_oid the relative oid of the operation.
2357 \param action the action to perform.
2358 \param data input/output string.
2359 \param datalen size in bytes of data.
2360 \return SUCCESS on sucess.
2361*/
2362SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen);
2363
2364/*!
2365 \brief Switch on the privilege awareness for the process and request required privileges
2366 \return 0 on success
2367*/
2368
2369SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_set_process_privileges(void);
2370
2371/*!
2372 \brief Set the maximum priority the process can obtain
2373 \return 0 on success
2374*/
2375
2376SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t set_normal_priority(void);
2377SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t set_auto_priority(void);
2378SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t set_realtime_priority(void);
2379SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t set_low_priority(void);
2380
2381/*!
2382 \brief Change user and/or group of the running process
2383 \param user name of the user to switch to (or NULL)
2384 \param group name of the group to switch to (or NULL)
2385 \return 0 on success, -1 otherwise
2386
2387 Several possible combinations:
2388 - user only (group NULL): switch to user and his primary group (and supplementary groups, if supported)
2389 - user and group: switch to user and specified group (only)
2390 - group only (user NULL): switch group only
2391*/
2392SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t change_user_group(const char *user, const char *group);
2393
2394/*!
2395 \brief Run endlessly until the system is shutdown
2396 \param bg divert console to the background
2397*/
2398SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_runtime_loop(int bg);
2399
2400/*!
2401 \brief Set the output console to the desired file
2402 \param console the file path
2403*/
2404SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_set_console(const char *console);
2405
2406/*!
2407 \brief Breakdown a number of milliseconds into various time spec
2408 \param total_ms a number of milliseconds
2409 \param duration an object to store the results
2410*/
2411SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration);
2412
2413/*!
2414 \brief Number of microseconds the system has been up
2415 \return a number of microseconds
2416*/
2417SWITCH_DECLARE(switch_time_t)__attribute__((visibility("default"))) switch_time_t switch_core_uptime(void);
2418
2419/*!
2420 \brief send a control message to the core
2421 \param cmd the command
2422 \param val the command arguement (if needed)
2423 \return 0 on success nonzero on error
2424*/
2425SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_session_ctl(switch_session_ctl_t cmd, void *val);
2426
2427/*!
2428 \brief Get the output console
2429 \return the FILE stream
2430*/
2431SWITCH_DECLARE(FILE *)__attribute__((visibility("default"))) FILE * switch_core_get_console(void);
2432
2433#ifndef SWIG
2434/*!
2435 \brief Launch a thread
2436*/
2437SWITCH_DECLARE(switch_thread_t *)__attribute__((visibility("default"))) switch_thread_t * switch_core_launch_thread(void *(SWITCH_THREAD_FUNC * func) (switch_thread_t *, void *),
2438 void *obj, switch_memory_pool_t *pool);
2439#endif
2440
2441/*!
2442 \brief Initiate Globals
2443*/
2444SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_set_globals(void);
2445
2446/*!
2447 \brief Checks if 2 sessions are using the same endpoint module
2448 \param a the first session
2449 \param b the second session
2450 \return TRUE or FALSE
2451*/
2452SWITCH_DECLARE(uint8_t)__attribute__((visibility("default"))) uint8_t switch_core_session_compare(switch_core_session_t *a, switch_core_session_t *b);
2453/*!
2454 \brief Checks if a session is using a specific endpoint
2455 \param session the session
2456 \param endpoint_interface interface of the endpoint to check
2457 \return TRUE or FALSE
2458*/
2459SWITCH_DECLARE(uint8_t)__attribute__((visibility("default"))) uint8_t switch_core_session_check_interface(switch_core_session_t *session, const switch_endpoint_interface_t *endpoint_interface);
2460
2461SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_video_read_callback(switch_core_session_t *session,
2462 switch_core_video_thread_callback_func_t func, void *user_data);
2463
2464SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_video_read_callback(switch_core_session_t *session, switch_frame_t *frame);
2465
2466SWITCH_DECLARE(switch_hash_index_t *)__attribute__((visibility("default"))) switch_hash_index_t * switch_core_mime_index(void);
2467SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_mime_ext2type(const char *ext);
2468SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_mime_type2ext(const char *type);
2469SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_mime_add_type(const char *type, const char *ext);
2470
2471SWITCH_DECLARE(switch_loadable_module_interface_t *)__attribute__((visibility("default"))) switch_loadable_module_interface_t
*
switch_loadable_module_create_module_interface(switch_memory_pool_t *pool, const char *name);
2472SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_loadable_module_create_interface(switch_loadable_module_interface_t *mod, switch_module_interface_name_t iname);
2473/*!
2474 \brief Get the current epoch time in microseconds
2475 \return the current epoch time in microseconds
2476*/
2477SWITCH_DECLARE(switch_time_t)__attribute__((visibility("default"))) switch_time_t switch_micro_time_now(void);
2478SWITCH_DECLARE(switch_time_t)__attribute__((visibility("default"))) switch_time_t switch_mono_micro_time_now(void);
2479SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_reclaim(void);
2480SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_reclaim_events(void);
2481SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_reclaim_logger(void);
2482SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_reclaim_all(void);
2483SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_setrlimits(void);
2484SWITCH_DECLARE(switch_time_t)__attribute__((visibility("default"))) switch_time_t switch_time_ref(void);
2485SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_sync(void);
2486/*!
2487 \brief Get the current epoch time
2488 \param [out] (optional) The current epoch time
2489 \return The current epoch time
2490*/
2491SWITCH_DECLARE(time_t)__attribute__((visibility("default"))) time_t switch_epoch_time_now(time_t *t);
2492SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_lookup_timezone(const char *tz_name);
2493SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_strftime_tz(const char *tz, const char *format, char *date, size_t len, switch_time_t thetime);
2494SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_time_exp_tz_name(const char *tz, switch_time_exp_t *tm, switch_time_t thetime);
2495SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_load_network_lists(switch_bool_t reload);
2496SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_check_network_list_ip_port_token(const char *ip_str, int port, const char *list_name, const char **token);
2497SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token);
2498#define switch_check_network_list_ip(_ip_str, _list_name)switch_check_network_list_ip_token(_ip_str, _list_name, ((void
*)0))
switch_check_network_list_ip_token(_ip_str, _list_name, NULL((void*)0))
2499SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_monotonic(switch_bool_t enable);
2500SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_timerfd(int enable);
2501SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_nanosleep(switch_bool_t enable);
2502SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_matrix(switch_bool_t enable);
2503SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_cond_yield(switch_bool_t enable);
2504SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_use_system_time(switch_bool_t enable);
2505SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_min_dtmf_duration(uint32_t duration);
2506SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_max_dtmf_duration(uint32_t duration);
2507SWITCH_DECLARE(double)__attribute__((visibility("default"))) double switch_core_min_idle_cpu(double new_limit);
2508SWITCH_DECLARE(double)__attribute__((visibility("default"))) double switch_core_idle_cpu(void);
2509SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_default_dtmf_duration(uint32_t duration);
2510SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_console_set_complete(const char *string);
2511SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_console_set_alias(const char *string);
2512SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_system(const char *cmd, switch_bool_t wait);
2513SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_stream_system(const char *cmd, switch_stream_handle_t *stream);
2514SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cond_yield(switch_interval_time_t t);
2515SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cond_next(void);
2516SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_chat_send_args(const char *dest_proto, const char *proto, const char *from, const char *to,
2517 const char *subject, const char *body, const char *type, const char *hint, switch_bool_t blocking);
2518SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_chat_send(const char *dest_proto, switch_event_t *message_event);
2519SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_chat_deliver(const char *dest_proto, switch_event_t **message_event);
2520
2521SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_preprocess_session(switch_core_session_t *session, const char *cmds);
2522SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_sqldb_pause(void);
2523SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_sqldb_resume(void);
2524
2525
2526///\}
2527
2528/*!
2529 \}
2530*/
2531
2532typedef int (*switch_core_db_event_callback_func_t) (void *pArg, switch_event_t *event);
2533
2534#define CACHE_DB_LEN256 256
2535typedef enum {
2536 CDF_INUSE = (1 << 0),
2537 CDF_PRUNE = (1 << 1),
2538 CDF_NONEXPIRING = (1 << 2)
2539} cache_db_flag_t;
2540
2541typedef enum {
2542 SCDB_TYPE_CORE_DB,
2543 SCDB_TYPE_ODBC,
2544 SCDB_TYPE_DATABASE_INTERFACE
2545} switch_cache_db_handle_type_t;
2546
2547typedef union {
2548 switch_coredb_handle_t *core_db_dbh;
2549 switch_odbc_handle_t *odbc_dbh;
2550 switch_database_interface_handle_t *database_interface_dbh;
2551} switch_cache_db_native_handle_t;
2552
2553typedef struct {
2554 char *db_path;
2555 switch_bool_t in_memory;
2556} switch_cache_db_core_db_options_t;
2557
2558typedef struct {
2559 char *dsn;
2560 char *user;
2561 char *pass;
2562} switch_cache_db_odbc_options_t;
2563
2564typedef struct {
2565 const char *original_dsn;
2566 char *connection_string;
2567 char prefix[16];
2568 switch_database_interface_t *database_interface;
2569 switch_bool_t make_module_no_unloadable;
2570} switch_cache_db_database_interface_options_t;
2571
2572typedef union {
2573 switch_cache_db_core_db_options_t core_db_options;
2574 switch_cache_db_odbc_options_t odbc_options;
2575 switch_cache_db_database_interface_options_t database_interface_options;
2576} switch_cache_db_connection_options_t;
2577
2578struct switch_cache_db_handle;
2579typedef struct switch_cache_db_handle switch_cache_db_handle_t;
2580
2581static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_t type)
2582{
2583 const char *type_str = "INVALID";
2584
2585 switch (type) {
2586 case SCDB_TYPE_DATABASE_INTERFACE:
2587 {
2588 type_str = "DATABASE_INTERFACE";
2589 }
2590 break;
2591 case SCDB_TYPE_ODBC:
2592 {
2593 type_str = "ODBC";
2594 }
2595 break;
2596 case SCDB_TYPE_CORE_DB:
2597 {
2598 type_str = "CORE_DB";
2599 }
2600 break;
2601 }
2602
2603 return type_str;
2604}
2605
2606SWITCH_DECLARE(switch_cache_db_handle_type_t)__attribute__((visibility("default"))) switch_cache_db_handle_type_t switch_cache_db_get_type(switch_cache_db_handle_t *dbh);
2607
2608/*!
2609 \brief Returns the handle to the pool, immediately available for other
2610 threads to use.
2611 \param [in] The handle
2612*/
2613SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t ** dbh);
2614/*!
2615 \brief Returns the handle to the pool, handle is NOT available to
2616 other threads until the allocating thread actually terminates.
2617 \param [in] The handle
2618*/
2619SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_release_db_handle(switch_cache_db_handle_t ** dbh);
2620/*!
2621 \brief Gets a new cached handle from the pool, potentially creating a new connection.
2622 The connection is bound to the thread until it (the thread) terminates unless
2623 you dismiss rather than release.
2624 \param [out] dbh The handle
2625 \param [in] type - ODBC or SQLLITE
2626 \param [in] connection_options (userid, password, etc)
2627*/
2628SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t _switch_cache_db_get_db_handle(switch_cache_db_handle_t ** dbh,
2629 switch_cache_db_handle_type_t type,
2630 switch_cache_db_connection_options_t *connection_options,
2631 const char *file, const char *func, int line);
2632#define switch_cache_db_get_db_handle(_a, _b, _c)_switch_cache_db_get_db_handle(_a, _b, _c, "./src/include/switch_core.h"
, (const char *)__func__, 2632)
_switch_cache_db_get_db_handle(_a, _b, _c, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2632)
2633
2634SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t _switch_cache_db_get_db_handle_dsn_ex(switch_cache_db_handle_t **dbh, const char *dsn, switch_bool_t make_module_no_unloadable,
2635 const char *file, const char *func, int line);
2636SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t _switch_cache_db_get_db_handle_dsn(switch_cache_db_handle_t **dbh, const char *dsn,
2637 const char *file, const char *func, int line);
2638#define switch_cache_db_get_db_handle_dsn(_a, _b)_switch_cache_db_get_db_handle_dsn(_a, _b, "./src/include/switch_core.h"
, (const char *)__func__, 2638)
_switch_cache_db_get_db_handle_dsn(_a, _b, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2638)
2639
2640/*!
2641 \brief Executes the create schema sql
2642 \param [in] dbh The handle
2643 \param [in] sql - sql to run
2644 \param [out] err - Error if it exists
2645*/
2646SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_cache_db_create_schema(switch_cache_db_handle_t *dbh, char *sql, char **err);
2647/*!
2648 \brief Executes the sql and returns the result as a string
2649 \param [in] dbh The handle
2650 \param [in] sql - sql to run
2651 \param [out] str - buffer for result
2652 \param [in] len - length of str buffer
2653 \param [out] err - Error if it exists
2654*/
2655SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_cache_db_execute_sql2str(switch_cache_db_handle_t *dbh, char *sql, char *str, size_t len, char **err);
2656/*!
2657 \brief Executes the sql
2658 \param [in] dbh The handle
2659 \param [in] sql - sql to run
2660 \param [out] err - Error if it exists
2661*/
2662SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_cache_db_execute_sql(switch_cache_db_handle_t *dbh, char *sql, char **err);
2663/*!
2664 \brief Executes the sql and uses callback for row-by-row processing
2665 \param [in] dbh The handle
2666 \param [in] sql - sql to run
2667 \param [in] callback - function pointer to callback
2668 \param [in] pdata - data to pass to callback
2669 \param [out] err - Error if it exists
2670*/
2671SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_cache_db_execute_sql_callback(switch_cache_db_handle_t *dbh, const char *sql,
2672 switch_core_db_callback_func_t callback, void *pdata, char **err);
2673
2674/*!
2675 \brief Executes the sql and uses callback for row-by-row processing
2676 \param [in] dbh The handle
2677 \param [in] sql - sql to run
2678 \param [in] callback - function pointer to callback
2679 \param [in] err_callback - function pointer to callback when error occurs
2680 \param [in] pdata - data to pass to callback
2681 \param [out] err - Error if it exists
2682*/
2683SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_cache_db_execute_sql_callback_err(switch_cache_db_handle_t *dbh, const char *sql,
2684 switch_core_db_callback_func_t callback,
2685 switch_core_db_err_callback_func_t err_callback,
2686 void *pdata, char **err);
2687
2688/*!
2689 \brief Get the affected rows of the last performed query
2690 \param [in] dbh The handle
2691 \param [out] the number of affected rows
2692*/
2693SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_cache_db_affected_rows(switch_cache_db_handle_t *dbh);
2694
2695/*!
2696 \brief load an external extension to db
2697 \param [in] dbh The handle
2698 \param [out] the path to the extension
2699*/
2700SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_cache_db_load_extension(switch_cache_db_handle_t *dbh, const char *extension);
2701
2702/*!
2703 \brief Provides some feedback as to the status of the db connection pool
2704 \param [in] stream stream for status
2705*/
2706SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_status(switch_stream_handle_t *stream);
2707SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t _switch_core_db_handle(switch_cache_db_handle_t ** dbh, const char *file, const char *func, int line);
2708#define switch_core_db_handle(_a)_switch_core_db_handle(_a, "./src/include/switch_core.h", (const
char *)__func__, 2708)
_switch_core_db_handle(_a, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2708)
2709
2710SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_cache_db_test_reactive(switch_cache_db_handle_t *db,
2711 const char *test_sql, const char *drop_sql, const char *reactive_sql);
2712SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_cache_db_test_reactive_ex(switch_cache_db_handle_t *db,
2713 const char *test_sql, const char *drop_sql, const char *reactive_sql, const char *row_size_limited_reactive_sql);
2714SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_cache_db_persistant_execute(switch_cache_db_handle_t *dbh, const char *sql, uint32_t retries);
2715SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_cache_db_persistant_execute_trans_full(switch_cache_db_handle_t *dbh, char *sql, uint32_t retries,
2716 const char *pre_trans_execute,
2717 const char *post_trans_execute,
2718 const char *inner_pre_trans_execute,
2719 const char *inner_post_trans_execute);
2720#define switch_cache_db_persistant_execute_trans(_d, _s, _r)switch_cache_db_persistant_execute_trans_full(_d, _s, _r, ((void
*)0), ((void*)0), ((void*)0), ((void*)0))
switch_cache_db_persistant_execute_trans_full(_d, _s, _r, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0))
2721
2722SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_database_interface_flush_handles(switch_database_interface_t *database_interface);
2723
2724/*!
2725\brief Returns error if no suitable database interface found to serve core db dsn.
2726*/
2727SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_check_core_db_dsn(void);
2728
2729/*!
2730\brief Returns error if no suitable database interface found for a dsn.
2731*/
2732SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_database_available(char* dsn);
2733
2734SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_set_signal_handlers(void);
2735SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_debug_level(void);
2736SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sps(void);
2737SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sps_last(void);
2738SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sps_peak(void);
2739SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sps_peak_fivemin(void);
2740SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sessions_peak(void);
2741SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sessions_peak_fivemin(void);
2742SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_flush_handles(void);
2743SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_banner(void);
2744SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_session_in_thread(switch_core_session_t *session);
2745SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_default_ptime(const char *name, uint32_t number);
2746SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_default_rate(const char *name, uint32_t number);
2747SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_max_audio_channels(uint32_t limit);
2748
2749/*!
2750 \brief Add user registration
2751 \param [in] user
2752 \param [in] realm
2753 \param [in] token
2754 \param [in] url - a freeswitch dial string
2755 \param [in] expires
2756 \param [in] network_ip
2757 \param [in] network_port
2758 \param [in] network_proto - one of tls, tcp, udp
2759 \param [in] metadata - generic metadata supplied by module
2760 \param [out] err - Error if it exists
2761*/
2762SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_add_registration(const char *user, const char *realm, const char *token, const char *url, uint32_t expires,
2763 const char *network_ip, const char *network_port, const char *network_proto,
2764 const char *metadata);
2765/*!
2766 \brief Delete user registration
2767 \param [in] user
2768 \param [in] realm
2769 \param [in] token
2770 \param [out] err - Error if it exists
2771*/
2772SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_del_registration(const char *user, const char *realm, const char *token);
2773/*!
2774 \brief Expire user registrations
2775 \param [in] force delete all registrations
2776 \param [out] err - Error if it exists
2777*/
2778SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_expire_registration(int force);
2779
2780/*!
2781 \brief Get RTP port range start value
2782 \param[in] void
2783 \param[out] RTP port range start value
2784*/
2785SWITCH_DECLARE(uint16_t)__attribute__((visibility("default"))) uint16_t switch_core_get_rtp_port_range_start_port(void);
2786
2787/*!
2788 \brief Get RTP port range end value
2789 \param[in] void
2790 \param[out] RTP port range end value
2791*/
2792SWITCH_DECLARE(uint16_t)__attribute__((visibility("default"))) uint16_t switch_core_get_rtp_port_range_end_port(void);
2793
2794SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var);
2795SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_say_file_handle_get_path(switch_say_file_handle_t *sh);
2796SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_say_file_handle_detach_path(switch_say_file_handle_t *sh);
2797SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_say_file_handle_destroy(switch_say_file_handle_t **sh);
2798SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_say_file_handle_create(switch_say_file_handle_t **sh, const char *ext, switch_event_t **var_event);
2799SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_say_file(switch_say_file_handle_t *sh, const char *fmt, ...);
2800SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_max_file_desc(void);
2801SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_close_extra_files(int *keep, int keep_ttl);
2802SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_thread_set_cpu_affinity(int cpu);
2803SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_os_yield(void);
2804SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max);
2805SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_gen_encoded_silence(unsigned char *data, const switch_codec_implementation_t *read_impl, switch_size_t len);
2806
2807SWITCH_DECLARE(switch_cache_db_handle_type_t)__attribute__((visibility("default"))) switch_cache_db_handle_type_t switch_core_dbtype(void);
2808SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_sql_exec(const char *sql);
2809SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_recovery_recover(const char *technology, const char *profile_name);
2810SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_recovery_untrack(switch_core_session_t *session, switch_bool_t force);
2811SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_recovery_track(switch_core_session_t *session);
2812SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_recovery_flush(const char *technology, const char *profile_name);
2813
2814SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_pause(switch_sql_queue_manager_t *qm, switch_bool_t flush);
2815SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_resume(switch_sql_queue_manager_t *qm);
2816
2817SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_sql_queue_manager_size(switch_sql_queue_manager_t *qm, uint32_t index);
2818SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_push_confirm(switch_sql_queue_manager_t *qm, const char *sql, uint32_t pos, switch_bool_t dup);
2819SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_push(switch_sql_queue_manager_t *qm, const char *sql, uint32_t pos, switch_bool_t dup);
2820SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_destroy(switch_sql_queue_manager_t **qmp);
2821SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_init_name(const char *name,
2822 switch_sql_queue_manager_t **qmp,
2823 uint32_t numq, const char *dsn, uint32_t max_trans,
2824 const char *pre_trans_execute,
2825 const char *post_trans_execute,
2826 const char *inner_pre_trans_execute,
2827 const char *inner_post_trans_execute);
2828
2829#define switch_sql_queue_manager_init(_q, _n, _d, _m, _p1, _p2, _ip1, _ip2)switch_sql_queue_manager_init_name("./src/include/switch_core.h"
, _q, _n, _d, _m, _p1, _p2, _ip1, _ip2)
switch_sql_queue_manager_init_name(__FILE__"./src/include/switch_core.h", _q, _n, _d, _m, _p1, _p2, _ip1, _ip2)
2830
2831SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_start(switch_sql_queue_manager_t *qm);
2832SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_stop(switch_sql_queue_manager_t *qm);
2833SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_cache_db_execute_sql_event_callback(switch_cache_db_handle_t *dbh,
2834 const char *sql, switch_core_db_event_callback_func_t callback, void *pdata, char **err);
2835
2836SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_execute_sql_callback(switch_sql_queue_manager_t *qm, const char *sql,
2837 switch_core_db_callback_func_t callback,
2838 void *pdata);
2839SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_execute_sql_callback_err(switch_sql_queue_manager_t *qm, const char *sql,
2840 switch_core_db_callback_func_t callback,
2841 switch_core_db_err_callback_func_t err_callback,
2842 void *pdata);
2843
2844SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_execute_sql_event_callback(switch_sql_queue_manager_t *qm, const char *sql,
2845 switch_core_db_event_callback_func_t callback,
2846 void *pdata);
2847SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_execute_sql_event_callback_err(switch_sql_queue_manager_t *qm, const char *sql,
2848 switch_core_db_event_callback_func_t callback,
2849 switch_core_db_err_callback_func_t err_callback,
2850 void *pdata);
2851
2852SWITCH_DECLARE(pid_t)__attribute__((visibility("default"))) pid_t switch_fork(void);
2853
2854SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_gen_certs(const char *prefix);
2855SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_check_dtls_pem(const char *file);
2856SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_cert_gen_fingerprint(const char *prefix, dtls_fingerprint_t *fp);
2857SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_cert_expand_fingerprint(dtls_fingerprint_t *fp, const char *str);
2858SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_cert_verify(dtls_fingerprint_t *fp);
2859SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t _switch_core_session_request_video_refresh(switch_core_session_t *session, int force, const char *file, const char *func, int line);
2860#define switch_core_session_request_video_refresh(_s)_switch_core_session_request_video_refresh(_s, 0, "./src/include/switch_core.h"
, (const char *)__func__, 2860)
_switch_core_session_request_video_refresh(_s, 0, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2860)
2861#define switch_core_session_force_request_video_refresh(_s)_switch_core_session_request_video_refresh(_s, 1, "./src/include/switch_core.h"
, (const char *)__func__, 2861)
_switch_core_session_request_video_refresh(_s, 1, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2861)
2862SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_send_and_request_video_refresh(switch_core_session_t *session);
2863SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_system(const char *cmd, switch_bool_t wait);
2864SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream);
2865SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_stream_system(const char *cmd, switch_stream_handle_t *stream);
2866
2867SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_spawn(const char *cmd, switch_bool_t wait);
2868SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_stream_spawn(const char *cmd, switch_bool_t shell, switch_bool_t wait, switch_stream_handle_t *stream);
2869
2870SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_debug_pool(switch_stream_handle_t *stream);
2871
2872SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_override_io_routines(switch_core_session_t *session, switch_io_routines_t *ior);
2873
2874SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_major(void);
2875SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_minor(void);
2876SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_micro(void);
2877
2878SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_revision(void);
2879SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_revision_human(void);
2880SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_full(void);
2881SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_full_human(void);
2882
2883SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_autobind_cpu(void);
2884
2885SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_start_text_thread(switch_core_session_t *session);
2886
2887SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_get_event_channel_key_separator(void);
2888
2889SWITCH_END_EXTERN_C
2890#endif
2891/* For Emacs:
2892 * Local Variables:
2893 * mode:c
2894 * indent-tabs-mode:t
2895 * tab-width:4
2896 * c-basic-offset:4
2897 * End:
2898 * For VIM:
2899 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
2900 */