Bug Summary

File:src/switch_xml.c
Warning:line 860, column 13
Potential leak of memory pointed to by 'pe'

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-150934-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));
17
Calling 'switch_must_malloc'
20
Returned allocated memory
834
835 for (s[len] = '\0'; s;) {
21
Loop condition is true. Entering loop body
836 while (*s && *s != '<' && *s != '%')
22
Assuming the condition is true
23
Assuming the condition is false
837 s++; /* find next declaration */
838
839 if (!*s)
24
Taking false branch
840 break;
841 else if (!strncmp(s, "<!ENTITY", 8)) { /* parse entity definitions */
25
Taking true branch
842 c = s += strspn(s + 8, SWITCH_XML_WS"\t\r\n ") + 8; /* skip white space separator */
843 n = s + strspn(s, SWITCH_XML_WS"\t\r\n " "%"); /* find name */
844 *(s = n + strcspn(n, SWITCH_XML_WS"\t\r\n ")) = ';'; /* append ; to name */
845
846 v = s + strspn(s + 1, SWITCH_XML_WS"\t\r\n ") + 1; /* find value */
847 if ((q = *(v++)) != '"' && q != '\'') { /* skip externals */
26
Assuming the condition is false
848 s = strchr(s, '>');
849 continue;
850 }
851
852 for (i = 0, ent = (*c == '%') ? pe : root->ent; ent[i]; i++);
27
'?' condition is false
28
Loop condition is false. Execution continues on line 853
853 sstmp = (char **) switch_must_realloc(ent, (i + 3) * sizeof(char *)); /* space for next ent */
854 ent = sstmp;
855 if (*c == '%')
29
Taking true branch
856 pe = ent;
857 else
858 root->ent = ent;
859
860 *(++s) = '\0'; /* null terminate name */
30
Potential leak of memory pointed to by 'pe'
861 if ((s = strchr(v, q)))
862 *(s++) = '\0'; /* null terminate value */
863 ent[i + 1] = switch_xml_decode(v, pe, '%'); /* set value */
864 ent[i + 2] = NULL((void*)0); /* null terminate entity list */
865 if (!switch_xml_ent_ok(n, ent[i + 1], ent)) { /* circular reference */
866 if (ent[i + 1] != v)
867 free(ent[i + 1]);
868 switch_xml_err(root, v, "circular entity declaration &%s", n);
869 break;
870 } else
871 ent[i] = n; /* set entity name */
872 } else if (!strncmp(s, "<!ATTLIST", 9)) { /* parse default attributes */
873 t = s + strspn(s + 9, SWITCH_XML_WS"\t\r\n ") + 9; /* skip whitespace separator */
874 if (!*t) {
875 switch_xml_err(root, t, "unclosed <!ATTLIST");
876 break;
877 }
878 if (*(s = t + strcspn(t, SWITCH_XML_WS"\t\r\n " ">")) == '>')
879 continue;
880 else
881 *s = '\0'; /* null terminate tag name */
882 for (i = 0; root->attr[i] && strcmp(n, root->attr[i][0]); i++);
883
884 //while (*(n = ++s + strspn(s, SWITCH_XML_WS)) && *n != '>') {
885 // gcc 4.4 you are a creep
886 for (;;) {
887 s++;
888 if (!(*(n = s + strspn(s, SWITCH_XML_WS"\t\r\n ")) && *n != '>')) {
889 break;
890 }
891 if (*(s = n + strcspn(n, SWITCH_XML_WS"\t\r\n ")))
892 *s = '\0'; /* attr name */
893 else {
894 switch_xml_err(root, t, "malformed <!ATTLIST");
895 break;
896 }
897
898 s += strspn(s + 1, SWITCH_XML_WS"\t\r\n ") + 1; /* find next token */
899 c = (strncmp(s, "CDATA", 5)) ? (char *) "*" : (char *) " "; /* is it cdata? */
900 if (!strncmp(s, "NOTATION", 8))
901 s += strspn(s + 8, SWITCH_XML_WS"\t\r\n ") + 8;
902 s = (*s == '(') ? strchr(s, ')') : s + strcspn(s, SWITCH_XML_WS"\t\r\n ");
903 if (!s) {
904 switch_xml_err(root, t, "malformed <!ATTLIST");
905 break;
906 }
907
908 s += strspn(s, SWITCH_XML_WS"\t\r\n " ")"); /* skip white space separator */
909 if (!strncmp(s, "#FIXED", 6))
910 s += strspn(s + 6, SWITCH_XML_WS"\t\r\n ") + 6;
911 if (*s == '#') { /* no default value */
912 s += strcspn(s, SWITCH_XML_WS"\t\r\n " ">") - 1;
913 if (*c == ' ')
914 continue; /* cdata is default, nothing to do */
915 v = NULL((void*)0);
916 } else if ((*s == '"' || *s == '\'') && /* default value */
917 (s = strchr(v = s + 1, *s)))
918 *s = '\0';
919 else {
920 switch_xml_err(root, t, "malformed <!ATTLIST");
921 break;
922 }
923
924 if (!root->attr[i]) { /* new tag name */
925 root->attr = (!i) ? (char ***) switch_must_malloc(2 * sizeof(char **))
926 : (char ***) switch_must_realloc(root->attr, (i + 2) * sizeof(char **));
927 root->attr[i] = (char **) switch_must_malloc(2 * sizeof(char *));
928 root->attr[i][0] = t; /* set tag name */
929 root->attr[i][1] = (char *) (root->attr[i + 1] = NULL((void*)0));
930 }
931
932 for (j = 1; root->attr[i][j]; j += 3); /* find end of list */
933 sstmp = (char **) switch_must_realloc(root->attr[i], (j + 4) * sizeof(char *));
934
935 root->attr[i] = sstmp;
936 root->attr[i][j + 3] = NULL((void*)0); /* null terminate list */
937 root->attr[i][j + 2] = c; /* is it cdata? */
938 root->attr[i][j + 1] = (v) ? switch_xml_decode(v, root->ent, *c) : NULL((void*)0);
939 root->attr[i][j] = n; /* attribute name */
940 }
941 } else if (!strncmp(s, "<!--", 4))
942 s = strstr(s + 4, "-->"); /* comments */
943 else if (!strncmp(s, "<?", 2)) { /* processing instructions */
944 if ((s = strstr(c = s + 2, "?>")))
945 switch_xml_proc_inst(root, c, s++ - c);
946 } else if (*s == '<')
947 s = strchr(s, '>'); /* skip other declarations */
948 else if (*(s++) == '%' && !root->standalone)
949 break;
950 }
951
952 free(pe);
953 return !*root->err;
954}
955
956/* Converts a UTF-16 string to UTF-8. Returns a new string that must be freed
957 or NULL if no conversion was needed. */
958static char *switch_xml_str2utf8(char **s, switch_size_t *len)
959{
960 char *u;
961 switch_size_t l = 0, sl, max = *len;
962 long c, d;
963 int b, be = (**s == '\xFE') ? 1 : (**s == '\xFF') ? 0 : -1;
964
965 if (be == -1)
966 return NULL((void*)0); /* not UTF-16 */
967
968 u = (char *) switch_must_malloc(max);
969 for (sl = 2; sl < *len - 1; sl += 2) {
970 c = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF) /* UTF-16BE */
971 : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF); /* UTF-16LE */
972 if (c >= 0xD800 && c <= 0xDFFF && (sl += 2) < *len - 1) { /* high-half */
973 d = (be) ? (((*s)[sl] & 0xFF) << 8) | ((*s)[sl + 1] & 0xFF)
974 : (((*s)[sl + 1] & 0xFF) << 8) | ((*s)[sl] & 0xFF);
975 c = (((c & 0x3FF) << 10) | (d & 0x3FF)) + 0x10000;
976 }
977
978 while (l + 6 > max) {
979 char *tmp;
980 tmp = (char *) switch_must_realloc(u, max += SWITCH_XML_BUFSIZE1024);
981 u = tmp;
982 }
983 if (c < 0x80)
984 u[l++] = (char) c; /* US-ASCII subset */
985 else { /* multi-byte UTF-8 sequence */
986 for (b = 0, d = c; d; d /= 2)
987 b++; /* bits in c */
988 b = (b - 2) / 5; /* bytes in payload */
989 u[l++] = (char) ((0xFF << (7 - b)) | (c >> (6 * b))); /* head */
990 while (b)
991 u[l++] = (char) (0x80 | ((c >> (6 * --b)) & 0x3F)); /* payload */
992 }
993 }
994 return *s = (char *) switch_must_realloc(u, *len = l);
995}
996
997/* frees a tag attribute list */
998static void switch_xml_free_attr(char **attr)
999{
1000 int i = 0;
1001 char *m;
1002
1003 if (!attr || attr == SWITCH_XML_NIL)
1004 return; /* nothing to free */
1005 while (attr[i])
1006 i += 2; /* find end of attribute list */
1007 m = attr[i + 1]; /* list of which names and values are malloced */
1008 for (i = 0; m[i]; i++) {
1009 if (m[i] & SWITCH_XML_NAMEM)
1010 free(attr[i * 2]);
1011 if (m[i] & SWITCH_XML_TXTM)
1012 free(attr[(i * 2) + 1]);
1013 }
1014 free(m);
1015 free(attr);
1016}
1017
1018SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_str_dynamic(char *s, switch_bool_t dup)
1019{
1020 switch_xml_root_t root;
1021 char *data;
1022
1023 switch_assert(s)((s) ? (void) (0) : __assert_fail ("s", "src/switch_xml.c", 1023
, __extension__ __PRETTY_FUNCTION__))
;
1024 data = dup ? switch_must_strdup(s) : s;
1025
1026 if ((root = (switch_xml_root_t) switch_xml_parse_str(data, strlen(data)))) {
1027 root->dynamic = 1; /* Make sure we free the memory is switch_xml_free() */
1028 return &root->xml;
1029 } else {
1030 if (dup) {
1031 free(data);
1032 }
1033 return NULL((void*)0);
1034 }
1035}
1036
1037/* parse the given xml string and return a switch_xml structure */
1038SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_str(char *s, switch_size_t len)
1039{
1040 switch_xml_root_t root = (switch_xml_root_t) switch_xml_new(NULL((void*)0));
1041 char q, e, *d, **attr, **a = NULL((void*)0); /* initialize a to avoid compile warning */
1042 int l, i, j;
1043
1044 root->m = s;
1045 if (!len)
1
Assuming 'len' is not equal to 0
2
Taking false branch
1046 return switch_xml_err(root, s, "root tag missing");
1047 root->u = switch_xml_str2utf8(&s, &len); /* convert utf-16 to utf-8 */
1048 root->e = (root->s = s) + len; /* record start and end of work area */
1049
1050 e = s[len - 1]; /* save end char */
1051 s[len - 1] = '\0'; /* turn end char into null terminator */
1052
1053 while (*s && *s != '<')
3
Loop condition is false. Execution continues on line 1055
1054 s++; /* find first tag */
1055 if (!*s)
4
Taking false branch
1056 return switch_xml_err(root, s, "root tag missing");
1057
1058 for (;;) {
5
Loop condition is true. Entering loop body
1059 attr = (char **) SWITCH_XML_NIL;
1060 d = ++s;
1061
1062 if (isalpha((int) (*s))((*__ctype_b_loc ())[(int) (((int) (*s)))] & (unsigned short
int) _ISalpha)
|| *s == '_' || *s == ':' || (int8_t) * s < '\0') { /* new tag */
6
Taking false branch
1063 if (!root->cur)
1064 return switch_xml_err(root, d, "markup outside of root element");
1065
1066 s += strcspn(s, SWITCH_XML_WS"\t\r\n " "/>");
1067 while (isspace((int) (*s))((*__ctype_b_loc ())[(int) (((int) (*s)))] & (unsigned short
int) _ISspace)
)
1068 *(s++) = '\0'; /* null terminate tag name */
1069
1070 if (*s && *s != '/' && *s != '>') /* find tag in default attr list */
1071 for (i = 0; (a = root->attr[i]) && strcmp(a[0], d); i++);
1072
1073 for (l = 0; *s && *s != '/' && *s != '>'; l += 2) { /* new attrib */
1074 attr = (l) ? (char **) switch_must_realloc(attr, (l + 4) * sizeof(char *))
1075 : (char **) switch_must_malloc(4 * sizeof(char *)); /* allocate space */
1076 attr[l + 3] = (l) ? (char *) switch_must_realloc(attr[l + 1], (l / 2) + 2)
1077 : (char *) switch_must_malloc(2); /* mem for list of maloced vals */
1078 strcpy(attr[l + 3] + (l / 2), " "); /* value is not malloced */
1079 attr[l + 2] = NULL((void*)0); /* null terminate list */
1080 attr[l + 1] = (char *) ""; /* temporary attribute value */
1081 attr[l] = s; /* set attribute name */
1082
1083 s += strcspn(s, SWITCH_XML_WS"\t\r\n " "=/>");
1084 if (*s == '=' || isspace((int) (*s))((*__ctype_b_loc ())[(int) (((int) (*s)))] & (unsigned short
int) _ISspace)
) {
1085 *(s++) = '\0'; /* null terminate tag attribute name */
1086 q = *(s += strspn(s, SWITCH_XML_WS"\t\r\n " "="));
1087 if (q == '"' || q == '\'') { /* attribute value */
1088 attr[l + 1] = ++s;
1089 while (*s && *s != q)
1090 s++;
1091 if (*s)
1092 *(s++) = '\0'; /* null terminate attribute val */
1093 else {
1094 switch_xml_free_attr(attr);
1095 return switch_xml_err(root, d, "missing %c", q);
1096 }
1097
1098 for (j = 1; a && a[j] && strcmp(a[j], attr[l]); j += 3);
1099 attr[l + 1] = switch_xml_decode(attr[l + 1], root->ent, (a && a[j]) ? *a[j + 2] : ' ');
1100 if (attr[l + 1] < d || attr[l + 1] > s)
1101 attr[l + 3][l / 2] = SWITCH_XML_TXTM; /* value malloced */
1102 }
1103 }
1104 while (isspace((int) (*s))((*__ctype_b_loc ())[(int) (((int) (*s)))] & (unsigned short
int) _ISspace)
)
1105 s++;
1106 }
1107
1108 if (*s == '/') { /* self closing tag */
1109 *(s++) = '\0';
1110 if ((*s && *s != '>') || (!*s && e != '>')) {
1111 if (l)
1112 switch_xml_free_attr(attr);
1113 return switch_xml_err(root, d, "missing >");
1114 }
1115 switch_xml_open_tag(root, d, attr);
1116 switch_xml_close_tag(root, d, s);
1117 } else if ((q = *s) == '>' || (!*s && e == '>')) { /* open tag */
1118 *s = '\0'; /* temporarily null terminate tag name */
1119 switch_xml_open_tag(root, d, attr);
1120 *s = q;
1121 } else {
1122 if (l)
1123 switch_xml_free_attr(attr);
1124 return switch_xml_err(root, d, "missing >");
1125 }
1126 } else if (*s == '/') { /* close tag */
7
Taking false branch
1127 s += strcspn(d = s + 1, SWITCH_XML_WS"\t\r\n " ">") + 1;
1128 if (!(q = *s) && e != '>')
1129 return switch_xml_err(root, d, "missing >");
1130 *s = '\0'; /* temporarily null terminate tag name */
1131 if (switch_xml_close_tag(root, d, s))
1132 return &root->xml;
1133 if (isspace((int) (*s = q))((*__ctype_b_loc ())[(int) (((int) (*s = q)))] & (unsigned
short int) _ISspace)
)
1134 s += strspn(s, SWITCH_XML_WS"\t\r\n ");
1135 } else if (!strncmp(s, "!--", 3)) { /* xml comment */
8
Assuming the condition is false
9
Taking false branch
1136 if (!(s = strstr(s + 3, "--")) || (*(s += 2) != '>' && *s) || (!*s && e != '>'))
1137 return switch_xml_err(root, d, "unclosed <!--");
1138 } else if (!strncmp(s, "![CDATA[", 8)) { /* cdata */
10
Assuming the condition is false
11
Taking false branch
1139 if ((s = strstr(s, "]]>"))) {
1140 if (root && root->cur) {
1141 root->cur->flags |= SWITCH_XML_CDATA;
1142 }
1143 switch_xml_char_content(root, d + 8, (s += 2) - d - 10, 'c');
1144 } else {
1145 return switch_xml_err(root, d, "unclosed <![CDATA[");
1146 }
1147 } else if (!strncmp(s, "!DOCTYPE", 8)) { /* dtd */
12
Taking true branch
1148 for (l = 0; *s && ((!l && *s != '>') || (l && (*s != ']' || *(s + strspn(s + 1, SWITCH_XML_WS"\t\r\n ") + 1) != '>'))); l = (*s == '[') ? 1 : l)
13
'?' condition is true
14
Loop condition is false. Execution continues on line 1150
1149 s += strcspn(s + 1, "[]>") + 1;
1150 if (!*s && e != '>')
1151 return switch_xml_err(root, d, "unclosed <!DOCTYPE");
1152 d = (l) ? strchr(d, '[') + 1 : d;
15
'?' condition is true
1153 if (l && !switch_xml_internal_dtd(root, d, s++ - d))
16
Calling 'switch_xml_internal_dtd'
1154 return &root->xml;
1155 } else if (*s == '?') { /* <?...?> processing instructions */
1156 do {
1157 s = strchr(s, '?');
1158 } while (s && *(++s) && *s != '>');
1159 if (!s || (!*s && e != '>'))
1160 return switch_xml_err(root, d, "unclosed <?");
1161 else
1162 switch_xml_proc_inst(root, d + 1, s - d - 2);
1163 } else
1164 return switch_xml_err(root, d, "unexpected <");
1165
1166 if (!s || !*s)
1167 break;
1168 *s = '\0';
1169 d = ++s;
1170 if (*s && *s != '<') { /* tag character content */
1171 while (*s && *s != '<')
1172 s++;
1173 if (*s)
1174 switch_xml_char_content(root, d, s - d, '&');
1175 else
1176 break;
1177 } else if (!*s)
1178 break;
1179 }
1180
1181 if (!root->cur)
1182 return &root->xml;
1183 else if (!root->cur->name)
1184 return switch_xml_err(root, d, "root tag missing");
1185 else
1186 return switch_xml_err(root, d, "unclosed tag <%s>", root->cur->name);
1187}
1188
1189/* Wrapper for switch_xml_parse_str() that accepts a file stream. Reads the entire
1190 stream into memory and then parses it. For xml files, use switch_xml_parse_file()
1191 or switch_xml_parse_fd() */
1192SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_fp(FILE * fp)
1193{
1194 switch_xml_root_t root;
1195 switch_size_t l, len = 0;
1196 char *s;
1197
1198 s = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
1199
1200 do {
1201 len += (l = fread((s + len), 1, SWITCH_XML_BUFSIZE1024, fp));
1202 if (l == SWITCH_XML_BUFSIZE1024) {
1203 s = (char *) switch_must_realloc(s, len + SWITCH_XML_BUFSIZE1024);
1204 }
1205 } while (s && l == SWITCH_XML_BUFSIZE1024);
1206
1207 if (!s)
1208 return NULL((void*)0);
1209 root = (switch_xml_root_t) switch_xml_parse_str(s, len);
1210 root->dynamic = 1; /* so we know to free s in switch_xml_free() */
1211 return &root->xml;
1212}
1213
1214/* A wrapper for switch_xml_parse_str() that accepts a file descriptor. First
1215 attempts to mem map the file. Failing that, reads the file into memory.
1216 Returns NULL on failure. */
1217SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_fd(int fd)
1218{
1219 switch_xml_root_t root;
1220 struct stat st;
1221 switch_ssize_t l;
1222 void *m;
1223
1224 if (fd < 0)
1225 return NULL((void*)0);
1226 fstat(fd, &st);
1227
1228 if (!st.st_size) {
1229 return NULL((void*)0);
1230 }
1231
1232 m = switch_must_malloc(st.st_size);
1233
1234 if (!(0<(l = read(fd, m, st.st_size)))
1235 || !(root = (switch_xml_root_t) switch_xml_parse_str((char *) m, l))) {
1236 free(m);
1237 return NULL((void*)0);
1238 }
1239 root->dynamic = 1; /* so we know to free s in switch_xml_free() */
1240
1241 return &root->xml;
1242}
1243
1244static char *expand_vars(char *buf, char *ebuf, switch_size_t elen, switch_size_t *newlen, const char **err)
1245{
1246 char *var, *val;
1247 char *rp = buf;
1248 char *wp = ebuf;
1249 char *ep = ebuf + elen - 1;
1250
1251 if (!(var = strstr(rp, "$${"))) {
1252 *newlen = strlen(buf);
1253 return buf;
1254 }
1255
1256 while (*rp && wp < ep) {
1257
1258 if (*rp == '$' && *(rp + 1) == '$' && *(rp + 2) == '{') {
1259 char *e = switch_find_end_paren(rp + 2, '{', '}');
1260
1261 if (e) {
1262 rp += 3;
1263 var = rp;
1264 *e++ = '\0';
1265 rp = e;
1266 if ((val = switch_core_get_variable_dup(var))) {
1267 char *p;
1268 for (p = val; p && *p && wp <= ep; p++) {
1269 *wp++ = *p;
1270 }
1271 free(val);
1272 }
1273 continue;
1274 } else if (err) {
1275 *err = "unterminated ${var}";
1276 }
1277 }
1278
1279 *wp++ = *rp++;
1280 }
1281
1282 if (wp == ep) {
1283 return NULL((void*)0);
1284 }
1285
1286 *wp++ = '\0';
1287 *newlen = strlen(ebuf);
1288
1289 return ebuf;
1290}
1291
1292static FILE *preprocess_exec(const char *cwd, const char *command, FILE *write_fd, int rlevel)
1293{
1294#ifdef WIN32
1295 FILE *fp = NULL((void*)0);
1296 char buffer[1024];
1297
1298 if (!command || !strlen(command)) goto end;
1299
1300 if ((fp = _popen(command, "r"))) {
1301 while (fgets(buffer, sizeof(buffer), fp) != NULL((void*)0)) {
1302 if (fwrite(buffer, 1, strlen(buffer), write_fd) <= 0) {
1303 break;
1304 }
1305 }
1306
1307 if(feof(fp)) {
1308 _pclose(fp);
1309 } else {
1310 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1310, ((void*)0)
, SWITCH_LOG_ERROR, "Exec failed to read the pipe of [%s] to the end\n", command);
1311 }
1312 } else {
1313 switch_snprintf(buffer, sizeof(buffer), "<!-- exec can not execute [%s] -->", command);
1314 fwrite( buffer, 1, strlen(buffer), write_fd);
1315 }
1316#else
1317 int fds[2], pid = 0;
1318
1319 if (pipe(fds)) {
1320 goto end;
1321 } else { /* good to go */
1322 pid = switch_fork();
1323
1324 if (pid < 0) { /* ok maybe not */
1325 close(fds[0]);
1326 close(fds[1]);
1327 goto end;
1328 } else if (pid) { /* parent */
1329 char buf[1024] = "";
1330 int bytes;
1331 close(fds[1]);
1332 while ((bytes = read(fds[0], buf, sizeof(buf))) > 0) {
1333 if (fwrite(buf, 1, bytes, write_fd) <= 0) {
1334 break;
1335 }
1336 }
1337 close(fds[0]);
1338 waitpid(pid, NULL((void*)0), 0);
1339 } else { /* child */
1340 switch_close_extra_files(fds, 2);
1341 close(fds[0]);
1342 dup2(fds[1], STDOUT_FILENO1);
1343 switch_system(command, SWITCH_TRUE);
1344 close(fds[1]);
1345 exit(0);
1346 }
1347 }
1348#endif
1349 end:
1350
1351 return write_fd;
1352
1353}
1354
1355static FILE *preprocess_glob(const char *cwd, const char *pattern, FILE *write_fd, int rlevel)
1356{
1357 char *full_path = NULL((void*)0);
1358 char *dir_path = NULL((void*)0), *e = NULL((void*)0);
1359 glob_t glob_data;
1360 size_t n;
1361 int glob_return;
1362
1363 if (!switch_is_file_path(pattern)) {
1364 full_path = switch_mprintf("%s%s%s", cwd, SWITCH_PATH_SEPARATOR"/", pattern);
1365 pattern = full_path;
1366 }
1367
1368 glob_return = glob(pattern, GLOB_ERR(1 << 0), NULL((void*)0), &glob_data);
1369 if (glob_return == GLOB_NOSPACE1 || glob_return == GLOB_ABORTED2) {
1370 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1370, ((void*)0)
, SWITCH_LOG_ERROR, "Error including %s\n", pattern);
1371 goto end;
1372 } else if (glob_return == GLOB_NOMATCH3) {
1373 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1373, ((void*)0)
, SWITCH_LOG_INFO, "No files to include at %s\n", pattern);
1374 goto end;
1375 }
1376
1377 for (n = 0; n < glob_data.gl_pathc; ++n) {
1378 dir_path = switch_must_strdup(glob_data.gl_pathv[n]);
1379
1380 if ((e = strrchr(dir_path, *SWITCH_PATH_SEPARATOR"/"))) {
1381 *e = '\0';
1382 }
1383 if (preprocess(dir_path, glob_data.gl_pathv[n], write_fd, rlevel) < 0) {
1384 if (rlevel > 100) {
1385 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1385, ((void*)0)
, SWITCH_LOG_ERROR, "Error including %s (Maximum recursion limit reached)\n", pattern);
1386 }
1387 }
1388 free(dir_path);
1389 }
1390 globfree(&glob_data);
1391
1392 end:
1393
1394 switch_safe_free(full_path)if (full_path) {free(full_path);full_path=((void*)0);};
1395
1396 return write_fd;
1397}
1398
1399static int preprocess(const char *cwd, const char *file, FILE *write_fd, int rlevel)
1400{
1401 FILE *read_fd = NULL((void*)0);
1402 switch_size_t cur = 0, ml = 0;
1403 char *q, *cmd, *buf = NULL((void*)0), *ebuf = NULL((void*)0);
1404 char *tcmd, *targ;
1405 int line = 0;
1406 switch_size_t len = 0, eblen = 0;
1407
1408 if (rlevel > 100) {
1409 return -1;
1410 }
1411
1412 if (!(read_fd = fopen(file, "r"))) {
1413 const char *reason = strerror(errno(*__errno_location ()));
1414 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1414, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't open %s (%s)\n", file, reason);
1415 return -1;
1416 }
1417
1418 setvbuf(read_fd, (char *) NULL((void*)0), _IOFBF0, 65536);
1419
1420 for(;;) {
1421 char *arg, *e;
1422 const char *err = NULL((void*)0);
1423 char *bp;
1424
1425 switch_safe_free(ebuf)if (ebuf) {free(ebuf);ebuf=((void*)0);};
1426
1427 if ((cur = switch_fp_read_dline(read_fd, &buf, &len)) <= 0) {
1428 break;
1429 }
1430
1431 eblen = len * 2;
1432 ebuf = switch_must_malloc(eblen);
1433 memset(ebuf, 0, eblen);
1434
1435 while (!(bp = expand_vars(buf, ebuf, eblen, &cur, &err))) {
1436 eblen *= 2;
1437 ebuf = switch_must_realloc(ebuf, eblen);
1438 memset(ebuf, 0, eblen);
1439 }
1440
1441 line++;
1442
1443 if (err) {
1444 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1444, ((void*)0)
, SWITCH_LOG_ERROR, "Error [%s] in file %s line %d\n", err, file, line);
1445 }
1446
1447 /* we ignore <include> or </include> for the sake of validators as well as <?xml version="1.0"?> type stuff */
1448 if (strstr(buf, "<include>") || strstr(buf, "</include>") || strstr(buf, "<?")) {
1449 continue;
1450 }
1451
1452 if (ml) {
1453 if ((e = strstr(buf, "-->"))) {
1454 ml = 0;
1455 bp = e + 3;
1456 cur = strlen(bp);
1457 } else {
1458 continue;
1459 }
1460 }
1461
1462 if ((tcmd = (char *) switch_stristr("X-pre-process", bp))) {
1463 if (*(tcmd - 1) != '<') {
1464 continue;
1465 }
1466 if ((e = strstr(tcmd, "/>"))) {
1467 e += 2;
1468 *e = '\0';
1469 if (fwrite(e, 1, (unsigned) strlen(e), write_fd) != (int) strlen(e)) {
1470 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1470, ((void*)0)
, SWITCH_LOG_ERROR, "Short write!\n");
1471 }
1472 }
1473
1474 if (!(tcmd = (char *) switch_stristr("cmd", tcmd))) {
1475 continue;
1476 }
1477
1478 if (!(tcmd = (char *) switch_stristr("=", tcmd))) {
1479 continue;
1480 }
1481
1482 if (!(tcmd = (char *) switch_stristr("\"", tcmd))) {
1483 continue;
1484 }
1485
1486 tcmd++;
1487
1488
1489 if ((e = strchr(tcmd, '"'))) {
1490 *e++ = '\0';
1491 }
1492
1493 if (!(targ = (char *) switch_stristr("data", e))) {
1494 continue;
1495 }
1496
1497 if (!(targ = (char *) switch_stristr("=", targ))) {
1498 continue;
1499 }
1500
1501 if (!(targ = (char *) switch_stristr("\"", targ))) {
1502 continue;
1503 }
1504
1505 targ++;
1506
1507 if ((e = strchr(targ, '"'))) {
1508 *e++ = '\0';
1509 }
1510
1511 if (!strcasecmp(tcmd, "set")) {
1512 char *name = (char *) targ;
1513 char *val = strchr(name, '=');
1514
1515 if (val) {
1516 char *ve = val++;
1517 while (*val && *val == ' ') {
1518 val++;
1519 }
1520 *ve-- = '\0';
1521 while (*ve && *ve == ' ') {
1522 *ve-- = '\0';
1523 }
1524 }
1525
1526 if (val) {
1527 switch_core_set_variable(name, val);
1528 }
1529
1530 } else if (!strcasecmp(tcmd, "exec-set")) {
1531 preprocess_exec_set(targ);
1532 } else if (!strcasecmp(tcmd, "stun-set")) {
1533 preprocess_stun_set(targ);
1534 } else if (!strcasecmp(tcmd, "env-set")) {
1535 preprocess_env_set(targ);
1536 } else if (!strcasecmp(tcmd, "include")) {
1537 preprocess_glob(cwd, targ, write_fd, rlevel + 1);
1538 } else if (!strcasecmp(tcmd, "exec")) {
1539 preprocess_exec(cwd, targ, write_fd, rlevel + 1);
1540 }
1541
1542 continue;
1543 }
1544
1545 if ((cmd = strstr(bp, "<!--#"))) {
1546 if (fwrite(bp, 1, (unsigned) (cmd - bp), write_fd) != (unsigned) (cmd - bp)) {
1547 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1547, ((void*)0)
, SWITCH_LOG_ERROR, "Short write!\n");
1548 }
1549 if ((e = strstr(cmd, "-->"))) {
1550 *e = '\0';
1551 e += 3;
1552 if (fwrite(e, 1, (unsigned) strlen(e), write_fd) != (int) strlen(e)) {
1553 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1553, ((void*)0)
, SWITCH_LOG_ERROR, "Short write!\n");
1554 }
1555 } else {
1556 ml++;
1557 }
1558
1559 cmd += 5;
1560 if ((e = strchr(cmd, '\r')) || (e = strchr(cmd, '\n'))) {
1561 *e = '\0';
1562 }
1563
1564 if ((arg = strchr(cmd, ' '))) {
1565 *arg++ = '\0';
1566 if ((q = strchr(arg, '"'))) {
1567 char *qq = q + 1;
1568
1569 if ((qq = strchr(qq, '"'))) {
1570 *qq = '\0';
1571 arg = q + 1;
1572 }
1573 }
1574
1575 if (!strcasecmp(cmd, "set")) {
1576 char *name = arg;
1577 char *val = strchr(name, '=');
1578
1579 if (val) {
1580 char *ve = val++;
1581 while (*val && *val == ' ') {
1582 val++;
1583 }
1584 *ve-- = '\0';
1585 while (*ve && *ve == ' ') {
1586 *ve-- = '\0';
1587 }
1588 }
1589
1590 if (val) {
1591 switch_core_set_variable(name, val);
1592 }
1593
1594 } else if (!strcasecmp(cmd, "exec-set")) {
1595 preprocess_exec_set(arg);
1596 } else if (!strcasecmp(cmd, "stun-set")) {
1597 preprocess_stun_set(arg);
1598 } else if (!strcasecmp(cmd, "include")) {
1599 preprocess_glob(cwd, arg, write_fd, rlevel + 1);
1600 } else if (!strcasecmp(cmd, "exec")) {
1601 preprocess_exec(cwd, arg, write_fd, rlevel + 1);
1602 }
1603 }
1604
1605 continue;
1606 }
1607
1608 if (fwrite(bp, 1, (unsigned) cur, write_fd) != (int) cur) {
1609 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1609, ((void*)0)
, SWITCH_LOG_ERROR, "Short write!\n");
1610 }
1611
1612 }
1613
1614 switch_safe_free(buf)if (buf) {free(buf);buf=((void*)0);};
1615 switch_safe_free(ebuf)if (ebuf) {free(ebuf);ebuf=((void*)0);};
1616
1617 fclose(read_fd);
1618
1619 return 0;
1620}
1621
1622SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_file_simple(const char *file)
1623{
1624 int fd = -1;
1625 struct stat st;
1626 switch_ssize_t l;
1627 void *m;
1628 switch_xml_root_t root;
1629
1630 if ((fd = open(file, O_RDONLY00, 0)) > -1) {
1631 fstat(fd, &st);
1632 if (!st.st_size) goto error;
1633 m = switch_must_malloc(st.st_size);
1634
1635 if (!(0<(l = read(fd, m, st.st_size)))) goto error;
1636 if (!(root = (switch_xml_root_t) switch_xml_parse_str((char *) m, l))) goto error;
1637 root->dynamic = 1;
1638 close(fd);
1639 return &root->xml;
1640 }
1641
1642 error:
1643
1644 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1644, ((void*)0)
, SWITCH_LOG_ERROR, "Error Parsing File [%s]\n", file);
1645
1646 return NULL((void*)0);
1647}
1648
1649SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_parse_file(const char *file)
1650{
1651 int fd = -1;
1652 FILE *write_fd = NULL((void*)0);
1653 switch_xml_t xml = NULL((void*)0);
1654 char *new_file = NULL((void*)0);
1655 char *new_file_tmp = NULL((void*)0);
1656 const char *abs, *absw;
1657
1658 abs = strrchr(file, '/');
1659 absw = strrchr(file, '\\');
1660 if (abs || absw) {
1661 abs > absw ? abs++ : (abs = ++absw);
1662 } else {
1663 abs = file;
1664 }
1665
1666 switch_mutex_lock(FILE_LOCK);
1667
1668 if (!(new_file = switch_mprintf("%s%s%s.fsxml", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR"/", abs))) {
1669 goto done;
1670 }
1671
1672 if (!(new_file_tmp = switch_mprintf("%s%s%s.fsxml.tmp", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR"/", abs))) {
1673 goto done;
1674 }
1675
1676 if ((write_fd = fopen(new_file_tmp, "w+")) == NULL((void*)0)) {
1677 goto done;
1678 }
1679
1680 setvbuf(write_fd, (char *) NULL((void*)0), _IOFBF0, 65536);
1681
1682 if (preprocess(SWITCH_GLOBAL_dirs.conf_dir, file, write_fd, 0) > -1) {
1683 fclose(write_fd);
1684 write_fd = NULL((void*)0);
1685 unlink (new_file);
1686
1687 if ( rename(new_file_tmp,new_file) ) {
1688 goto done;
1689 }
1690 if ((fd = open(new_file, O_RDONLY00, 0)) > -1) {
1691 if ((xml = switch_xml_parse_fd(fd))) {
1692 if (strcmp(abs, SWITCH_GLOBAL_filenames.conf_name)) {
1693 xml->free_path = new_file;
1694 new_file = NULL((void*)0);
1695 }
1696 }
1697 close(fd);
1698 fd = -1;
1699 }
1700 }
1701
1702 done:
1703
1704 switch_mutex_unlock(FILE_LOCK);
1705
1706 if (write_fd) {
1707 fclose(write_fd);
1708 write_fd = NULL((void*)0);
1709 }
1710
1711 if (fd > -1) {
1712 close(fd);
1713 }
1714
1715 switch_safe_free(new_file_tmp)if (new_file_tmp) {free(new_file_tmp);new_file_tmp=((void*)0)
;}
;
1716 switch_safe_free(new_file)if (new_file) {free(new_file);new_file=((void*)0);};
1717
1718 return xml;
1719}
1720
1721SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate(const char *section,
1722 const char *tag_name,
1723 const char *key_name,
1724 const char *key_value,
1725 switch_xml_t *root, switch_xml_t *node, switch_event_t *params, switch_bool_t clone)
1726{
1727 switch_xml_t conf = NULL((void*)0);
1728 switch_xml_t tag = NULL((void*)0);
1729 switch_xml_t xml = NULL((void*)0);
1730 switch_xml_binding_t *binding;
1731 uint8_t loops = 0;
1732 switch_xml_section_t sections = BINDINGS ? switch_xml_parse_section_string(section) : 0;
1733
1734 switch_thread_rwlock_rdlock(B_RWLOCK);
1735
1736 for (binding = BINDINGS; binding; binding = binding->next) {
1737 if (binding->sections && !(sections & binding->sections)) {
1738 continue;
1739 }
1740
1741 if ((xml = binding->function(section, tag_name, key_name, key_value, params, binding->user_data))) {
1742 const char *err = NULL((void*)0);
1743
1744 err = switch_xml_error(xml);
1745 if (zstr(err)_zstr(err)) {
1746 if ((conf = switch_xml_find_child(xml, "section", "name", "result"))) {
1747 switch_xml_t p;
1748 const char *aname;
1749
1750 if ((p = switch_xml_child(conf, "result"))) {
1751 aname = switch_xml_attr(p, "status");
1752 if (aname && !strcasecmp(aname, "not found")) {
1753 switch_xml_free(xml);
1754 xml = NULL((void*)0);
1755 continue;
1756 }
1757 }
1758 }
1759 break;
1760 } else {
1761 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 1761, ((void*)0)
, SWITCH_LOG_ERROR, "Error[%s]\n", err);
1762 switch_xml_free(xml);
1763 xml = NULL((void*)0);
1764 }
1765 }
1766 }
1767 switch_thread_rwlock_unlock(B_RWLOCK);
1768
1769 for (;;) {
1770 if (!xml) {
1771 if (!(xml = switch_xml_root())) {
1772 *node = NULL((void*)0);
1773 *root = NULL((void*)0);
1774 return SWITCH_STATUS_FALSE;
1775 }
1776 }
1777
1778 if ((conf = switch_xml_find_child(xml, "section", "name", section)) && (tag = switch_xml_find_child(conf, tag_name, key_name, key_value))) {
1779 if (clone) {
1780 char *x = switch_xml_toxml(tag, SWITCH_FALSE)switch_xml_toxml_ex(tag, SWITCH_FALSE, SWITCH_TRUE);
1781 switch_assert(x)((x) ? (void) (0) : __assert_fail ("x", "src/switch_xml.c", 1781
, __extension__ __PRETTY_FUNCTION__))
;
1782 *node = *root = switch_xml_parse_str_dynamic(x, SWITCH_FALSE); /* x will be free()'d in switch_xml_free() */
1783 switch_xml_free(xml);
1784 } else {
1785 *node = tag;
1786 *root = xml;
1787 }
1788 return SWITCH_STATUS_SUCCESS;
1789 } else {
1790 switch_xml_free(xml);
1791 xml = NULL((void*)0);
1792 *node = NULL((void*)0);
1793 *root = NULL((void*)0);
1794 if (loops++ > 1) {
1795 break;
1796 }
1797 }
1798 }
1799
1800 return SWITCH_STATUS_FALSE;
1801}
1802
1803SWITCH_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)
1804{
1805 switch_event_t *my_params = NULL((void*)0);
1806 switch_status_t status;
1807 *domain = NULL((void*)0);
1808
1809 if (!params) {
1810 switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("src/switch_xml.c", (const
char * )(const char *)__func__, 1810, &my_params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
1811 switch_assert(my_params)((my_params) ? (void) (0) : __assert_fail ("my_params", "src/switch_xml.c"
, 1811, __extension__ __PRETTY_FUNCTION__))
;
1812 switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain_name);
1813 params = my_params;
1814 }
1815
1816 status = switch_xml_locate("directory", "domain", "name", domain_name, root, domain, params, SWITCH_FALSE);
1817 if (my_params) {
1818 switch_event_destroy(&my_params);
1819 }
1820 return status;
1821}
1822
1823SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate_group(const char *group_name,
1824 const char *domain_name,
1825 switch_xml_t *root, switch_xml_t *domain, switch_xml_t *group, switch_event_t *params)
1826{
1827 switch_status_t status = SWITCH_STATUS_FALSE;
1828 switch_event_t *my_params = NULL((void*)0);
1829 switch_xml_t groups = NULL((void*)0);
1830
1831 *root = NULL((void*)0);
1832 *group = NULL((void*)0);
1833 *domain = NULL((void*)0);
1834
1835 if (!params) {
1836 switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("src/switch_xml.c", (const
char * )(const char *)__func__, 1836, &my_params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
1837 switch_assert(my_params)((my_params) ? (void) (0) : __assert_fail ("my_params", "src/switch_xml.c"
, 1837, __extension__ __PRETTY_FUNCTION__))
;
1838 params = my_params;
1839 }
1840
1841 if (group_name) {
1842 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "group_name", group_name);
1843 }
1844
1845 if (domain_name) {
1846 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain_name);
1847 }
1848
1849 if ((status = switch_xml_locate_domain(domain_name, params, root, domain)) != SWITCH_STATUS_SUCCESS) {
1850 goto end;
1851 }
1852
1853 status = SWITCH_STATUS_FALSE;
1854
1855 if ((groups = switch_xml_child(*domain, "groups"))) {
1856 if ((*group = switch_xml_find_child(groups, "group", "name", group_name))) {
1857 status = SWITCH_STATUS_SUCCESS;
1858 }
1859 }
1860
1861 end:
1862
1863 if (my_params) {
1864 switch_event_destroy(&my_params);
1865 }
1866
1867 return status;
1868}
1869
1870static switch_status_t find_user_in_tag(switch_xml_t tag, const char *ip, const char *user_name,
1871 const char *key, switch_event_t *params, switch_xml_t *user)
1872{
1873 const char *type = "!pointer";
1874 const char *val;
1875
1876 if (params && (val = switch_event_get_header(params, "user_type")switch_event_get_header_idx(params, "user_type", -1))) {
1877 if (!strcasecmp(val, "any")) {
1878 type = NULL((void*)0);
1879 } else {
1880 type = val;
1881 }
1882 }
1883
1884 if (ip) {
1885 if ((*user = switch_xml_find_child_multi(tag, "user", "ip", ip, "type", type, NULL((void*)0)))) {
1886 return SWITCH_STATUS_SUCCESS;
1887 }
1888 }
1889
1890 if (user_name) {
1891 if (!strcasecmp(key, "id")) {
1892 if ((*user = switch_xml_find_child_multi(tag, "user", key, user_name, "number-alias", user_name, "type", type, NULL((void*)0)))) {
1893 return SWITCH_STATUS_SUCCESS;
1894 }
1895 } else {
1896 if ((*user = switch_xml_find_child_multi(tag, "user", key, user_name, "type", type, NULL((void*)0)))) {
1897 return SWITCH_STATUS_SUCCESS;
1898 }
1899 }
1900 }
1901
1902 return SWITCH_STATUS_FALSE;
1903
1904}
1905
1906SWITCH_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)
1907{
1908 switch_xml_t group = NULL((void*)0), groups = NULL((void*)0), users = NULL((void*)0);
1909 switch_status_t status = SWITCH_STATUS_FALSE;
1910
1911 if ((groups = switch_xml_child(domain, "groups"))) {
1912 for (group = switch_xml_child(groups, "group"); group; group = group->next) {
1913 if ((users = switch_xml_child(group, "users"))) {
1914 if ((status = find_user_in_tag(users, NULL((void*)0), user_name, "id", NULL((void*)0), user)) == SWITCH_STATUS_SUCCESS) {
1915 if (ingroup) {
1916 *ingroup = group;
1917 }
1918 break;
1919 }
1920 }
1921 }
1922 } else {
1923 if ((users = switch_xml_child(domain, "users"))) {
1924 status = find_user_in_tag(users, NULL((void*)0), user_name, "id", NULL((void*)0), user);
1925 } else {
1926 status = find_user_in_tag(domain, NULL((void*)0), user_name, "id", NULL((void*)0), user);
1927 }
1928 }
1929
1930 return status;
1931}
1932
1933
1934SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_dup(switch_xml_t xml)
1935{
1936 char *x = switch_xml_toxml(xml, SWITCH_FALSE)switch_xml_toxml_ex(xml, SWITCH_FALSE, SWITCH_TRUE);
1937 return switch_xml_parse_str_dynamic(x, SWITCH_FALSE);
1938}
1939
1940
1941static void do_merge(switch_xml_t in, switch_xml_t src, const char *container, const char *tag_name)
1942{
1943 switch_xml_t itag, tag, param, iparam, iitag;
1944
1945 if (!(itag = switch_xml_child(in, container))) {
1946 itag = switch_xml_add_child_d(in, container, 0);
1947 }
1948
1949 if ((tag = switch_xml_child(src, container))) {
1950 for (param = switch_xml_child(tag, tag_name); param; param = param->next) {
1951 const char *var = switch_xml_attr(param, "name");
1952 const char *val = switch_xml_attr(param, "value");
1953
1954 switch_bool_t add_child = SWITCH_TRUE;
1955
1956 for (iparam = switch_xml_child(itag, tag_name); iparam; iparam = iparam->next) {
1957 const char *ivar = switch_xml_attr(iparam, "name");
1958
1959 if (var && ivar && !strcasecmp(var, ivar)) {
1960 add_child = SWITCH_FALSE;
1961 break;
1962 }
1963 }
1964
1965 if (add_child) {
1966 iitag = switch_xml_add_child_d(itag, tag_name, 0);
1967 switch_xml_set_attr_d(iitag, "name", var);
1968 switch_xml_set_attr_d(iitag, "value", val);
1969 }
1970 }
1971 }
1972
1973}
1974
1975
1976SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_xml_merge_user(switch_xml_t user, switch_xml_t domain, switch_xml_t group)
1977{
1978 const char *domain_name = switch_xml_attr(domain, "name");
1979
1980 do_merge(user, group, "params", "param");
1981 do_merge(user, group, "variables", "variable");
1982 do_merge(user, group, "profile-variables", "variable");
1983 do_merge(user, domain, "params", "param");
1984 do_merge(user, domain, "variables", "variable");
1985 do_merge(user, domain, "profile-variables", "variable");
1986
1987 if (!zstr(domain_name)_zstr(domain_name)) {
1988 switch_xml_set_attr_d(user, "domain-name", domain_name);
1989 }
1990}
1991
1992SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_xml_clear_user_cache(const char *key, const char *user_name, const char *domain_name)
1993{
1994 switch_hash_index_t *hi = NULL((void*)0);
1995 void *val;
1996 const void *var;
1997 char mega_key[1024];
1998 int r = 0;
1999 switch_xml_t lookup;
2000 char *expires_val = NULL((void*)0);
2001
2002 switch_mutex_lock(CACHE_MUTEX);
2003
2004 if (key && user_name && domain_name) {
2005 switch_snprintf(mega_key, sizeof(mega_key), "%s%s%s", key, user_name, domain_name);
2006
2007 if ((lookup = switch_core_hash_find(CACHE_HASH, mega_key))) {
2008 switch_core_hash_delete(CACHE_HASH, mega_key);
2009 if ((expires_val = switch_core_hash_find(CACHE_EXPIRES_HASH, mega_key))) {
2010 switch_core_hash_delete(CACHE_EXPIRES_HASH, mega_key);
2011 free(expires_val);
2012 expires_val = NULL((void*)0);
2013 }
2014 switch_xml_free(lookup);
2015 r++;
2016 }
2017
2018 } else {
2019
2020 while ((hi = switch_core_hash_first_iter( CACHE_HASH, hi))) {
2021 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
2022 switch_xml_free(val);
2023 switch_core_hash_delete(CACHE_HASH, var);
2024 r++;
2025 }
2026
2027 while ((hi = switch_core_hash_first_iter( CACHE_EXPIRES_HASH, hi))) {
2028 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
2029 switch_safe_free(val)if (val) {free(val);val=((void*)0);};
2030 switch_core_hash_delete(CACHE_EXPIRES_HASH, var);
2031 }
2032
2033 switch_safe_free(hi)if (hi) {free(hi);hi=((void*)0);};
2034 }
2035
2036 switch_mutex_unlock(CACHE_MUTEX);
2037
2038 return r;
2039
2040}
2041
2042static switch_status_t switch_xml_locate_user_cache(const char *key, const char *user_name, const char *domain_name, switch_xml_t *user)
2043{
2044 char mega_key[1024];
2045 switch_status_t status = SWITCH_STATUS_FALSE;
2046 switch_xml_t lookup;
2047
2048 switch_snprintf(mega_key, sizeof(mega_key), "%s%s%s", key, user_name, domain_name);
2049
2050 switch_mutex_lock(CACHE_MUTEX);
2051 if ((lookup = switch_core_hash_find(CACHE_HASH, mega_key))) {
2052 char *expires_lookup = NULL((void*)0);
2053
2054 if ((expires_lookup = switch_core_hash_find(CACHE_EXPIRES_HASH, mega_key))) {
2055 switch_time_t time_expires = 0;
2056 switch_time_t time_now = 0;
2057
2058 time_now = switch_micro_time_now();
2059 time_expires = atol(expires_lookup);
2060 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2060, ((void*)0)
, SWITCH_LOG_DEBUG, "Cache Info\nTime Now:\t%ld\nExpires:\t%ld\n", (long)time_now, (long)time_expires);
2061 if (time_expires < time_now) {
2062 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2062, ((void*)0)
, SWITCH_LOG_DEBUG, "Cache expired for %s@%s, doing fresh lookup\n", user_name, domain_name);
2063 } else {
2064 *user = switch_xml_dup(lookup);
2065 status = SWITCH_STATUS_SUCCESS;
2066 }
2067 } else {
2068 *user = switch_xml_dup(lookup);
2069 status = SWITCH_STATUS_SUCCESS;
2070 }
2071 }
2072 switch_mutex_unlock(CACHE_MUTEX);
2073
2074 return status;
2075}
2076
2077static void switch_xml_user_cache(const char *key, const char *user_name, const char *domain_name, switch_xml_t user, switch_time_t expires)
2078{
2079 char mega_key[1024];
2080 switch_xml_t lookup;
2081 char *expires_lookup;
2082
2083 switch_snprintf(mega_key, sizeof(mega_key), "%s%s%s", key, user_name, domain_name);
2084
2085 switch_mutex_lock(CACHE_MUTEX);
2086 if ((lookup = switch_core_hash_find(CACHE_HASH, mega_key))) {
2087 switch_core_hash_delete(CACHE_HASH, mega_key);
2088 switch_xml_free(lookup);
2089 }
2090 if ((expires_lookup = switch_core_hash_find(CACHE_EXPIRES_HASH, mega_key))) {
2091 switch_core_hash_delete(CACHE_EXPIRES_HASH, mega_key);
2092 switch_safe_free(expires_lookup)if (expires_lookup) {free(expires_lookup);expires_lookup=((void
*)0);}
;
2093 }
2094 if (expires) {
2095 char *expires_val = switch_must_malloc(1024);
2096 if (sprintf(expires_val, "%ld", (long)expires)) {
2097 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))
;
2098 } else {
2099 switch_safe_free(expires_val)if (expires_val) {free(expires_val);expires_val=((void*)0);};
2100 }
2101 }
2102 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))
;
2103 switch_mutex_unlock(CACHE_MUTEX);
2104}
2105
2106SWITCH_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,
2107 const char *ip, switch_xml_t *user, switch_event_t *params)
2108{
2109 switch_xml_t xml, domain, group, x_user, x_user_dup;
2110 switch_status_t status = SWITCH_STATUS_FALSE;
2111 char *kdup = NULL((void*)0);
2112 char *keys[10] = {0};
2113 int i, nkeys;
2114
2115 if (strchr(key, ':')) {
2116 kdup = switch_must_strdup(key);
2117 nkeys = switch_split(kdup, ':', keys)switch_separate_string(kdup, ':', keys, (sizeof(keys) / sizeof
(keys[0])))
;
2118 } else {
2119 keys[0] = (char *)key;
2120 nkeys = 1;
2121 }
2122
2123 for(i = 0; i < nkeys; i++) {
2124 if ((status = switch_xml_locate_user_cache(keys[i], user_name, domain_name, &x_user)) == SWITCH_STATUS_SUCCESS) {
2125 *user = x_user;
2126 break;
2127 } else if ((status = switch_xml_locate_user(keys[i], user_name, domain_name, ip, &xml, &domain, &x_user, &group, params)) == SWITCH_STATUS_SUCCESS) {
2128 const char *cacheable = NULL((void*)0);
2129
2130 x_user_dup = switch_xml_dup(x_user);
2131 switch_xml_merge_user(x_user_dup, domain, group);
2132
2133 cacheable = switch_xml_attr(x_user_dup, "cacheable");
2134 if (!zstr(cacheable)_zstr(cacheable)) {
2135 switch_time_t expires = 0;
2136 switch_time_t time_now = 0;
2137
2138 if (switch_is_number(cacheable)) {
2139 int cache_ms = atol(cacheable);
2140 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2140, ((void*)0)
, SWITCH_LOG_DEBUG, "caching lookup for user %s@%s for %d milliseconds\n",
2141 user_name, domain_name, cache_ms);
2142 time_now = switch_micro_time_now();
2143 expires = time_now + (cache_ms * 1000);
2144 } else {
2145 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2145, ((void*)0)
, SWITCH_LOG_DEBUG, "caching lookup for user %s@%s indefinitely\n", user_name, domain_name);
2146 }
2147 switch_xml_user_cache(keys[i], user_name, domain_name, x_user_dup, expires);
2148 }
2149 *user = x_user_dup;
2150 switch_xml_free(xml);
2151 break;
2152 }
2153 }
2154
2155 switch_safe_free(kdup)if (kdup) {free(kdup);kdup=((void*)0);};
2156
2157 return status;
2158
2159}
2160
2161SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_locate_user(const char *key,
2162 const char *user_name,
2163 const char *domain_name,
2164 const char *ip,
2165 switch_xml_t *root,
2166 switch_xml_t *domain, switch_xml_t *user, switch_xml_t *ingroup, switch_event_t *params)
2167{
2168 switch_status_t status = SWITCH_STATUS_FALSE;
2169 switch_event_t *my_params = NULL((void*)0);
2170 switch_xml_t group = NULL((void*)0), groups = NULL((void*)0), users = NULL((void*)0);
2171
2172 *root = NULL((void*)0);
2173 *user = NULL((void*)0);
2174 *domain = NULL((void*)0);
2175
2176 if (ingroup) {
2177 *ingroup = NULL((void*)0);
2178 }
2179
2180 if (!params) {
2181 switch_event_create(&my_params, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("src/switch_xml.c", (const
char * )(const char *)__func__, 2181, &my_params, SWITCH_EVENT_REQUEST_PARAMS
, ((void*)0))
;
2182 switch_assert(my_params)((my_params) ? (void) (0) : __assert_fail ("my_params", "src/switch_xml.c"
, 2182, __extension__ __PRETTY_FUNCTION__))
;
2183 params = my_params;
2184 }
2185
2186 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "key", key);
2187
2188 if (user_name) {
2189 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "user", user_name);
2190 }
2191
2192 if (domain_name) {
2193 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain_name);
2194 }
2195
2196 if (ip) {
2197 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "ip", ip);
2198 }
2199
2200 if ((status = switch_xml_locate_domain(domain_name, params, root, domain)) != SWITCH_STATUS_SUCCESS) {
2201 goto end;
2202 }
2203
2204 status = SWITCH_STATUS_FALSE;
2205
2206 if ((groups = switch_xml_child(*domain, "groups"))) {
2207 for (group = switch_xml_child(groups, "group"); group; group = group->next) {
2208 if ((users = switch_xml_child(group, "users"))) {
2209 if ((status = find_user_in_tag(users, ip, user_name, key, params, user)) == SWITCH_STATUS_SUCCESS) {
2210 if (ingroup) {
2211 *ingroup = group;
2212 }
2213 break;
2214 }
2215 }
2216 }
2217 }
2218
2219 if (status != SWITCH_STATUS_SUCCESS) {
2220 if ((users = switch_xml_child(*domain, "users"))) {
2221 status = find_user_in_tag(users, ip, user_name, key, params, user);
2222 } else {
2223 status = find_user_in_tag(*domain, ip, user_name, key, params, user);
2224 }
2225 }
2226
2227 end:
2228
2229 if (my_params) {
2230 switch_event_destroy(&my_params);
2231 }
2232
2233 if (status != SWITCH_STATUS_SUCCESS && root && *root) {
2234 switch_xml_free(*root);
2235 *root = NULL((void*)0);
2236 *domain = NULL((void*)0);
2237 }
2238
2239 return status;
2240}
2241
2242SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_root(void)
2243{
2244 switch_xml_t xml;
2245
2246 switch_mutex_lock(REFLOCK);
2247 xml = MAIN_XML_ROOT;
2248 xml->refs++;
2249 switch_mutex_unlock(REFLOCK);
2250
2251 return xml;
2252}
2253
2254struct destroy_xml {
2255 switch_xml_t xml;
2256 switch_memory_pool_t *pool;
2257};
2258
2259static void *SWITCH_THREAD_FUNC destroy_thread(switch_thread_t *thread, void *obj)
2260{
2261 struct destroy_xml *dx = (struct destroy_xml *) obj;
2262 switch_memory_pool_t *pool = dx->pool;
2263 switch_xml_free(dx->xml);
2264 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_xml.c"
, (const char *)__func__, 2264)
;
2265 return NULL((void*)0);
2266}
2267
2268SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_xml_free_in_thread(switch_xml_t xml, int stacksize)
2269{
2270 switch_thread_t *thread;
2271 switch_threadattr_t *thd_attr;
2272 switch_memory_pool_t *pool = NULL((void*)0);
2273 struct destroy_xml *dx;
2274
2275 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "src/switch_xml.c"
, (const char *)__func__, 2275)
;
2276
2277 switch_threadattr_create(&thd_attr, pool);
2278 switch_threadattr_detach_set(thd_attr, 1);
2279 /* TBD figure out how much space we need by looking at the xml_t when stacksize == 0 */
2280 switch_threadattr_stacksize_set(thd_attr, stacksize);
2281
2282 dx = switch_core_alloc(pool, sizeof(*dx))switch_core_perform_alloc(pool, sizeof(*dx), "src/switch_xml.c"
, (const char *)__func__, 2282)
;
2283 dx->pool = pool;
2284 dx->xml = xml;
2285
2286 switch_thread_create(&thread, thd_attr, destroy_thread, dx, pool);
2287}
2288
2289static char not_so_threadsafe_error_buffer[256] = "";
2290
2291SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_set_root(switch_xml_t new_main)
2292{
2293 switch_xml_t old_root = NULL((void*)0);
2294
2295 switch_mutex_lock(REFLOCK);
2296
2297 old_root = MAIN_XML_ROOT;
2298 MAIN_XML_ROOT = new_main;
2299 switch_set_flag(MAIN_XML_ROOT, SWITCH_XML_ROOT)(MAIN_XML_ROOT)->flags |= (SWITCH_XML_ROOT);
2300 MAIN_XML_ROOT->refs++;
2301
2302 if (old_root) {
2303 if (old_root->refs) {
2304 old_root->refs--;
2305 }
2306
2307 if (!old_root->refs) {
2308 switch_xml_free(old_root);
2309 }
2310 }
2311
2312 switch_mutex_unlock(REFLOCK);
2313
2314 return SWITCH_STATUS_SUCCESS;
2315}
2316
2317SWITCH_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)
2318{
2319 if (XML_LOCK) {
2320 switch_mutex_lock(XML_LOCK);
2321 }
2322
2323 XML_OPEN_ROOT_FUNCTION = func;
2324 XML_OPEN_ROOT_FUNCTION_USER_DATA = user_data;
2325
2326 if (XML_LOCK) {
2327 switch_mutex_unlock(XML_LOCK);
2328 }
2329 return SWITCH_STATUS_SUCCESS;
2330}
2331
2332SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_open_root(uint8_t reload, const char **err)
2333{
2334 switch_xml_t root = NULL((void*)0);
2335 switch_event_t *event;
2336
2337 switch_mutex_lock(XML_LOCK);
2338
2339 if (XML_OPEN_ROOT_FUNCTION) {
2340 root = XML_OPEN_ROOT_FUNCTION(reload, err, XML_OPEN_ROOT_FUNCTION_USER_DATA);
2341 }
2342 switch_mutex_unlock(XML_LOCK);
2343
2344
2345 if (root) {
2346 if (switch_event_create(&event, SWITCH_EVENT_RELOADXML)switch_event_create_subclass_detailed("src/switch_xml.c", (const
char * )(const char *)__func__, 2346, &event, SWITCH_EVENT_RELOADXML
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2347 if (switch_event_fire(&event)switch_event_fire_detailed("src/switch_xml.c", (const char * )
(const char *)__func__, 2347, &event, ((void*)0))
!= SWITCH_STATUS_SUCCESS) {
2348 switch_event_destroy(&event);
2349 }
2350 }
2351 }
2352
2353 return root;
2354}
2355
2356SWITCH_DECLARE_NONSTD(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t __switch_xml_open_root(uint8_t reload, const char **err, void *user_data)
2357{
2358 char path_buf[1024];
2359 uint8_t errcnt = 0;
2360 switch_xml_t new_main, r = NULL((void*)0);
2361
2362 if (MAIN_XML_ROOT) {
2363 if (!reload) {
2364 r = switch_xml_root();
2365 goto done;
2366 }
2367 }
2368
2369 switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR"/", SWITCH_GLOBAL_filenames.conf_name);
2370 if ((new_main = switch_xml_parse_file(path_buf))) {
2371 *err = switch_xml_error(new_main);
2372 switch_copy_string(not_so_threadsafe_error_buffer, *err, sizeof(not_so_threadsafe_error_buffer));
2373 *err = not_so_threadsafe_error_buffer;
2374 if (!zstr(*err)_zstr(*err)) {
2375 switch_xml_free(new_main);
2376 new_main = NULL((void*)0);
2377 errcnt++;
2378 } else {
2379 *err = "Success";
2380 switch_xml_set_root(new_main);
2381
2382 }
2383 } else {
2384 *err = "Cannot Open log directory or XML Root!";
2385 errcnt++;
2386 }
2387
2388 if (errcnt == 0) {
2389 r = switch_xml_root();
2390 }
2391
2392 done:
2393
2394 return r;
2395}
2396
2397SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_reload(const char **err)
2398{
2399 switch_xml_t xml_root;
2400
2401 if ((xml_root = switch_xml_open_root(1, err))) {
2402 switch_xml_free(xml_root);
2403 return SWITCH_STATUS_SUCCESS;
2404 }
2405
2406 return SWITCH_STATUS_GENERR;
2407}
2408
2409SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_init(switch_memory_pool_t *pool, const char **err)
2410{
2411 switch_xml_t xml;
2412 XML_MEMORY_POOL = pool;
2413 *err = "Success";
2414
2415 switch_mutex_init(&CACHE_MUTEX, SWITCH_MUTEX_NESTED0x1, XML_MEMORY_POOL);
2416 switch_mutex_init(&XML_LOCK, SWITCH_MUTEX_NESTED0x1, XML_MEMORY_POOL);
2417 switch_mutex_init(&REFLOCK, SWITCH_MUTEX_NESTED0x1, XML_MEMORY_POOL);
2418 switch_mutex_init(&FILE_LOCK, SWITCH_MUTEX_NESTED0x1, XML_MEMORY_POOL);
2419 switch_core_hash_init(&CACHE_HASH)switch_core_hash_init_case(&CACHE_HASH, SWITCH_TRUE);
2420 switch_core_hash_init(&CACHE_EXPIRES_HASH)switch_core_hash_init_case(&CACHE_EXPIRES_HASH, SWITCH_TRUE
)
;
2421
2422 switch_thread_rwlock_create(&B_RWLOCK, XML_MEMORY_POOL);
2423
2424 assert(pool != NULL)((pool != ((void*)0)) ? (void) (0) : __assert_fail ("pool != NULL"
, "src/switch_xml.c", 2424, __extension__ __PRETTY_FUNCTION__
))
;
2425
2426 if ((xml = switch_xml_open_root(FALSE0, err))) {
2427 switch_xml_free(xml);
2428 return SWITCH_STATUS_SUCCESS;
2429 } else {
2430 return SWITCH_STATUS_FALSE;
2431 }
2432}
2433
2434SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_xml_destroy(void)
2435{
2436 switch_status_t status = SWITCH_STATUS_FALSE;
2437
2438
2439 switch_mutex_lock(XML_LOCK);
2440 switch_mutex_lock(REFLOCK);
2441
2442 if (MAIN_XML_ROOT) {
2443 switch_xml_t xml = MAIN_XML_ROOT;
2444 MAIN_XML_ROOT = NULL((void*)0);
2445 switch_xml_free(xml);
2446 status = SWITCH_STATUS_SUCCESS;
2447 }
2448
2449 switch_mutex_unlock(XML_LOCK);
2450 switch_mutex_unlock(REFLOCK);
2451
2452 switch_xml_clear_user_cache(NULL((void*)0), NULL((void*)0), NULL((void*)0));
2453
2454 switch_core_hash_destroy(&CACHE_HASH);
2455 switch_core_hash_destroy(&CACHE_EXPIRES_HASH);
2456
2457 return status;
2458}
2459
2460SWITCH_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)
2461{
2462 switch_xml_t xml = NULL((void*)0), cfg = NULL((void*)0);
2463
2464 *node = NULL((void*)0);
2465
2466 assert(MAIN_XML_ROOT != NULL)((MAIN_XML_ROOT != ((void*)0)) ? (void) (0) : __assert_fail (
"MAIN_XML_ROOT != NULL", "src/switch_xml.c", 2466, __extension__
__PRETTY_FUNCTION__))
;
2467
2468 if (switch_xml_locate("configuration", "configuration", "name", file_path, &xml, &cfg, params, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
2469 *node = cfg;
2470 }
2471
2472 return xml;
2473
2474}
2475
2476/* Encodes ampersand sequences appending the results to *dst, reallocating *dst
2477 if length exceeds max. a is non-zero for attribute encoding. Returns *dst */
2478static 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)
2479{
2480 const char *e = NULL((void*)0);
2481 int immune = 0;
2482 int expecting_x_utf_8_char = 0;
2483 int unicode_char = 0x000000;
2484
2485 if (!(s && *s))
2486 return *dst;
2487
2488 if (len) {
2489 e = s + len;
2490 }
2491
2492 while (s != e) {
2493 while (*dlen + 10 > *max) {
2494 *dst = (char *) switch_must_realloc(*dst, *max += SWITCH_XML_BUFSIZE1024);
2495 }
2496
2497 if (immune) {
2498 if (*s == '\0') {
2499 return *dst;
2500 }
2501 (*dst)[(*dlen)++] = *s;
2502 } else
2503 switch (*s) {
2504 case '\0':
2505 return *dst;
2506 case '&':
2507 *dlen += sprintf(*dst + *dlen, "&amp;");
2508 break;
2509 case '<':
2510 if (*(s + 1) == '!') {
2511 (*dst)[(*dlen)++] = *s;
2512 immune++;
2513 break;
2514 }
2515 *dlen += sprintf(*dst + *dlen, "&lt;");
2516 break;
2517 case '>':
2518 *dlen += sprintf(*dst + *dlen, "&gt;");
2519 break;
2520 case '"':
2521 *dlen += sprintf(*dst + *dlen, (a) ? "&quot;" : "\"");
2522 break;
2523 case '\n':
2524 *dlen += sprintf(*dst + *dlen, (a) ? "&#xA;" : "\n");
2525 break;
2526 case '\t':
2527 *dlen += sprintf(*dst + *dlen, (a) ? "&#x9;" : "\t");
2528 break;
2529 case '\r':
2530 *dlen += sprintf(*dst + *dlen, "&#xD;");
2531 break;
2532 default:
2533 if (use_utf8_encoding && expecting_x_utf_8_char == 0 && ((*s >> 8) & 0x01)) {
2534 int num = 1;
2535 for (;num<4;num++) {
2536 if (! ((*s >> (7-num)) & 0x01)) {
2537 break;
2538 }
2539 }
2540 switch (num) {
2541 case 2:
2542 unicode_char = *s & 0x1f;
2543 break;
2544 case 3:
2545 unicode_char = *s & 0x0f;
2546 break;
2547 case 4:
2548 unicode_char = *s & 0x07;
2549 break;
2550 default:
2551 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2551, ((void*)0)
, SWITCH_LOG_WARNING, "Invalid UTF-8 Initial charactere, skip it\n");
2552 /* ERROR HERE */
2553 break;
2554 }
2555 expecting_x_utf_8_char = num - 1;
2556
2557 } else if (use_utf8_encoding && expecting_x_utf_8_char > 0) {
2558 if (((*s >> 6) & 0x03) == 0x2) {
2559
2560 unicode_char = unicode_char << 6;
2561 unicode_char = unicode_char | (*s & 0x3f);
2562 } else {
2563 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2563, ((void*)0)
, SWITCH_LOG_WARNING, "Invalid UTF-8 character to ampersand, skip it\n");
2564 expecting_x_utf_8_char = 0;
2565 break;
2566 }
2567 expecting_x_utf_8_char--;
2568 if (expecting_x_utf_8_char == 0) {
2569 *dlen += sprintf(*dst + *dlen, "&#x%X;", unicode_char);
2570 }
2571 } else {
2572 (*dst)[(*dlen)++] = *s;
2573 }
2574 }
2575 s++;
2576 }
2577 return *dst;
2578}
2579
2580#define XML_INDENT" " " "
2581/* Recursively converts each tag to xml appending it to *s. Reallocates *s if
2582 its length exceeds max. start is the location of the previous tag in the
2583 parent tag's character content. Returns *s. */
2584static 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)
2585{
2586 int i, j;
2587 char *txt;
2588 switch_size_t off;
2589 uint32_t lcount;
2590 uint32_t loops = 0;
2591
2592 tailrecurse:
2593 off = 0;
2594 txt = "";
2595
2596 if (loops++) {
2597 isroot = 0;
2598 }
2599
2600 if (!isroot && xml->parent) {
2601 txt = (char *) xml->parent->txt;
2602 }
2603
2604 /* parent character content up to this tag */
2605 *s = switch_xml_ampencode(txt + start, xml->off - start, s, len, max, 0, use_utf8_encoding);
2606
2607 while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT" ") * (*count)) + 1 > *max) { /* reallocate s */
2608 *s = (char *) switch_must_realloc(*s, *max += SWITCH_XML_BUFSIZE1024);
2609 }
2610
2611 if (*len && *(*s + (*len) - 1) == '>') {
2612 *len += sprintf(*s + *len, "\n"); /* indent */
2613 }
2614 for (lcount = 0; lcount < *count; lcount++) {
2615 *len += sprintf(*s + *len, "%s", XML_INDENT" "); /* indent */
2616 }
2617
2618 *len += sprintf(*s + *len, "<%s", xml->name); /* open tag */
2619 for (i = 0; xml->attr[i]; i += 2) { /* tag attributes */
2620 if (switch_xml_attr(xml, xml->attr[i]) != xml->attr[i + 1])
2621 continue;
2622 while (*len + strlen(xml->attr[i]) + 7 + (strlen(XML_INDENT" ") * (*count)) > *max) { /* reallocate s */
2623 *s = (char *) switch_must_realloc(*s, *max += SWITCH_XML_BUFSIZE1024);
2624 }
2625
2626 *len += sprintf(*s + *len, " %s=\"", xml->attr[i]);
2627 switch_xml_ampencode(xml->attr[i + 1], 0, s, len, max, 1, use_utf8_encoding);
2628 *len += sprintf(*s + *len, "\"");
2629 }
2630
2631 for (i = 0; attr[i] && strcmp(attr[i][0], xml->name); i++);
2632 for (j = 1; attr[i] && attr[i][j]; j += 3) { /* default attributes */
2633 if (!attr[i][j + 1] || switch_xml_attr(xml, attr[i][j]) != attr[i][j + 1])
2634 continue; /* skip duplicates and non-values */
2635 while (*len + strlen(attr[i][j]) + 8 + (strlen(XML_INDENT" ") * (*count)) > *max) { /* reallocate s */
2636 *s = (char *) switch_must_realloc(*s, *max += SWITCH_XML_BUFSIZE1024);
2637 }
2638
2639 *len += sprintf(*s + *len, " %s=\"", attr[i][j]);
2640 switch_xml_ampencode(attr[i][j + 1], 0, s, len, max, 1, use_utf8_encoding);
2641 *len += sprintf(*s + *len, "\"");
2642 }
2643
2644 *len += sprintf(*s + *len, (xml->child || xml->txt) ? ">" : "/>\n");
2645
2646 if (xml->child) {
2647 (*count)++;
2648 *s = switch_xml_toxml_r(xml->child, s, len, max, 0, attr, count, 0, use_utf8_encoding);
2649
2650 } else {
2651 *s = switch_xml_ampencode(xml->txt, 0, s, len, max, 0, use_utf8_encoding); /* data */
2652 }
2653
2654 while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT" ") * (*count)) > *max) { /* reallocate s */
2655 *s = (char *) switch_must_realloc(*s, *max += SWITCH_XML_BUFSIZE1024);
2656 }
2657
2658 if (xml->child || xml->txt) {
2659 if (*(*s + (*len) - 1) == '\n') {
2660 for (lcount = 0; lcount < *count; lcount++) {
2661 *len += sprintf(*s + *len, "%s", XML_INDENT" "); /* indent */
2662 }
2663 }
2664 *len += sprintf(*s + (*len), "</%s>\n", xml->name); /* close tag */
2665 }
2666
2667 while (txt[off] && off < xml->off)
2668 off++; /* make sure off is within bounds */
2669
2670 if (!isroot && xml->ordered) {
2671 xml = xml->ordered;
2672 start = off;
2673 goto tailrecurse;
2674/*
2675 return switch_xml_toxml_r(xml->ordered, s, len, max, off, attr, count, use_utf8_encoding);
2676*/
2677 } else {
2678 if (*count > 0)
2679 (*count)--;
2680 return switch_xml_ampencode(txt + off, 0, s, len, max, 0, use_utf8_encoding);
2681 }
2682}
2683
2684SWITCH_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)
2685{
2686 char *s = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
2687
2688 return switch_xml_toxml_buf_ex(xml, s, SWITCH_XML_BUFSIZE1024, 0, prn_header, use_utf8_encoding);
2689}
2690
2691SWITCH_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)
2692{
2693 char *r, *s;
2694
2695 s = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
2696
2697 r = switch_xml_toxml_buf_ex(xml, s, SWITCH_XML_BUFSIZE1024, 0, prn_header, use_utf8_encoding);
2698
2699 return r;
2700}
2701
2702SWITCH_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)
2703{
2704 char *r, *s, *h;
2705 switch_size_t rlen = 0;
2706 switch_size_t len = SWITCH_XML_BUFSIZE1024;
2707
2708 s = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
2709 h = (char *) switch_must_malloc(SWITCH_XML_BUFSIZE1024);
2710
2711 r = switch_xml_toxml_buf_ex(xml, s, SWITCH_XML_BUFSIZE1024, 0, prn_header, use_utf8_encoding);
2712 h = switch_xml_ampencode(r, 0, &h, &rlen, &len, 1, use_utf8_encoding);
2713 switch_safe_free(r)if (r) {free(r);r=((void*)0);};
2714 return h;
2715}
2716
2717/* converts a switch_xml structure back to xml, returning a string of xml data that
2718 must be freed */
2719SWITCH_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)
2720{
2721 switch_xml_t p = (xml) ? xml->parent : NULL((void*)0);
2722 switch_xml_root_t root = (switch_xml_root_t) xml;
2723 switch_size_t len = 0, max = buflen;
2724 char *s, *t, *n;
2725 int i, j, k;
2726 uint32_t count = 0;
2727
2728 s = buf;
2729 assert(s != NULL)((s != ((void*)0)) ? (void) (0) : __assert_fail ("s != NULL",
"src/switch_xml.c", 2729, __extension__ __PRETTY_FUNCTION__)
)
;
2730 memset(s, 0, max);
2731 len += offset;
2732 if (prn_header) {
2733 len += sprintf(s + len, "<?xml version=\"1.0\"?>\n");
2734 }
2735
2736 if (!xml || !xml->name) {
2737 return (char *) switch_must_realloc(s, len + 1);
2738 }
2739
2740 while (root->xml.parent) {
2741 root = (switch_xml_root_t) root->xml.parent; /* root tag */
2742 }
2743
2744 for (i = 0; !p && root->pi[i]; i++) { /* pre-root processing instructions */
2745 for (k = 2; root->pi[i][k - 1]; k++);
2746 for (j = 1; (n = root->pi[i][j]); j++) {
2747 if (root->pi[i][k][j - 1] == '>') {
2748 continue; /* not pre-root */
2749 }
2750 while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max) {
2751 s = (char *) switch_must_realloc(s, max += SWITCH_XML_BUFSIZE1024);
2752 }
2753 len += sprintf(s + len, "<?%s%s%s?>", t, *n ? " " : "", n);
2754 }
2755 }
2756
2757 s = switch_xml_toxml_r(xml, &s, &len, &max, 0, root->attr, &count, 1, use_utf8_encoding);
2758
2759 for (i = 0; !p && root->pi[i]; i++) { /* post-root processing instructions */
2760 for (k = 2; root->pi[i][k - 1]; k++);
2761 for (j = 1; (n = root->pi[i][j]); j++) {
2762 if (root->pi[i][k][j - 1] == '<') {
2763 continue; /* not post-root */
2764 }
2765 while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max) {
2766 s = (char *) switch_must_realloc(s, max += SWITCH_XML_BUFSIZE1024);
2767 }
2768 len += sprintf(s + len, "\n<?%s%s%s?>", t, *n ? " " : "", n);
2769 }
2770 }
2771
2772 return (char *) switch_must_realloc(s, len + 1);
2773}
2774
2775/* free the memory allocated for the switch_xml structure */
2776SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_xml_free(switch_xml_t xml)
2777{
2778 switch_xml_root_t root;
2779 int i, j;
2780 char **a, *s;
2781 switch_xml_t orig_xml;
2782 int refs = 0;
2783
2784 tailrecurse:
2785 root = (switch_xml_root_t) xml;
2786 if (!xml) {
2787 return;
2788 }
2789
2790 if (switch_test_flag(xml, SWITCH_XML_ROOT)((xml)->flags & SWITCH_XML_ROOT)) {
2791 switch_mutex_lock(REFLOCK);
2792
2793 if (xml->refs) {
2794 xml->refs--;
2795 refs = xml->refs;
2796 }
2797 switch_mutex_unlock(REFLOCK);
2798 }
2799
2800 if (refs) {
2801 return;
2802 }
2803
2804 if (xml->free_path) {
2805 if (unlink(xml->free_path) != 0) {
2806 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 2806, ((void*)0)
, SWITCH_LOG_WARNING, "Failed to delete file [%s]\n", xml->free_path);
2807 }
2808 switch_safe_free(xml->free_path)if (xml->free_path) {free(xml->free_path);xml->free_path
=((void*)0);}
;
2809 }
2810
2811 switch_xml_free(xml->child);
2812 /*switch_xml_free(xml->ordered); */
2813
2814 if (!xml->parent) { /* free root tag allocations */
2815#if (_MSC_VER >= 1400) // VC8+
2816 __analysis_assume(sizeof(root->ent) > 44); /* tail recursion confuses code analysis */
2817#endif
2818 for (i = 10; root->ent[i]; i += 2) /* 0 - 9 are default entities (<>&"') */
2819 if ((s = root->ent[i + 1]) < root->s || s > root->e)
2820 free(s);
2821 free(root->ent); /* free list of general entities */
2822
2823 for (i = 0; (a = root->attr[i]); i++) {
2824 for (j = 1; a[j++]; j += 2) /* free malloced attribute values */
2825 if (a[j] && (a[j] < root->s || a[j] > root->e))
2826 free(a[j]);
2827 free(a);
2828 }
2829 if (root->attr[0])
2830 free(root->attr); /* free default attribute list */
2831
2832 for (i = 0; root->pi[i]; i++) {
2833 for (j = 1; root->pi[i][j]; j++);
2834 free(root->pi[i][j + 1]);
2835 free(root->pi[i]);
2836 }
2837 if (root->pi[0])
2838 free(root->pi); /* free processing instructions */
2839
2840 if (root->dynamic == 1)
2841 free(root->m); /* malloced xml data */
2842 if (root->u)
2843 free(root->u); /* utf8 conversion */
2844 }
2845
2846 switch_xml_free_attr(xml->attr); /* tag attributes */
2847 if ((xml->flags & SWITCH_XML_TXTM))
2848 free(xml->txt); /* character content */
2849 if ((xml->flags & SWITCH_XML_NAMEM))
2850 free(xml->name); /* tag name */
2851 if (xml->ordered) {
2852 orig_xml = xml;
2853 xml = xml->ordered;
2854 free(orig_xml);
2855 goto tailrecurse;
2856 }
2857 free(xml);
2858}
2859
2860/* return parser error message or empty string if none */
2861SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_xml_error(switch_xml_t xml)
2862{
2863 while (xml && xml->parent)
2864 xml = xml->parent; /* find root tag */
2865 return (xml) ? ((switch_xml_root_t) xml)->err : "";
2866}
2867
2868/* returns a new empty switch_xml structure with the given root tag name */
2869SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_new(const char *name)
2870{
2871 static const char *ent[] = { "lt;", "&#60;", "gt;", "&#62;", "quot;", "&#34;",
2872 "apos;", "&#39;", "amp;", "&#38;", NULL((void*)0)
2873 };
2874 switch_xml_root_t root = (switch_xml_root_t) switch_must_malloc(sizeof(struct switch_xml_root));
2875
2876 memset(root, '\0', sizeof(struct switch_xml_root));
2877 root->xml.name = (char *) name;
2878 root->cur = &root->xml;
2879 strcpy(root->err, root->xml.txt = (char *) "");
2880 root->ent = (char **) memcpy(switch_must_malloc(sizeof(ent)), ent, sizeof(ent));
2881 root->attr = root->pi = (char ***) (root->xml.attr = SWITCH_XML_NIL);
2882 return &root->xml;
2883}
2884
2885/* inserts an existing tag into a switch_xml structure */
2886SWITCH_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)
2887{
2888 switch_xml_t cur, prev, head;
2889
2890 xml->next = xml->sibling = xml->ordered = NULL((void*)0);
2891 xml->off = off;
2892 xml->parent = dest;
2893
2894 if ((head = dest->child)) { /* already have sub tags */
2895 if (head->off <= off) { /* not first subtag */
2896 for (cur = head; cur->ordered && cur->ordered->off <= off; cur = cur->ordered);
2897 xml->ordered = cur->ordered;
2898 cur->ordered = xml;
2899 } else { /* first subtag */
2900 xml->ordered = head;
2901 dest->child = xml;
2902 }
2903
2904 for (cur = head, prev = NULL((void*)0); cur && strcmp(cur->name, xml->name); prev = cur, cur = cur->sibling); /* find tag type */
2905 if (cur && cur->off <= off) { /* not first of type */
2906 while (cur->next && cur->next->off <= off)
2907 cur = cur->next;
2908 xml->next = cur->next;
2909 cur->next = xml;
2910 } else { /* first tag of this type */
2911 if (prev && cur)
2912 prev->sibling = cur->sibling; /* remove old first */
2913 xml->next = cur; /* old first tag is now next */
2914 for (cur = head, prev = NULL((void*)0); cur && cur->off <= off; prev = cur, cur = cur->sibling); /* new sibling insert point */
2915 xml->sibling = cur;
2916 if (prev)
2917 prev->sibling = xml;
2918 }
2919 } else
2920 dest->child = xml; /* only sub tag */
2921
2922 return xml;
2923}
2924
2925/* Adds a child tag. off is the offset of the child tag relative to the start
2926 of the parent tag's character content. Returns the child tag */
2927SWITCH_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)
2928{
2929 switch_xml_t child;
2930
2931 if (!xml)
2932 return NULL((void*)0);
2933 child = (switch_xml_t) switch_must_malloc(sizeof(struct switch_xml));
2934
2935 memset(child, '\0', sizeof(struct switch_xml));
2936 child->name = (char *) name;
2937 child->attr = SWITCH_XML_NIL;
2938 child->off = off;
2939 child->parent = xml;
2940 child->txt = (char *) "";
2941
2942 return switch_xml_insert(child, xml, off);
2943}
2944
2945/* Adds a child tag. off is the offset of the child tag relative to the start
2946 of the parent tag's character content. Returns the child tag */
2947SWITCH_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)
2948{
2949 if (!xml) return NULL((void*)0);
2950 return switch_xml_set_flag(switch_xml_add_child(xml, strdup(name), off), SWITCH_XML_NAMEM);
2951}
2952
2953/* sets the character content for the given tag and returns the tag */
2954SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_txt(switch_xml_t xml, const char *txt)
2955{
2956 if (!xml)
2957 return NULL((void*)0);
2958 if (xml->flags & SWITCH_XML_TXTM)
2959 free(xml->txt); /* existing txt was malloced */
2960 xml->flags &= ~SWITCH_XML_TXTM;
2961 xml->txt = (char *) txt;
2962 return xml;
2963}
2964
2965/* sets the character content for the given tag and returns the tag */
2966SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_txt_d(switch_xml_t xml, const char *txt)
2967{
2968 if (!xml) return NULL((void*)0);
2969 return switch_xml_set_flag(switch_xml_set_txt(xml, strdup(txt)), SWITCH_XML_TXTM);
2970}
2971
2972/* Sets the given tag attribute or adds a new attribute if not found. A value
2973 of NULL will remove the specified attribute. Returns the tag given */
2974SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_attr(switch_xml_t xml, const char *name, const char *value)
2975{
2976 int l = 0, c;
2977
2978 if (!xml)
2979 return NULL((void*)0);
2980 while (xml->attr[l] && strcmp(xml->attr[l], name))
2981 l += 2;
2982 if (!xml->attr[l]) { /* not found, add as new attribute */
2983 if (!value)
2984 return xml; /* nothing to do */
2985 if (xml->attr == SWITCH_XML_NIL) { /* first attribute */
2986 xml->attr = (char **) switch_must_malloc(4 * sizeof(char *));
2987 xml->attr[l + 1] = switch_must_strdup(""); /* empty list of malloced names/vals */
2988 } else {
2989 xml->attr = (char **) switch_must_realloc(xml->attr, (l + 4) * sizeof(char *));
2990 }
2991
2992 xml->attr[l] = (char *) name; /* set attribute name */
2993 xml->attr[l + 2] = NULL((void*)0); /* null terminate attribute list */
2994 xml->attr[l + 3] = (char *) switch_must_realloc(xml->attr[l + 1], (c = (int) strlen(xml->attr[l + 1])) + 2);
2995 strcpy(xml->attr[l + 3] + c, " "); /* set name/value as not malloced */
2996 if (xml->flags & SWITCH_XML_DUP)
2997 xml->attr[l + 3][c] = SWITCH_XML_NAMEM;
2998 } else if (xml->flags & SWITCH_XML_DUP)
2999 free((char *) name); /* name was strduped */
3000
3001 for (c = l; xml->attr[c]; c += 2); /* find end of attribute list */
3002 if (xml->attr[c + 1][l / 2] & SWITCH_XML_TXTM)
3003 free(xml->attr[l + 1]); /* old val */
3004 if (xml->flags & SWITCH_XML_DUP)
3005 xml->attr[c + 1][l / 2] |= SWITCH_XML_TXTM;
3006 else
3007 xml->attr[c + 1][l / 2] &= ~SWITCH_XML_TXTM;
3008
3009 if (value)
3010 xml->attr[l + 1] = (char *) value; /* set attribute value */
3011 else { /* remove attribute */
3012 if (xml->attr[c + 1][l / 2] & SWITCH_XML_NAMEM)
3013 free(xml->attr[l]);
3014 memmove(xml->attr + l, xml->attr + l + 2, (c - l + 2) * sizeof(char *));
3015 xml->attr = (char **) switch_must_realloc(xml->attr, (c + 2) * sizeof(char *));
3016 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 */
3017 }
3018 xml->flags &= ~SWITCH_XML_DUP; /* clear strdup() flag */
3019
3020 return xml;
3021}
3022
3023/* Sets the given tag attribute or adds a new attribute if not found. A value
3024 of NULL will remove the specified attribute. Returns the tag given */
3025SWITCH_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)
3026{
3027 if (!xml) return NULL((void*)0);
3028 return switch_xml_set_attr(switch_xml_set_flag(xml, SWITCH_XML_DUP), strdup(name), strdup(switch_str_nil(value)(value ? value : "")));
3029}
3030
3031/* Sets the given tag attribute or adds a new attribute if not found. A value
3032 of NULL will remove the specified attribute. Returns the tag given */
3033SWITCH_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)
3034{
3035 if (!xml) return NULL((void*)0);
3036 return switch_xml_set_attr(switch_xml_set_flag(xml, SWITCH_XML_DUP), strdup(name), strdup(value));
3037}
3038
3039/* sets a flag for the given tag and returns the tag */
3040SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_set_flag(switch_xml_t xml, switch_xml_flag_t flag)
3041{
3042 if (xml)
3043 xml->flags |= flag;
3044 return xml;
3045}
3046
3047/* removes a tag along with its subtags without freeing its memory */
3048SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_xml_cut(switch_xml_t xml)
3049{
3050 switch_xml_t cur;
3051
3052 if (!xml)
3053 return NULL((void*)0); /* nothing to do */
3054 if (xml->next)
3055 xml->next->sibling = xml->sibling; /* patch sibling list */
3056
3057 if (xml->parent) { /* not root tag */
3058 cur = xml->parent->child; /* find head of subtag list */
3059 if (cur == xml)
3060 xml->parent->child = xml->ordered; /* first subtag */
3061 else { /* not first subtag */
3062 while (cur->ordered != xml)
3063 cur = cur->ordered;
3064 cur->ordered = cur->ordered->ordered; /* patch ordered list */
3065
3066 cur = xml->parent->child; /* go back to head of subtag list */
3067 if (strcmp(cur->name, xml->name)) { /* not in first sibling list */
3068 while (strcmp(cur->sibling->name, xml->name))
3069 cur = cur->sibling;
3070 if (cur->sibling == xml) { /* first of a sibling list */
3071 cur->sibling = (xml->next) ? xml->next : cur->sibling->sibling;
3072 } else
3073 cur = cur->sibling; /* not first of a sibling list */
3074 }
3075
3076 while (cur->next && cur->next != xml)
3077 cur = cur->next;
3078 if (cur->next)
3079 cur->next = cur->next->next; /* patch next list */
3080 }
3081 }
3082 xml->ordered = xml->sibling = xml->next = NULL((void*)0); /* prevent switch_xml_free() from clobbering ordered list */
3083 return xml;
3084}
3085
3086SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_xml_std_datetime_check(switch_xml_t xcond, int *offset, const char *tzname)
3087{
3088
3089 const char *xdt = switch_xml_attr(xcond, "date-time");
3090 const char *xyear = switch_xml_attr(xcond, "year");
3091 const char *xyday = switch_xml_attr(xcond, "yday");
3092 const char *xmon = switch_xml_attr(xcond, "mon");
3093 const char *xmday = switch_xml_attr(xcond, "mday");
3094 const char *xweek = switch_xml_attr(xcond, "week");
3095 const char *xmweek = switch_xml_attr(xcond, "mweek");
3096 const char *xwday = switch_xml_attr(xcond, "wday");
3097 const char *xhour = switch_xml_attr(xcond, "hour");
3098 const char *xminute = switch_xml_attr(xcond, "minute");
3099 const char *xminday = switch_xml_attr(xcond, "minute-of-day");
3100 const char *xtod = switch_xml_attr(xcond, "time-of-day");
3101 const char *tzoff = switch_xml_attr(xcond, "tz-offset");
3102 const char *isdst = switch_xml_attr(xcond, "dst");
3103
3104 int loffset = -1000;
3105 int eoffset = -1000;
3106 int dst = -1000;
3107 switch_time_t ts = switch_micro_time_now();
3108 int time_match = -1;
3109 switch_time_exp_t tm, tm2;
3110
3111 if (!zstr(isdst)_zstr(isdst)) {
3112 dst = switch_true(isdst);
3113 }
3114
3115 if (!zstr(tzoff)_zstr(tzoff) && switch_is_number(tzoff)) {
3116 loffset = atoi(tzoff);
3117 }
3118
3119 switch_time_exp_lt(&tm2, ts);
3120
3121 if (offset) {
3122 eoffset = *offset;
3123 switch_time_exp_tz(&tm, ts, *offset * 3600);
3124 } else if (!zstr(tzname)_zstr(tzname)) {
3125 switch_time_exp_tz_name(tzname, &tm, ts);
3126 } else {
3127 tm = tm2;
3128 }
3129
3130 if (eoffset == -1000) {
3131 eoffset = tm.tm_gmtoff / 3600;
3132 }
3133
3134 if (loffset == -1000) {
3135 loffset = eoffset;
3136 }
3137
3138
3139 if (time_match && tzoff) {
3140 time_match = loffset == eoffset;
3141 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3141, ((void*)0)
, SWITCH_LOG_DEBUG9,
3142 "XML DateTime Check: TZOFFSET[%d] == %d (%s)\n", eoffset, loffset, time_match ? "PASS" : "FAIL");
3143
3144 }
3145
3146 if (time_match && dst > -1) {
3147 time_match = (tm2.tm_isdst > 0 && dst > 0);
3148 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3148, ((void*)0)
, SWITCH_LOG_DEBUG9,
3149 "XML DateTime Check: DST[%s] == %s (%s)\n",
3150 tm2.tm_isdst > 0 ? "true" : "false", dst > 0 ? "true" : "false", time_match ? "PASS" : "FAIL");
3151
3152 }
3153
3154 if (time_match && xdt) {
3155 char tmpdate[80];
3156 switch_size_t retsize;
3157 switch_strftime(tmpdate, &retsize, sizeof(tmpdate), "%Y-%m-%d %H:%M:%S", &tm);
3158 time_match = switch_fulldate_cmp(xdt, &ts);
3159 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3159, ((void*)0)
, SWITCH_LOG_DEBUG,
3160 "XML DateTime Check: date time[%s] =~ %s (%s)\n", tmpdate, xdt, time_match ? "PASS" : "FAIL");
3161 }
3162
3163 if (time_match && xyear) {
3164 int test = tm.tm_year + 1900;
3165 time_match = switch_number_cmp(xyear, test);
3166 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3166, ((void*)0)
, SWITCH_LOG_DEBUG9,
3167 "XML DateTime Check: year[%d] =~ %s (%s)\n", test, xyear, time_match ? "PASS" : "FAIL");
3168 }
3169
3170 if (time_match && xyday) {
3171 int test = tm.tm_yday + 1;
3172 time_match = switch_number_cmp(xyday, test);
3173 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3173, ((void*)0)
, SWITCH_LOG_DEBUG9,
3174 "XML DateTime Check: day of year[%d] =~ %s (%s)\n", test, xyday, time_match ? "PASS" : "FAIL");
3175 }
3176
3177 if (time_match && xmon) {
3178 int test = tm.tm_mon + 1;
3179 time_match = switch_number_cmp(xmon, test);
3180 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3180, ((void*)0)
, SWITCH_LOG_DEBUG9,
3181 "XML DateTime Check: month[%d] =~ %s (%s)\n", test, xmon, time_match ? "PASS" : "FAIL");
3182 }
3183
3184 if (time_match && xmday) {
3185 int test = tm.tm_mday;
3186 time_match = switch_number_cmp(xmday, test);
3187 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3187, ((void*)0)
, SWITCH_LOG_DEBUG9,
3188 "XML DateTime Check: day of month[%d] =~ %s (%s)\n", test, xmday, time_match ? "PASS" : "FAIL");
3189 }
3190
3191 if (time_match && xweek) {
3192 int test = (int) (tm.tm_yday / 7 + 1);
3193 time_match = switch_number_cmp(xweek, test);
3194 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3194, ((void*)0)
, SWITCH_LOG_DEBUG9,
3195 "XML DateTime Check: week of year[%d] =~ %s (%s)\n", test, xweek, time_match ? "PASS" : "FAIL");
3196 }
3197
3198 if (time_match && xmweek) {
3199 /* calculate the day of the week of the first of the month (0-6) */
3200 int firstdow = (int) (7 - (tm.tm_mday - (tm.tm_wday + 1)) % 7) % 7;
3201 /* calculate the week of the month (1-6)*/
3202 int test = (int) ceil((tm.tm_mday + firstdow) / 7.0);
3203 time_match = switch_number_cmp(xmweek, test);
3204 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3204, ((void*)0)
, SWITCH_LOG_DEBUG9,
3205 "XML DateTime: week of month[%d] =~ %s (%s)\n", test, xmweek, time_match ? "PASS" : "FAIL");
3206 }
3207
3208 if (time_match && xwday) {
3209 int test = tm.tm_wday + 1;
3210 time_match = switch_dow_cmp(xwday, test);
3211 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3211, ((void*)0)
, SWITCH_LOG_DEBUG9,
3212 "XML DateTime Check: day of week[%s] =~ %s (%s)\n", switch_dow_int2str(test), xwday, time_match ? "PASS" : "FAIL");
3213 }
3214 if (time_match && xhour) {
3215 int test = tm.tm_hour;
3216 time_match = switch_number_cmp(xhour, test);
3217 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3217, ((void*)0)
, SWITCH_LOG_DEBUG9,
3218 "XML DateTime Check: hour[%d] =~ %s (%s)\n", test, xhour, time_match ? "PASS" : "FAIL");
3219 }
3220
3221 if (time_match && xminute) {
3222 int test = tm.tm_min;
3223 time_match = switch_number_cmp(xminute, test);
3224 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3224, ((void*)0)
, SWITCH_LOG_DEBUG9,
3225 "XML DateTime Check: minute[%d] =~ %s (%s)\n", test, xminute, time_match ? "PASS" : "FAIL");
3226 }
3227
3228 if (time_match && xminday) {
3229 int test = (tm.tm_hour * 60) + (tm.tm_min + 1);
3230 time_match = switch_number_cmp(xminday, test);
3231 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3231, ((void*)0)
, SWITCH_LOG_DEBUG9,
3232 "XML DateTime Check: minute of day[%d] =~ %s (%s)\n", test, xminday, time_match ? "PASS" : "FAIL");
3233 }
3234
3235 if (time_match && xtod) {
3236 int test = (tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec;
3237 char tmpdate[10];
3238 switch_snprintf(tmpdate, 10, "%d:%d:%d", tm.tm_hour, tm.tm_min, tm.tm_sec);
3239 time_match = switch_tod_cmp(xtod, 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: time of day[%s] =~ %s (%s)\n", tmpdate, xtod, time_match ? "PASS" : "FAIL");
3242 }
3243
3244 return time_match;
3245}
3246
3247SWITCH_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) {
3248 switch_status_t status = SWITCH_STATUS_FALSE;
3249
3250 if (switch_xml_locate("languages", NULL((void*)0), NULL((void*)0), NULL((void*)0), root, node, params, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
3251 switch_xml_t sub_macros;
3252
3253 if (switch_xml_locate("phrases", NULL((void*)0), NULL((void*)0), NULL((void*)0), root, node, params, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
3254 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3254, ((void*)0)
, SWITCH_LOG_ERROR, "Open of languages and phrases failed.\n");
3255 goto done;
3256 }
3257 if (!(sub_macros = switch_xml_child(*node, "macros"))) {
3258 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3258, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find macros tag.\n");
3259 switch_xml_free(*root);
3260 *root = NULL((void*)0);
3261 *node = NULL((void*)0);
3262 goto done;
3263 }
3264 if (!(*language = switch_xml_find_child(sub_macros, "language", "name", str_language))) {
3265 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3265, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find language %s.\n", str_language);
3266 switch_xml_free(*root);
3267 *root = NULL((void*)0);
3268 *node = NULL((void*)0);
3269 goto done;
3270 }
3271 *macros = *language;
3272 } else {
3273 if (!(*language = switch_xml_find_child(*node, "language", "name", str_language))) {
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 language %s.\n", str_language);
3275 switch_xml_free(*root);
3276 *root = NULL((void*)0);
3277 goto done;
3278 }
3279 if (!(*phrases = switch_xml_child(*language, "phrases"))) {
3280 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3280, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find phrases tag.\n");
3281 switch_xml_free(*root);
3282 *root = NULL((void*)0);
3283 *node = NULL((void*)0);
3284 *language = NULL((void*)0);
3285 goto done;
3286 }
3287
3288 if (!(*macros = switch_xml_child(*phrases, "macros"))) {
3289 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3289, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find macros tag.\n");
3290 switch_xml_free(*root);
3291 *root = NULL((void*)0);
3292 *node = NULL((void*)0);
3293 *language = NULL((void*)0);
3294 *phrases = NULL((void*)0);
3295 goto done;
3296 }
3297 }
3298 status = SWITCH_STATUS_SUCCESS;
3299
3300done:
3301 return status;
3302}
3303
3304SWITCH_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) {
3305 switch_status_t status;
3306
3307 if ((status = switch_xml_locate_language_ex(root, node, params, language, phrases, macros, str_language)) != SWITCH_STATUS_SUCCESS) {
3308 char *str_language_dup = strdup(str_language);
3309 char *secondary;
3310 switch_assert(str_language_dup)((str_language_dup) ? (void) (0) : __assert_fail ("str_language_dup"
, "src/switch_xml.c", 3310, __extension__ __PRETTY_FUNCTION__
))
;
3311 if ((secondary = strchr(str_language_dup, '-'))) {
3312 *secondary++ = '\0';
3313 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_xml.c", (const char *)__func__
, 3313, ((void*)0)
, SWITCH_LOG_WARNING,
3314 "language %s not found. trying %s by removing %s\n", str_language, str_language_dup, secondary);
3315 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "lang", str_language_dup);
3316 status = switch_xml_locate_language_ex(root, node, params, language, phrases, macros, str_language_dup);
3317 }
3318 switch_safe_free(str_language_dup)if (str_language_dup) {free(str_language_dup);str_language_dup
=((void*)0);}
;
3319 }
3320
3321 return status;
3322}
3323
3324#ifdef WIN32
3325/*
3326 * globbing functions for windows, part of libc on unix, this code was cut and paste from
3327 * freebsd lib and distilled a bit to work with windows
3328 */
3329
3330/*
3331 * Copyright (c) 1989, 1993
3332 * The Regents of the University of California. All rights reserved.
3333 *
3334 * This code is derived from software contributed to Berkeley by
3335 * Guido van Rossum.
3336 *
3337 * Redistribution and use in source and binary forms, with or without
3338 * modification, are permitted provided that the following conditions
3339 * are met:
3340 * 1. Redistributions of source code must retain the above copyright
3341 * notice, this list of conditions and the following disclaimer.
3342 * 2. Redistributions in binary form must reproduce the above copyright
3343 * notice, this list of conditions and the following disclaimer in the
3344 * documentation and/or other materials provided with the distribution.
3345 * 4. Neither the name of the University nor the names of its contributors
3346 * may be used to endorse or promote products derived from this software
3347 * without specific prior written permission.
3348 *
3349 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
3350 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3351 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3352 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3353 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3354 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3355 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3356 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3357 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3358 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3359 * SUCH DAMAGE.
3360 */
3361
3362#define DOLLAR '$'
3363#define DOT '.'
3364#define EOS '\0'
3365#define LBRACKET '['
3366#define NOT '!'
3367#define QUESTION '?'
3368#define RANGE '-'
3369#define RBRACKET ']'
3370#define SEP '/'
3371#define WIN_SEP '/'
3372#define STAR '*'
3373#define TILDE '~'
3374#define UNDERSCORE '_'
3375#define LBRACE '{'
3376#define RBRACE '}'
3377#define SLASH '/'
3378#define COMMA ','
3379
3380#define M_QUOTE (char)0x80
3381#define M_PROTECT (char)0x40
3382#define M_MASK (char)0xff
3383#define M_ASCII (char)0x7f
3384
3385#define CHAR(c) ((char)((c)&M_ASCII))
3386#define META(c) ((char)((c)|M_QUOTE))
3387#define M_ALL META('*')
3388#define M_END META(']')
3389#define M_NOT META('!')
3390#define M_ONE META('?')
3391#define M_RNG META('-')
3392#define M_SET META('[')
3393#define ismeta(c) (((c)&M_QUOTE) != 0)
3394
3395#ifndef MAXPATHLEN
3396#define MAXPATHLEN 256
3397#endif
3398
3399static int compare(const void *, const void *);
3400static int glob0(const char *, glob_t *, size_t *);
3401static int glob1(char *, glob_t *, size_t *);
3402static int glob2(char *, char *, char *, char *, glob_t *, size_t *);
3403static int glob3(char *, char *, char *, char *, char *, glob_t *, size_t *);
3404static int globextend(const char *, glob_t *, size_t *);
3405static int match(char *, char *, char *);
3406
3407#pragma warning(push)
3408#pragma warning(disable:4310)
3409
3410int glob(const char *pattern, int flags, int (*errfunc) (const char *, int), glob_t *pglob)
3411{
3412 const unsigned char *patnext;
3413 size_t limit;
3414 char c;
3415 char *bufnext, *bufend, patbuf[MAXPATHLEN];
3416
3417 patnext = (unsigned char *) pattern;
3418 if (!(flags & GLOB_APPEND(1 << 5))) {
3419 pglob->gl_pathc = 0;
3420 pglob->gl_pathv = NULL((void*)0);
3421 if (!(flags & GLOB_DOOFFS(1 << 3)))
3422 pglob->gl_offs = 0;
3423 }
3424 if (flags & GLOB_LIMIT) {
3425 limit = pglob->gl_matchc;
3426 if (limit == 0)
3427 limit = 9999999;
3428 } else
3429 limit = 0;
3430 pglob->gl_flags = flags & ~GLOB_MAGCHAR(1 << 8);
3431 pglob->gl_errfunc = errfunc;
3432 pglob->gl_matchc = 0;
3433
3434 bufnext = patbuf;
3435 bufend = bufnext + MAXPATHLEN - 1;
3436 while (bufnext < bufend && (c = *patnext++) != EOS)
3437 *bufnext++ = c;
3438 *bufnext = EOS;
3439
3440 return glob0(patbuf, pglob, &limit);
3441}
3442
3443/*
3444 * The main glob() routine: compiles the pattern (optionally processing
3445 * quotes), calls glob1() to do the real pattern matching, and finally
3446 * sorts the list (unless unsorted operation is requested). Returns 0
3447 * if things went well, nonzero if errors occurred.
3448 */
3449static int glob0(const char *pattern, glob_t *pglob, size_t *limit)
3450{
3451 const char *qpatnext;
3452 int c, err;
3453 size_t oldpathc;
3454 char *bufnext, patbuf[MAXPATHLEN];
3455
3456 qpatnext = pattern;
3457 oldpathc = pglob->gl_pathc;
3458 bufnext = patbuf;
3459
3460 /* We don't need to check for buffer overflow any more. */
3461 while ((c = *qpatnext++) != EOS) {
3462 switch (c) {
3463 case SEP:
3464 *bufnext++ = WIN_SEP;
3465 break;
3466 case LBRACKET:
3467 c = *qpatnext;
3468 if (c == NOT)
3469 ++qpatnext;
3470 if (*qpatnext == EOS || strchr((char *) qpatnext + 1, RBRACKET) == NULL((void*)0)) {
3471 *bufnext++ = LBRACKET;
3472 if (c == NOT)
3473 --qpatnext;
3474 break;
3475 }
3476 *bufnext++ = M_SET;
3477 if (c == NOT)
3478 *bufnext++ = M_NOT;
3479 c = *qpatnext++;
3480 do {
3481 *bufnext++ = CHAR(c);
3482 if (*qpatnext == RANGE && (c = qpatnext[1]) != RBRACKET) {
3483 *bufnext++ = M_RNG;
3484 *bufnext++ = CHAR(c);
3485 qpatnext += 2;
3486 }
3487 } while ((c = *qpatnext++) != RBRACKET);
3488 pglob->gl_flags |= GLOB_MAGCHAR(1 << 8);
3489 *bufnext++ = M_END;
3490 break;
3491 case QUESTION:
3492 pglob->gl_flags |= GLOB_MAGCHAR(1 << 8);
3493 *bufnext++ = M_ONE;
3494 break;
3495 case STAR:
3496 pglob->gl_flags |= GLOB_MAGCHAR(1 << 8);
3497 /* collapse adjacent stars to one,
3498 * to avoid exponential behavior
3499 */
3500 if (bufnext == patbuf || bufnext[-1] != M_ALL)
3501 *bufnext++ = M_ALL;
3502 break;
3503 default:
3504 *bufnext++ = CHAR(c);
3505 break;
3506 }
3507 }
3508 *bufnext = EOS;
3509
3510 if ((err = glob1(patbuf, pglob, limit)) != 0)
3511 return (err);
3512
3513 /*
3514 * If there was no match we are going to append the pattern
3515 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
3516 * and the pattern did not contain any magic characters
3517 * GLOB_NOMAGIC is there just for compatibility with csh.
3518 */
3519 if (pglob->gl_pathc == oldpathc) {
3520 if (((pglob->gl_flags & GLOB_NOCHECK(1 << 4)) || ((pglob->gl_flags & GLOB_NOMAGIC(1 << 11)) && !(pglob->gl_flags & GLOB_MAGCHAR(1 << 8)))))
3521 return (globextend(pattern, pglob, limit));
3522 else
3523 return (GLOB_NOMATCH3);
3524 }
3525 if (!(pglob->gl_flags & GLOB_NOSORT(1 << 2)))
3526 qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, pglob->gl_pathc - oldpathc, sizeof(char *), compare);
3527 return (0);
3528}
3529
3530static int compare(const void *p, const void *q)
3531{
3532 return (strcmp(*(char **) p, *(char **) q));
3533}
3534
3535static int glob1(char *pattern, glob_t *pglob, size_t *limit)
3536{
3537 char pathbuf[MAXPATHLEN];
3538
3539 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
3540 if (*pattern == EOS)
3541 return (0);
3542 return (glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1, pattern, pglob, limit));
3543}
3544
3545/*
3546 * The functions glob2 and glob3 are mutually recursive; there is one level
3547 * of recursion for each segment in the pattern that contains one or more
3548 * meta characters.
3549 */
3550static int glob2(char *pathbuf, char *pathend, char *pathend_last, char *pattern, glob_t *pglob, size_t *limit)
3551{
3552 struct stat sb;
3553 char *p, *q;
3554 int anymeta;
3555
3556 /*
3557 * Loop over pattern segments until end of pattern or until
3558 * segment with meta character found.
3559 */
3560 for (anymeta = 0;;) {
3561 if (*pattern == EOS) { /* End of pattern? */
3562 *pathend = EOS;
3563 if (stat(pathbuf, &sb))
3564 return (0);
3565
3566 if (((pglob->gl_flags & GLOB_MARK(1 << 1)) && pathend[-1] != SEP && pathend[-1] != WIN_SEP) && (_S_IFDIR & sb.st_mode)) {
3567 if (pathend + 1 > pathend_last)
3568 return (GLOB_ABORTED2);
3569 *pathend++ = WIN_SEP;
3570 *pathend = EOS;
3571 }
3572 ++pglob->gl_matchc;
3573 return (globextend(pathbuf, pglob, limit));
3574 }
3575
3576 /* Find end of next segment, copy tentatively to pathend. */
3577 q = pathend;
3578 p = pattern;
3579 while (*p != EOS && *p != SEP && *p != WIN_SEP) {
3580 if (ismeta(*p))
3581 anymeta = 1;
3582 if (q + 1 > pathend_last)
3583 return (GLOB_ABORTED2);
3584 *q++ = *p++;
3585 }
3586
3587 if (!anymeta) { /* No expansion, do next segment. */
3588 pathend = q;
3589 pattern = p;
3590 while (*pattern == SEP || *pattern == WIN_SEP) {
3591 if (pathend + 1 > pathend_last)
3592 return (GLOB_ABORTED2);
3593 *pathend++ = *pattern++;
3594 }
3595 } else /* Need expansion, recurse. */
3596 return (glob3(pathbuf, pathend, pathend_last, pattern, p, pglob, limit));
3597 }
3598 /* NOTREACHED */
3599}
3600
3601static int glob3(char *pathbuf, char *pathend, char *pathend_last, char *pattern, char *restpattern, glob_t *pglob, size_t *limit)
3602{
3603 int err;
3604 apr_dir_t *dirp;
3605 apr_pool_t *pool;
3606
3607 apr_pool_create(&pool, NULL((void*)0));
3608
3609 if (pathend > pathend_last)
3610 return (GLOB_ABORTED2);
3611 *pathend = EOS;
3612 errno(*__errno_location ()) = 0;
3613
3614 if (apr_dir_open(&dirp, pathbuf, pool) != APR_SUCCESS) {
3615 /* TODO: don't call for ENOENT or ENOTDIR? */
3616 apr_pool_destroy(pool);
3617 if (pglob->gl_errfunc) {
3618 if (pglob->gl_errfunc(pathbuf, errno(*__errno_location ())) || pglob->gl_flags & GLOB_ERR(1 << 0))
3619 return (GLOB_ABORTED2);
3620 }
3621 return (0);
3622 }
3623
3624 err = 0;
3625
3626 /* Search directory for matching names. */
3627 while (dirp) {
3628 apr_finfo_t dp;
3629 unsigned char *sc;
3630 char *dc;
3631
3632 if (apr_dir_read(&dp, APR_FINFO_NAME, dirp) != APR_SUCCESS)
3633 break;
3634 if (!(dp.valid & APR_FINFO_NAME) || !(dp.name) || !strlen(dp.name))
3635 break;
3636
3637 /* Initial DOT must be matched literally. */
3638 if (dp.name[0] == DOT && *pattern != DOT)
3639 continue;
3640 dc = pathend;
3641 sc = (unsigned char *) dp.name;
3642
3643 while (dc < pathend_last && (*dc++ = *sc++) != EOS);
3644
3645 if (!match(pathend, pattern, restpattern)) {
3646 *pathend = EOS;
3647 continue;
3648 }
3649 err = glob2(pathbuf, --dc, pathend_last, restpattern, pglob, limit);
3650 if (err)
3651 break;
3652 }
3653
3654 if (dirp)
3655 apr_dir_close(dirp);
3656 apr_pool_destroy(pool);
3657 return (err);
3658}
3659
3660
3661/*
3662 * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
3663 * add the new item, and update gl_pathc.
3664 *
3665 * This assumes the BSD realloc, which only copies the block when its size
3666 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
3667 * behavior.
3668 *
3669 * Return 0 if new item added, error code if memory couldn't be allocated.
3670 *
3671 * Invariant of the glob_t structure:
3672 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
3673 * gl_pathv points to (gl_offs + gl_pathc + 1) items.
3674 */
3675static int globextend(const char *path, glob_t *pglob, size_t *limit)
3676{
3677 char **pathv;
3678 char *copy;
3679 size_t i;
3680 size_t newsize, len;
3681 const char *p;
3682
3683 if (*limit && pglob->gl_pathc > *limit) {
3684 errno(*__errno_location ()) = 0;
3685 return (GLOB_NOSPACE1);
3686 }
3687
3688 newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
3689 pathv = pglob->gl_pathv ? switch_must_realloc((char *) pglob->gl_pathv, newsize) : switch_must_malloc(newsize);
3690
3691 if (pglob->gl_pathv == NULL((void*)0) && pglob->gl_offs > 0) {
3692 /* first time around -- clear initial gl_offs items */
3693 pathv += pglob->gl_offs;
3694 for (i = pglob->gl_offs; i-- > 0;)
3695 *--pathv = NULL((void*)0);
3696 }
3697 pglob->gl_pathv = pathv;
3698
3699 for (p = path; *p++;)
3700 continue;
3701 len = (size_t) (p - path);
3702 copy = switch_must_malloc(len);
3703 memcpy(copy, path, len);
3704 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
3705 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL((void*)0);
3706 return (copy == NULL((void*)0) ? GLOB_NOSPACE1 : 0);
3707}
3708
3709/*
3710 * pattern matching function for filenames. Each occurrence of the *
3711 * pattern causes a recursion level.
3712 */
3713static int match(char *name, char *pat, char *patend)
3714{
3715 int ok, negate_range;
3716 char c, k;
3717 char s1[6];
3718
3719 while (pat < patend) {
3720 c = *pat++;
3721 switch (c & M_MASK) {
3722 case M_ALL:
3723 if (pat == patend)
3724 return (1);
3725 do
3726 if (match(name, pat, patend))
3727 return (1);
3728 while (*name++ != EOS);
3729 return (0);
3730 case M_ONE:
3731 if (*name++ == EOS)
3732 return (0);
3733 break;
3734 case M_SET:
3735 ok = 0;
3736 if ((k = *name++) == EOS)
3737 return (0);
3738 if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
3739 ++pat;
3740 while (((c = *pat++) & M_MASK) != M_END)
3741 if ((*pat & M_MASK) == M_RNG) {
3742 memset(s1, 0, sizeof(s1));
3743 s1[0] = c;
3744 s1[2] = k;
3745 s1[4] = pat[1];
3746 if (strcoll(&s1[0], &s1[2]) <= 0 && strcoll(&s1[2], &s1[4]) <= 0)
3747 ok = 1;
3748 pat += 2;
3749 } else if (c == k)
3750 ok = 1;
3751 if (ok == negate_range)
3752 return (0);
3753 break;
3754 default:
3755 if (*name++ != c)
3756 return (0);
3757 break;
3758 }
3759 }
3760 return (*name == EOS);
3761}
3762
3763/* Free allocated data belonging to a glob_t structure. */
3764void globfree(glob_t *pglob)
3765{
3766 size_t i;
3767 char **pp;
3768
3769 if (pglob->gl_pathv != NULL((void*)0)) {
3770 pp = pglob->gl_pathv + pglob->gl_offs;
3771 for (i = pglob->gl_pathc; i--; ++pp)
3772 if (*pp)
3773 free(*pp);
3774 free(pglob->gl_pathv);
3775 pglob->gl_pathv = NULL((void*)0);
3776 }
3777}
3778
3779#pragma warning(pop)
3780#endif
3781
3782/* For Emacs:
3783 * Local Variables:
3784 * mode:c
3785 * indent-tabs-mode:t
3786 * tab-width:4
3787 * c-basic-offset:4
3788 * End:
3789 * For VIM:
3790 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3791 */

./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/*!
1462 \brief Insert data into a hash
1463 \param hash the hash to add data to
1464 \param key the name of the key to add the data to
1465 \param data the data to add
1466 \param mutex optional mutex to lock
1467 \return SWITCH_STATUS_SUCCESS if the data is added
1468 \note the string key must be a constant or a dynamic string
1469*/
1470SWITCH_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,
1471 _In_opt_ switch_mutex_t *mutex);
1472/*!
1473 \brief Retrieve data from a given hash
1474 \param hash the hash to retrieve from
1475 \param key the key to retrieve
1476 \param mutex optional rwlock to wrlock
1477 \return a pointer to the data held in the key
1478*/
1479SWITCH_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);
1480
1481/*!
1482 \brief Delete data from a hash based on desired key
1483 \param hash the hash to delete from
1484 \param key the key from which to delete the data
1485 \return The value stored if the data is deleted otherwise NULL
1486*/
1487SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_hash_delete(_In_ switch_hash_t *hash, _In_z_ const char *key);
1488
1489/*!
1490 \brief Delete data from a hash based on desired key
1491 \param hash the hash to delete from
1492 \param key the key from which to delete the data
1493 \param mutex optional mutex to lock
1494 \return a pointer to the deleted data
1495*/
1496SWITCH_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);
1497
1498/*!
1499 \brief Delete data from a hash based on desired key
1500 \param hash the hash to delete from
1501 \param key the key from which to delete the data
1502 \param mutex optional rwlock to wrlock
1503 \return a pointer to the deleted data
1504*/
1505SWITCH_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);
1506
1507/*!
1508 \brief Delete data from a hash based on callback function
1509 \param hash the hash to delete from
1510 \param callback the function to call which returns SWITCH_TRUE to delete, SWITCH_FALSE to preserve
1511 \return SWITCH_STATUS_SUCCESS if any data is deleted
1512*/
1513SWITCH_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);
1514
1515/*!
1516 \brief Retrieve data from a given hash
1517 \param hash the hash to retrieve from
1518 \param key the key to retrieve
1519 \return a pointer to the data held in the key
1520*/
1521SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_hash_find(_In_ switch_hash_t *hash, _In_z_ const char *key);
1522
1523
1524/*!
1525 \brief Retrieve data from a given hash
1526 \param hash the hash to retrieve from
1527 \param key the key to retrieve
1528 \param mutex optional mutex to lock
1529 \return a pointer to the data held in the key
1530*/
1531SWITCH_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);
1532
1533/*!
1534 \brief Retrieve data from a given hash
1535 \param hash the hash to retrieve from
1536 \param key the key to retrieve
1537 \param mutex optional rwlock to rdlock
1538 \return a pointer to the data held in the key
1539*/
1540SWITCH_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);
1541
1542/*!
1543 \brief Gets the first element of a hashtable
1544 \param deprecate_me [deprecated] NULL
1545 \param hash the hashtable to use
1546 \return The element, or NULL if it wasn't found
1547*/
1548SWITCH_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);
1549#define switch_core_hash_first(_h)switch_core_hash_first_iter(_h, ((void*)0)) switch_core_hash_first_iter(_h, NULL((void*)0))
1550
1551/*!
1552 \brief tells if a hash is empty
1553 \param hash the hashtable
1554 \return TRUE or FALSE depending on if the hash is empty
1555*/
1556SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_hash_empty(switch_hash_t *hash);
1557
1558/*!
1559 \brief Gets the next element of a hashtable
1560 \param hi The current element
1561 \return The next element, or NULL if there are no more
1562*/
1563SWITCH_DECLARE(switch_hash_index_t *)__attribute__((visibility("default"))) switch_hash_index_t * switch_core_hash_next(_In_ switch_hash_index_t **hi);
1564
1565/*!
1566 \brief Gets the key and value of the current hash element
1567 \param hi The current element
1568 \param key [out] the key
1569 \param klen [out] the key's size
1570 \param val [out] the value
1571*/
1572SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_hash_this(_In_ switch_hash_index_t *hi, _Out_opt_ptrdiff_cap_(klen)
1573 const void **key, _Out_opt_ switch_ssize_t *klen, _Out_ void **val);
1574
1575SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_hash_this_val(switch_hash_index_t *hi, void *val);
1576
1577SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_inthash_init(switch_inthash_t **hash);
1578SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_inthash_destroy(switch_inthash_t **hash);
1579SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_inthash_insert(switch_inthash_t *hash, uint32_t key, const void *data);
1580SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_inthash_delete(switch_inthash_t *hash, uint32_t key);
1581SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_core_inthash_find(switch_inthash_t *hash, uint32_t key);
1582
1583///\}
1584
1585///\defgroup timer Timer Functions
1586///\ingroup core1
1587///\{
1588/*!
1589 \brief Request a timer handle using given time module
1590 \param timer a timer object to allocate to
1591 \param timer_name the name of the timer module to use
1592 \param interval desired interval
1593 \param samples the number of samples to increment on each cycle
1594 \param pool the memory pool to use for allocation
1595 \return
1596*/
1597SWITCH_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,
1598 switch_memory_pool_t *pool);
1599
1600SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_calibrate_clock(void);
1601
1602/*!
1603 \brief Wait for one cycle on an existing timer
1604 \param timer the timer to wait on
1605 \return the newest sample count
1606*/
1607SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_next(switch_timer_t *timer);
1608
1609/*!
1610 \brief Step the timer one step
1611 \param timer the timer to wait on
1612 \return the newest sample count
1613*/
1614SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_step(switch_timer_t *timer);
1615
1616SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_sync(switch_timer_t *timer);
1617
1618/*!
1619 \brief Check if the current step has been exceeded
1620 \param timer the timer to wait on
1621 \param step increment timer if a tick was detected
1622 \return the newest sample count
1623*/
1624SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_check(switch_timer_t *timer, switch_bool_t step);
1625
1626/*!
1627 \brief Destroy an allocated timer
1628 \param timer timer to destroy
1629 \return SWITCH_STATUS_SUCCESS after destruction
1630*/
1631SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_timer_destroy(switch_timer_t *timer);
1632///\}
1633
1634///\defgroup codecs Codec Functions
1635///\ingroup core1
1636///\{
1637/*!
1638 \brief Initialize a codec handle
1639 \param codec the handle to initilize
1640 \param codec_name the name of the codec module to use
1641 \param fmtp codec parameters to send
1642 \param rate the desired rate (0 for any)
1643 \param ms the desired number of milliseconds (0 for any)
1644 \param channels the desired number of channels (0 for any)
1645 \param flags flags to alter behaviour
1646 \param codec_settings desired codec settings
1647 \param pool the memory pool to use
1648 \return SWITCH_STATUS_SUCCESS if the handle is allocated
1649*/
1650#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
)
\
1651 switch_core_codec_init_with_bitrate(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, 0, _flags, _codec_settings, _pool)
1652SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_init_with_bitrate(switch_codec_t *codec,
1653 const char *codec_name,
1654 const char *fmtp,
1655 const char *modname,
1656 uint32_t rate,
1657 int ms,
1658 int channels,
1659 uint32_t bitrate,
1660 uint32_t flags,
1661 const switch_codec_settings_t *codec_settings,
1662 switch_memory_pool_t *pool);
1663
1664SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_copy(switch_codec_t *codec, switch_codec_t *new_codec,
1665 const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool);
1666SWITCH_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);
1667SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_reset(switch_codec_t *codec);
1668
1669/*!
1670 \brief Encode data using a codec handle
1671 \param codec the codec handle to use
1672 \param other_codec the codec handle of the last codec used
1673 \param decoded_data the raw data
1674 \param decoded_data_len then length of the raw buffer
1675 \param decoded_rate the rate of the decoded data
1676 \param encoded_data the buffer to write the encoded data to
1677 \param encoded_data_len the size of the encoded_data buffer
1678 \param encoded_rate the new rate of the encoded data
1679 \param flag flags to exchange
1680 \return SWITCH_STATUS_SUCCESS if the data was encoded
1681 \note encoded_data_len will be rewritten to the in-use size of encoded_data
1682*/
1683SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_encode(switch_codec_t *codec,
1684 switch_codec_t *other_codec,
1685 void *decoded_data,
1686 uint32_t decoded_data_len,
1687 uint32_t decoded_rate,
1688 void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag);
1689
1690/*!
1691 \brief Decode data using a codec handle
1692 \param codec the codec handle to use
1693 \param other_codec the codec handle of the last codec used
1694 \param encoded_data the buffer to read the encoded data from
1695 \param encoded_data_len the size of the encoded_data buffer
1696 \param encoded_rate the rate of the encoded data
1697 \param decoded_data the raw data buffer
1698 \param decoded_data_len then length of the raw buffer
1699 \param decoded_rate the new rate of the decoded data
1700 \param flag flags to exchange
1701 \return SWITCH_STATUS_SUCCESS if the data was decoded
1702 \note decoded_data_len will be rewritten to the in-use size of decoded_data
1703*/
1704SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_decode(switch_codec_t *codec,
1705 switch_codec_t *other_codec,
1706 void *encoded_data,
1707 uint32_t encoded_data_len,
1708 uint32_t encoded_rate,
1709 void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag);
1710
1711/*!
1712 \brief Encode video data using a codec handle
1713 \param codec the codec handle to use
1714 \param frame the frame to encode
1715*/
1716SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_encode_video(switch_codec_t *codec, switch_frame_t *frame);
1717
1718
1719/*!
1720 \brief send control data using a codec handle
1721 \param codec the codec handle to use
1722 \param cmd the command to send
1723 \param ctype the type of the arguement
1724 \param cmd_data a void pointer to the data matching the passed type
1725 \param atype the type of the extra arguement
1726 \param cmd_arg a void pointer to the data matching the passed type
1727 \param rtype the type of the response if any
1728 \param ret_data a void pointer to a pointer of return data
1729 \return SWITCH_STATUS_SUCCESS if the command was received
1730*/
1731SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_control(switch_codec_t *codec,
1732 switch_codec_control_command_t cmd,
1733 switch_codec_control_type_t ctype,
1734 void *cmd_data,
1735 switch_codec_control_type_t atype,
1736 void *cmd_arg,
1737 switch_codec_control_type_t *rtype,
1738 void **ret_data);
1739
1740/*!
1741 \brief Decode video data using a codec handle
1742 \param codec the codec handle to use
1743 \param frame the frame to be decoded
1744 \param img the new image in I420 format, allocated by the codec
1745 \param flag flags to exchange
1746 \return SWITCH_STATUS_SUCCESS if the data was decoded, and a non-NULL img
1747*/
1748SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_decode_video(switch_codec_t *codec, switch_frame_t *frame);
1749
1750/*!
1751 \brief Destroy an initalized codec handle
1752 \param codec the codec handle to destroy
1753 \return SWITCH_STATUS_SUCCESS if the codec was destroyed
1754*/
1755SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_codec_destroy(switch_codec_t *codec);
1756
1757/*!
1758 \brief Assign the read codec to a given session
1759 \param session session to add the codec to
1760 \param codec the codec to add
1761 \return SWITCH_STATUS_SUCCESS if successful
1762*/
1763SWITCH_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);
1764
1765/*!
1766 \brief Assign the original read codec to a given session. This is the read codec used by an endpoint.
1767 \param session session to add the codec to
1768 \param codec the codec to add
1769 \return SWITCH_STATUS_SUCCESS if successful
1770*/
1771SWITCH_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);
1772
1773SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_unset_read_codec(_In_ switch_core_session_t *session);
1774SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_unset_write_codec(_In_ switch_core_session_t *session);
1775
1776
1777SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_lock_codec_write(_In_ switch_core_session_t *session);
1778SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_unlock_codec_write(_In_ switch_core_session_t *session);
1779SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_lock_codec_read(_In_ switch_core_session_t *session);
1780SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_unlock_codec_read(_In_ switch_core_session_t *session);
1781
1782
1783SWITCH_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);
1784SWITCH_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);
1785SWITCH_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);
1786SWITCH_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);
1787SWITCH_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);
1788
1789
1790/*!
1791 \brief Retrieve the read codec from a given session
1792 \param session session to retrieve from
1793 \return a pointer to the codec
1794*/
1795SWITCH_DECLARE(switch_codec_t *)__attribute__((visibility("default"))) switch_codec_t * switch_core_session_get_read_codec(_In_ switch_core_session_t *session);
1796
1797/*!
1798 \brief Retrieve the effevtive read codec from a given session
1799 \param session session to retrieve from
1800 \return a pointer to the codec
1801*/
1802SWITCH_DECLARE(switch_codec_t *)__attribute__((visibility("default"))) switch_codec_t * switch_core_session_get_effective_read_codec(_In_ switch_core_session_t *session);
1803
1804/*!
1805 \brief Assign the write codec to a given session
1806 \param session session to add the codec to
1807 \param codec the codec to add
1808 \return SWITCH_STATUS_SUCCESS if successful
1809*/
1810SWITCH_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);
1811
1812/*!
1813 \brief Retrieve the write 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_write_codec(_In_ switch_core_session_t *session);
1818
1819/*!
1820 \brief Retrieve the effevtive write 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_write_codec(_In_ switch_core_session_t *session);
1825
1826/*!
1827 \brief Assign the video_read 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_video_read_codec(_In_ switch_core_session_t *session, switch_codec_t *codec);
1833
1834/*!
1835 \brief Retrieve the video_read 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_video_read_codec(_In_ switch_core_session_t *session);
1840
1841/*!
1842 \brief Assign the video_write codec to a given session
1843 \param session session to add the codec to
1844 \param codec the codec to add
1845 \return SWITCH_STATUS_SUCCESS if successful
1846*/
1847SWITCH_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);
1848
1849/*!
1850 \brief Retrieve the video_write codec from a given session
1851 \param session session to retrieve from
1852 \return a pointer to the codec
1853*/
1854SWITCH_DECLARE(switch_codec_t *)__attribute__((visibility("default"))) switch_codec_t * switch_core_session_get_video_write_codec(_In_ switch_core_session_t *session);
1855
1856///\}
1857///\defgroup db Database Functions
1858///\ingroup core1
1859///\{
1860/*!
1861 \brief Open a core db (SQLite) file
1862 \param filename the path to the db file to open
1863 \return the db handle
1864*/
1865SWITCH_DECLARE(switch_core_db_t *)__attribute__((visibility("default"))) switch_core_db_t * switch_core_db_open_file(const char *filename);
1866
1867/*!
1868 \brief Open a core db (SQLite) in-memory
1869 \param uri to the db to open
1870 \return the db handle
1871*/
1872SWITCH_DECLARE(switch_core_db_t *)__attribute__((visibility("default"))) switch_core_db_t * switch_core_db_open_in_memory(const char *uri);
1873
1874/*!
1875 \brief Execute a sql stmt until it is accepted
1876 \param db the db handle
1877 \param sql the sql to execute
1878 \param retries the number of retries to use
1879 \return SWITCH_STATUS_SUCCESS if successful
1880
1881*/
1882SWITCH_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);
1883SWITCH_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);
1884SWITCH_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);
1885
1886
1887
1888/*!
1889 \brief perform a test query then perform a reactive query if the first one fails
1890 \param db the db handle
1891 \param test_sql the test sql
1892 \param drop_sql the drop sql
1893 \param reactive_sql the reactive sql
1894*/
1895SWITCH_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);
1896
1897///\}
1898
1899///\defgroup Media File Functions
1900///\ingroup core1
1901///\{
1902
1903SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_perform_file_open(const char *file, const char *func, int line,
1904 _In_ switch_file_handle_t *fh,
1905 _In_opt_z_ const char *file_path,
1906 _In_ uint32_t channels,
1907 _In_ uint32_t rate, _In_ unsigned int flags, _In_opt_ switch_memory_pool_t *pool);
1908
1909/*!
1910 \brief Open a media file using file format modules
1911 \param _fh a file handle to use
1912 \param _file_path the path to the file
1913 \param _channels the number of channels
1914 \param _rate the sample rate
1915 \param _flags read/write flags
1916 \param _pool the pool to use (NULL for new pool)
1917 \return SWITCH_STATUS_SUCCESS if the file is opened
1918 \note the loadable module used is chosen based on the file extension
1919*/
1920#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__, 1920, _fh, _file_path, _channels, _rate
, _flags, _pool)
\
1921 switch_core_perform_file_open(__FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__1921, _fh, _file_path, _channels, _rate, _flags, _pool)
1922
1923/*!
1924 \brief Read media from a file handle
1925 \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)
1926 \param data the buffer to read the data to
1927 \param len the max size of the buffer
1928 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes read if successful
1929*/
1930SWITCH_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);
1931
1932/*!
1933 \brief Write media to a file handle
1934 \param fh the file handle to write to
1935 \param data the buffer to write
1936 \param len the amount of data to write from the buffer
1937 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes written if successful
1938*/
1939SWITCH_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);
1940
1941/*!
1942 \brief Write media to a file handle
1943 \param fh the file handle to write to
1944 \param data the buffer to write
1945 \param len the amount of data to write from the buffer
1946 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes written if successful
1947*/
1948SWITCH_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);
1949SWITCH_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);
1950
1951/*!
1952 \brief Seek a position in a file
1953 \param fh the file handle to seek
1954 \param cur_pos the current position in the file
1955 \param samples the amount of samples to seek from the beginning of the file
1956 \param whence the indicator (see traditional seek)
1957 \return SWITCH_STATUS_SUCCESS with cur_pos adjusted to new position
1958*/
1959SWITCH_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);
1960
1961/*!
1962 \brief Set metadata to the desired string
1963 \param fh the file handle to set data to
1964 \param col the enum of the col name
1965 \param string the string to add
1966 \return SWITCH_STATUS_SUCCESS with cur_pos adjusted to new position
1967*/
1968SWITCH_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);
1969
1970/*!
1971 \brief get metadata of the desired string
1972 \param fh the file handle to get data from
1973 \param col the enum of the col name
1974 \param string pointer to the string to fetch
1975 \return SWITCH_STATUS_SUCCESS with cur_pos adjusted to new position
1976*/
1977SWITCH_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);
1978
1979/*!
1980 \brief Pre close an open file handle, then can get file size etc., no more wirte to the file
1981 \param fh the file handle to close
1982 \return SWITCH_STATUS_SUCCESS if the file handle was pre closed
1983*/
1984SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_pre_close(_In_ switch_file_handle_t *fh);
1985
1986/*!
1987 \brief Duplicates a file handle using another pool
1988 \param oldfh the file handle to duplicate
1989 \param newfh pointer to assign new file handle to
1990 \param pool the pool to use (NULL for new pool)
1991 \return SWITCH_STATUS_SUCCESS if the file handle was duplicated
1992*/
1993
1994SWITCH_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);
1995
1996/*!
1997 \brief Close an open file handle
1998 \param fh the file handle to close
1999 \return SWITCH_STATUS_SUCCESS if the file handle was closed
2000*/
2001SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_close(_In_ switch_file_handle_t *fh);
2002
2003SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_command(switch_file_handle_t *fh, switch_file_command_t command);
2004
2005SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_file_truncate(switch_file_handle_t *fh, int64_t offset);
2006SWITCH_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);
2007
2008
2009///\}
2010
2011///\defgroup speech ASR/TTS Functions
2012///\ingroup core1
2013///\{
2014/*!
2015 \brief Open a speech handle
2016 \param sh a speech handle to use
2017 \param module_name the speech module to use
2018 \param voice_name the desired voice name
2019 \param rate the sampling rate
2020 \param interval the sampling interval
2021 \param flags tts flags
2022 \param pool the pool to use (NULL for new pool)
2023 \return SWITCH_STATUS_SUCCESS if the handle is opened
2024*/
2025SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_speech_open(_In_ switch_speech_handle_t *sh,
2026 const char *module_name,
2027 const char *voice_name,
2028 _In_ unsigned int rate,
2029 _In_ unsigned int interval,
2030 _In_ unsigned int channels,
2031 switch_speech_flag_t *flags, _In_opt_ switch_memory_pool_t *pool);
2032/*!
2033 \brief Feed text to the TTS module
2034 \param sh the speech handle to feed
2035 \param text the buffer to write
2036 \param flags flags in/out for fine tuning
2037 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes written if successful
2038*/
2039SWITCH_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);
2040
2041/*!
2042 \brief Flush TTS audio on a given handle
2043 \param sh the speech handle
2044*/
2045SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_speech_flush_tts(switch_speech_handle_t *sh);
2046
2047/*!
2048 \brief Set a text parameter on a TTS handle
2049 \param sh the speech handle
2050 \param param the parameter
2051 \param val the value
2052*/
2053SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_speech_text_param_tts(switch_speech_handle_t *sh, char *param, const char *val);
2054
2055/*!
2056 \brief Set a numeric parameter on a TTS handle
2057 \param sh the speech handle
2058 \param param the parameter
2059 \param val the value
2060*/
2061SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_speech_numeric_param_tts(switch_speech_handle_t *sh, char *param, int val);
2062
2063/*!
2064 \brief Set a float parameter on a TTS handle
2065 \param sh the speech handle
2066 \param param the parameter
2067 \param val the value
2068*/
2069SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_speech_float_param_tts(switch_speech_handle_t *sh, char *param, double val);
2070
2071/*!
2072 \brief Read rendered audio from the TTS module
2073 \param sh the speech handle to read
2074 \param data the buffer to read to
2075 \param datalen the max size / written size of the data
2076 \param rate the rate of the read audio
2077 \param flags flags in/out for fine tuning
2078 \return SWITCH_STATUS_SUCCESS with len adjusted to the bytes written if successful
2079*/
2080SWITCH_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);
2081/*!
2082 \brief Close an open speech handle
2083 \param sh the speech handle to close
2084 \param flags flags in/out for fine tuning
2085 \return SWITCH_STATUS_SUCCESS if the file handle was closed
2086*/
2087SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_speech_close(switch_speech_handle_t *sh, switch_speech_flag_t *flags);
2088
2089
2090/*!
2091 \brief Open an asr handle
2092 \param ah the asr handle to open
2093 \param module_name the name of the asr module
2094 \param codec the preferred codec
2095 \param rate the preferred rate
2096 \param dest the destination address
2097 \param flags flags to influence behaviour
2098 \param pool the pool to use (NULL for new pool)
2099 \return SWITCH_STATUS_SUCCESS if the asr handle was opened
2100*/
2101SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_open(switch_asr_handle_t *ah,
2102 const char *module_name,
2103 const char *codec, int rate, const char *dest, switch_asr_flag_t *flags, switch_memory_pool_t *pool);
2104
2105/*!
2106 \brief Close an asr handle
2107 \param ah the handle to close
2108 \param flags flags to influence behaviour
2109 \return SWITCH_STATUS_SUCCESS
2110*/
2111SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
2112
2113/*!
2114 \brief Feed audio data to an asr handle
2115 \param ah the handle to feed data to
2116 \param data a pointer to the data
2117 \param len the size in bytes of the data
2118 \param flags flags to influence behaviour
2119 \return SWITCH_STATUS_SUCCESS
2120*/
2121SWITCH_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);
2122
2123/*!
2124 \brief Feed DTMF to an asr handle
2125 \param ah the handle to feed data to
2126 \param dtmf a string of DTMF digits
2127 \param flags flags to influence behaviour
2128 \return SWITCH_STATUS_SUCCESS
2129*/
2130SWITCH_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);
2131
2132/*!
2133 \brief Check an asr handle for results
2134 \param ah the handle to check
2135 \param flags flags to influence behaviour
2136 \return SWITCH_STATUS_SUCCESS
2137*/
2138SWITCH_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);
2139
2140/*!
2141 \brief Get results from an asr handle
2142 \param ah the handle to get results from
2143 \param xmlstr a pointer to dynamically allocate an xml result string to
2144 \param flags flags to influence behaviour
2145 \return SWITCH_STATUS_SUCCESS
2146*/
2147SWITCH_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);
2148
2149/*!
2150 \brief Get result headers from an asr handle
2151 \param ah the handle to get results from
2152 \param headers a pointer to dynamically allocate an switch_event_t result to
2153 \param flags flags to influence behaviour
2154 \return SWITCH_STATUS_SUCCESS
2155*/
2156SWITCH_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);
2157
2158/*!
2159 \brief Load a grammar to an asr handle
2160 \param ah the handle to load to
2161 \param grammar the grammar text, file path, or URI
2162 \param name the grammar name
2163 \return SWITCH_STATUS_SUCCESS
2164*/
2165SWITCH_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);
2166
2167/*!
2168 \brief Unload a grammar from an asr handle
2169 \param ah the handle to unload the grammar from
2170 \param name the name of the grammar to unload
2171 \return SWITCH_STATUS_SUCCESS
2172*/
2173SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_unload_grammar(switch_asr_handle_t *ah, const char *name);
2174
2175/*!
2176 \brief Enable a grammar from an asr handle
2177 \param ah the handle to enable the grammar from
2178 \param name the name of the grammar to enable
2179 \return SWITCH_STATUS_SUCCESS
2180*/
2181SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_enable_grammar(switch_asr_handle_t *ah, const char *name);
2182
2183/*!
2184 \brief Disable a grammar from an asr handle
2185 \param ah the handle to disable the grammar from
2186 \param name the name of the grammar to disable
2187 \return SWITCH_STATUS_SUCCESS
2188*/
2189SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_disable_grammar(switch_asr_handle_t *ah, const char *name);
2190
2191/*!
2192 \brief Disable all grammars from an asr handle
2193 \param ah the handle to disable the grammars from
2194 \return SWITCH_STATUS_SUCCESS
2195*/
2196SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_disable_all_grammars(switch_asr_handle_t *ah);
2197
2198/*!
2199 \brief Pause detection on an asr handle
2200 \param ah the handle to pause
2201 \return SWITCH_STATUS_SUCCESS
2202*/
2203SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_pause(switch_asr_handle_t *ah);
2204
2205/*!
2206 \brief Resume detection on an asr handle
2207 \param ah the handle to resume
2208 \return SWITCH_STATUS_SUCCESS
2209*/
2210SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_resume(switch_asr_handle_t *ah);
2211
2212/*!
2213 \brief Start input timers on an asr handle
2214 \param ah the handle to start timers on
2215 \return SWITCH_STATUS_SUCCESS
2216*/
2217SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_asr_start_input_timers(switch_asr_handle_t *ah);
2218
2219/*!
2220 \brief Set a text parameter on an asr handle
2221 \param sh the asr handle
2222 \param param the parameter
2223 \param val the value
2224*/
2225SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_asr_text_param(switch_asr_handle_t *ah, char *param, const char *val);
2226
2227/*!
2228 \brief Set a numeric parameter on an asr handle
2229 \param sh the asr handle
2230 \param param the parameter
2231 \param val the value
2232*/
2233SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_asr_numeric_param(switch_asr_handle_t *ah, char *param, int val);
2234
2235/*!
2236 \brief Set a float parameter on an asr handle
2237 \param sh the asr handle
2238 \param param the parameter
2239 \param val the value
2240*/
2241SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_asr_float_param(switch_asr_handle_t *ah, char *param, double val);
2242
2243///\}
2244
2245
2246///\defgroup dir Directory Service Functions
2247///\ingroup core1
2248///\{
2249/*!
2250 \brief Open a directory handle
2251 \param dh a directory handle to use
2252 \param module_name the directory module to use
2253 \param source the source of the db (ip, hostname, path etc)
2254 \param dsn the username or designation of the lookup
2255 \param passwd the password
2256 \param pool the pool to use (NULL for new pool)
2257 \return SWITCH_STATUS_SUCCESS if the handle is opened
2258*/
2259SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_open(switch_directory_handle_t *dh,
2260 char *module_name, char *source, char *dsn, char *passwd, switch_memory_pool_t *pool);
2261
2262/*!
2263 \brief Query a directory handle
2264 \param dh a directory handle to use
2265 \param base the base to query against
2266 \param query a string of filters or query data
2267 \return SWITCH_STATUS_SUCCESS if the query is successful
2268*/
2269SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_query(switch_directory_handle_t *dh, char *base, char *query);
2270
2271/*!
2272 \brief Obtain the next record in a lookup
2273 \param dh a directory handle to use
2274 \return SWITCH_STATUS_SUCCESS if another record exists
2275*/
2276SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_next(switch_directory_handle_t *dh);
2277
2278/*!
2279 \brief Obtain the next name/value pair in the current record
2280 \param dh a directory handle to use
2281 \param var a pointer to pointer of the name to fill in
2282 \param val a pointer to pointer of the value to fill in
2283 \return SWITCH_STATUS_SUCCESS if an item exists
2284*/
2285SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_next_pair(switch_directory_handle_t *dh, char **var, char **val);
2286
2287/*!
2288 \brief Close an open directory handle
2289 \param dh a directory handle to close
2290 \return SWITCH_STATUS_SUCCESS if handle was closed
2291*/
2292SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_directory_close(switch_directory_handle_t *dh);
2293///\}
2294
2295
2296///\defgroup misc Misc
2297///\ingroup core1
2298///\{
2299/*!
2300 \brief Retrieve a FILE stream of a given text channel name
2301 \param channel text channel enumeration
2302 \return a FILE stream
2303*/
2304SWITCH_DECLARE(FILE *)__attribute__((visibility("default"))) FILE * switch_core_data_channel(switch_text_channel_t channel);
2305
2306/*!
2307 \brief Determines if the core is ready to take calls
2308 \return SWITCH_TRUE or SWITCH_FALSE
2309*/
2310SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_ready(void);
2311
2312SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_running(void);
2313
2314/*!
2315 \brief Determines if the core is ready to take inbound calls
2316 \return SWITCH_TRUE or SWITCH_FALSE
2317*/
2318SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_ready_inbound(void);
2319
2320/*!
2321 \brief Determines if the core is ready to place outbound calls
2322 \return SWITCH_TRUE or SWITCH_FALSE
2323*/
2324SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_ready_outbound(void);
2325
2326/*!
2327 \brief return core flags
2328 \return core flags
2329*/
2330SWITCH_DECLARE(switch_core_flag_t)__attribute__((visibility("default"))) switch_core_flag_t switch_core_flags(void);
2331
2332/*!
2333 \brief Execute a management operation.
2334 \param relative_oid the relative oid of the operation.
2335 \param action the action to perform.
2336 \param data input/output string.
2337 \param datalen size in bytes of data.
2338 \return SUCCESS on sucess.
2339*/
2340SWITCH_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);
2341
2342/*!
2343 \brief Switch on the privilege awareness for the process and request required privileges
2344 \return 0 on success
2345*/
2346
2347SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_set_process_privileges(void);
2348
2349/*!
2350 \brief Set the maximum priority the process can obtain
2351 \return 0 on success
2352*/
2353
2354SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t set_normal_priority(void);
2355SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t set_auto_priority(void);
2356SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t set_realtime_priority(void);
2357SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t set_low_priority(void);
2358
2359/*!
2360 \brief Change user and/or group of the running process
2361 \param user name of the user to switch to (or NULL)
2362 \param group name of the group to switch to (or NULL)
2363 \return 0 on success, -1 otherwise
2364
2365 Several possible combinations:
2366 - user only (group NULL): switch to user and his primary group (and supplementary groups, if supported)
2367 - user and group: switch to user and specified group (only)
2368 - group only (user NULL): switch group only
2369*/
2370SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t change_user_group(const char *user, const char *group);
2371
2372/*!
2373 \brief Run endlessly until the system is shutdown
2374 \param bg divert console to the background
2375*/
2376SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_runtime_loop(int bg);
2377
2378/*!
2379 \brief Set the output console to the desired file
2380 \param console the file path
2381*/
2382SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_set_console(const char *console);
2383
2384/*!
2385 \brief Breakdown a number of milliseconds into various time spec
2386 \param total_ms a number of milliseconds
2387 \param duration an object to store the results
2388*/
2389SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration);
2390
2391/*!
2392 \brief Number of microseconds the system has been up
2393 \return a number of microseconds
2394*/
2395SWITCH_DECLARE(switch_time_t)__attribute__((visibility("default"))) switch_time_t switch_core_uptime(void);
2396
2397/*!
2398 \brief send a control message to the core
2399 \param cmd the command
2400 \param val the command arguement (if needed)
2401 \return 0 on success nonzero on error
2402*/
2403SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_session_ctl(switch_session_ctl_t cmd, void *val);
2404
2405/*!
2406 \brief Get the output console
2407 \return the FILE stream
2408*/
2409SWITCH_DECLARE(FILE *)__attribute__((visibility("default"))) FILE * switch_core_get_console(void);
2410
2411#ifndef SWIG
2412/*!
2413 \brief Launch a thread
2414*/
2415SWITCH_DECLARE(switch_thread_t *)__attribute__((visibility("default"))) switch_thread_t * switch_core_launch_thread(void *(SWITCH_THREAD_FUNC * func) (switch_thread_t *, void *),
2416 void *obj, switch_memory_pool_t *pool);
2417#endif
2418
2419/*!
2420 \brief Initiate Globals
2421*/
2422SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_set_globals(void);
2423
2424/*!
2425 \brief Checks if 2 sessions are using the same endpoint module
2426 \param a the first session
2427 \param b the second session
2428 \return TRUE or FALSE
2429*/
2430SWITCH_DECLARE(uint8_t)__attribute__((visibility("default"))) uint8_t switch_core_session_compare(switch_core_session_t *a, switch_core_session_t *b);
2431/*!
2432 \brief Checks if a session is using a specific endpoint
2433 \param session the session
2434 \param endpoint_interface interface of the endpoint to check
2435 \return TRUE or FALSE
2436*/
2437SWITCH_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);
2438
2439SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_set_video_read_callback(switch_core_session_t *session,
2440 switch_core_video_thread_callback_func_t func, void *user_data);
2441
2442SWITCH_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);
2443
2444SWITCH_DECLARE(switch_hash_index_t *)__attribute__((visibility("default"))) switch_hash_index_t * switch_core_mime_index(void);
2445SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_mime_ext2type(const char *ext);
2446SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_mime_type2ext(const char *type);
2447SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_mime_add_type(const char *type, const char *ext);
2448
2449SWITCH_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);
2450SWITCH_DECLARE(void *)__attribute__((visibility("default"))) void * switch_loadable_module_create_interface(switch_loadable_module_interface_t *mod, switch_module_interface_name_t iname);
2451/*!
2452 \brief Get the current epoch time in microseconds
2453 \return the current epoch time in microseconds
2454*/
2455SWITCH_DECLARE(switch_time_t)__attribute__((visibility("default"))) switch_time_t switch_micro_time_now(void);
2456SWITCH_DECLARE(switch_time_t)__attribute__((visibility("default"))) switch_time_t switch_mono_micro_time_now(void);
2457SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_reclaim(void);
2458SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_reclaim_events(void);
2459SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_reclaim_logger(void);
2460SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_reclaim_all(void);
2461SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_setrlimits(void);
2462SWITCH_DECLARE(switch_time_t)__attribute__((visibility("default"))) switch_time_t switch_time_ref(void);
2463SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_sync(void);
2464/*!
2465 \brief Get the current epoch time
2466 \param [out] (optional) The current epoch time
2467 \return The current epoch time
2468*/
2469SWITCH_DECLARE(time_t)__attribute__((visibility("default"))) time_t switch_epoch_time_now(time_t *t);
2470SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_lookup_timezone(const char *tz_name);
2471SWITCH_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);
2472SWITCH_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);
2473SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_load_network_lists(switch_bool_t reload);
2474SWITCH_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);
2475SWITCH_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);
2476#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))
2477SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_monotonic(switch_bool_t enable);
2478SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_timerfd(int enable);
2479SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_nanosleep(switch_bool_t enable);
2480SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_matrix(switch_bool_t enable);
2481SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_cond_yield(switch_bool_t enable);
2482SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_time_set_use_system_time(switch_bool_t enable);
2483SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_min_dtmf_duration(uint32_t duration);
2484SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_max_dtmf_duration(uint32_t duration);
2485SWITCH_DECLARE(double)__attribute__((visibility("default"))) double switch_core_min_idle_cpu(double new_limit);
2486SWITCH_DECLARE(double)__attribute__((visibility("default"))) double switch_core_idle_cpu(void);
2487SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_default_dtmf_duration(uint32_t duration);
2488SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_console_set_complete(const char *string);
2489SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_console_set_alias(const char *string);
2490SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_system(const char *cmd, switch_bool_t wait);
2491SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_stream_system(const char *cmd, switch_stream_handle_t *stream);
2492SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cond_yield(switch_interval_time_t t);
2493SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cond_next(void);
2494SWITCH_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,
2495 const char *subject, const char *body, const char *type, const char *hint, switch_bool_t blocking);
2496SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_chat_send(const char *dest_proto, switch_event_t *message_event);
2497SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_chat_deliver(const char *dest_proto, switch_event_t **message_event);
2498
2499SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_ivr_preprocess_session(switch_core_session_t *session, const char *cmds);
2500SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_sqldb_pause(void);
2501SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_sqldb_resume(void);
2502
2503
2504///\}
2505
2506/*!
2507 \}
2508*/
2509
2510typedef int (*switch_core_db_event_callback_func_t) (void *pArg, switch_event_t *event);
2511
2512#define CACHE_DB_LEN256 256
2513typedef enum {
2514 CDF_INUSE = (1 << 0),
2515 CDF_PRUNE = (1 << 1),
2516 CDF_NONEXPIRING = (1 << 2)
2517} cache_db_flag_t;
2518
2519typedef enum {
2520 SCDB_TYPE_CORE_DB,
2521 SCDB_TYPE_ODBC,
2522 SCDB_TYPE_DATABASE_INTERFACE
2523} switch_cache_db_handle_type_t;
2524
2525typedef union {
2526 switch_coredb_handle_t *core_db_dbh;
2527 switch_odbc_handle_t *odbc_dbh;
2528 switch_database_interface_handle_t *database_interface_dbh;
2529} switch_cache_db_native_handle_t;
2530
2531typedef struct {
2532 char *db_path;
2533 switch_bool_t in_memory;
2534} switch_cache_db_core_db_options_t;
2535
2536typedef struct {
2537 char *dsn;
2538 char *user;
2539 char *pass;
2540} switch_cache_db_odbc_options_t;
2541
2542typedef struct {
2543 const char *original_dsn;
2544 char *connection_string;
2545 char prefix[16];
2546 switch_database_interface_t *database_interface;
2547 switch_bool_t make_module_no_unloadable;
2548} switch_cache_db_database_interface_options_t;
2549
2550typedef union {
2551 switch_cache_db_core_db_options_t core_db_options;
2552 switch_cache_db_odbc_options_t odbc_options;
2553 switch_cache_db_database_interface_options_t database_interface_options;
2554} switch_cache_db_connection_options_t;
2555
2556struct switch_cache_db_handle;
2557typedef struct switch_cache_db_handle switch_cache_db_handle_t;
2558
2559static inline const char *switch_cache_db_type_name(switch_cache_db_handle_type_t type)
2560{
2561 const char *type_str = "INVALID";
2562
2563 switch (type) {
2564 case SCDB_TYPE_DATABASE_INTERFACE:
2565 {
2566 type_str = "DATABASE_INTERFACE";
2567 }
2568 break;
2569 case SCDB_TYPE_ODBC:
2570 {
2571 type_str = "ODBC";
2572 }
2573 break;
2574 case SCDB_TYPE_CORE_DB:
2575 {
2576 type_str = "CORE_DB";
2577 }
2578 break;
2579 }
2580
2581 return type_str;
2582}
2583
2584SWITCH_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);
2585
2586/*!
2587 \brief Returns the handle to the pool, immediately available for other
2588 threads to use.
2589 \param [in] The handle
2590*/
2591SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_dismiss_db_handle(switch_cache_db_handle_t ** dbh);
2592/*!
2593 \brief Returns the handle to the pool, handle is NOT available to
2594 other threads until the allocating thread actually terminates.
2595 \param [in] The handle
2596*/
2597SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_release_db_handle(switch_cache_db_handle_t ** dbh);
2598/*!
2599 \brief Gets a new cached handle from the pool, potentially creating a new connection.
2600 The connection is bound to the thread until it (the thread) terminates unless
2601 you dismiss rather than release.
2602 \param [out] dbh The handle
2603 \param [in] type - ODBC or SQLLITE
2604 \param [in] connection_options (userid, password, etc)
2605*/
2606SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t _switch_cache_db_get_db_handle(switch_cache_db_handle_t ** dbh,
2607 switch_cache_db_handle_type_t type,
2608 switch_cache_db_connection_options_t *connection_options,
2609 const char *file, const char *func, int line);
2610#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__, 2610)
_switch_cache_db_get_db_handle(_a, _b, _c, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2610)
2611
2612SWITCH_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,
2613 const char *file, const char *func, int line);
2614SWITCH_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,
2615 const char *file, const char *func, int line);
2616#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__, 2616)
_switch_cache_db_get_db_handle_dsn(_a, _b, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2616)
2617
2618/*!
2619 \brief Executes the create schema sql
2620 \param [in] dbh The handle
2621 \param [in] sql - sql to run
2622 \param [out] err - Error if it exists
2623*/
2624SWITCH_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);
2625/*!
2626 \brief Executes the sql and returns the result as a string
2627 \param [in] dbh The handle
2628 \param [in] sql - sql to run
2629 \param [out] str - buffer for result
2630 \param [in] len - length of str buffer
2631 \param [out] err - Error if it exists
2632*/
2633SWITCH_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);
2634/*!
2635 \brief Executes the sql
2636 \param [in] dbh The handle
2637 \param [in] sql - sql to run
2638 \param [out] err - Error if it exists
2639*/
2640SWITCH_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);
2641/*!
2642 \brief Executes the sql and uses callback for row-by-row processing
2643 \param [in] dbh The handle
2644 \param [in] sql - sql to run
2645 \param [in] callback - function pointer to callback
2646 \param [in] pdata - data to pass to callback
2647 \param [out] err - Error if it exists
2648*/
2649SWITCH_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,
2650 switch_core_db_callback_func_t callback, void *pdata, char **err);
2651
2652/*!
2653 \brief Executes the sql and uses callback for row-by-row processing
2654 \param [in] dbh The handle
2655 \param [in] sql - sql to run
2656 \param [in] callback - function pointer to callback
2657 \param [in] err_callback - function pointer to callback when error occurs
2658 \param [in] pdata - data to pass to callback
2659 \param [out] err - Error if it exists
2660*/
2661SWITCH_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,
2662 switch_core_db_callback_func_t callback,
2663 switch_core_db_err_callback_func_t err_callback,
2664 void *pdata, char **err);
2665
2666/*!
2667 \brief Get the affected rows of the last performed query
2668 \param [in] dbh The handle
2669 \param [out] the number of affected rows
2670*/
2671SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_cache_db_affected_rows(switch_cache_db_handle_t *dbh);
2672
2673/*!
2674 \brief load an external extension to db
2675 \param [in] dbh The handle
2676 \param [out] the path to the extension
2677*/
2678SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_cache_db_load_extension(switch_cache_db_handle_t *dbh, const char *extension);
2679
2680/*!
2681 \brief Provides some feedback as to the status of the db connection pool
2682 \param [in] stream stream for status
2683*/
2684SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_status(switch_stream_handle_t *stream);
2685SWITCH_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);
2686#define switch_core_db_handle(_a)_switch_core_db_handle(_a, "./src/include/switch_core.h", (const
char *)__func__, 2686)
_switch_core_db_handle(_a, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2686)
2687
2688SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_cache_db_test_reactive(switch_cache_db_handle_t *db,
2689 const char *test_sql, const char *drop_sql, const char *reactive_sql);
2690SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_cache_db_test_reactive_ex(switch_cache_db_handle_t *db,
2691 const char *test_sql, const char *drop_sql, const char *reactive_sql, const char *row_size_limited_reactive_sql);
2692SWITCH_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);
2693SWITCH_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,
2694 const char *pre_trans_execute,
2695 const char *post_trans_execute,
2696 const char *inner_pre_trans_execute,
2697 const char *inner_post_trans_execute);
2698#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))
2699
2700SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_database_interface_flush_handles(switch_database_interface_t *database_interface);
2701
2702/*!
2703\brief Returns error if no suitable database interface found to serve core db dsn.
2704*/
2705SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_check_core_db_dsn(void);
2706
2707/*!
2708\brief Returns error if no suitable database interface found for a dsn.
2709*/
2710SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_database_available(char* dsn);
2711
2712SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_set_signal_handlers(void);
2713SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_debug_level(void);
2714SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sps(void);
2715SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sps_last(void);
2716SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sps_peak(void);
2717SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sps_peak_fivemin(void);
2718SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sessions_peak(void);
2719SWITCH_DECLARE(int32_t)__attribute__((visibility("default"))) int32_t switch_core_sessions_peak_fivemin(void);
2720SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_cache_db_flush_handles(void);
2721SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_banner(void);
2722SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_session_in_thread(switch_core_session_t *session);
2723SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_default_ptime(const char *name, uint32_t number);
2724SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_default_rate(const char *name, uint32_t number);
2725SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_core_max_audio_channels(uint32_t limit);
2726
2727/*!
2728 \brief Add user registration
2729 \param [in] user
2730 \param [in] realm
2731 \param [in] token
2732 \param [in] url - a freeswitch dial string
2733 \param [in] expires
2734 \param [in] network_ip
2735 \param [in] network_port
2736 \param [in] network_proto - one of tls, tcp, udp
2737 \param [in] metadata - generic metadata supplied by module
2738 \param [out] err - Error if it exists
2739*/
2740SWITCH_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,
2741 const char *network_ip, const char *network_port, const char *network_proto,
2742 const char *metadata);
2743/*!
2744 \brief Delete user registration
2745 \param [in] user
2746 \param [in] realm
2747 \param [in] token
2748 \param [out] err - Error if it exists
2749*/
2750SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_del_registration(const char *user, const char *realm, const char *token);
2751/*!
2752 \brief Expire user registrations
2753 \param [in] force delete all registrations
2754 \param [out] err - Error if it exists
2755*/
2756SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_expire_registration(int force);
2757
2758/*!
2759 \brief Get RTP port range start value
2760 \param[in] void
2761 \param[out] RTP port range start value
2762*/
2763SWITCH_DECLARE(uint16_t)__attribute__((visibility("default"))) uint16_t switch_core_get_rtp_port_range_start_port(void);
2764
2765/*!
2766 \brief Get RTP port range end value
2767 \param[in] void
2768 \param[out] RTP port range end value
2769*/
2770SWITCH_DECLARE(uint16_t)__attribute__((visibility("default"))) uint16_t switch_core_get_rtp_port_range_end_port(void);
2771
2772SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_say_file_handle_get_variable(switch_say_file_handle_t *sh, const char *var);
2773SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_say_file_handle_get_path(switch_say_file_handle_t *sh);
2774SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_say_file_handle_detach_path(switch_say_file_handle_t *sh);
2775SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_say_file_handle_destroy(switch_say_file_handle_t **sh);
2776SWITCH_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);
2777SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_say_file(switch_say_file_handle_t *sh, const char *fmt, ...);
2778SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_max_file_desc(void);
2779SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_close_extra_files(int *keep, int keep_ttl);
2780SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_thread_set_cpu_affinity(int cpu);
2781SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_os_yield(void);
2782SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max);
2783SWITCH_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);
2784
2785SWITCH_DECLARE(switch_cache_db_handle_type_t)__attribute__((visibility("default"))) switch_cache_db_handle_type_t switch_core_dbtype(void);
2786SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_sql_exec(const char *sql);
2787SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_recovery_recover(const char *technology, const char *profile_name);
2788SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_recovery_untrack(switch_core_session_t *session, switch_bool_t force);
2789SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_recovery_track(switch_core_session_t *session);
2790SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_recovery_flush(const char *technology, const char *profile_name);
2791
2792SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_pause(switch_sql_queue_manager_t *qm, switch_bool_t flush);
2793SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_resume(switch_sql_queue_manager_t *qm);
2794
2795SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_sql_queue_manager_size(switch_sql_queue_manager_t *qm, uint32_t index);
2796SWITCH_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);
2797SWITCH_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);
2798SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_destroy(switch_sql_queue_manager_t **qmp);
2799SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_init_name(const char *name,
2800 switch_sql_queue_manager_t **qmp,
2801 uint32_t numq, const char *dsn, uint32_t max_trans,
2802 const char *pre_trans_execute,
2803 const char *post_trans_execute,
2804 const char *inner_pre_trans_execute,
2805 const char *inner_post_trans_execute);
2806
2807#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)
2808
2809SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_start(switch_sql_queue_manager_t *qm);
2810SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_sql_queue_manager_stop(switch_sql_queue_manager_t *qm);
2811SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_cache_db_execute_sql_event_callback(switch_cache_db_handle_t *dbh,
2812 const char *sql, switch_core_db_event_callback_func_t callback, void *pdata, char **err);
2813
2814SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_execute_sql_callback(switch_sql_queue_manager_t *qm, const char *sql,
2815 switch_core_db_callback_func_t callback,
2816 void *pdata);
2817SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_execute_sql_callback_err(switch_sql_queue_manager_t *qm, const char *sql,
2818 switch_core_db_callback_func_t callback,
2819 switch_core_db_err_callback_func_t err_callback,
2820 void *pdata);
2821
2822SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_execute_sql_event_callback(switch_sql_queue_manager_t *qm, const char *sql,
2823 switch_core_db_event_callback_func_t callback,
2824 void *pdata);
2825SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_sql_queue_manager_execute_sql_event_callback_err(switch_sql_queue_manager_t *qm, const char *sql,
2826 switch_core_db_event_callback_func_t callback,
2827 switch_core_db_err_callback_func_t err_callback,
2828 void *pdata);
2829
2830SWITCH_DECLARE(pid_t)__attribute__((visibility("default"))) pid_t switch_fork(void);
2831
2832SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_gen_certs(const char *prefix);
2833SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_core_check_dtls_pem(const char *file);
2834SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_cert_gen_fingerprint(const char *prefix, dtls_fingerprint_t *fp);
2835SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_cert_expand_fingerprint(dtls_fingerprint_t *fp, const char *str);
2836SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_core_cert_verify(dtls_fingerprint_t *fp);
2837SWITCH_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);
2838#define switch_core_session_request_video_refresh(_s)_switch_core_session_request_video_refresh(_s, 0, "./src/include/switch_core.h"
, (const char *)__func__, 2838)
_switch_core_session_request_video_refresh(_s, 0, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2838)
2839#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__, 2839)
_switch_core_session_request_video_refresh(_s, 1, __FILE__"./src/include/switch_core.h", __SWITCH_FUNC__(const char *)__func__, __LINE__2839)
2840SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_send_and_request_video_refresh(switch_core_session_t *session);
2841SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_system(const char *cmd, switch_bool_t wait);
2842SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream);
2843SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_stream_system(const char *cmd, switch_stream_handle_t *stream);
2844
2845SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_spawn(const char *cmd, switch_bool_t wait);
2846SWITCH_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);
2847
2848SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_session_debug_pool(switch_stream_handle_t *stream);
2849
2850SWITCH_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);
2851
2852SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_major(void);
2853SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_minor(void);
2854SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_micro(void);
2855
2856SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_revision(void);
2857SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_revision_human(void);
2858SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_full(void);
2859SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char *switch_version_full_human(void);
2860
2861SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_autobind_cpu(void);
2862
2863SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_core_session_start_text_thread(switch_core_session_t *session);
2864
2865SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_core_get_event_channel_key_separator(void);
2866
2867SWITCH_END_EXTERN_C
2868#endif
2869/* For Emacs:
2870 * Local Variables:
2871 * mode:c
2872 * indent-tabs-mode:t
2873 * tab-width:4
2874 * c-basic-offset:4
2875 * End:
2876 * For VIM:
2877 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
2878 */