Bug Summary

File:src/switch_event.c
Location:line 1877, column 18
Description:Potential leak of memory pointed to by '__retval'

Annotated Source Code

1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4 *
5 * Version: MPL 1.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18 *
19 * The Initial Developer of the Original Code is
20 * Anthony Minessale II <anthm@freeswitch.org>
21 * Portions created by the Initial Developer are Copyright (C)
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 *
26 * Anthony Minessale II <anthm@freeswitch.org>
27 * Michael Jerris <mike@jerris.com>
28 * Paul D. Tinsley <pdt at jackhammer.org>
29 * William King <william.king@quentustech.com>
30 * Raymond Chandler <intralanman@freeswitch.org>
31 *
32 * switch_event.c -- Event System
33 *
34 */
35
36#include <switch.h>
37#include <switch_event.h>
38#include "tpl.h"
39#include "private/switch_core_pvt.h"
40
41//#define SWITCH_EVENT_RECYCLE
42#define DISPATCH_QUEUE_LEN10000 10000
43//#define DEBUG_DISPATCH_QUEUES
44
45/*! \brief A node to store binded events */
46struct switch_event_node {
47 /*! the id of the node */
48 char *id;
49 /*! the event id enumeration to bind to */
50 switch_event_types_t event_id;
51 /*! the event subclass to bind to for custom events */
52 char *subclass_name;
53 /*! a callback function to execute when the event is triggered */
54 switch_event_callback_t callback;
55 /*! private data */
56 void *user_data;
57 struct switch_event_node *next;
58};
59
60/*! \brief A registered custom event subclass */
61struct switch_event_subclass {
62 /*! the owner of the subclass */
63 char *owner;
64 /*! the subclass name */
65 char *name;
66 /*! the subclass was reserved by a listener so it's ok for a module to reserve it still */
67 int bind;
68};
69
70
71static struct {
72 switch_event_channel_id_t ID;
73 switch_thread_rwlock_t *rwlock;
74 switch_hash_t *hash;
75 switch_hash_t *perm_hash;
76 switch_hash_t *lahash;
77 switch_mutex_t *lamutex;
78} event_channel_manager;
79
80#define MAX_DISPATCH_VAL64 64
81static unsigned int MAX_DISPATCH = MAX_DISPATCH_VAL64;
82static unsigned int SOFT_MAX_DISPATCH = 0;
83static char guess_ip_v4[80] = "";
84static char guess_ip_v6[80] = "";
85static switch_event_node_t *EVENT_NODES[SWITCH_EVENT_ALL + 1] = { NULL((void*)0) };
86static switch_thread_rwlock_t *RWLOCK = NULL((void*)0);
87static switch_mutex_t *BLOCK = NULL((void*)0);
88static switch_mutex_t *POOL_LOCK = NULL((void*)0);
89static switch_memory_pool_t *RUNTIME_POOL = NULL((void*)0);
90static switch_memory_pool_t *THRUNTIME_POOL = NULL((void*)0);
91static switch_thread_t *EVENT_DISPATCH_QUEUE_THREADS[MAX_DISPATCH_VAL64] = { 0 };
92static uint8_t EVENT_DISPATCH_QUEUE_RUNNING[MAX_DISPATCH_VAL64] = { 0 };
93static switch_queue_t *EVENT_DISPATCH_QUEUE = NULL((void*)0);
94static switch_queue_t *EVENT_CHANNEL_DISPATCH_QUEUE = NULL((void*)0);
95static switch_mutex_t *EVENT_QUEUE_MUTEX = NULL((void*)0);
96static switch_hash_t *CUSTOM_HASH = NULL((void*)0);
97static int THREAD_COUNT = 0;
98static int DISPATCH_THREAD_COUNT = 0;
99static int EVENT_CHANNEL_DISPATCH_THREAD_COUNT = 0;
100static int EVENT_CHANNEL_DISPATCH_THREAD_STARTING = 0;
101static int SYSTEM_RUNNING = 0;
102static uint64_t EVENT_SEQUENCE_NR = 0;
103#ifdef SWITCH_EVENT_RECYCLE
104static switch_queue_t *EVENT_RECYCLE_QUEUE = NULL((void*)0);
105static switch_queue_t *EVENT_HEADER_RECYCLE_QUEUE = NULL((void*)0);
106#endif
107
108static void unsub_all_switch_event_channel(void);
109
110static char *my_dup(const char *s)
111{
112 size_t len = strlen(s) + 1;
113 void *new = malloc(len);
114 switch_assert(new)((new) ? (void) (0) : __assert_fail ("new", "src/switch_event.c"
, 114, __PRETTY_FUNCTION__))
;
115
116 return (char *) memcpy(new, s, len);
117}
118
119#ifndef ALLOC
120#define ALLOC(size)malloc(size) malloc(size)
121#endif
122#ifndef DUP
123#define DUP(str)my_dup(str) my_dup(str)
124#endif
125#ifndef FREE
126#define FREE(ptr)if (ptr) {free(ptr);ptr=((void*)0);} switch_safe_free(ptr)if (ptr) {free(ptr);ptr=((void*)0);}
127#endif
128
129/* make sure this is synced with the switch_event_types_t enum in switch_types.h
130 also never put any new ones before EVENT_ALL
131*/
132static char *EVENT_NAMES[] = {
133 "CUSTOM",
134 "CLONE",
135 "CHANNEL_CREATE",
136 "CHANNEL_DESTROY",
137 "CHANNEL_STATE",
138 "CHANNEL_CALLSTATE",
139 "CHANNEL_ANSWER",
140 "CHANNEL_HANGUP",
141 "CHANNEL_HANGUP_COMPLETE",
142 "CHANNEL_EXECUTE",
143 "CHANNEL_EXECUTE_COMPLETE",
144 "CHANNEL_HOLD",
145 "CHANNEL_UNHOLD",
146 "CHANNEL_BRIDGE",
147 "CHANNEL_UNBRIDGE",
148 "CHANNEL_PROGRESS",
149 "CHANNEL_PROGRESS_MEDIA",
150 "CHANNEL_OUTGOING",
151 "CHANNEL_PARK",
152 "CHANNEL_UNPARK",
153 "CHANNEL_APPLICATION",
154 "CHANNEL_ORIGINATE",
155 "CHANNEL_UUID",
156 "API",
157 "LOG",
158 "INBOUND_CHAN",
159 "OUTBOUND_CHAN",
160 "STARTUP",
161 "SHUTDOWN",
162 "PUBLISH",
163 "UNPUBLISH",
164 "TALK",
165 "NOTALK",
166 "SESSION_CRASH",
167 "MODULE_LOAD",
168 "MODULE_UNLOAD",
169 "DTMF",
170 "MESSAGE",
171 "PRESENCE_IN",
172 "NOTIFY_IN",
173 "PRESENCE_OUT",
174 "PRESENCE_PROBE",
175 "MESSAGE_WAITING",
176 "MESSAGE_QUERY",
177 "ROSTER",
178 "CODEC",
179 "BACKGROUND_JOB",
180 "DETECTED_SPEECH",
181 "DETECTED_TONE",
182 "PRIVATE_COMMAND",
183 "HEARTBEAT",
184 "TRAP",
185 "ADD_SCHEDULE",
186 "DEL_SCHEDULE",
187 "EXE_SCHEDULE",
188 "RE_SCHEDULE",
189 "RELOADXML",
190 "NOTIFY",
191 "PHONE_FEATURE",
192 "PHONE_FEATURE_SUBSCRIBE",
193 "SEND_MESSAGE",
194 "RECV_MESSAGE",
195 "REQUEST_PARAMS",
196 "CHANNEL_DATA",
197 "GENERAL",
198 "COMMAND",
199 "SESSION_HEARTBEAT",
200 "CLIENT_DISCONNECTED",
201 "SERVER_DISCONNECTED",
202 "SEND_INFO",
203 "RECV_INFO",
204 "RECV_RTCP_MESSAGE",
205 "CALL_SECURE",
206 "NAT",
207 "RECORD_START",
208 "RECORD_STOP",
209 "PLAYBACK_START",
210 "PLAYBACK_STOP",
211 "CALL_UPDATE",
212 "FAILURE",
213 "SOCKET_DATA",
214 "MEDIA_BUG_START",
215 "MEDIA_BUG_STOP",
216 "CONFERENCE_DATA_QUERY",
217 "CONFERENCE_DATA",
218 "CALL_SETUP_REQ",
219 "CALL_SETUP_RESULT",
220 "CALL_DETAIL",
221 "DEVICE_STATE",
222 "ALL"
223};
224
225static int switch_events_match(switch_event_t *event, switch_event_node_t *node)
226{
227 int match = 0;
228
229 if (node->event_id == SWITCH_EVENT_ALL) {
230 match++;
231
232 if (!node->subclass_name) {
233 return match;
234 }
235 }
236
237 if (match || event->event_id == node->event_id) {
238
239 if (event->subclass_name && node->subclass_name) {
240 if (!strncasecmp(node->subclass_name, "file:", 5)) {
241 char *file_header;
242 if ((file_header = switch_event_get_header(event, "file")switch_event_get_header_idx(event, "file", -1)) != 0) {
243 match = strstr(node->subclass_name + 5, file_header) ? 1 : 0;
244 }
245 } else if (!strncasecmp(node->subclass_name, "func:", 5)) {
246 char *func_header;
247 if ((func_header = switch_event_get_header(event, "function")switch_event_get_header_idx(event, "function", -1)) != 0) {
248 match = strstr(node->subclass_name + 5, func_header) ? 1 : 0;
249 }
250 } else if (event->subclass_name && node->subclass_name) {
251 match = strstr(event->subclass_name, node->subclass_name) ? 1 : 0;
252 }
253 } else if ((event->subclass_name && !node->subclass_name) || (!event->subclass_name && !node->subclass_name)) {
254 match = 1;
255 } else {
256 match = 0;
257 }
258 }
259
260 return match;
261}
262
263
264static void *SWITCH_THREAD_FUNC switch_event_deliver_thread(switch_thread_t *thread, void *obj)
265{
266 switch_event_t *event = (switch_event_t *) obj;
267
268 switch_event_deliver(&event);
269
270 return NULL((void*)0);
271}
272
273static void switch_event_deliver_thread_pool(switch_event_t **event)
274{
275 switch_thread_data_t *td;
276
277 td = malloc(sizeof(*td));
278 switch_assert(td)((td) ? (void) (0) : __assert_fail ("td", "src/switch_event.c"
, 278, __PRETTY_FUNCTION__))
;
279
280 td->alloc = 1;
281 td->func = switch_event_deliver_thread;
282 td->obj = *event;
283 td->pool = NULL((void*)0);
284
285 *event = NULL((void*)0);
286
287 switch_thread_pool_launch_thread(&td);
288
289}
290
291static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *thread, void *obj)
292{
293 switch_queue_t *queue = (switch_queue_t *) obj;
294 int my_id = 0;
295
296 switch_mutex_lock(EVENT_QUEUE_MUTEX);
297 THREAD_COUNT++;
298 DISPATCH_THREAD_COUNT++;
299
300 for (my_id = 0; my_id < MAX_DISPATCH_VAL64; my_id++) {
301 if (EVENT_DISPATCH_QUEUE_THREADS[my_id] == thread) {
302 break;
303 }
304 }
305
306 if ( my_id >= MAX_DISPATCH_VAL64 ) {
307 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
308 return NULL((void*)0);
309 }
310
311 EVENT_DISPATCH_QUEUE_RUNNING[my_id] = 1;
312 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
313
314
315 for (;;) {
316 void *pop = NULL((void*)0);
317 switch_event_t *event = NULL((void*)0);
318
319 if (!SYSTEM_RUNNING) {
320 break;
321 }
322
323 if (switch_queue_pop(queue, &pop) != SWITCH_STATUS_SUCCESS) {
324 continue;
325 }
326
327 if (!pop) {
328 break;
329 }
330
331 event = (switch_event_t *) pop;
332 switch_event_deliver(&event);
333 switch_os_yield();
334 }
335
336
337 switch_mutex_lock(EVENT_QUEUE_MUTEX);
338 EVENT_DISPATCH_QUEUE_RUNNING[my_id] = 0;
339 THREAD_COUNT--;
340 DISPATCH_THREAD_COUNT--;
341 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
342
343 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 343, ((void*)0)
, SWITCH_LOG_CONSOLE, "Dispatch Thread %d Ended.\n", my_id);
344 return NULL((void*)0);
345
346}
347
348static int PENDING = 0;
349
350static switch_status_t switch_event_queue_dispatch_event(switch_event_t **eventp)
351{
352
353 switch_event_t *event = *eventp;
354
355 if (!SYSTEM_RUNNING) {
356 return SWITCH_STATUS_FALSE;
357 }
358
359 while (event) {
360 int launch = 0;
361
362 switch_mutex_lock(EVENT_QUEUE_MUTEX);
363
364 if (!PENDING && switch_queue_size(EVENT_DISPATCH_QUEUE) > (unsigned int)(DISPATCH_QUEUE_LEN10000 * DISPATCH_THREAD_COUNT)) {
365 if (SOFT_MAX_DISPATCH + 1 > MAX_DISPATCH) {
366 launch++;
367 PENDING++;
368 }
369 }
370
371 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
372
373 if (launch) {
374 if (SOFT_MAX_DISPATCH + 1 < MAX_DISPATCH) {
375 switch_event_launch_dispatch_threads(SOFT_MAX_DISPATCH + 1);
376 }
377
378 switch_mutex_lock(EVENT_QUEUE_MUTEX);
379 PENDING--;
380 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
381 }
382
383 *eventp = NULL((void*)0);
384 switch_queue_push(EVENT_DISPATCH_QUEUE, event);
385 event = NULL((void*)0);
386
387 }
388
389 return SWITCH_STATUS_SUCCESS;
390}
391
392SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_event_deliver(switch_event_t **event)
393{
394 switch_event_types_t e;
395 switch_event_node_t *node;
396
397 if (SYSTEM_RUNNING) {
398 switch_thread_rwlock_rdlock(RWLOCK);
399 for (e = (*event)->event_id;; e = SWITCH_EVENT_ALL) {
400 for (node = EVENT_NODES[e]; node; node = node->next) {
401 if (switch_events_match(*event, node)) {
402 (*event)->bind_user_data = node->user_data;
403 node->callback(*event);
404 }
405 }
406
407 if (e == SWITCH_EVENT_ALL) {
408 break;
409 }
410 }
411 switch_thread_rwlock_unlock(RWLOCK);
412 }
413
414 switch_event_destroy(event);
415}
416
417SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_running(void)
418{
419 return SYSTEM_RUNNING ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
420}
421
422SWITCH_DECLARE(const char *)__attribute__((visibility("default"))) const char * switch_event_name(switch_event_types_t event)
423{
424 switch_assert(BLOCK != NULL)((BLOCK != ((void*)0)) ? (void) (0) : __assert_fail ("BLOCK != ((void*)0)"
, "src/switch_event.c", 424, __PRETTY_FUNCTION__))
;
425 switch_assert(RUNTIME_POOL != NULL)((RUNTIME_POOL != ((void*)0)) ? (void) (0) : __assert_fail ("RUNTIME_POOL != ((void*)0)"
, "src/switch_event.c", 425, __PRETTY_FUNCTION__))
;
426
427 return EVENT_NAMES[event];
428}
429
430SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_name_event(const char *name, switch_event_types_t *type)
431{
432 switch_event_types_t x;
433 switch_assert(BLOCK != NULL)((BLOCK != ((void*)0)) ? (void) (0) : __assert_fail ("BLOCK != ((void*)0)"
, "src/switch_event.c", 433, __PRETTY_FUNCTION__))
;
434 switch_assert(RUNTIME_POOL != NULL)((RUNTIME_POOL != ((void*)0)) ? (void) (0) : __assert_fail ("RUNTIME_POOL != ((void*)0)"
, "src/switch_event.c", 434, __PRETTY_FUNCTION__))
;
435
436 for (x = 0; x <= SWITCH_EVENT_ALL; x++) {
437 if ((strlen(name) > 13 && !strcasecmp(name + 13, EVENT_NAMES[x])) || !strcasecmp(name, EVENT_NAMES[x])) {
438 *type = x;
439 return SWITCH_STATUS_SUCCESS;
440 }
441 }
442
443 return SWITCH_STATUS_FALSE;
444}
445
446SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_free_subclass_detailed(const char *owner, const char *subclass_name)
447{
448 switch_event_subclass_t *subclass;
449 switch_status_t status = SWITCH_STATUS_FALSE;
450
451 switch_assert(RUNTIME_POOL != NULL)((RUNTIME_POOL != ((void*)0)) ? (void) (0) : __assert_fail ("RUNTIME_POOL != ((void*)0)"
, "src/switch_event.c", 451, __PRETTY_FUNCTION__))
;
452 switch_assert(CUSTOM_HASH != NULL)((CUSTOM_HASH != ((void*)0)) ? (void) (0) : __assert_fail ("CUSTOM_HASH != ((void*)0)"
, "src/switch_event.c", 452, __PRETTY_FUNCTION__))
;
453
454 if ((subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name))) {
455 if (!strcmp(owner, subclass->owner)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(owner) && __builtin_constant_p (subclass->owner)
&& (__s1_len = __builtin_strlen (owner), __s2_len = __builtin_strlen
(subclass->owner), (!((size_t)(const void *)((owner) + 1)
- (size_t)(const void *)(owner) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((subclass->owner) + 1) - (size_t
)(const void *)(subclass->owner) == 1) || __s2_len >= 4
)) ? __builtin_strcmp (owner, subclass->owner) : (__builtin_constant_p
(owner) && ((size_t)(const void *)((owner) + 1) - (size_t
)(const void *)(owner) == 1) && (__s1_len = __builtin_strlen
(owner), __s1_len < 4) ? (__builtin_constant_p (subclass->
owner) && ((size_t)(const void *)((subclass->owner
) + 1) - (size_t)(const void *)(subclass->owner) == 1) ? __builtin_strcmp
(owner, subclass->owner) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (subclass
->owner); int __result = (((const unsigned char *) (const char
*) (owner))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
owner))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
owner))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (owner
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
subclass->owner) && ((size_t)(const void *)((subclass
->owner) + 1) - (size_t)(const void *)(subclass->owner)
== 1) && (__s2_len = __builtin_strlen (subclass->
owner), __s2_len < 4) ? (__builtin_constant_p (owner) &&
((size_t)(const void *)((owner) + 1) - (size_t)(const void *
)(owner) == 1) ? __builtin_strcmp (owner, subclass->owner)
: (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (owner); int __result = (((const unsigned
char *) (const char *) (subclass->owner))[0] - __s2[0]); if
(__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (subclass->owner))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (subclass->owner
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (subclass
->owner))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(owner, subclass->owner)))); })
) {
456 switch_thread_rwlock_wrlock(RWLOCK);
457 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 457, ((void*)0)
, SWITCH_LOG_NOTICE, "Subclass reservation deleted for %s:%s\n", owner, subclass_name);
458 switch_core_hash_delete(CUSTOM_HASH, subclass_name);
459 FREE(subclass->owner)if (subclass->owner) {free(subclass->owner);subclass->
owner=((void*)0);}
;
460 FREE(subclass->name)if (subclass->name) {free(subclass->name);subclass->
name=((void*)0);}
;
461 FREE(subclass)if (subclass) {free(subclass);subclass=((void*)0);};
462 status = SWITCH_STATUS_SUCCESS;
463 switch_thread_rwlock_unlock(RWLOCK);
464 } else {
465 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 465, ((void*)0)
, SWITCH_LOG_NOTICE, "Subclass reservation %s inuse by listeners, detaching..\n", subclass_name);
466 subclass->bind = 1;
467 }
468 }
469
470 return status;
471}
472
473SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_reserve_subclass_detailed(const char *owner, const char *subclass_name)
474{
475 switch_event_subclass_t *subclass;
476
477 switch_assert(RUNTIME_POOL != NULL)((RUNTIME_POOL != ((void*)0)) ? (void) (0) : __assert_fail ("RUNTIME_POOL != ((void*)0)"
, "src/switch_event.c", 477, __PRETTY_FUNCTION__))
;
478 switch_assert(CUSTOM_HASH != NULL)((CUSTOM_HASH != ((void*)0)) ? (void) (0) : __assert_fail ("CUSTOM_HASH != ((void*)0)"
, "src/switch_event.c", 478, __PRETTY_FUNCTION__))
;
479
480 if ((subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name))) {
481 /* a listener reserved it for us, now we can lock it so nobody else can have it */
482 if (subclass->bind) {
483 subclass->bind = 0;
484 return SWITCH_STATUS_SUCCESS;
485 }
486 return SWITCH_STATUS_INUSE;
487 }
488
489 switch_zmalloc(subclass, sizeof(*subclass))(void)((((subclass = calloc(1, (sizeof(*subclass))))) ? (void
) (0) : __assert_fail ("(subclass = calloc(1, (sizeof(*subclass))))"
, "src/switch_event.c", 489, __PRETTY_FUNCTION__)),subclass)
;
490
491 subclass->owner = DUP(owner)my_dup(owner);
492 subclass->name = DUP(subclass_name)my_dup(subclass_name);
493
494 switch_core_hash_insert(CUSTOM_HASH, subclass->name, subclass)switch_core_hash_insert_destructor(CUSTOM_HASH, subclass->
name, subclass, ((void*)0))
;
495
496 return SWITCH_STATUS_SUCCESS;
497}
498
499SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_core_memory_reclaim_events(void)
500{
501#ifdef SWITCH_EVENT_RECYCLE
502
503 void *pop;
504 int size;
505 size = switch_queue_size(EVENT_RECYCLE_QUEUE);
506
507 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 507, ((void*)0)
, SWITCH_LOG_CONSOLE, "Returning %d recycled event(s) %d bytes\n", size, (int) sizeof(switch_event_t) * size);
508 size = switch_queue_size(EVENT_HEADER_RECYCLE_QUEUE);
509 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 509, ((void*)0)
, SWITCH_LOG_CONSOLE, "Returning %d recycled event header(s) %d bytes\n",
510 size, (int) sizeof(switch_event_header_t) * size);
511
512 while (switch_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS && pop) {
513 free(pop);
514 }
515 while (switch_queue_trypop(EVENT_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS && pop) {
516 free(pop);
517 }
518#else
519 return;
520#endif
521
522}
523
524SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_shutdown(void)
525{
526 uint32_t x = 0;
527 int last = 0;
528 switch_hash_index_t *hi;
529 const void *var;
530 void *val;
531
532 switch_mutex_lock(EVENT_QUEUE_MUTEX);
533 SYSTEM_RUNNING = 0;
534 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
535
536 unsub_all_switch_event_channel();
537
538 if (EVENT_CHANNEL_DISPATCH_QUEUE) {
539 switch_queue_trypush(EVENT_CHANNEL_DISPATCH_QUEUE, NULL((void*)0));
540 switch_queue_interrupt_all(EVENT_CHANNEL_DISPATCH_QUEUE);
541 }
542
543 if (runtime.events_use_dispatch) {
544 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 544, ((void*)0)
, SWITCH_LOG_CONSOLE, "Stopping dispatch queues\n");
545
546 for(x = 0; x < (uint32_t)DISPATCH_THREAD_COUNT; x++) {
547 switch_queue_trypush(EVENT_DISPATCH_QUEUE, NULL((void*)0));
548 }
549
550
551 switch_queue_interrupt_all(EVENT_DISPATCH_QUEUE);
552
553 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 553, ((void*)0)
, SWITCH_LOG_CONSOLE, "Stopping dispatch threads\n");
554
555 for(x = 0; x < (uint32_t)DISPATCH_THREAD_COUNT; x++) {
556 switch_status_t st;
557 switch_thread_join(&st, EVENT_DISPATCH_QUEUE_THREADS[x]);
558 }
559 }
560
561 x = 0;
562 while (x < 100 && THREAD_COUNT) {
563 switch_yield(100000)switch_sleep(100000);;
564 if (THREAD_COUNT == last) {
565 x++;
566 }
567 last = THREAD_COUNT;
568 }
569
570 if (runtime.events_use_dispatch) {
571 void *pop = NULL((void*)0);
572 switch_event_t *event = NULL((void*)0);
573
574 while (switch_queue_trypop(EVENT_DISPATCH_QUEUE, &pop) == SWITCH_STATUS_SUCCESS && pop) {
575 event = (switch_event_t *) pop;
576 switch_event_destroy(&event);
577 }
578 }
579
580 for (hi = switch_core_hash_first(CUSTOM_HASH)switch_core_hash_first_iter(CUSTOM_HASH, ((void*)0)); hi; hi = switch_core_hash_next(&hi)) {
581 switch_event_subclass_t *subclass;
582 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
583 if ((subclass = (switch_event_subclass_t *) val)) {
584 FREE(subclass->name)if (subclass->name) {free(subclass->name);subclass->
name=((void*)0);}
;
585 FREE(subclass->owner)if (subclass->owner) {free(subclass->owner);subclass->
owner=((void*)0);}
;
586 FREE(subclass)if (subclass) {free(subclass);subclass=((void*)0);};
587 }
588 }
589
590 switch_core_hash_destroy(&event_channel_manager.lahash);
591 switch_core_hash_destroy(&event_channel_manager.hash);
592 switch_core_hash_destroy(&event_channel_manager.perm_hash);
593
594 switch_core_hash_destroy(&CUSTOM_HASH);
595 switch_core_memory_reclaim_events();
596
597 return SWITCH_STATUS_SUCCESS;
598}
599
600static void check_dispatch(void)
601{
602 if (!EVENT_DISPATCH_QUEUE) {
603 switch_mutex_lock(BLOCK);
604
605 if (!EVENT_DISPATCH_QUEUE) {
606 switch_queue_create(&EVENT_DISPATCH_QUEUE, DISPATCH_QUEUE_LEN10000 * MAX_DISPATCH, THRUNTIME_POOL);
607 switch_event_launch_dispatch_threads(1);
608
609 while (!THREAD_COUNT) {
610 switch_cond_next();
611 }
612 }
613 switch_mutex_unlock(BLOCK);
614 }
615}
616
617
618
619SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_event_launch_dispatch_threads(uint32_t max)
620{
621 switch_threadattr_t *thd_attr;
622 uint32_t index = 0;
623 int launched = 0;
624 uint32_t sanity = 200;
625
626 switch_memory_pool_t *pool = RUNTIME_POOL;
627
628 check_dispatch();
629
630 if (max > MAX_DISPATCH) {
631 return;
632 }
633
634 if (max < SOFT_MAX_DISPATCH) {
635 return;
636 }
637
638 for (index = SOFT_MAX_DISPATCH; index < max && index < MAX_DISPATCH; index++) {
639 if (EVENT_DISPATCH_QUEUE_THREADS[index]) {
640 continue;
641 }
642
643 switch_threadattr_create(&thd_attr, pool);
644 switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE240 * 1024);
645 switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME);
646 switch_thread_create(&EVENT_DISPATCH_QUEUE_THREADS[index], thd_attr, switch_event_dispatch_thread, EVENT_DISPATCH_QUEUE, pool);
647 while(--sanity && !EVENT_DISPATCH_QUEUE_RUNNING[index]) switch_yield(10000)switch_sleep(10000);;
648
649 if (index == 1) {
650 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 650, ((void*)0)
, SWITCH_LOG_WARNING, "Create event dispatch thread %d\n", index);
651 } else {
652 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 652, ((void*)0)
, SWITCH_LOG_WARNING, "Create additional event dispatch thread %d\n", index);
653 }
654 launched++;
655 }
656
657 SOFT_MAX_DISPATCH = index;
658}
659
660SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_init(switch_memory_pool_t *pool)
661{
662 /* don't need any more dispatch threads than we have CPU's*/
663 MAX_DISPATCH = (switch_core_cpu_count() / 2) + 1;
664 if (MAX_DISPATCH < 2) {
665 MAX_DISPATCH = 2;
666 }
667
668 switch_assert(pool != NULL)((pool != ((void*)0)) ? (void) (0) : __assert_fail ("pool != ((void*)0)"
, "src/switch_event.c", 668, __PRETTY_FUNCTION__))
;
669 THRUNTIME_POOL = RUNTIME_POOL = pool;
670 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 670, ((void*)0)
, SWITCH_LOG_INFO, "Activate Eventing Engine.\n");
671 switch_thread_rwlock_create(&RWLOCK, RUNTIME_POOL);
672 switch_mutex_init(&BLOCK, SWITCH_MUTEX_NESTED0x1, RUNTIME_POOL);
673 switch_mutex_init(&POOL_LOCK, SWITCH_MUTEX_NESTED0x1, RUNTIME_POOL);
674 switch_mutex_init(&EVENT_QUEUE_MUTEX, SWITCH_MUTEX_NESTED0x1, RUNTIME_POOL);
675 switch_core_hash_init(&CUSTOM_HASH)switch_core_hash_init_case(&CUSTOM_HASH, SWITCH_TRUE);
676
677 switch_core_hash_init(&event_channel_manager.lahash)switch_core_hash_init_case(&event_channel_manager.lahash,
SWITCH_TRUE)
;
678 switch_mutex_init(&event_channel_manager.lamutex, SWITCH_MUTEX_NESTED0x1, RUNTIME_POOL);
679
680 switch_thread_rwlock_create(&event_channel_manager.rwlock, RUNTIME_POOL);
681 switch_core_hash_init(&event_channel_manager.hash)switch_core_hash_init_case(&event_channel_manager.hash, SWITCH_TRUE
)
;
682 switch_core_hash_init(&event_channel_manager.perm_hash)switch_core_hash_init_case(&event_channel_manager.perm_hash
, SWITCH_TRUE)
;
683 event_channel_manager.ID = 1;
684
685 switch_mutex_lock(EVENT_QUEUE_MUTEX);
686 SYSTEM_RUNNING = -1;
687 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
688
689 //switch_threadattr_create(&thd_attr, pool);
690 switch_find_local_ip(guess_ip_v4, sizeof(guess_ip_v4), NULL((void*)0), AF_INET2);
691 switch_find_local_ip(guess_ip_v6, sizeof(guess_ip_v6), NULL((void*)0), AF_INET610);
692
693
694#ifdef SWITCH_EVENT_RECYCLE
695 switch_queue_create(&EVENT_RECYCLE_QUEUE, 250000, THRUNTIME_POOL);
696 switch_queue_create(&EVENT_HEADER_RECYCLE_QUEUE, 250000, THRUNTIME_POOL);
697#endif
698
699 check_dispatch();
700
701 switch_mutex_lock(EVENT_QUEUE_MUTEX);
702 SYSTEM_RUNNING = 1;
703 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
704
705 return SWITCH_STATUS_SUCCESS;
706}
707
708SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_create_subclass_detailed(const char *file, const char *func, int line,
709 switch_event_t **event, switch_event_types_t event_id, const char *subclass_name)
710{
711#ifdef SWITCH_EVENT_RECYCLE
712 void *pop;
713#endif
714
715 *event = NULL((void*)0);
716
717 if ((event_id != SWITCH_EVENT_CLONE && event_id != SWITCH_EVENT_CUSTOM) && subclass_name) {
718 return SWITCH_STATUS_GENERR;
719 }
720#ifdef SWITCH_EVENT_RECYCLE
721 if (EVENT_RECYCLE_QUEUE && switch_queue_trypop(EVENT_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS && pop) {
722 *event = (switch_event_t *) pop;
723 } else {
724#endif
725 *event = ALLOC(sizeof(switch_event_t))malloc(sizeof(switch_event_t));
726 switch_assert(*event)((*event) ? (void) (0) : __assert_fail ("*event", "src/switch_event.c"
, 726, __PRETTY_FUNCTION__))
;
727#ifdef SWITCH_EVENT_RECYCLE
728 }
729#endif
730
731 memset(*event, 0, sizeof(switch_event_t));
732
733 if (event_id == SWITCH_EVENT_REQUEST_PARAMS || event_id == SWITCH_EVENT_CHANNEL_DATA || event_id == SWITCH_EVENT_MESSAGE) {
734 (*event)->flags |= EF_UNIQ_HEADERS;
735 }
736
737 if (event_id != SWITCH_EVENT_CLONE) {
738 (*event)->event_id = event_id;
739 switch_event_prep_for_delivery_detailed(file, func, line, *event);
740 }
741
742 if (subclass_name) {
743 (*event)->subclass_name = DUP(subclass_name)my_dup(subclass_name);
744 switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Event-Subclass", subclass_name);
745 }
746
747 return SWITCH_STATUS_SUCCESS;
748}
749
750SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_set_priority(switch_event_t *event, switch_priority_t priority)
751{
752 event->priority = priority;
753 switch_event_add_header_string(event, SWITCH_STACK_TOP, "priority", switch_priority_name(priority));
754 return SWITCH_STATUS_SUCCESS;
755}
756
757SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_rename_header(switch_event_t *event, const char *header_name, const char *new_header_name)
758{
759 switch_event_header_t *hp;
760 switch_ssize_t hlen = -1;
761 unsigned long hash = 0;
762 int x = 0;
763
764 switch_assert(event)((event) ? (void) (0) : __assert_fail ("event", "src/switch_event.c"
, 764, __PRETTY_FUNCTION__))
;
765
766 if (!header_name) {
767 return SWITCH_STATUS_FALSE;
768 }
769
770 hash = switch_ci_hashfunc_default(header_name, &hlen);
771
772 for (hp = event->headers; hp; hp = hp->next) {
773 if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name)) {
774 FREE(hp->name)if (hp->name) {free(hp->name);hp->name=((void*)0);};
775 hp->name = DUP(new_header_name)my_dup(new_header_name);
776 hlen = -1;
777 hp->hash = switch_ci_hashfunc_default(hp->name, &hlen);
778 x++;
779 }
780 }
781
782 return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
783}
784
785
786SWITCH_DECLARE(switch_event_header_t *)__attribute__((visibility("default"))) switch_event_header_t * switch_event_get_header_ptr(switch_event_t *event, const char *header_name)
787{
788 switch_event_header_t *hp;
789 switch_ssize_t hlen = -1;
790 unsigned long hash = 0;
791
792 switch_assert(event)((event) ? (void) (0) : __assert_fail ("event", "src/switch_event.c"
, 792, __PRETTY_FUNCTION__))
;
793
794 if (!header_name)
795 return NULL((void*)0);
796
797 hash = switch_ci_hashfunc_default(header_name, &hlen);
798
799 for (hp = event->headers; hp; hp = hp->next) {
800 if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name)) {
801 return hp;
802 }
803 }
804 return NULL((void*)0);
805}
806
807SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_event_get_header_idx(switch_event_t *event, const char *header_name, int idx)
808{
809 switch_event_header_t *hp;
810
811 if ((hp = switch_event_get_header_ptr(event, header_name))) {
812 if (idx > -1) {
813 if (idx < hp->idx) {
814 return hp->array[idx];
815 } else {
816 return NULL((void*)0);
817 }
818 }
819
820 return hp->value;
821 } else if (!strcmp(header_name, "_body")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(header_name) && __builtin_constant_p ("_body") &&
(__s1_len = __builtin_strlen (header_name), __s2_len = __builtin_strlen
("_body"), (!((size_t)(const void *)((header_name) + 1) - (size_t
)(const void *)(header_name) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(("_body") + 1) - (size_t)(const void
*)("_body") == 1) || __s2_len >= 4)) ? __builtin_strcmp (
header_name, "_body") : (__builtin_constant_p (header_name) &&
((size_t)(const void *)((header_name) + 1) - (size_t)(const void
*)(header_name) == 1) && (__s1_len = __builtin_strlen
(header_name), __s1_len < 4) ? (__builtin_constant_p ("_body"
) && ((size_t)(const void *)(("_body") + 1) - (size_t
)(const void *)("_body") == 1) ? __builtin_strcmp (header_name
, "_body") : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ("_body"); int __result = ((
(const unsigned char *) (const char *) (header_name))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (header_name))[1]
- __s2[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (header_name))[2]
- __s2[2]); if (__s1_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) (header_name))[3]
- __s2[3]); } } __result; }))) : (__builtin_constant_p ("_body"
) && ((size_t)(const void *)(("_body") + 1) - (size_t
)(const void *)("_body") == 1) && (__s2_len = __builtin_strlen
("_body"), __s2_len < 4) ? (__builtin_constant_p (header_name
) && ((size_t)(const void *)((header_name) + 1) - (size_t
)(const void *)(header_name) == 1) ? __builtin_strcmp (header_name
, "_body") : (- (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) (header_name); int __result
= (((const unsigned char *) (const char *) ("_body"))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("_body"))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("_body"))[2] - __s2
[2]); if (__s2_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) ("_body"))[3] - __s2
[3]); } } __result; })))) : __builtin_strcmp (header_name, "_body"
)))); })
) {
822 return event->body;
823 }
824
825 return NULL((void*)0);
826}
827
828SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_event_get_body(switch_event_t *event)
829{
830 return (event ? event->body : NULL((void*)0));
831}
832
833SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_del_header_val(switch_event_t *event, const char *header_name, const char *val)
834{
835 switch_event_header_t *hp, *lp = NULL((void*)0), *tp;
836 switch_status_t status = SWITCH_STATUS_FALSE;
837 int x = 0;
838 switch_ssize_t hlen = -1;
839 unsigned long hash = 0;
840
841 tp = event->headers;
842 hash = switch_ci_hashfunc_default(header_name, &hlen);
843 while (tp) {
844 hp = tp;
845 tp = tp->next;
846
847 x++;
848 switch_assert(x < 1000000)((x < 1000000) ? (void) (0) : __assert_fail ("x < 1000000"
, "src/switch_event.c", 848, __PRETTY_FUNCTION__))
;
849
850 if ((!hp->hash || hash == hp->hash) && !strcasecmp(header_name, hp->name) && (zstr(val)_zstr(val) || !strcmp(hp->value, val)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(hp->value) && __builtin_constant_p (val) &&
(__s1_len = __builtin_strlen (hp->value), __s2_len = __builtin_strlen
(val), (!((size_t)(const void *)((hp->value) + 1) - (size_t
)(const void *)(hp->value) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((val) + 1) - (size_t)(const void *
)(val) == 1) || __s2_len >= 4)) ? __builtin_strcmp (hp->
value, val) : (__builtin_constant_p (hp->value) &&
((size_t)(const void *)((hp->value) + 1) - (size_t)(const
void *)(hp->value) == 1) && (__s1_len = __builtin_strlen
(hp->value), __s1_len < 4) ? (__builtin_constant_p (val
) && ((size_t)(const void *)((val) + 1) - (size_t)(const
void *)(val) == 1) ? __builtin_strcmp (hp->value, val) : (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) (val); int __result = (((const unsigned char
*) (const char *) (hp->value))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (hp->value))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (hp->value))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (hp->value))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (val) && ((size_t)(const
void *)((val) + 1) - (size_t)(const void *)(val) == 1) &&
(__s2_len = __builtin_strlen (val), __s2_len < 4) ? (__builtin_constant_p
(hp->value) && ((size_t)(const void *)((hp->value
) + 1) - (size_t)(const void *)(hp->value) == 1) ? __builtin_strcmp
(hp->value, val) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (hp->value
); int __result = (((const unsigned char *) (const char *) (val
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (val)
)[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (val)
)[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (val))[
3] - __s2[3]); } } __result; })))) : __builtin_strcmp (hp->
value, val)))); })
)) {
851 if (lp) {
852 lp->next = hp->next;
853 } else {
854 event->headers = hp->next;
855 }
856 if (hp == event->last_header || !hp->next) {
857 event->last_header = lp;
858 }
859 FREE(hp->name)if (hp->name) {free(hp->name);hp->name=((void*)0);};
860
861 if (hp->idx) {
862 int i = 0;
863
864 for (i = 0; i < hp->idx; i++) {
865 FREE(hp->array[i])if (hp->array[i]) {free(hp->array[i]);hp->array[i]=(
(void*)0);}
;
866 }
867 FREE(hp->array)if (hp->array) {free(hp->array);hp->array=((void*)0)
;}
;
868 }
869
870 FREE(hp->value)if (hp->value) {free(hp->value);hp->value=((void*)0)
;}
;
871
872 memset(hp, 0, sizeof(*hp));
873#ifdef SWITCH_EVENT_RECYCLE
874 if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != SWITCH_STATUS_SUCCESS) {
875 FREE(hp)if (hp) {free(hp);hp=((void*)0);};
876 }
877#else
878 FREE(hp)if (hp) {free(hp);hp=((void*)0);};
879#endif
880 status = SWITCH_STATUS_SUCCESS;
881 } else {
882 lp = hp;
883 }
884 }
885
886 return status;
887}
888
889static switch_event_header_t *new_header(const char *header_name)
890{
891 switch_event_header_t *header;
892
893#ifdef SWITCH_EVENT_RECYCLE
894 void *pop;
895 if (EVENT_HEADER_RECYCLE_QUEUE && switch_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS) {
896 header = (switch_event_header_t *) pop;
897 } else {
898#endif
899 header = ALLOC(sizeof(*header))malloc(sizeof(*header));
900 switch_assert(header)((header) ? (void) (0) : __assert_fail ("header", "src/switch_event.c"
, 900, __PRETTY_FUNCTION__))
;
901#ifdef SWITCH_EVENT_RECYCLE
902 }
903#endif
904
905 memset(header, 0, sizeof(*header));
906 header->name = DUP(header_name)my_dup(header_name);
907
908 return header;
909
910}
911
912SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_event_add_array(switch_event_t *event, const char *var, const char *val)
913{
914 char *data;
915 char **array;
916 int max = 0;
917 int len;
918 const char *p;
919 int i;
920
921 if (strlen(val) < 8) {
922 return -1;
923 }
924
925 p = val + 7;
926
927 max = 1;
928
929 while((p = strstr(p, "|:"))) {
930 max++;
931 p += 2;
932 }
933
934 if (!max) {
935 return -2;
936 }
937
938 data = strdup(val + 7)(__extension__ (__builtin_constant_p (val + 7) && ((size_t
)(const void *)((val + 7) + 1) - (size_t)(const void *)(val +
7) == 1) ? (((const char *) (val + 7))[0] == '\0' ? (char *)
calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
val + 7) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, val + 7
, __len); __retval; })) : __strdup (val + 7)))
;
939
940 len = (sizeof(char *) * max) + 1;
941 switch_assert(len)((len) ? (void) (0) : __assert_fail ("len", "src/switch_event.c"
, 941, __PRETTY_FUNCTION__))
;
942
943 array = malloc(len);
944 memset(array, 0, len);
945
946 switch_separate_string_string(data, "|:", array, max);
947
948 for(i = 0; i < max; i++) {
949 switch_event_add_header_string(event, SWITCH_STACK_PUSH, var, array[i]);
950 }
951
952 free(array);
953 free(data);
954
955 return 0;
956}
957
958static switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, char *data)
959{
960 switch_event_header_t *header = NULL((void*)0);
961 switch_ssize_t hlen = -1;
962 int exists = 0, fly = 0;
963 char *index_ptr;
964 int index = 0;
965 char *real_header_name = NULL((void*)0);
966
967
968 if (!strcmp(header_name, "_body")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(header_name) && __builtin_constant_p ("_body") &&
(__s1_len = __builtin_strlen (header_name), __s2_len = __builtin_strlen
("_body"), (!((size_t)(const void *)((header_name) + 1) - (size_t
)(const void *)(header_name) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(("_body") + 1) - (size_t)(const void
*)("_body") == 1) || __s2_len >= 4)) ? __builtin_strcmp (
header_name, "_body") : (__builtin_constant_p (header_name) &&
((size_t)(const void *)((header_name) + 1) - (size_t)(const void
*)(header_name) == 1) && (__s1_len = __builtin_strlen
(header_name), __s1_len < 4) ? (__builtin_constant_p ("_body"
) && ((size_t)(const void *)(("_body") + 1) - (size_t
)(const void *)("_body") == 1) ? __builtin_strcmp (header_name
, "_body") : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ("_body"); int __result = ((
(const unsigned char *) (const char *) (header_name))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (header_name))[1]
- __s2[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (header_name))[2]
- __s2[2]); if (__s1_len > 2 && __result == 0) __result
= (((const unsigned char *) (const char *) (header_name))[3]
- __s2[3]); } } __result; }))) : (__builtin_constant_p ("_body"
) && ((size_t)(const void *)(("_body") + 1) - (size_t
)(const void *)("_body") == 1) && (__s2_len = __builtin_strlen
("_body"), __s2_len < 4) ? (__builtin_constant_p (header_name
) && ((size_t)(const void *)((header_name) + 1) - (size_t
)(const void *)(header_name) == 1) ? __builtin_strcmp (header_name
, "_body") : (- (__extension__ ({ const unsigned char *__s2 =
(const unsigned char *) (const char *) (header_name); int __result
= (((const unsigned char *) (const char *) ("_body"))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("_body"))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("_body"))[2] - __s2
[2]); if (__s2_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) ("_body"))[3] - __s2
[3]); } } __result; })))) : __builtin_strcmp (header_name, "_body"
)))); })
) {
969 switch_event_set_body(event, data);
970 }
971
972 if ((index_ptr = strchr(header_name, '[')(__extension__ (__builtin_constant_p ('[') && !__builtin_constant_p
(header_name) && ('[') == '\0' ? (char *) __rawmemchr
(header_name, '[') : __builtin_strchr (header_name, '[')))
)) {
973 index_ptr++;
974 index = atoi(index_ptr);
975 real_header_name = DUP(header_name)my_dup(header_name);
976 if ((index_ptr = strchr(real_header_name, '[')(__extension__ (__builtin_constant_p ('[') && !__builtin_constant_p
(real_header_name) && ('[') == '\0' ? (char *) __rawmemchr
(real_header_name, '[') : __builtin_strchr (real_header_name
, '[')))
)) {
977 *index_ptr++ = '\0';
978 }
979 header_name = real_header_name;
980 }
981
982 if (index_ptr || (stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) {
983
984 if (!(header = switch_event_get_header_ptr(event, header_name)) && index_ptr) {
985
986 header = new_header(header_name);
987
988 if (switch_test_flag(event, EF_UNIQ_HEADERS)((event)->flags & EF_UNIQ_HEADERS)) {
989 switch_event_del_header(event, header_name)switch_event_del_header_val(event, header_name, ((void*)0));
990 }
991
992 fly++;
993 }
994
995 if (header || (header = switch_event_get_header_ptr(event, header_name))) {
996
997 if (index_ptr) {
998 if (index > -1 && index <= 4000) {
999 if (index < header->idx) {
1000 FREE(header->array[index])if (header->array[index]) {free(header->array[index]);header
->array[index]=((void*)0);}
;
1001 header->array[index] = DUP(data)my_dup(data);
1002 } else {
1003 int i;
1004 char **m;
1005
1006 m = realloc(header->array, sizeof(char *) * (index + 1));
1007 switch_assert(m)((m) ? (void) (0) : __assert_fail ("m", "src/switch_event.c",
1007, __PRETTY_FUNCTION__))
;
1008 header->array = m;
1009 for (i = header->idx; i < index; i++) {
1010 m[i] = DUP("")my_dup("");
1011 }
1012 m[index] = DUP(data)my_dup(data);
1013 header->idx = index + 1;
1014 if (!fly) {
1015 exists = 1;
1016 }
1017
1018 goto redraw;
1019 }
1020 }
1021 goto end;
1022 } else {
1023 if ((stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) {
1024 exists++;
1025 stack &= ~(SWITCH_STACK_TOP | SWITCH_STACK_BOTTOM);
1026 } else {
1027 header = NULL((void*)0);
1028 }
1029 }
1030 }
1031 }
1032
1033
1034 if (!header) {
1035
1036 if (zstr(data)_zstr(data)) {
1037 switch_event_del_header(event, header_name)switch_event_del_header_val(event, header_name, ((void*)0));
1038 FREE(data)if (data) {free(data);data=((void*)0);};
1039 goto end;
1040 }
1041
1042 if (switch_test_flag(event, EF_UNIQ_HEADERS)((event)->flags & EF_UNIQ_HEADERS)) {
1043 switch_event_del_header(event, header_name)switch_event_del_header_val(event, header_name, ((void*)0));
1044 }
1045
1046 if (strstr(data, "ARRAY::")) {
1047 switch_event_add_array(event, header_name, data);
1048 FREE(data)if (data) {free(data);data=((void*)0);};
1049 goto end;
1050 }
1051
1052
1053 header = new_header(header_name);
1054 }
1055
1056 if ((stack & SWITCH_STACK_PUSH) || (stack & SWITCH_STACK_UNSHIFT)) {
1057 char **m = NULL((void*)0);
1058 switch_size_t len = 0;
1059 char *hv;
1060 int i = 0, j = 0;
1061
1062 if (header->value && !header->idx) {
1063 m = malloc(sizeof(char *));
1064 switch_assert(m)((m) ? (void) (0) : __assert_fail ("m", "src/switch_event.c",
1064, __PRETTY_FUNCTION__))
;
1065 m[0] = header->value;
1066 header->value = NULL((void*)0);
1067 header->array = m;
1068 header->idx++;
1069 m = NULL((void*)0);
1070 }
1071
1072 i = header->idx + 1;
1073 m = realloc(header->array, sizeof(char *) * i);
1074 switch_assert(m)((m) ? (void) (0) : __assert_fail ("m", "src/switch_event.c",
1074, __PRETTY_FUNCTION__))
;
1075
1076 if ((stack & SWITCH_STACK_PUSH)) {
1077 m[header->idx] = data;
1078 } else if ((stack & SWITCH_STACK_UNSHIFT)) {
1079 for (j = header->idx; j > 0; j--) {
1080 m[j] = m[j-1];
1081 }
1082 m[0] = data;
1083 }
1084
1085 header->idx++;
1086 header->array = m;
1087
1088 redraw:
1089 len = 0;
1090 for(j = 0; j < header->idx; j++) {
1091 len += strlen(header->array[j]) + 2;
1092 }
1093
1094 if (len) {
1095 len += 8;
1096 hv = realloc(header->value, len);
1097 switch_assert(hv)((hv) ? (void) (0) : __assert_fail ("hv", "src/switch_event.c"
, 1097, __PRETTY_FUNCTION__))
;
1098 header->value = hv;
1099
1100 if (header->idx > 1) {
1101 switch_snprintf(header->value, len, "ARRAY::");
1102 } else {
1103 *header->value = '\0';
1104 }
1105
1106 hv += strlen(header->value);
1107 for(j = 0; j < header->idx; j++) {
1108 if (j > 0) {
1109 memcpy(hv, "|:", 2);
1110 hv += 2;
1111 }
1112 memcpy(hv, header->array[j], strlen(header->array[j]));
1113 hv += strlen(header->array[j]);
1114 }
1115 *hv = '\0';
1116 }
1117
1118 } else {
1119 switch_safe_free(header->value)if (header->value) {free(header->value);header->value
=((void*)0);}
;
1120 header->value = data;
1121 }
1122
1123 if (!exists) {
1124 header->hash = switch_ci_hashfunc_default(header->name, &hlen);
1125
1126 if ((stack & SWITCH_STACK_TOP)) {
1127 header->next = event->headers;
1128 event->headers = header;
1129 if (!event->last_header) {
1130 event->last_header = header;
1131 }
1132 } else {
1133 if (event->last_header) {
1134 event->last_header->next = header;
1135 } else {
1136 event->headers = header;
1137 header->next = NULL((void*)0);
1138 }
1139 event->last_header = header;
1140 }
1141 }
1142
1143 end:
1144
1145 switch_safe_free(real_header_name)if (real_header_name) {free(real_header_name);real_header_name
=((void*)0);}
;
1146
1147 return SWITCH_STATUS_SUCCESS;
1148}
1149
1150SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *fmt, ...)
1151{
1152 int ret = 0;
1153 char *data;
1154 va_list ap;
1155
1156 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1157 ret = switch_vasprintf(&data, fmt, ap);
1158 va_end(ap)__builtin_va_end(ap);
1159
1160 if (ret == -1) {
1161 return SWITCH_STATUS_MEMERR;
1162 }
1163
1164 return switch_event_base_add_header(event, stack, header_name, data);
1165}
1166
1167SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_set_subclass_name(switch_event_t *event, const char *subclass_name)
1168{
1169 if (!event || !subclass_name)
1170 return SWITCH_STATUS_GENERR;
1171
1172 switch_safe_free(event->subclass_name)if (event->subclass_name) {free(event->subclass_name);event
->subclass_name=((void*)0);}
;
1173 event->subclass_name = DUP(subclass_name)my_dup(subclass_name);
1174 switch_event_del_header(event, "Event-Subclass")switch_event_del_header_val(event, "Event-Subclass", ((void*)
0))
;
1175 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Event-Subclass", event->subclass_name);
1176 return SWITCH_STATUS_SUCCESS;
1177}
1178
1179SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
1180{
1181 if (data) {
1182 return switch_event_base_add_header(event, stack, header_name, (stack & SWITCH_STACK_NODUP) ? (char *)data : DUP(data)my_dup(data));
1183 }
1184 return SWITCH_STATUS_GENERR;
1185}
1186
1187SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_set_body(switch_event_t *event, const char *body)
1188{
1189 switch_safe_free(event->body)if (event->body) {free(event->body);event->body=((void
*)0);}
;
1190
1191 if (body) {
1192 event->body = DUP(body)my_dup(body);
1193 }
1194
1195 return SWITCH_STATUS_SUCCESS;
1196}
1197
1198SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_add_body(switch_event_t *event, const char *fmt, ...)
1199{
1200 int ret = 0;
1201 char *data;
1202
1203 va_list ap;
1204 if (fmt) {
1205 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1206 ret = switch_vasprintf(&data, fmt, ap);
1207 va_end(ap)__builtin_va_end(ap);
1208
1209 if (ret == -1) {
1210 return SWITCH_STATUS_GENERR;
1211 } else {
1212 switch_safe_free(event->body)if (event->body) {free(event->body);event->body=((void
*)0);}
;
1213 event->body = data;
1214 return SWITCH_STATUS_SUCCESS;
1215 }
1216 } else {
1217 return SWITCH_STATUS_GENERR;
1218 }
1219}
1220
1221SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_event_destroy(switch_event_t **event)
1222{
1223 switch_event_t *ep = *event;
1224 switch_event_header_t *hp, *this;
1225
1226 if (ep) {
1227 for (hp = ep->headers; hp;) {
1228 this = hp;
1229 hp = hp->next;
1230
1231 if (this->idx) {
1232 if (!this->array) {
1233 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 1233, ((void*)0)
, SWITCH_LOG_CRIT, "INDEX WITH NO ARRAY WTF?? [%s][%s]\n", this->name, this->value);
1234 } else {
1235 int i = 0;
1236
1237 for (i = 0; i < this->idx; i++) {
1238 FREE(this->array[i])if (this->array[i]) {free(this->array[i]);this->array
[i]=((void*)0);}
;
1239 }
1240 FREE(this->array)if (this->array) {free(this->array);this->array=((void
*)0);}
;
1241 }
1242 }
1243
1244 FREE(this->name)if (this->name) {free(this->name);this->name=((void*
)0);}
;
1245 FREE(this->value)if (this->value) {free(this->value);this->value=((void
*)0);}
;
1246
1247
1248#ifdef SWITCH_EVENT_RECYCLE
1249 if (switch_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != SWITCH_STATUS_SUCCESS) {
1250 FREE(this)if (this) {free(this);this=((void*)0);};
1251 }
1252#else
1253 FREE(this)if (this) {free(this);this=((void*)0);};
1254#endif
1255
1256
1257 }
1258 FREE(ep->body)if (ep->body) {free(ep->body);ep->body=((void*)0);};
1259 FREE(ep->subclass_name)if (ep->subclass_name) {free(ep->subclass_name);ep->
subclass_name=((void*)0);}
;
1260#ifdef SWITCH_EVENT_RECYCLE
1261 if (switch_queue_trypush(EVENT_RECYCLE_QUEUE, ep) != SWITCH_STATUS_SUCCESS) {
1262 FREE(ep)if (ep) {free(ep);ep=((void*)0);};
1263 }
1264#else
1265 FREE(ep)if (ep) {free(ep);ep=((void*)0);};
1266#endif
1267
1268 }
1269 *event = NULL((void*)0);
1270}
1271
1272
1273SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_event_merge(switch_event_t *event, switch_event_t *tomerge)
1274{
1275 switch_event_header_t *hp;
1276
1277 switch_assert(tomerge && event)((tomerge && event) ? (void) (0) : __assert_fail ("tomerge && event"
, "src/switch_event.c", 1277, __PRETTY_FUNCTION__))
;
1278
1279 for (hp = tomerge->headers; hp; hp = hp->next) {
1280 if (hp->idx) {
1281 int i;
1282
1283 for(i = 0; i < hp->idx; i++) {
1284 switch_event_add_header_string(event, SWITCH_STACK_PUSH, hp->name, hp->array[i]);
1285 }
1286 } else {
1287 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, hp->name, hp->value);
1288 }
1289 }
1290}
1291
1292SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_dup(switch_event_t **event, switch_event_t *todup)
1293{
1294 switch_event_header_t *hp;
1295
1296 if (switch_event_create_subclass(event, SWITCH_EVENT_CLONE, todup->subclass_name)switch_event_create_subclass_detailed("src/switch_event.c", (
const char * )(const char *)__func__, 1296, event, SWITCH_EVENT_CLONE
, todup->subclass_name)
!= SWITCH_STATUS_SUCCESS) {
1297 return SWITCH_STATUS_GENERR;
1298 }
1299
1300 (*event)->event_id = todup->event_id;
1301 (*event)->event_user_data = todup->event_user_data;
1302 (*event)->bind_user_data = todup->bind_user_data;
1303 (*event)->flags = todup->flags;
1304 for (hp = todup->headers; hp; hp = hp->next) {
1305 if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(hp->name) && __builtin_constant_p ("Event-Subclass"
) && (__s1_len = __builtin_strlen (hp->name), __s2_len
= __builtin_strlen ("Event-Subclass"), (!((size_t)(const void
*)((hp->name) + 1) - (size_t)(const void *)(hp->name) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
(("Event-Subclass") + 1) - (size_t)(const void *)("Event-Subclass"
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (hp->name
, "Event-Subclass") : (__builtin_constant_p (hp->name) &&
((size_t)(const void *)((hp->name) + 1) - (size_t)(const void
*)(hp->name) == 1) && (__s1_len = __builtin_strlen
(hp->name), __s1_len < 4) ? (__builtin_constant_p ("Event-Subclass"
) && ((size_t)(const void *)(("Event-Subclass") + 1) -
(size_t)(const void *)("Event-Subclass") == 1) ? __builtin_strcmp
(hp->name, "Event-Subclass") : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ("Event-Subclass"
); int __result = (((const unsigned char *) (const char *) (hp
->name))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
hp->name))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
hp->name))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (hp
->name))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("Event-Subclass") && ((size_t)(const void *)(("Event-Subclass"
) + 1) - (size_t)(const void *)("Event-Subclass") == 1) &&
(__s2_len = __builtin_strlen ("Event-Subclass"), __s2_len <
4) ? (__builtin_constant_p (hp->name) && ((size_t
)(const void *)((hp->name) + 1) - (size_t)(const void *)(hp
->name) == 1) ? __builtin_strcmp (hp->name, "Event-Subclass"
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (hp->name); int __result = (((const
unsigned char *) (const char *) ("Event-Subclass"))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("Event-Subclass"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ("Event-Subclass"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("Event-Subclass"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (hp->
name, "Event-Subclass")))); })
) {
1306 continue;
1307 }
1308
1309 if (hp->idx) {
1310 int i;
1311 for (i = 0; i < hp->idx; i++) {
1312 switch_event_add_header_string(*event, SWITCH_STACK_PUSH, hp->name, hp->array[i]);
1313 }
1314 } else {
1315 switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, hp->name, hp->value);
1316 }
1317 }
1318
1319 if (todup->body) {
1320 (*event)->body = DUP(todup->body)my_dup(todup->body);
1321 }
1322
1323 (*event)->key = todup->key;
1324
1325 return SWITCH_STATUS_SUCCESS;
1326}
1327
1328
1329SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_dup_reply(switch_event_t **event, switch_event_t *todup)
1330{
1331 switch_event_header_t *hp;
1332 char hname[1024] = "";
1333 char *p;
1334
1335 if (switch_event_create_subclass(event, SWITCH_EVENT_CLONE, todup->subclass_name)switch_event_create_subclass_detailed("src/switch_event.c", (
const char * )(const char *)__func__, 1335, event, SWITCH_EVENT_CLONE
, todup->subclass_name)
!= SWITCH_STATUS_SUCCESS) {
1336 return SWITCH_STATUS_GENERR;
1337 }
1338
1339 (*event)->event_id = todup->event_id;
1340 (*event)->event_user_data = todup->event_user_data;
1341 (*event)->bind_user_data = todup->bind_user_data;
1342 (*event)->flags = todup->flags;
1343
1344 for (hp = todup->headers; hp; hp = hp->next) {
1345 char *name = hp->name, *value = hp->value;
1346
1347 if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(hp->name) && __builtin_constant_p ("Event-Subclass"
) && (__s1_len = __builtin_strlen (hp->name), __s2_len
= __builtin_strlen ("Event-Subclass"), (!((size_t)(const void
*)((hp->name) + 1) - (size_t)(const void *)(hp->name) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
(("Event-Subclass") + 1) - (size_t)(const void *)("Event-Subclass"
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (hp->name
, "Event-Subclass") : (__builtin_constant_p (hp->name) &&
((size_t)(const void *)((hp->name) + 1) - (size_t)(const void
*)(hp->name) == 1) && (__s1_len = __builtin_strlen
(hp->name), __s1_len < 4) ? (__builtin_constant_p ("Event-Subclass"
) && ((size_t)(const void *)(("Event-Subclass") + 1) -
(size_t)(const void *)("Event-Subclass") == 1) ? __builtin_strcmp
(hp->name, "Event-Subclass") : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ("Event-Subclass"
); int __result = (((const unsigned char *) (const char *) (hp
->name))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
hp->name))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
hp->name))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (hp
->name))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("Event-Subclass") && ((size_t)(const void *)(("Event-Subclass"
) + 1) - (size_t)(const void *)("Event-Subclass") == 1) &&
(__s2_len = __builtin_strlen ("Event-Subclass"), __s2_len <
4) ? (__builtin_constant_p (hp->name) && ((size_t
)(const void *)((hp->name) + 1) - (size_t)(const void *)(hp
->name) == 1) ? __builtin_strcmp (hp->name, "Event-Subclass"
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (hp->name); int __result = (((const
unsigned char *) (const char *) ("Event-Subclass"))[0] - __s2
[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ("Event-Subclass"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ("Event-Subclass"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("Event-Subclass"
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (hp->
name, "Event-Subclass")))); })
) {
1348 continue;
1349 }
1350
1351 if (!strncasecmp(hp->name, "from_", 5)) {
1352 p = hp->name + 5;
1353 switch_snprintf(hname, sizeof(hname), "to_%s", p);
1354 name = hname;
1355 } else if (!strncasecmp(hp->name, "to_", 3)) {
1356 p = hp->name + 3;
1357 switch_snprintf(hname, sizeof(hname), "from_%s", p);
1358 name = hname;
1359 } else if (!strcasecmp(name, "to")) {
1360 name = "from";
1361 } else if (!strcasecmp(name, "from")) {
1362 name = "to";
1363 }
1364
1365 if (hp->idx) {
1366 int i;
1367 for (i = 0; i < hp->idx; i++) {
1368 switch_event_add_header_string(*event, SWITCH_STACK_PUSH, name, hp->array[i]);
1369 }
1370 } else {
1371 switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, name, value);
1372 }
1373 }
1374
1375 switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "replying", "true");
1376
1377 if (todup->body) {
1378 switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "orig_body", todup->body);
1379 }
1380
1381 (*event)->key = todup->key;
1382
1383 return SWITCH_STATUS_SUCCESS;
1384}
1385
1386#define SWITCH_SERIALIZED_EVENT_MAP"S(iiisss)A(S(ss))" "S(iiisss)A(S(ss))"
1387
1388SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_binary_deserialize(switch_event_t **eventp, void **data, switch_size_t len, switch_bool_t destroy)
1389{
1390 switch_event_t *event;
1391 tpl_node *tn;
1392 switch_serial_event_t e;
1393 switch_serial_event_header_t sh;
1394 int how = TPL_MEM(1 << 1);
1395
1396 switch_event_create(&event, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("src/switch_event.c", (
const char * )(const char *)__func__, 1396, &event, SWITCH_EVENT_CLONE
, ((void*)0))
;
1397 switch_assert(event)((event) ? (void) (0) : __assert_fail ("event", "src/switch_event.c"
, 1397, __PRETTY_FUNCTION__))
;
1398
1399 tn = tpl_map(SWITCH_SERIALIZED_EVENT_MAP"S(iiisss)A(S(ss))", &e, &sh);
1400
1401 if (!destroy) {
1402 how |= TPL_EXCESS_OK(1 << 3);
1403 }
1404
1405 tpl_load(tn, how, data, len);
1406
1407 tpl_unpack(tn, 0);
1408
1409 event->event_id = e.event_id;
1410 event->priority = e.priority;
1411 event->flags = e.flags;
1412
1413 event->owner = e.owner;
1414 event->subclass_name = e.subclass_name;
1415 event->body = e.body;
1416
1417
1418 while(tpl_unpack(tn, 1)) {
1419 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, sh.name, sh.value);
1420 }
1421
1422 *eventp = event;
1423
1424 tpl_free(tn);
1425
1426 if (destroy) {
1427 free(*data);
1428 }
1429
1430 *data = NULL((void*)0);
1431
1432 return SWITCH_STATUS_SUCCESS;
1433
1434}
1435
1436SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_binary_serialize(switch_event_t *event, void **data, switch_size_t *len)
1437{
1438 tpl_node *tn;
1439 switch_serial_event_t e;
1440 switch_serial_event_header_t sh;
1441 switch_event_header_t *eh;
1442 int how = TPL_MEM(1 << 1);
1443
1444 e.event_id = event->event_id;
1445 e.priority = event->priority;
1446 e.flags = event->flags;
1447
1448 e.owner = event->owner;
1449 e.subclass_name = event->subclass_name;
1450 e.body = event->body;
1451
1452 tn = tpl_map(SWITCH_SERIALIZED_EVENT_MAP"S(iiisss)A(S(ss))", &e, &sh);
1453
1454 tpl_pack(tn, 0);
1455
1456 for (eh = event->headers; eh; eh = eh->next) {
1457 if (eh->idx) continue; // no arrays yet
1458
1459 sh.name = eh->name;
1460 sh.value = eh->value;
1461
1462 tpl_pack(tn, 1);
1463 }
1464
1465 if (*len > 0) {
1466 how |= TPL_PREALLOCD(1 << 2);
1467 }
1468
1469 tpl_dump(tn, how, data, len);
1470
1471 tpl_free(tn);
1472
1473 return SWITCH_STATUS_SUCCESS;
1474}
1475
1476
1477SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_serialize(switch_event_t *event, char **str, switch_bool_t encode)
1478{
1479 switch_size_t len = 0;
1480 switch_event_header_t *hp;
1481 switch_size_t llen = 0, dlen = 0, blocksize = 512, encode_len = 1536, new_len = 0;
1482 char *buf;
1483 char *encode_buf = NULL((void*)0); /* used for url encoding of variables to make sure unsafe things stay out of the serialized copy */
1484
1485 *str = NULL((void*)0);
1486
1487 dlen = blocksize * 2;
1488
1489 if (!(buf = malloc(dlen))) {
1490 abort();
1491 }
1492
1493 /* go ahead and give ourselves some space to work with, should save a few reallocs */
1494 if (!(encode_buf = malloc(encode_len))) {
1495 abort();
1496 }
1497
1498 /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "hit serialized!.\n"); */
1499 for (hp = event->headers; hp; hp = hp->next) {
1500 /*
1501 * grab enough memory to store 3x the string (url encode takes one char and turns it into %XX)
1502 * so we could end up with a string that is 3 times the originals length, unlikely but rather
1503 * be safe than destroy the string, also add one for the null. And try to be smart about using
1504 * the memory, allocate and only reallocate if we need more. This avoids an alloc, free CPU
1505 * destroying loop.
1506 */
1507
1508 if (hp->idx) {
1509 int i;
1510 new_len = 0;
1511 for(i = 0; i < hp->idx; i++) {
1512 new_len += (strlen(hp->array[i]) * 3) + 1;
1513 }
1514 } else {
1515 new_len = (strlen(hp->value) * 3) + 1;
1516 }
1517
1518 if (encode_len < new_len) {
1519 char *tmp;
1520
1521 /* keep track of the size of our allocation */
1522 encode_len = new_len;
1523
1524 if (!(tmp = realloc(encode_buf, encode_len))) {
1525 abort();
1526 }
1527
1528 encode_buf = tmp;
1529 }
1530
1531 /* handle any bad things in the string like newlines : etc that screw up the serialized format */
1532
1533
1534 if (encode) {
1535 switch_url_encode(hp->value, encode_buf, encode_len);
1536 } else {
1537 switch_snprintf(encode_buf, encode_len, "[%s]", hp->value);
1538 }
1539
1540
1541 llen = strlen(hp->name) + strlen(encode_buf) + 8;
1542
1543 if ((len + llen) > dlen) {
1544 char *m = buf;
1545 dlen += (blocksize + (len + llen));
1546 if (!(buf = realloc(buf, dlen))) {
1547 buf = m;
1548 abort();
1549 }
1550 }
1551
1552 switch_snprintf(buf + len, dlen - len, "%s: %s\n", hp->name, *encode_buf == '\0' ? "_undef_" : encode_buf);
1553 len = strlen(buf);
1554 }
1555
1556 /* we are done with the memory we used for encoding, give it back */
1557 switch_safe_free(encode_buf)if (encode_buf) {free(encode_buf);encode_buf=((void*)0);};
1558
1559 if (event->body) {
1560 int blen = (int) strlen(event->body);
1561 llen = blen;
1562
1563 if (blen) {
1564 llen += 25;
1565 } else {
1566 llen += 5;
1567 }
1568
1569 if ((len + llen) > dlen) {
1570 char *m = buf;
1571 dlen += (blocksize + (len + llen));
1572 if (!(buf = realloc(buf, dlen))) {
1573 buf = m;
1574 abort();
1575 }
1576 }
1577
1578 if (blen) {
1579 switch_snprintf(buf + len, dlen - len, "Content-Length: %d\n\n%s", blen, event->body);
1580 } else {
1581 switch_snprintf(buf + len, dlen - len, "\n");
1582 }
1583 } else {
1584 switch_snprintf(buf + len, dlen - len, "\n");
1585 }
1586
1587 *str = buf;
1588
1589 return SWITCH_STATUS_SUCCESS;
1590}
1591
1592SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_create_array_pair(switch_event_t **event, char **names, char **vals, int len)
1593{
1594 int r;
1595 char *name, *val;
1596
1597 switch_event_create(event, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("src/switch_event.c", (
const char * )(const char *)__func__, 1597, event, SWITCH_EVENT_CLONE
, ((void*)0))
;
1598
1599 for (r = 0; r < len; r++) {
1600 val = switch_str_nil(vals[r])(vals[r] ? vals[r] : "");
1601 name = names[r];
1602
1603 if (zstr(name)_zstr(name)) {
1604 name = "Unknown";
1605 }
1606
1607 switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, name, val);
1608 }
1609
1610 return SWITCH_STATUS_SUCCESS;
1611
1612}
1613
1614SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_create_brackets(char *data, char a, char b, char c, switch_event_t **event, char **new_data, switch_bool_t dup)
1615{
1616 char *vdata, *vdatap = NULL((void*)0);
1617 char *end, *check_a, *check_b;
1618 switch_event_t *e = *event;
1619 char *var_array[1024] = { 0 };
1620 int var_count = 0;
1621 char *next = NULL((void*)0), *vnext = NULL((void*)0);
1622
1623 if (dup) {
1624 vdatap = strdup(data)(__extension__ (__builtin_constant_p (data) && ((size_t
)(const void *)((data) + 1) - (size_t)(const void *)(data) ==
1) ? (((const char *) (data))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen (data) + 1
; char *__retval = (char *) malloc (__len); if (__retval != (
(void*)0)) __retval = (char *) memcpy (__retval, data, __len)
; __retval; })) : __strdup (data)))
;
1625 vdata = vdatap;
1626 } else {
1627 vdata = data;
1628 }
1629
1630 end = switch_find_end_paren(vdata, a, b);
1631
1632 check_a = end;
1633
1634 while (check_a && (check_b = switch_strchr_strict(check_a, a, " "))) {
1635 if ((check_b = switch_find_end_paren(check_b, a, b))) {
1636 check_a = check_b;
1637 }
1638 }
1639
1640 if (check_a) end = check_a;
1641
1642 if (end) {
1643 next = end;
1644 vdata++;
1645 *end++ = '\0';
1646 } else {
1647 if (dup) {
1648 free(vdatap);
1649 }
1650 return SWITCH_STATUS_FALSE;
1651 }
1652
1653 if (!e) {
1654 switch_event_create_plain(&e, SWITCH_EVENT_CHANNEL_DATA);
1655 }
1656
1657
1658 for (;;) {
1659 if (next) {
1660 char *pnext;
1661
1662 *next++ = '\0';
1663
1664 if ((pnext = switch_strchr_strict(next, a, " "))) {
1665 next = pnext + 1;
1666 }
1667
1668 vnext = switch_find_end_paren(next, a, b);
1669 next = NULL((void*)0);
1670 }
1671
1672
1673 if (vdata) {
1674 if (*vdata == '^' && *(vdata + 1) == '^') {
1675 vdata += 2;
1676 c = *vdata++;
1677 }
1678 }
1679
1680 if ((var_count = switch_separate_string(vdata, c, var_array, (sizeof(var_array) / sizeof(var_array[0]))))) {
1681 int x = 0;
1682 for (x = 0; x < var_count; x++) {
1683 char *inner_var_array[2] = { 0 };
1684 int inner_var_count;
1685
1686 if ((inner_var_count = switch_separate_string(var_array[x], '=',
1687 inner_var_array, (sizeof(inner_var_array) / sizeof(inner_var_array[0])))) == 2) {
1688 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 1688, ((void*)0)
, SWITCH_LOG_DEBUG, "Parsing variable [%s]=[%s]\n", inner_var_array[0], inner_var_array[1]);
1689 switch_event_add_header_string(e, SWITCH_STACK_BOTTOM, inner_var_array[0], inner_var_array[1]);
1690 }
1691 }
1692 }
1693
1694 if (vnext) {
1695 vdata = vnext;
1696 vnext = NULL((void*)0);
1697 } else {
1698 break;
1699 }
1700
1701 }
1702
1703 *event = e;
1704
1705 if (dup) {
1706 *new_data = strdup(end)(__extension__ (__builtin_constant_p (end) && ((size_t
)(const void *)((end) + 1) - (size_t)(const void *)(end) == 1
) ? (((const char *) (end))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (end) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, end, __len); __retval
; })) : __strdup (end)))
;
1707 free(vdatap);
1708 } else {
1709 *new_data = end;
1710 }
1711
1712 return SWITCH_STATUS_SUCCESS;
1713
1714}
1715
1716
1717
1718SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_create_json(switch_event_t **event, const char *json)
1719{
1720 switch_event_t *new_event;
1721 cJSON *cj, *cjp;
1722
1723
1724 if (!(cj = cJSON_Parse(json))) {
1725 return SWITCH_STATUS_FALSE;
1726 }
1727
1728 if (switch_event_create(&new_event, SWITCH_EVENT_CLONE)switch_event_create_subclass_detailed("src/switch_event.c", (
const char * )(const char *)__func__, 1728, &new_event, SWITCH_EVENT_CLONE
, ((void*)0))
!= SWITCH_STATUS_SUCCESS) {
1729 cJSON_Delete(cj);
1730 return SWITCH_STATUS_FALSE;
1731 }
1732
1733 for (cjp = cj->child; cjp; cjp = cjp->next) {
1734 char *name = cjp->string;
1735 char *value = cjp->valuestring;
1736
1737 if (name && value) {
1738 if (!strcasecmp(name, "_body")) {
1739 switch_event_add_body(new_event, value, SWITCH_VA_NONE"%s", "");
1740 } else {
1741 if (!strcasecmp(name, "event-name")) {
1742 switch_event_del_header(new_event, "event-name")switch_event_del_header_val(new_event, "event-name", ((void*)
0))
;
1743 switch_name_event(value, &new_event->event_id);
1744 }
1745
1746 switch_event_add_header_string(new_event, SWITCH_STACK_BOTTOM, name, value);
1747 }
1748
1749 } else if (name) {
1750 if (cjp->type == cJSON_Array5) {
1751 int i, x = cJSON_GetArraySize(cjp);
1752
1753 for (i = 0; i < x; i++) {
1754 cJSON *item = cJSON_GetArrayItem(cjp, i);
1755
1756 if (item && item->type == cJSON_String4 && item->valuestring) {
1757 switch_event_add_header_string(new_event, SWITCH_STACK_PUSH, name, item->valuestring);
1758 }
1759 }
1760 }
1761 }
1762 }
1763
1764 cJSON_Delete(cj);
1765 *event = new_event;
1766 return SWITCH_STATUS_SUCCESS;
1767}
1768
1769SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_serialize_json_obj(switch_event_t *event, cJSON **json)
1770{
1771 switch_event_header_t *hp;
1772 cJSON *cj;
1773
1774 cj = cJSON_CreateObject();
1775
1776 for (hp = event->headers; hp; hp = hp->next) {
1777 if (hp->idx) {
1778 cJSON *a = cJSON_CreateArray();
1779 int i;
1780
1781 for(i = 0; i < hp->idx; i++) {
1782 cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i]));
1783 }
1784
1785 cJSON_AddItemToObject(cj, hp->name, a);
1786
1787 } else {
1788 cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
1789 }
1790 }
1791
1792 if (event->body) {
1793 int blen = (int) strlen(event->body);
1794 char tmp[25];
1795
1796 switch_snprintf(tmp, sizeof(tmp), "%d", blen);
1797
1798 cJSON_AddItemToObject(cj, "Content-Length", cJSON_CreateString(tmp));
1799 cJSON_AddItemToObject(cj, "_body", cJSON_CreateString(event->body));
1800 }
1801
1802 *json = cj;
1803
1804 return SWITCH_STATUS_SUCCESS;
1805}
1806
1807SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_serialize_json(switch_event_t *event, char **str)
1808{
1809
1810 cJSON *cj;
1811 *str = NULL((void*)0);
1812
1813 if (switch_event_serialize_json_obj(event, &cj) == SWITCH_STATUS_SUCCESS) {
1814 *str = cJSON_PrintUnformatted(cj);
1815 cJSON_Delete(cj);
1816
1817 return SWITCH_STATUS_SUCCESS;
1818 }
1819
1820 return SWITCH_STATUS_FALSE;
1821}
1822
1823static switch_xml_t add_xml_header(switch_xml_t xml, char *name, char *value, int offset)
1824{
1825 switch_xml_t header = switch_xml_add_child_d(xml, name, offset)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ (
__builtin_constant_p (name) && ((size_t)(const void *
)((name) + 1) - (size_t)(const void *)(name) == 1) ? (((const
char *) (name))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t
) 1) : ({ size_t __len = strlen (name) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, name, __len); __retval; })) : __strdup
(name))), offset), SWITCH_XML_NAMEM)
;
1826
1827 if (header) {
1828 switch_size_t encode_len = (strlen(value) * 3) + 1;
1829 char *encode_buf = malloc(encode_len);
1830
1831 switch_assert(encode_buf)((encode_buf) ? (void) (0) : __assert_fail ("encode_buf", "src/switch_event.c"
, 1831, __PRETTY_FUNCTION__))
;
1832
1833 memset(encode_buf, 0, encode_len);
1834 switch_url_encode((char *) value, encode_buf, encode_len);
1835 switch_xml_set_txt_d(header, encode_buf)switch_xml_set_flag(switch_xml_set_txt(header, (__extension__
(__builtin_constant_p (encode_buf) && ((size_t)(const
void *)((encode_buf) + 1) - (size_t)(const void *)(encode_buf
) == 1) ? (((const char *) (encode_buf))[0] == '\0' ? (char *
) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (
encode_buf) + 1; char *__retval = (char *) malloc (__len); if
(__retval != ((void*)0)) __retval = (char *) memcpy (__retval
, encode_buf, __len); __retval; })) : __strdup (encode_buf)))
), SWITCH_XML_TXTM)
;
1836 free(encode_buf);
1837 }
1838
1839 return header;
1840}
1841
1842SWITCH_DECLARE(switch_xml_t)__attribute__((visibility("default"))) switch_xml_t switch_event_xmlize(switch_event_t *event, const char *fmt,...)
1843{
1844 switch_event_header_t *hp;
1845 char *data = NULL((void*)0), *body = NULL((void*)0);
1846 int ret = 0;
1847 switch_xml_t xml = NULL((void*)0);
1848 uint32_t off = 0;
1849 va_list ap;
1850 switch_xml_t xheaders = NULL((void*)0);
1851
1852 if (!(xml = switch_xml_new("event"))) {
1
Assuming 'xml' is not null
2
Taking false branch
1853 return xml;
1854 }
1855
1856 if (!zstr(fmt)_zstr(fmt)) {
3
Taking true branch
1857 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1858#ifdef HAVE_VASPRINTF1
1859 ret = vasprintf(&data, fmt, ap);
1860#else
1861 data = (char *) malloc(2048);
1862 if (!data) {
1863 va_end(ap)__builtin_va_end(ap);
1864 return NULL((void*)0);
1865 }
1866 ret = vsnprintf(data, 2048, fmt, ap);
1867#endif
1868 va_end(ap)__builtin_va_end(ap);
1869 if (ret == -1) {
4
Taking false branch
1870#ifndef HAVE_VASPRINTF1
1871 free(data);
1872#endif
1873 return NULL((void*)0);
1874 }
1875 }
1876
1877 if ((xheaders = switch_xml_add_child_d(xml, "headers", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ (
__builtin_constant_p ("headers") && ((size_t)(const void
*)(("headers") + 1) - (size_t)(const void *)("headers") == 1
) ? (((const char *) ("headers"))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ("headers"
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, "headers"
, __len); __retval; })) : __strdup ("headers"))), off++), SWITCH_XML_NAMEM
)
)) {
5
Within the expansion of the macro 'switch_xml_add_child_d':
a
Memory is allocated
b
Assuming '__retval' is not equal to null
c
Potential leak of memory pointed to by '__retval'
1878 int hoff = 0;
1879 for (hp = event->headers; hp; hp = hp->next) {
1880
1881 if (hp->idx) {
1882 int i;
1883 for (i = 0; i < hp->idx; i++) {
1884 add_xml_header(xheaders, hp->name, hp->array[i], hoff++);
1885 }
1886 } else {
1887 add_xml_header(xheaders, hp->name, hp->value, hoff++);
1888 }
1889 }
1890 }
1891
1892 if (!zstr(data)_zstr(data)) {
1893 body = data;
1894 } else if (event->body) {
1895 body = event->body;
1896 }
1897
1898 if (body) {
1899 int blen = (int) strlen(body);
1900 char blena[25];
1901 switch_snprintf(blena, sizeof(blena), "%d", blen);
1902 if (blen) {
1903 switch_xml_t xbody = NULL((void*)0);
1904
1905 add_xml_header(xml, "Content-Length", blena, off++);
1906 if ((xbody = switch_xml_add_child_d(xml, "body", off++)switch_xml_set_flag(switch_xml_add_child(xml, (__extension__ (
__builtin_constant_p ("body") && ((size_t)(const void
*)(("body") + 1) - (size_t)(const void *)("body") == 1) ? ((
(const char *) ("body"))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen ("body") + 1; char
*__retval = (char *) malloc (__len); if (__retval != ((void*
)0)) __retval = (char *) memcpy (__retval, "body", __len); __retval
; })) : __strdup ("body"))), off++), SWITCH_XML_NAMEM)
)) {
1907 switch_xml_set_txt_d(xbody, body)switch_xml_set_flag(switch_xml_set_txt(xbody, (__extension__ (
__builtin_constant_p (body) && ((size_t)(const void *
)((body) + 1) - (size_t)(const void *)(body) == 1) ? (((const
char *) (body))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t
) 1) : ({ size_t __len = strlen (body) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, body, __len); __retval; })) : __strdup
(body)))), SWITCH_XML_TXTM)
;
1908 }
1909 }
1910 }
1911
1912 if (data) {
1913 free(data);
1914 }
1915
1916 return xml;
1917}
1918
1919SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_event_prep_for_delivery_detailed(const char *file, const char *func, int line, switch_event_t *event)
1920{
1921 switch_time_exp_t tm;
1922 char date[80] = "";
1923 switch_size_t retsize;
1924 switch_time_t ts = switch_micro_time_now();
1925
1926 switch_mutex_lock(EVENT_QUEUE_MUTEX);
1927 EVENT_SEQUENCE_NR++;
1928 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
1929
1930
1931 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Event-Name", switch_event_name(event->event_id));
1932 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Core-UUID", switch_core_get_uuid());
1933 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Hostname", switch_core_get_hostname());
1934 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Switchname", switch_core_get_switchname());
1935 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-IPv4", guess_ip_v4);
1936 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-IPv6", guess_ip_v6);
1937
1938 switch_time_exp_lt(&tm, ts);
1939 switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
1940 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Event-Date-Local", date);
1941 switch_rfc822_date(date, ts);
1942 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Event-Date-GMT", date);
1943 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Date-Timestamp", "%" SWITCH_UINT64_T_FMT"lu", (uint64_t) ts);
1944 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Event-Calling-File", switch_cut_path(file));
1945 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Event-Calling-Function", func);
1946 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Calling-Line-Number", "%d", line);
1947 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Sequence", "%" SWITCH_UINT64_T_FMT"lu", (uint64_t) EVENT_SEQUENCE_NR);
1948
1949
1950}
1951
1952SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_fire_detailed(const char *file, const char *func, int line, switch_event_t **event, void *user_data)
1953{
1954
1955 switch_assert(BLOCK != NULL)((BLOCK != ((void*)0)) ? (void) (0) : __assert_fail ("BLOCK != ((void*)0)"
, "src/switch_event.c", 1955, __PRETTY_FUNCTION__))
;
1956 switch_assert(RUNTIME_POOL != NULL)((RUNTIME_POOL != ((void*)0)) ? (void) (0) : __assert_fail ("RUNTIME_POOL != ((void*)0)"
, "src/switch_event.c", 1956, __PRETTY_FUNCTION__))
;
1957 switch_assert(EVENT_QUEUE_MUTEX != NULL)((EVENT_QUEUE_MUTEX != ((void*)0)) ? (void) (0) : __assert_fail
("EVENT_QUEUE_MUTEX != ((void*)0)", "src/switch_event.c", 1957
, __PRETTY_FUNCTION__))
;
1958 switch_assert(RUNTIME_POOL != NULL)((RUNTIME_POOL != ((void*)0)) ? (void) (0) : __assert_fail ("RUNTIME_POOL != ((void*)0)"
, "src/switch_event.c", 1958, __PRETTY_FUNCTION__))
;
1959
1960 if (SYSTEM_RUNNING <= 0) {
1961 /* sorry we're closed */
1962 switch_event_destroy(event);
1963 return SWITCH_STATUS_SUCCESS;
1964 }
1965
1966 if (user_data) {
1967 (*event)->event_user_data = user_data;
1968 }
1969
1970
1971
1972 if (runtime.events_use_dispatch) {
1973 check_dispatch();
1974
1975 if (switch_event_queue_dispatch_event(event) != SWITCH_STATUS_SUCCESS) {
1976 switch_event_destroy(event);
1977 return SWITCH_STATUS_FALSE;
1978 }
1979 } else {
1980 switch_event_deliver_thread_pool(event);
1981 }
1982
1983 return SWITCH_STATUS_SUCCESS;
1984}
1985
1986SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_bind_removable(const char *id, switch_event_types_t event, const char *subclass_name,
1987 switch_event_callback_t callback, void *user_data, switch_event_node_t **node)
1988{
1989 switch_event_node_t *event_node;
1990 switch_event_subclass_t *subclass = NULL((void*)0);
1991
1992 switch_assert(BLOCK != NULL)((BLOCK != ((void*)0)) ? (void) (0) : __assert_fail ("BLOCK != ((void*)0)"
, "src/switch_event.c", 1992, __PRETTY_FUNCTION__))
;
1993 switch_assert(RUNTIME_POOL != NULL)((RUNTIME_POOL != ((void*)0)) ? (void) (0) : __assert_fail ("RUNTIME_POOL != ((void*)0)"
, "src/switch_event.c", 1993, __PRETTY_FUNCTION__))
;
1994
1995 if (node) {
1996 *node = NULL((void*)0);
1997 }
1998
1999 if (subclass_name) {
2000 if (!(subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name))) {
2001 switch_event_reserve_subclass_detailed(id, subclass_name);
2002 subclass = switch_core_hash_find(CUSTOM_HASH, subclass_name);
2003 subclass->bind = 1;
2004 }
2005 if (!subclass) {
2006 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 2006, ((void*)0)
, SWITCH_LOG_ERROR, "Could not reserve subclass. '%s'\n", subclass_name);
2007 return SWITCH_STATUS_FALSE;
2008 }
2009 }
2010
2011 if (event <= SWITCH_EVENT_ALL) {
2012 switch_zmalloc(event_node, sizeof(*event_node))(void)((((event_node = calloc(1, (sizeof(*event_node))))) ? (
void) (0) : __assert_fail ("(event_node = calloc(1, (sizeof(*event_node))))"
, "src/switch_event.c", 2012, __PRETTY_FUNCTION__)),event_node
)
;
2013 switch_thread_rwlock_wrlock(RWLOCK);
2014 switch_mutex_lock(BLOCK);
2015 /* <LOCKED> ----------------------------------------------- */
2016 event_node->id = DUP(id)my_dup(id);
2017 event_node->event_id = event;
2018 if (subclass_name) {
2019 event_node->subclass_name = DUP(subclass_name)my_dup(subclass_name);
2020 }
2021 event_node->callback = callback;
2022 event_node->user_data = user_data;
2023
2024 if (EVENT_NODES[event]) {
2025 event_node->next = EVENT_NODES[event];
2026 }
2027
2028 EVENT_NODES[event] = event_node;
2029 switch_mutex_unlock(BLOCK);
2030 switch_thread_rwlock_unlock(RWLOCK);
2031 /* </LOCKED> ----------------------------------------------- */
2032
2033 if (node) {
2034 *node = event_node;
2035 }
2036
2037 return SWITCH_STATUS_SUCCESS;
2038 }
2039
2040 return SWITCH_STATUS_MEMERR;
2041}
2042
2043
2044SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_bind(const char *id, switch_event_types_t event, const char *subclass_name,
2045 switch_event_callback_t callback, void *user_data)
2046{
2047 return switch_event_bind_removable(id, event, subclass_name, callback, user_data, NULL((void*)0));
2048}
2049
2050
2051SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_unbind_callback(switch_event_callback_t callback)
2052{
2053 switch_event_node_t *n, *np, *lnp = NULL((void*)0);
2054 switch_status_t status = SWITCH_STATUS_FALSE;
2055 int id;
2056
2057 switch_thread_rwlock_wrlock(RWLOCK);
2058 switch_mutex_lock(BLOCK);
2059 /* <LOCKED> ----------------------------------------------- */
2060 for (id = 0; id <= SWITCH_EVENT_ALL; id++) {
2061 lnp = NULL((void*)0);
2062
2063 for (np = EVENT_NODES[id]; np;) {
2064 n = np;
2065 np = np->next;
2066 if (n->callback == callback) {
2067 if (lnp) {
2068 lnp->next = n->next;
2069 } else {
2070 EVENT_NODES[n->event_id] = n->next;
2071 }
2072
2073 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 2073, ((void*)0)
, SWITCH_LOG_NOTICE, "Event Binding deleted for %s:%s\n", n->id, switch_event_name(n->event_id));
2074 FREE(n->subclass_name)if (n->subclass_name) {free(n->subclass_name);n->subclass_name
=((void*)0);}
;
2075 FREE(n->id)if (n->id) {free(n->id);n->id=((void*)0);};
2076 FREE(n)if (n) {free(n);n=((void*)0);};
2077 status = SWITCH_STATUS_SUCCESS;
2078 } else {
2079 lnp = n;
2080 }
2081 }
2082 }
2083 switch_mutex_unlock(BLOCK);
2084 switch_thread_rwlock_unlock(RWLOCK);
2085 /* </LOCKED> ----------------------------------------------- */
2086
2087 return status;
2088}
2089
2090
2091
2092SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_unbind(switch_event_node_t **node)
2093{
2094 switch_event_node_t *n, *np, *lnp = NULL((void*)0);
2095 switch_status_t status = SWITCH_STATUS_FALSE;
2096
2097 n = *node;
2098
2099 if (!n) {
2100 return status;
2101 }
2102
2103 switch_thread_rwlock_wrlock(RWLOCK);
2104 switch_mutex_lock(BLOCK);
2105 /* <LOCKED> ----------------------------------------------- */
2106 for (np = EVENT_NODES[n->event_id]; np; np = np->next) {
2107 if (np == n) {
2108 if (lnp) {
2109 lnp->next = n->next;
2110 } else {
2111 EVENT_NODES[n->event_id] = n->next;
2112 }
2113 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 2113, ((void*)0)
, SWITCH_LOG_NOTICE, "Event Binding deleted for %s:%s\n", n->id, switch_event_name(n->event_id));
2114 FREE(n->subclass_name)if (n->subclass_name) {free(n->subclass_name);n->subclass_name
=((void*)0);}
;
2115 FREE(n->id)if (n->id) {free(n->id);n->id=((void*)0);};
2116 FREE(n)if (n) {free(n);n=((void*)0);};
2117 *node = NULL((void*)0);
2118 status = SWITCH_STATUS_SUCCESS;
2119 break;
2120 }
2121 lnp = np;
2122 }
2123 switch_mutex_unlock(BLOCK);
2124 switch_thread_rwlock_unlock(RWLOCK);
2125 /* </LOCKED> ----------------------------------------------- */
2126
2127 return status;
2128}
2129
2130SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_create_pres_in_detailed(char *file, char *func, int line,
2131 const char *proto, const char *login,
2132 const char *from, const char *from_domain,
2133 const char *status, const char *event_type,
2134 const char *alt_event_type, int event_count,
2135 const char *unique_id, const char *channel_state,
2136 const char *answer_state, const char *call_direction)
2137{
2138 switch_event_t *pres_event;
2139
2140 if (switch_event_create_subclass(&pres_event, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY)switch_event_create_subclass_detailed("src/switch_event.c", (
const char * )(const char *)__func__, 2140, &pres_event, SWITCH_EVENT_PRESENCE_IN
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2141 switch_event_add_header_string(pres_event, SWITCH_STACK_TOP, "proto", proto);
2142 switch_event_add_header_string(pres_event, SWITCH_STACK_TOP, "login", login);
2143 switch_event_add_header(pres_event, SWITCH_STACK_TOP, "from", "%s@%s", from, from_domain);
2144 switch_event_add_header_string(pres_event, SWITCH_STACK_TOP, "status", status);
2145 switch_event_add_header_string(pres_event, SWITCH_STACK_TOP, "event_type", event_type);
2146 switch_event_add_header_string(pres_event, SWITCH_STACK_TOP, "alt_event_type", alt_event_type);
2147 switch_event_add_header(pres_event, SWITCH_STACK_TOP, "event_count", "%d", event_count);
2148 switch_event_add_header_string(pres_event, SWITCH_STACK_TOP, "unique-id", alt_event_type);
2149 switch_event_add_header_string(pres_event, SWITCH_STACK_TOP, "channel-state", channel_state);
2150 switch_event_add_header_string(pres_event, SWITCH_STACK_TOP, "answer-state", answer_state);
2151 switch_event_add_header_string(pres_event, SWITCH_STACK_TOP, "presence-call-direction", call_direction);
2152 switch_event_fire_detailed(file, func, line, &pres_event, NULL((void*)0));
2153 return SWITCH_STATUS_SUCCESS;
2154 }
2155 return SWITCH_STATUS_MEMERR;
2156}
2157
2158#define resize(l){char *dp;olen += (len + l + block);cpos = c - data;if ((dp =
realloc(data, olen))) { data = dp; c = data + cpos; memset(c
, 0, olen - cpos); }}
{\
2159char *dp;\
2160olen += (len + l + block);\
2161cpos = c - data;\
2162if ((dp = realloc(data, olen))) {\
2163 data = dp;\
2164 c = data + cpos;\
2165 memset(c, 0, olen - cpos);\
2166 }} \
2167
2168SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_event_expand_headers_check(switch_event_t *event, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur)
2169{
2170 char *p, *c = NULL((void*)0);
2171 char *data, *indup, *endof_indup;
2172 size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128;
2173 const char *sub_val = NULL((void*)0);
2174 char *cloned_sub_val = NULL((void*)0), *expanded_sub_val = NULL((void*)0);
2175 char *func_val = NULL((void*)0);
2176 int nv = 0;
2177 char *gvar = NULL((void*)0), *sb = NULL((void*)0);
2178
2179 if (recur > 100) {
2180 return (char *) in;
2181 }
2182
2183 if (zstr(in)_zstr(in)) {
2184 return (char *) in;
2185 }
2186
2187 nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in);
2188
2189 if (!nv) {
2190 return (char *) in;
2191 }
2192
2193 nv = 0;
2194 olen = strlen(in) + 1;
2195 indup = strdup(in)(__extension__ (__builtin_constant_p (in) && ((size_t
)(const void *)((in) + 1) - (size_t)(const void *)(in) == 1) ?
(((const char *) (in))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (in) + 1; char *__retval
= (char *) malloc (__len); if (__retval != ((void*)0)) __retval
= (char *) memcpy (__retval, in, __len); __retval; })) : __strdup
(in)))
;
2196 endof_indup = end_of_p(indup)(*indup == '\0' ? indup : indup + strlen(indup) - 1) + 1;
2197
2198 if ((data = malloc(olen))) {
2199 memset(data, 0, olen);
2200 c = data;
2201 for (p = indup; p && p < endof_indup && *p; p++) {
2202 int global = 0;
2203 vtype = 0;
2204
2205 if (*p == '\\') {
2206 if (*(p + 1) == '$') {
2207 nv = 1;
2208 p++;
2209 if (*(p + 1) == '$') {
2210 p++;
2211 }
2212 } else if (*(p + 1) == '\'') {
2213 p++;
2214 continue;
2215 } else if (*(p + 1) == '\\') {
2216 *c++ = *p++;
2217 len++;
2218 continue;
2219 }
2220 }
2221
2222 if (*p == '$' && !nv) {
2223 if (*(p + 1) == '$') {
2224 p++;
2225 global++;
2226 }
2227
2228 if (*(p + 1)) {
2229 if (*(p + 1) == '{') {
2230 vtype = global ? 3 : 1;
2231 } else {
2232 nv = 1;
2233 }
2234 } else {
2235 nv = 1;
2236 }
2237 }
2238
2239 if (nv) {
2240 *c++ = *p;
2241 len++;
2242 nv = 0;
2243 continue;
2244 }
2245
2246 if (vtype) {
2247 char *s = p, *e, *vname, *vval = NULL((void*)0);
2248 size_t nlen;
2249
2250 s++;
2251
2252 if ((vtype == 1 || vtype == 3) && *s == '{') {
2253 br = 1;
2254 s++;
2255 }
2256
2257 e = s;
2258 vname = s;
2259 while (*e) {
2260 if (br == 1 && *e == '}') {
2261 br = 0;
2262 *e++ = '\0';
2263 break;
2264 }
2265
2266 if (br > 0) {
2267 if (e != s && *e == '{') {
2268 br++;
2269 } else if (br > 1 && *e == '}') {
2270 br--;
2271 }
2272 }
2273
2274 e++;
2275 }
2276 p = e > endof_indup ? endof_indup : e;
2277
2278 vval = NULL((void*)0);
2279 for(sb = vname; sb && *sb; sb++) {
2280 if (*sb == ' ') {
2281 vval = sb;
2282 break;
2283 } else if (*sb == '(') {
2284 vval = sb;
2285 br = 1;
2286 break;
2287 }
2288 }
2289
2290 if (vval) {
2291 e = vval - 1;
2292 *vval++ = '\0';
2293
2294 while (*e == ' ') {
2295 *e-- = '\0';
2296 }
2297 e = vval;
2298
2299 while (e && *e) {
2300 if (*e == '(') {
2301 br++;
2302 } else if (br > 1 && *e == ')') {
2303 br--;
2304 } else if (br == 1 && *e == ')') {
2305 *e = '\0';
2306 break;
2307 }
2308 e++;
2309 }
2310
2311 vtype = 2;
2312 }
2313
2314 if (vtype == 1 || vtype == 3) {
2315 char *expanded = NULL((void*)0);
2316 int offset = 0;
2317 int ooffset = 0;
2318 char *ptr;
2319 int idx = -1;
2320
2321 if ((expanded = switch_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) {
2322 expanded = NULL((void*)0);
2323 } else {
2324 vname = expanded;
2325 }
2326 if ((ptr = strchr(vname, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(vname) && (':') == '\0' ? (char *) __rawmemchr (vname
, ':') : __builtin_strchr (vname, ':')))
)) {
2327 *ptr++ = '\0';
2328 offset = atoi(ptr);
2329 if ((ptr = strchr(ptr, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(ptr) && (':') == '\0' ? (char *) __rawmemchr (ptr, ':'
) : __builtin_strchr (ptr, ':')))
)) {
2330 ptr++;
2331 ooffset = atoi(ptr);
2332 }
2333 }
2334
2335 if ((ptr = strchr(vname, '[')(__extension__ (__builtin_constant_p ('[') && !__builtin_constant_p
(vname) && ('[') == '\0' ? (char *) __rawmemchr (vname
, '[') : __builtin_strchr (vname, '[')))
) && strchr(ptr, ']')(__extension__ (__builtin_constant_p (']') && !__builtin_constant_p
(ptr) && (']') == '\0' ? (char *) __rawmemchr (ptr, ']'
) : __builtin_strchr (ptr, ']')))
) {
2336 *ptr++ = '\0';
2337 idx = atoi(ptr);
2338 }
2339
2340 if (vtype == 3 || !(sub_val = switch_event_get_header_idx(event, vname, idx))) {
2341 switch_safe_free(gvar)if (gvar) {free(gvar);gvar=((void*)0);};
2342 if ((gvar = switch_core_get_variable_dup(vname))) {
2343 sub_val = gvar;
2344 }
2345
2346 if (var_list && !switch_event_check_permission_list(var_list, vname)) {
2347 sub_val = "<Variable Expansion Permission Denied>";
2348 }
2349
2350
2351 if ((expanded_sub_val = switch_event_expand_headers_check(event, sub_val, var_list, api_list, recur+1)) == sub_val) {
2352 expanded_sub_val = NULL((void*)0);
2353 } else {
2354 sub_val = expanded_sub_val;
2355 }
2356 }
2357
2358 if (offset || ooffset) {
2359 cloned_sub_val = strdup(sub_val)(__extension__ (__builtin_constant_p (sub_val) && ((size_t
)(const void *)((sub_val) + 1) - (size_t)(const void *)(sub_val
) == 1) ? (((const char *) (sub_val))[0] == '\0' ? (char *) calloc
((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (sub_val
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, sub_val
, __len); __retval; })) : __strdup (sub_val)))
;
2360 switch_assert(cloned_sub_val)((cloned_sub_val) ? (void) (0) : __assert_fail ("cloned_sub_val"
, "src/switch_event.c", 2360, __PRETTY_FUNCTION__))
;
2361 sub_val = cloned_sub_val;
2362 }
2363
2364 if (offset >= 0) {
2365 sub_val += offset;
2366 } else if ((size_t) abs(offset) <= strlen(sub_val)) {
2367 sub_val = cloned_sub_val + (strlen(cloned_sub_val) + offset);
2368 }
2369
2370 if (ooffset > 0 && (size_t) ooffset < strlen(sub_val)) {
2371 if ((ptr = (char *) sub_val + ooffset)) {
2372 *ptr = '\0';
2373 }
2374 }
2375
2376
2377 switch_safe_free(expanded)if (expanded) {free(expanded);expanded=((void*)0);};
2378 } else {
2379 switch_stream_handle_t stream = { 0 };
2380 char *expanded = NULL((void*)0);
2381
2382 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "src/switch_event.c", 2382, __PRETTY_FUNCTION__)); memset(stream
.data, 0, 1024); stream.end = stream.data; stream.data_size =
1024; stream.write_function = switch_console_stream_write; stream
.raw_write_function = switch_console_stream_raw_write; stream
.alloc_len = 1024; stream.alloc_chunk = 1024
;
2383
2384 if (stream.data) {
2385 char *expanded_vname = NULL((void*)0);
2386
2387 if ((expanded_vname = switch_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) {
2388 expanded_vname = NULL((void*)0);
2389 } else {
2390 vname = expanded_vname;
2391 }
2392
2393 if ((expanded = switch_event_expand_headers_check(event, vval, var_list, api_list, recur+1)) == vval) {
2394 expanded = NULL((void*)0);
2395 } else {
2396 vval = expanded;
2397 }
2398
2399 if (!switch_core_test_flag(SCF_API_EXPANSION) || (api_list && !switch_event_check_permission_list(api_list, vname))) {
2400 func_val = NULL((void*)0);
2401 sub_val = "<API execute Permission Denied>";
2402 } else {
2403 if (switch_api_execute(vname, vval, NULL((void*)0), &stream) == SWITCH_STATUS_SUCCESS) {
2404 func_val = stream.data;
2405 sub_val = func_val;
2406 } else {
2407 free(stream.data);
2408 }
2409 }
2410
2411 switch_safe_free(expanded)if (expanded) {free(expanded);expanded=((void*)0);};
2412 switch_safe_free(expanded_vname)if (expanded_vname) {free(expanded_vname);expanded_vname=((void
*)0);}
;
2413
2414 } else {
2415 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 2415, ((void*)0)
, SWITCH_LOG_CRIT, "Memory Error!\n");
2416 free(data);
2417 free(indup);
2418 return (char *) in;
2419 }
2420 }
2421 if ((nlen = sub_val ? strlen(sub_val) : 0)) {
2422 if (len + nlen >= olen) {
2423 resize(nlen){char *dp;olen += (len + nlen + block);cpos = c - data;if ((dp
= realloc(data, olen))) { data = dp; c = data + cpos; memset
(c, 0, olen - cpos); }}
;
2424 }
2425
2426 len += nlen;
2427 strcat(c, sub_val);
2428 c += nlen;
2429 }
2430
2431 switch_safe_free(func_val)if (func_val) {free(func_val);func_val=((void*)0);};
2432 switch_safe_free(cloned_sub_val)if (cloned_sub_val) {free(cloned_sub_val);cloned_sub_val=((void
*)0);}
;
2433 switch_safe_free(expanded_sub_val)if (expanded_sub_val) {free(expanded_sub_val);expanded_sub_val
=((void*)0);}
;
2434 sub_val = NULL((void*)0);
2435 vname = NULL((void*)0);
2436 vtype = 0;
2437 br = 0;
2438 }
2439 if (len + 1 >= olen) {
2440 resize(1){char *dp;olen += (len + 1 + block);cpos = c - data;if ((dp =
realloc(data, olen))) { data = dp; c = data + cpos; memset(c
, 0, olen - cpos); }}
;
2441 }
2442
2443 if (sp) {
2444 *c++ = ' ';
2445 sp = 0;
2446 len++;
2447 }
2448
2449 if (*p == '$') {
2450 p--;
2451 } else {
2452 *c++ = *p;
2453 len++;
2454 }
2455 }
2456 }
2457 free(indup);
2458 switch_safe_free(gvar)if (gvar) {free(gvar);gvar=((void*)0);};
2459
2460 return data;
2461}
2462
2463SWITCH_DECLARE(char *)__attribute__((visibility("default"))) char * switch_event_build_param_string(switch_event_t *event, const char *prefix, switch_hash_t *vars_map)
2464{
2465 switch_stream_handle_t stream = { 0 };
2466 switch_size_t encode_len = 1024, new_len = 0;
2467 char *encode_buf = NULL((void*)0);
2468 const char *prof[12] = { 0 }, *prof_names[12] = {
2469 0};
2470 char *e = NULL((void*)0);
2471 switch_event_header_t *hi;
2472 uint32_t x = 0;
2473 void *data = NULL((void*)0);
2474
2475 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "src/switch_event.c", 2475, __PRETTY_FUNCTION__)); memset(stream
.data, 0, 1024); stream.end = stream.data; stream.data_size =
1024; stream.write_function = switch_console_stream_write; stream
.raw_write_function = switch_console_stream_raw_write; stream
.alloc_len = 1024; stream.alloc_chunk = 1024
;
2476
2477 if (prefix) {
2478 stream.write_function(&stream, "%s&", prefix);
2479 }
2480
2481 encode_buf = malloc(encode_len);
2482 switch_assert(encode_buf)((encode_buf) ? (void) (0) : __assert_fail ("encode_buf", "src/switch_event.c"
, 2482, __PRETTY_FUNCTION__))
;
2483
2484
2485
2486 for (x = 0; prof[x]; x++) {
2487 if (zstr(prof[x])_zstr(prof[x])) {
2488 continue;
2489 }
2490 new_len = (strlen(prof[x]) * 3) + 1;
2491 if (encode_len < new_len) {
2492 char *tmp;
2493
2494 encode_len = new_len;
2495
2496 if (!(tmp = realloc(encode_buf, encode_len))) {
2497 abort();
2498 }
2499
2500 encode_buf = tmp;
2501 }
2502 switch_url_encode(prof[x], encode_buf, encode_len);
2503 stream.write_function(&stream, "%s=%s&", prof_names[x], encode_buf);
2504 }
2505
2506 if (event) {
2507 if ((hi = event->headers)) {
2508
2509 for (; hi; hi = hi->next) {
2510 char *var = hi->name;
2511 char *val = hi->value;
2512
2513 if (vars_map != NULL((void*)0)) {
2514 if ((data = switch_core_hash_find(vars_map, var)) == NULL((void*)0) || strcasecmp(((char *) data), "enabled"))
2515 continue;
2516
2517 }
2518
2519 new_len = (strlen((char *) var) * 3) + 1;
2520 if (encode_len < new_len) {
2521 char *tmp;
2522
2523 encode_len = new_len;
2524
2525 tmp = realloc(encode_buf, encode_len);
2526 switch_assert(tmp)((tmp) ? (void) (0) : __assert_fail ("tmp", "src/switch_event.c"
, 2526, __PRETTY_FUNCTION__))
;
2527 encode_buf = tmp;
2528 }
2529
2530 switch_url_encode((char *) val, encode_buf, encode_len);
2531 stream.write_function(&stream, "%s=%s&", (char *) var, encode_buf);
2532
2533 }
2534 }
2535 }
2536
2537 e = (char *) stream.data + (strlen((char *) stream.data) - 1);
2538
2539 if (e && *e == '&') {
2540 *e = '\0';
2541 }
2542
2543 switch_safe_free(encode_buf)if (encode_buf) {free(encode_buf);encode_buf=((void*)0);};
2544
2545 return stream.data;
2546}
2547
2548SWITCH_DECLARE(int)__attribute__((visibility("default"))) int switch_event_check_permission_list(switch_event_t *list, const char *name)
2549{
2550 const char *v;
2551 int r = 0;
2552 int default_allow = 0;
2553
2554 if (!list) {
2555 return 1;
2556 }
2557
2558 default_allow = switch_test_flag(list, EF_DEFAULT_ALLOW)((list)->flags & EF_DEFAULT_ALLOW);
2559
2560 if (!list->headers) {
2561 return default_allow;
2562 }
2563
2564 if ((v = switch_event_get_header(list, name)switch_event_get_header_idx(list, name, -1))) {
2565 if (*v == 'd') {
2566 r = 0;
2567 } else {
2568 r = 1;
2569 }
2570 } else {
2571 r = default_allow;
2572 }
2573
2574 return r;
2575}
2576
2577SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_json_add_presence_data_cols(switch_event_t *event, cJSON *json, const char *prefix)
2578{
2579 const char *data;
2580
2581 if (!prefix) prefix = "";
2582
2583 if ((data = switch_event_get_header(event, "presence_data_cols")switch_event_get_header_idx(event, "presence_data_cols", -1))) {
2584 char *cols[128] = { 0 };
2585 char header_name[128] = "";
2586 int col_count = 0, i = 0;
2587 char *data_copy = NULL((void*)0);
2588
2589 data_copy = strdup(data)(__extension__ (__builtin_constant_p (data) && ((size_t
)(const void *)((data) + 1) - (size_t)(const void *)(data) ==
1) ? (((const char *) (data))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen (data) + 1
; char *__retval = (char *) malloc (__len); if (__retval != (
(void*)0)) __retval = (char *) memcpy (__retval, data, __len)
; __retval; })) : __strdup (data)))
;
2590
2591 col_count = switch_split(data_copy, ':', cols)switch_separate_string(data_copy, ':', cols, (sizeof(cols) / sizeof
(cols[0])))
;
2592
2593 for (i = 0; i < col_count; i++) {
2594 const char *val = NULL((void*)0);
2595 switch_snprintf(header_name, sizeof(header_name), "%s%s", prefix, cols[i]);
2596
2597 val = switch_event_get_header(event, cols[i])switch_event_get_header_idx(event, cols[i], -1);
2598 json_add_child_string(json, header_name, val);
2599 }
2600
2601 switch_safe_free(data_copy)if (data_copy) {free(data_copy);data_copy=((void*)0);};
2602 }
2603
2604}
2605
2606
2607SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_event_add_presence_data_cols(switch_channel_t *channel, switch_event_t *event, const char *prefix)
2608{
2609 const char *data;
2610
2611 if (!prefix) prefix = "";
2612
2613 if ((data = switch_channel_get_variable(channel, "presence_data_cols")switch_channel_get_variable_dup(channel, "presence_data_cols"
, SWITCH_TRUE, -1)
)) {
2614 char *cols[128] = { 0 };
2615 char header_name[128] = "";
2616 int col_count = 0, i = 0;
2617 char *data_copy = NULL((void*)0);
2618
2619 data_copy = strdup(data)(__extension__ (__builtin_constant_p (data) && ((size_t
)(const void *)((data) + 1) - (size_t)(const void *)(data) ==
1) ? (((const char *) (data))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen (data) + 1
; char *__retval = (char *) malloc (__len); if (__retval != (
(void*)0)) __retval = (char *) memcpy (__retval, data, __len)
; __retval; })) : __strdup (data)))
;
2620
2621 col_count = switch_split(data_copy, ':', cols)switch_separate_string(data_copy, ':', cols, (sizeof(cols) / sizeof
(cols[0])))
;
2622
2623 for (i = 0; i < col_count; i++) {
2624 const char *val = NULL((void*)0);
2625 switch_snprintf(header_name, sizeof(header_name), "%s%s", prefix, cols[i]);
2626
2627 val = switch_channel_get_variable(channel, cols[i])switch_channel_get_variable_dup(channel, cols[i], SWITCH_TRUE
, -1)
;
2628 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header_name, val);
2629 }
2630
2631 switch_safe_free(data_copy)if (data_copy) {free(data_copy);data_copy=((void*)0);};
2632 }
2633
2634}
2635
2636struct switch_event_channel_sub_node_head_s;
2637
2638typedef struct switch_event_channel_sub_node_s {
2639 switch_event_channel_func_t func;
2640 switch_event_channel_id_t id;
2641 struct switch_event_channel_sub_node_head_s *head;
2642 struct switch_event_channel_sub_node_s *next;
2643} switch_event_channel_sub_node_t;
2644
2645typedef struct switch_event_channel_sub_node_head_s {
2646 switch_event_channel_sub_node_t *node;
2647 switch_event_channel_sub_node_t *tail;
2648 char *event_channel;
2649} switch_event_channel_sub_node_head_t;
2650
2651static uint32_t switch_event_channel_unsub_head(switch_event_channel_func_t func, switch_event_channel_sub_node_head_t *head)
2652{
2653 uint32_t x = 0;
2654
2655 switch_event_channel_sub_node_t *thisnp = NULL((void*)0), *np, *last = NULL((void*)0);
2656
2657 np = head->tail = head->node;
2658
2659 while (np) {
2660
2661 thisnp = np;
2662 np = np->next;
2663
2664 if (!func || thisnp->func == func) {
2665 x++;
2666
2667 if (last) {
2668 last->next = np;
2669 } else {
2670 head->node = np;
2671 }
2672
2673
2674 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 2674, ((void*)0)
, SWITCH_LOG_DEBUG1, "UNSUBBING %p [%s]\n", (void *)(intptr_t)thisnp->func, thisnp->head->event_channel);
2675
2676
2677 thisnp->func = NULL((void*)0);
2678 free(thisnp);
2679 } else {
2680 last = thisnp;
2681 head->tail = last;
2682 }
2683 }
2684
2685 return x;
2686}
2687
2688static void unsub_all_switch_event_channel(void)
2689{
2690 switch_hash_index_t *hi = NULL((void*)0);
2691 const void *var;
2692 void *val;
2693 switch_event_channel_sub_node_head_t *head;
2694
2695 switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
2696
2697 while ((hi = switch_core_hash_first_iter( event_channel_manager.perm_hash, hi))) {
2698 switch_event_t *vals = NULL((void*)0);
2699 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
2700 vals = (switch_event_t *) val;
2701 switch_core_hash_delete(event_channel_manager.perm_hash, var);
2702 switch_event_destroy(&vals);
2703 }
2704
2705 while ((hi = switch_core_hash_first_iter( event_channel_manager.hash, hi))) {
2706 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
2707 head = (switch_event_channel_sub_node_head_t *) val;
2708 switch_event_channel_unsub_head(NULL((void*)0), head);
2709 switch_core_hash_delete(event_channel_manager.hash, head->event_channel);
2710 free(head->event_channel);
2711 free(head);
2712 }
2713
2714 switch_thread_rwlock_unlock(event_channel_manager.rwlock);
2715}
2716
2717static uint32_t switch_event_channel_unsub_channel(switch_event_channel_func_t func, const char *event_channel)
2718{
2719 switch_event_channel_sub_node_head_t *head;
2720 uint32_t x = 0;
2721
2722 switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
2723
2724 if (!event_channel) {
2725 switch_hash_index_t *hi;
2726 void *val;
2727
2728 for (hi = switch_core_hash_first(event_channel_manager.hash)switch_core_hash_first_iter(event_channel_manager.hash, ((void
*)0))
; hi; hi = switch_core_hash_next(&hi)) {
2729 switch_core_hash_this(hi, NULL((void*)0), NULL((void*)0), &val);
2730
2731 if (val) {
2732 head = (switch_event_channel_sub_node_head_t *) val;
2733 x += switch_event_channel_unsub_head(func, head);
2734 }
2735 }
2736
2737 } else {
2738 if ((head = switch_core_hash_find(event_channel_manager.hash, event_channel))) {
2739 x += switch_event_channel_unsub_head(func, head);
2740 }
2741 }
2742
2743 switch_thread_rwlock_unlock(event_channel_manager.rwlock);
2744
2745 return x;
2746}
2747
2748static switch_status_t switch_event_channel_sub_channel(const char *event_channel, switch_event_channel_func_t func, switch_event_channel_id_t id)
2749
2750{
2751 switch_event_channel_sub_node_t *node, *np;
2752 switch_event_channel_sub_node_head_t *head;
2753 switch_status_t status = SWITCH_STATUS_FALSE;
2754
2755 switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
2756
2757 if (!(head = switch_core_hash_find(event_channel_manager.hash, event_channel))) {
2758 switch_zmalloc(head, sizeof(*head))(void)((((head = calloc(1, (sizeof(*head))))) ? (void) (0) : __assert_fail
("(head = calloc(1, (sizeof(*head))))", "src/switch_event.c"
, 2758, __PRETTY_FUNCTION__)),head)
;
2759 head->event_channel = strdup(event_channel)(__extension__ (__builtin_constant_p (event_channel) &&
((size_t)(const void *)((event_channel) + 1) - (size_t)(const
void *)(event_channel) == 1) ? (((const char *) (event_channel
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (event_channel) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, event_channel, __len); __retval; }
)) : __strdup (event_channel)))
;
2760 switch_core_hash_insert(event_channel_manager.hash, event_channel, head)switch_core_hash_insert_destructor(event_channel_manager.hash
, event_channel, head, ((void*)0))
;
2761
2762 switch_zmalloc(node, sizeof(*node))(void)((((node = calloc(1, (sizeof(*node))))) ? (void) (0) : __assert_fail
("(node = calloc(1, (sizeof(*node))))", "src/switch_event.c"
, 2762, __PRETTY_FUNCTION__)),node)
;
2763 node->func = func;
2764 node->id = id;
2765
2766 node->head = head;
2767 head->node = node;
2768 head->tail = node;
2769 status = SWITCH_STATUS_SUCCESS;
2770 } else {
2771 int exist = 0;
2772
2773 for (np = head->node; np; np = np->next) {
2774 if (np->func == func) {
2775 exist = 1;
2776 break;
2777 }
2778 }
2779
2780 if (!exist) {
2781 switch_zmalloc(node, sizeof(*node))(void)((((node = calloc(1, (sizeof(*node))))) ? (void) (0) : __assert_fail
("(node = calloc(1, (sizeof(*node))))", "src/switch_event.c"
, 2781, __PRETTY_FUNCTION__)),node)
;
2782
2783 node->func = func;
2784 node->id = id;
2785 node->head = head;
2786
2787
2788 if (!head->node) {
2789 head->node = node;
2790 head->tail = node;
2791 } else {
2792 head->tail->next = node;
2793 head->tail = head->tail->next;
2794 }
2795 status = SWITCH_STATUS_SUCCESS;
2796 }
2797 }
2798
2799 switch_thread_rwlock_unlock(event_channel_manager.rwlock);
2800
2801 return status;
2802}
2803
2804typedef struct {
2805 char *event_channel;
2806 cJSON *json;
2807 char *key;
2808 switch_event_channel_id_t id;
2809} event_channel_data_t;
2810
2811
2812
2813static uint32_t _switch_event_channel_broadcast(const char *event_channel, const char *broadcast_channel,
2814 cJSON *json, const char *key, switch_event_channel_id_t id)
2815{
2816 switch_event_channel_sub_node_t *np;
2817 switch_event_channel_sub_node_head_t *head;
2818 uint32_t x = 0;
2819
2820 switch_thread_rwlock_rdlock(event_channel_manager.rwlock);
2821 if ((head = switch_core_hash_find(event_channel_manager.hash, event_channel))) {
2822 for (np = head->node; np; np = np->next) {
2823 if (np->id == id) {
2824 continue;
2825 }
2826
2827 np->func(broadcast_channel, json, key, id);
2828 x++;
2829 }
2830 }
2831 switch_thread_rwlock_unlock(event_channel_manager.rwlock);
2832
2833 return x;
2834}
2835
2836static void destroy_ecd(event_channel_data_t **ecdP)
2837{
2838 event_channel_data_t *ecd = *ecdP;
2839 *ecdP = NULL((void*)0);
2840
2841 switch_safe_free(ecd->event_channel)if (ecd->event_channel) {free(ecd->event_channel);ecd->
event_channel=((void*)0);}
;
2842 switch_safe_free(ecd->key)if (ecd->key) {free(ecd->key);ecd->key=((void*)0);};
2843 if (ecd->json) {
2844 cJSON_Delete(ecd->json);
2845 ecd->json = NULL((void*)0);
2846 }
2847
2848 free(ecd);
2849}
2850
2851static void ecd_deliver(event_channel_data_t **ecdP)
2852{
2853 event_channel_data_t *ecd = *ecdP;
2854 char *p;
2855
2856 *ecdP = NULL((void*)0);
2857
2858 _switch_event_channel_broadcast(ecd->event_channel, ecd->event_channel, ecd->json, ecd->key, ecd->id);
2859
2860 if ((p = strchr(ecd->event_channel, '.')(__extension__ (__builtin_constant_p ('.') && !__builtin_constant_p
(ecd->event_channel) && ('.') == '\0' ? (char *) __rawmemchr
(ecd->event_channel, '.') : __builtin_strchr (ecd->event_channel
, '.')))
)) {
2861 char *main_channel = strdup(ecd->event_channel)(__extension__ (__builtin_constant_p (ecd->event_channel) &&
((size_t)(const void *)((ecd->event_channel) + 1) - (size_t
)(const void *)(ecd->event_channel) == 1) ? (((const char *
) (ecd->event_channel))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (ecd->event_channel
) + 1; char *__retval = (char *) malloc (__len); if (__retval
!= ((void*)0)) __retval = (char *) memcpy (__retval, ecd->
event_channel, __len); __retval; })) : __strdup (ecd->event_channel
)))
;
2862 p = strchr(main_channel, '.')(__extension__ (__builtin_constant_p ('.') && !__builtin_constant_p
(main_channel) && ('.') == '\0' ? (char *) __rawmemchr
(main_channel, '.') : __builtin_strchr (main_channel, '.')))
;
2863 *p = '\0';
2864 _switch_event_channel_broadcast(main_channel, ecd->event_channel, ecd->json, ecd->key, ecd->id);
2865 free(main_channel);
2866 }
2867 _switch_event_channel_broadcast(SWITCH_EVENT_CHANNEL_GLOBAL"__global__", ecd->event_channel, ecd->json, ecd->key, ecd->id);
2868
2869 destroy_ecd(&ecd);
2870}
2871
2872static void *SWITCH_THREAD_FUNC switch_event_channel_deliver_thread(switch_thread_t *thread, void *obj)
2873{
2874 switch_queue_t *queue = (switch_queue_t *) obj;
2875 void *pop = NULL((void*)0);
2876 event_channel_data_t *ecd = NULL((void*)0);
2877
2878 switch_mutex_lock(EVENT_QUEUE_MUTEX);
2879 THREAD_COUNT++;
2880 EVENT_CHANNEL_DISPATCH_THREAD_COUNT++;
2881 EVENT_CHANNEL_DISPATCH_THREAD_STARTING = 0;
2882 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
2883
2884 while(SYSTEM_RUNNING) {
2885
2886 if (switch_queue_pop(queue, &pop) != SWITCH_STATUS_SUCCESS) {
2887 continue;
2888 }
2889
2890 if (!pop) {
2891 break;
2892 }
2893
2894 ecd = (event_channel_data_t *) pop;
2895 ecd_deliver(&ecd);
2896 switch_os_yield();
2897 }
2898
2899 while (switch_queue_trypop(queue, &pop) == SWITCH_STATUS_SUCCESS) {
2900 ecd = (event_channel_data_t *) pop;
2901 destroy_ecd(&ecd);
2902 }
2903
2904 switch_mutex_lock(EVENT_QUEUE_MUTEX);
2905 THREAD_COUNT--;
2906 EVENT_CHANNEL_DISPATCH_THREAD_COUNT--;
2907 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
2908
2909 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 2909, ((void*)0)
, SWITCH_LOG_CONSOLE, "Event Channel Dispatch Thread Ended.\n");
2910 return NULL((void*)0);
2911}
2912
2913SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_channel_broadcast(const char *event_channel, cJSON **json, const char *key, switch_event_channel_id_t id)
2914{
2915 event_channel_data_t *ecd = NULL((void*)0);
2916 switch_status_t status = SWITCH_STATUS_SUCCESS;
2917 int launch = 0;
2918
2919 if (!SYSTEM_RUNNING) {
2920 cJSON_Delete(*json);
2921 *json = NULL((void*)0);
2922 return SWITCH_STATUS_FALSE;
2923 }
2924
2925 switch_zmalloc(ecd, sizeof(*ecd))(void)((((ecd = calloc(1, (sizeof(*ecd))))) ? (void) (0) : __assert_fail
("(ecd = calloc(1, (sizeof(*ecd))))", "src/switch_event.c", 2925
, __PRETTY_FUNCTION__)),ecd)
;
2926
2927 ecd->event_channel = strdup(event_channel)(__extension__ (__builtin_constant_p (event_channel) &&
((size_t)(const void *)((event_channel) + 1) - (size_t)(const
void *)(event_channel) == 1) ? (((const char *) (event_channel
))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({
size_t __len = strlen (event_channel) + 1; char *__retval = (
char *) malloc (__len); if (__retval != ((void*)0)) __retval =
(char *) memcpy (__retval, event_channel, __len); __retval; }
)) : __strdup (event_channel)))
;
2928 ecd->json = *json;
2929 ecd->key = strdup(key)(__extension__ (__builtin_constant_p (key) && ((size_t
)(const void *)((key) + 1) - (size_t)(const void *)(key) == 1
) ? (((const char *) (key))[0] == '\0' ? (char *) calloc ((size_t
) 1, (size_t) 1) : ({ size_t __len = strlen (key) + 1; char *
__retval = (char *) malloc (__len); if (__retval != ((void*)0
)) __retval = (char *) memcpy (__retval, key, __len); __retval
; })) : __strdup (key)))
;
2930 ecd->id = id;
2931
2932 *json = NULL((void*)0);
2933
2934 switch_mutex_lock(EVENT_QUEUE_MUTEX);
2935 if (!EVENT_CHANNEL_DISPATCH_THREAD_COUNT && !EVENT_CHANNEL_DISPATCH_THREAD_STARTING && SYSTEM_RUNNING) {
2936 EVENT_CHANNEL_DISPATCH_THREAD_STARTING = 1;
2937 launch = 1;
2938 }
2939 switch_mutex_unlock(EVENT_QUEUE_MUTEX);
2940
2941 if (launch) {
2942 switch_thread_data_t *td;
2943
2944 if (!EVENT_CHANNEL_DISPATCH_QUEUE) {
2945 switch_queue_create(&EVENT_CHANNEL_DISPATCH_QUEUE, DISPATCH_QUEUE_LEN10000 * MAX_DISPATCH, THRUNTIME_POOL);
2946 }
2947
2948 td = malloc(sizeof(*td));
2949 switch_assert(td)((td) ? (void) (0) : __assert_fail ("td", "src/switch_event.c"
, 2949, __PRETTY_FUNCTION__))
;
2950
2951 td->alloc = 1;
2952 td->func = switch_event_channel_deliver_thread;
2953 td->obj = EVENT_CHANNEL_DISPATCH_QUEUE;
2954 td->pool = NULL((void*)0);
2955
2956 switch_thread_pool_launch_thread(&td);
2957 }
2958
2959 if ((status = switch_queue_trypush(EVENT_CHANNEL_DISPATCH_QUEUE, ecd) != SWITCH_STATUS_SUCCESS)) {
2960 cJSON_Delete(ecd->json);
2961 ecd->json = NULL((void*)0);
2962 destroy_ecd(&ecd);
2963 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "src/switch_event.c", (const char *)__func__
, 2963, ((void*)0)
, SWITCH_LOG_CRIT, "Event Channel Queue failure for channel %s\n", event_channel);
2964 } else {
2965 ecd = NULL((void*)0);
2966 }
2967
2968 return status;
2969}
2970
2971SWITCH_DECLARE(uint32_t)__attribute__((visibility("default"))) uint32_t switch_event_channel_unbind(const char *event_channel, switch_event_channel_func_t func)
2972{
2973 return switch_event_channel_unsub_channel(func, event_channel);
2974}
2975
2976SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_event_channel_bind(const char *event_channel, switch_event_channel_func_t func, switch_event_channel_id_t *id)
2977
2978{
2979 switch_status_t status = SWITCH_STATUS_SUCCESS;
2980
2981 switch_assert(id)((id) ? (void) (0) : __assert_fail ("id", "src/switch_event.c"
, 2981, __PRETTY_FUNCTION__))
;
2982
2983 if (!*id) {
2984 switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
2985 *id = event_channel_manager.ID++;
2986 switch_thread_rwlock_unlock(event_channel_manager.rwlock);
2987 }
2988
2989 status = switch_event_channel_sub_channel(event_channel, func, *id);
2990
2991 return status;
2992}
2993
2994SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_event_channel_permission_verify(const char *cookie, const char *event_channel)
2995{
2996 switch_event_t *vals;
2997 switch_bool_t r = SWITCH_FALSE;
2998
2999 switch_thread_rwlock_rdlock(event_channel_manager.rwlock);
3000 if ((vals = switch_core_hash_find(event_channel_manager.perm_hash, cookie))) {
3001 r = switch_true(switch_event_get_header(vals, event_channel)switch_event_get_header_idx(vals, event_channel, -1));
3002 }
3003 switch_thread_rwlock_unlock(event_channel_manager.rwlock);
3004
3005 return r;
3006}
3007
3008SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_event_channel_permission_modify(const char *cookie, const char *event_channel, switch_bool_t set)
3009{
3010 switch_event_t *vals;
3011
3012 switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
3013 if (!(vals = switch_core_hash_find(event_channel_manager.perm_hash, cookie))) {
3014 if (!set) goto end;
3015
3016 switch_event_create_plain(&vals, SWITCH_EVENT_CHANNEL_DATA);
3017 switch_core_hash_insert(event_channel_manager.perm_hash, cookie, vals)switch_core_hash_insert_destructor(event_channel_manager.perm_hash
, cookie, vals, ((void*)0))
;
3018 }
3019
3020 if (set) {
3021 switch_event_add_header_string(vals, SWITCH_STACK_BOTTOM, event_channel, "true");
3022 } else {
3023 switch_event_del_header(vals, event_channel)switch_event_del_header_val(vals, event_channel, ((void*)0));
3024 }
3025
3026
3027 end:
3028
3029 switch_thread_rwlock_unlock(event_channel_manager.rwlock);
3030}
3031
3032SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_event_channel_permission_clear(const char *cookie)
3033{
3034 switch_event_t *vals;
3035
3036 switch_thread_rwlock_wrlock(event_channel_manager.rwlock);
3037 if ((vals = switch_core_hash_find(event_channel_manager.perm_hash, cookie))) {
3038 switch_core_hash_delete(event_channel_manager.perm_hash, cookie);
3039 switch_event_destroy(&vals);
3040 }
3041 switch_thread_rwlock_unlock(event_channel_manager.rwlock);
3042}
3043
3044
3045typedef struct alias_node_s {
3046 char *event_channel;
3047 char *name;
3048 char *key;
3049 struct alias_node_s *next;
3050} alias_node_t;
3051
3052typedef struct la_node_s {
3053 char *name;
3054 cJSON *obj;
3055 struct la_node_s *next;
3056 int pos;
3057} la_node_t;
3058
3059struct switch_live_array_s {
3060 char *event_channel;
3061 char *name;
3062 char *key;
3063 la_node_t *head;
3064 la_node_t *tail;
3065 switch_memory_pool_t *pool;
3066 switch_hash_t *hash;
3067 switch_mutex_t *mutex;
3068 uint32_t serno;
3069 int pos;
3070 switch_bool_t visible;
3071 switch_bool_t new;
3072 switch_event_channel_id_t channel_id;
3073 switch_live_array_command_handler_t command_handler;
3074 void *user_data;
3075 alias_node_t *aliases;
3076 int refs;
3077};
3078
3079static switch_status_t la_broadcast(switch_live_array_t *la, cJSON **json)
3080{
3081 alias_node_t *np;
3082
3083 if (la->aliases) {
3084 switch_mutex_lock(la->mutex);
3085 for (np = la->aliases; np; np = np->next) {
3086 cJSON *dup = cJSON_Duplicate(*json, 1);
3087 cJSON *data = cJSON_GetObjectItem(dup, "data");
3088
3089 cJSON_ReplaceItemInObject(dup, "eventChannel", cJSON_CreateString(np->event_channel));
3090 cJSON_ReplaceItemInObject(data, "name", cJSON_CreateString(np->name));
3091
3092 switch_event_channel_broadcast(np->event_channel, &dup, __FILE__"src/switch_event.c", la->channel_id);
3093 }
3094 switch_mutex_unlock(la->mutex);
3095 }
3096
3097 return switch_event_channel_broadcast(la->event_channel, json, __FILE__"src/switch_event.c", la->channel_id);
3098
3099}
3100
3101
3102SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_live_array_visible(switch_live_array_t *la, switch_bool_t visible, switch_bool_t force)
3103{
3104 switch_status_t status = SWITCH_STATUS_FALSE;
3105
3106 switch_mutex_lock(la->mutex);
3107 if (la->visible != visible || force) {
3108 cJSON *msg, *data;
3109
3110 msg = cJSON_CreateObject();
3111 data = json_add_child_obj(msg, "data", NULL((void*)0));
3112
3113 cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
3114 cJSON_AddItemToObject(data, "action", cJSON_CreateString(visible ? "hide" : "show"));
3115 cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(la->serno++));
3116
3117 la_broadcast(la, &msg);
3118
3119 la->visible = visible;
3120 }
3121 switch_mutex_unlock(la->mutex);
3122
3123 return status;
3124}
3125
3126SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_live_array_clear(switch_live_array_t *la)
3127{
3128 la_node_t *cur, *np;
3129 cJSON *msg, *data;
3130
3131 switch_mutex_lock(la->mutex);
3132 np = la->head;
3133
3134 msg = cJSON_CreateObject();
3135 data = json_add_child_obj(msg, "data", NULL((void*)0));
3136
3137 cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
3138 cJSON_AddItemToObject(data, "action", cJSON_CreateString("clear"));
3139 cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
3140 cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(-1));
3141 cJSON_AddItemToObject(data, "data", cJSON_CreateObject());
3142
3143 la_broadcast(la, &msg);
3144
3145 while(np) {
3146 cur = np;
3147 np = np->next;
3148 cJSON_Delete(cur->obj);
3149 free(cur->name);
3150 free(cur);
3151 }
3152
3153 la->head = la->tail = NULL((void*)0);
3154
3155 switch_mutex_unlock(la->mutex);
3156
3157 return SWITCH_STATUS_SUCCESS;
3158}
3159
3160SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_live_array_bootstrap(switch_live_array_t *la, const char *sessid, switch_event_channel_id_t channel_id)
3161{
3162 la_node_t *np;
3163 cJSON *msg, *data;
3164
3165 switch_mutex_lock(la->mutex);
3166
3167#if OLD_WAY
3168 msg = cJSON_CreateObject();
3169 data = json_add_child_obj(msg, "data", NULL((void*)0));
3170
3171 cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
3172 cJSON_AddItemToObject(data, "action", cJSON_CreateString("clear"));
3173 cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
3174 cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(-1));
3175 cJSON_AddItemToObject(data, "data", cJSON_CreateObject());
3176
3177 switch_event_channel_broadcast(la->event_channel, &msg, __FILE__"src/switch_event.c", channel_id);
3178
3179 for (np = la->head; np; np = np->next) {
3180 msg = cJSON_CreateObject();
3181 data = json_add_child_obj(msg, "data", NULL((void*)0));
3182
3183 cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
3184 cJSON_AddItemToObject(data, "action", cJSON_CreateString("add"));
3185 cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
3186 cJSON_AddItemToObject(data, "hashKey", cJSON_CreateString(np->name));
3187 cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(la->serno++));
3188 cJSON_AddItemToObject(data, "data", cJSON_Duplicate(np->obj, 1));
3189 if (sessid) {
3190 cJSON_AddItemToObject(msg, "sessid", cJSON_CreateString(sessid));
3191 }
3192 switch_event_channel_broadcast(la->event_channel, &msg, __FILE__"src/switch_event.c", channel_id);
3193 }
3194#else
3195
3196
3197 msg = cJSON_CreateObject();
3198 data = json_add_child_obj(msg, "data", NULL((void*)0));
3199
3200 cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
3201 cJSON_AddItemToObject(data, "action", cJSON_CreateString("bootObj"));
3202 cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
3203 cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(-1));
3204
3205 if (sessid) {
3206 cJSON_AddItemToObject(msg, "sessid", cJSON_CreateString(sessid));
3207 }
3208
3209 data = json_add_child_array(data, "data");
3210
3211 for (np = la->head; np; np = np->next) {
3212 cJSON *row = cJSON_CreateArray();
3213 cJSON_AddItemToArray(row, cJSON_CreateString(np->name));
3214 cJSON_AddItemToArray(row, cJSON_Duplicate(np->obj, 1));
3215 cJSON_AddItemToArray(data, row);
3216 }
3217
3218 switch_event_channel_broadcast(la->event_channel, &msg, __FILE__"src/switch_event.c", channel_id);
3219
3220
3221#endif
3222
3223 if (!la->visible) {
3224 switch_live_array_visible(la, SWITCH_FALSE, SWITCH_TRUE);
3225 }
3226
3227 switch_mutex_unlock(la->mutex);
3228
3229 return SWITCH_STATUS_SUCCESS;
3230}
3231
3232SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_live_array_destroy(switch_live_array_t **live_arrayP)
3233{
3234 switch_live_array_t *la = *live_arrayP;
3235 switch_memory_pool_t *pool;
3236 alias_node_t *np;
3237 int done = 0;
3238
3239 *live_arrayP = NULL((void*)0);
3240
3241 switch_mutex_lock(la->mutex);
3242 if (la->refs) {
3243 la->refs--;
3244 }
3245 if (la->refs) done = 1;
3246 switch_mutex_unlock(la->mutex);
3247
3248 if (done) {
3249 return SWITCH_STATUS_SUCCESS;
3250 }
3251
3252 pool = la->pool;
3253
3254 switch_live_array_clear(la);
3255
3256 switch_core_hash_destroy(&la->hash);
3257
3258 switch_mutex_lock(event_channel_manager.lamutex);
3259 switch_core_hash_delete(event_channel_manager.lahash, la->key);
3260 for (np = la->aliases; np; np = np->next) {
3261 switch_core_hash_delete(event_channel_manager.lahash, np->key);
3262 }
3263 switch_mutex_unlock(event_channel_manager.lamutex);
3264
3265 switch_core_destroy_memory_pool(&pool)switch_core_perform_destroy_memory_pool(&pool, "src/switch_event.c"
, (const char *)__func__, 3265)
;
3266
3267 return SWITCH_STATUS_SUCCESS;
3268}
3269
3270SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_live_array_isnew(switch_live_array_t *la)
3271{
3272 return la->new;
3273}
3274
3275SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_live_array_clear_alias(switch_live_array_t *la, const char *event_channel, const char *name)
3276{
3277 alias_node_t *np, *last = NULL((void*)0), *del = NULL((void*)0);
3278 switch_bool_t r = SWITCH_FALSE;
3279
3280 switch_mutex_lock(la->mutex);
3281 for (np = la->aliases; np; np = np->next) {
3282 if (!strcmp(np->event_channel, event_channel)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(np->event_channel) && __builtin_constant_p (event_channel
) && (__s1_len = __builtin_strlen (np->event_channel
), __s2_len = __builtin_strlen (event_channel), (!((size_t)(const
void *)((np->event_channel) + 1) - (size_t)(const void *)
(np->event_channel) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((event_channel) + 1) - (size_t)(const
void *)(event_channel) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(np->event_channel, event_channel) : (__builtin_constant_p
(np->event_channel) && ((size_t)(const void *)((np
->event_channel) + 1) - (size_t)(const void *)(np->event_channel
) == 1) && (__s1_len = __builtin_strlen (np->event_channel
), __s1_len < 4) ? (__builtin_constant_p (event_channel) &&
((size_t)(const void *)((event_channel) + 1) - (size_t)(const
void *)(event_channel) == 1) ? __builtin_strcmp (np->event_channel
, event_channel) : (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) (event_channel); int
__result = (((const unsigned char *) (const char *) (np->
event_channel))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (np->event_channel))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (np->event_channel))[2] - __s2[2]); if (
__s1_len > 2 && __result == 0) __result = (((const
unsigned char *) (const char *) (np->event_channel))[3] -
__s2[3]); } } __result; }))) : (__builtin_constant_p (event_channel
) && ((size_t)(const void *)((event_channel) + 1) - (
size_t)(const void *)(event_channel) == 1) && (__s2_len
= __builtin_strlen (event_channel), __s2_len < 4) ? (__builtin_constant_p
(np->event_channel) && ((size_t)(const void *)((np
->event_channel) + 1) - (size_t)(const void *)(np->event_channel
) == 1) ? __builtin_strcmp (np->event_channel, event_channel
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (np->event_channel); int __result =
(((const unsigned char *) (const char *) (event_channel))[0]
- __s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (event_channel))[
1] - __s2[1]); if (__s2_len > 1 && __result == 0) {
__result = (((const unsigned char *) (const char *) (event_channel
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (event_channel
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (np->
event_channel, event_channel)))); })
&& !strcmp(np->name, name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(np->name) && __builtin_constant_p (name) &&
(__s1_len = __builtin_strlen (np->name), __s2_len = __builtin_strlen
(name), (!((size_t)(const void *)((np->name) + 1) - (size_t
)(const void *)(np->name) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((name) + 1) - (size_t)(const void *
)(name) == 1) || __s2_len >= 4)) ? __builtin_strcmp (np->
name, name) : (__builtin_constant_p (np->name) && (
(size_t)(const void *)((np->name) + 1) - (size_t)(const void
*)(np->name) == 1) && (__s1_len = __builtin_strlen
(np->name), __s1_len < 4) ? (__builtin_constant_p (name
) && ((size_t)(const void *)((name) + 1) - (size_t)(const
void *)(name) == 1) ? __builtin_strcmp (np->name, name) :
(__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (name); int __result = (((const unsigned
char *) (const char *) (np->name))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (np->name))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (np->name))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (np->name))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (name) && ((size_t)(const
void *)((name) + 1) - (size_t)(const void *)(name) == 1) &&
(__s2_len = __builtin_strlen (name), __s2_len < 4) ? (__builtin_constant_p
(np->name) && ((size_t)(const void *)((np->name
) + 1) - (size_t)(const void *)(np->name) == 1) ? __builtin_strcmp
(np->name, name) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (np->name)
; int __result = (((const unsigned char *) (const char *) (name
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (name
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (name
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (name))
[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (np->
name, name)))); })
) {
3283 r = SWITCH_TRUE;
3284 del = np;
3285
3286 if (last) {
3287 last->next = np->next;
3288 } else {
3289 la->aliases = np->next;
3290 }
3291 } else {
3292 last = np;
3293 }
3294 }
3295 switch_mutex_unlock(la->mutex);
3296
3297 if (r) {
3298 switch_mutex_lock(event_channel_manager.lamutex);
3299 switch_core_hash_delete(event_channel_manager.lahash, del->key);
3300 switch_mutex_unlock(event_channel_manager.lamutex);
3301 }
3302
3303
3304 return r;
3305}
3306
3307SWITCH_DECLARE(switch_bool_t)__attribute__((visibility("default"))) switch_bool_t switch_live_array_add_alias(switch_live_array_t *la, const char *event_channel, const char *name)
3308{
3309 alias_node_t *node = 0, *np;
3310 switch_bool_t exist = SWITCH_FALSE;
3311
3312 switch_mutex_lock(la->mutex);
3313 for (np = la->aliases; np && np->next; np = np->next) {
3314 if (!strcmp(np->event_channel, event_channel)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(np->event_channel) && __builtin_constant_p (event_channel
) && (__s1_len = __builtin_strlen (np->event_channel
), __s2_len = __builtin_strlen (event_channel), (!((size_t)(const
void *)((np->event_channel) + 1) - (size_t)(const void *)
(np->event_channel) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((event_channel) + 1) - (size_t)(const
void *)(event_channel) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(np->event_channel, event_channel) : (__builtin_constant_p
(np->event_channel) && ((size_t)(const void *)((np
->event_channel) + 1) - (size_t)(const void *)(np->event_channel
) == 1) && (__s1_len = __builtin_strlen (np->event_channel
), __s1_len < 4) ? (__builtin_constant_p (event_channel) &&
((size_t)(const void *)((event_channel) + 1) - (size_t)(const
void *)(event_channel) == 1) ? __builtin_strcmp (np->event_channel
, event_channel) : (__extension__ ({ const unsigned char *__s2
= (const unsigned char *) (const char *) (event_channel); int
__result = (((const unsigned char *) (const char *) (np->
event_channel))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (np->event_channel))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (np->event_channel))[2] - __s2[2]); if (
__s1_len > 2 && __result == 0) __result = (((const
unsigned char *) (const char *) (np->event_channel))[3] -
__s2[3]); } } __result; }))) : (__builtin_constant_p (event_channel
) && ((size_t)(const void *)((event_channel) + 1) - (
size_t)(const void *)(event_channel) == 1) && (__s2_len
= __builtin_strlen (event_channel), __s2_len < 4) ? (__builtin_constant_p
(np->event_channel) && ((size_t)(const void *)((np
->event_channel) + 1) - (size_t)(const void *)(np->event_channel
) == 1) ? __builtin_strcmp (np->event_channel, event_channel
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (np->event_channel); int __result =
(((const unsigned char *) (const char *) (event_channel))[0]
- __s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (event_channel))[
1] - __s2[1]); if (__s2_len > 1 && __result == 0) {
__result = (((const unsigned char *) (const char *) (event_channel
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (event_channel
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (np->
event_channel, event_channel)))); })
&& !strcmp(np->name, name)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(np->name) && __builtin_constant_p (name) &&
(__s1_len = __builtin_strlen (np->name), __s2_len = __builtin_strlen
(name), (!((size_t)(const void *)((np->name) + 1) - (size_t
)(const void *)(np->name) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((name) + 1) - (size_t)(const void *
)(name) == 1) || __s2_len >= 4)) ? __builtin_strcmp (np->
name, name) : (__builtin_constant_p (np->name) && (
(size_t)(const void *)((np->name) + 1) - (size_t)(const void
*)(np->name) == 1) && (__s1_len = __builtin_strlen
(np->name), __s1_len < 4) ? (__builtin_constant_p (name
) && ((size_t)(const void *)((name) + 1) - (size_t)(const
void *)(name) == 1) ? __builtin_strcmp (np->name, name) :
(__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (name); int __result = (((const unsigned
char *) (const char *) (np->name))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (np->name))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (np->name))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (np->name))[3] - __s2[3]); } } __result
; }))) : (__builtin_constant_p (name) && ((size_t)(const
void *)((name) + 1) - (size_t)(const void *)(name) == 1) &&
(__s2_len = __builtin_strlen (name), __s2_len < 4) ? (__builtin_constant_p
(np->name) && ((size_t)(const void *)((np->name
) + 1) - (size_t)(const void *)(np->name) == 1) ? __builtin_strcmp
(np->name, name) : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (np->name)
; int __result = (((const unsigned char *) (const char *) (name
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (name
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (name
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (name))
[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (np->
name, name)))); })
) {
3315 exist = SWITCH_TRUE;
3316 break;
3317 }
3318 }
3319
3320 if (!exist) {
3321 node = switch_core_alloc(la->pool, sizeof(*node))switch_core_perform_alloc(la->pool, sizeof(*node), "src/switch_event.c"
, (const char *)__func__, 3321)
;
3322 node->event_channel = switch_core_strdup(la->pool, event_channel)switch_core_perform_strdup(la->pool, event_channel, "src/switch_event.c"
, (const char *)__func__, 3322)
;
3323 node->name = switch_core_strdup(la->pool, name)switch_core_perform_strdup(la->pool, name, "src/switch_event.c"
, (const char *)__func__, 3323)
;
3324 node->key = switch_core_sprintf(la->pool, "%s.%s", event_channel, name);
3325
3326 if (np) {
3327 np->next = node;
3328 } else {
3329 la->aliases = node;
3330 }
3331 }
3332
3333 switch_mutex_unlock(la->mutex);
3334
3335 if (!exist) {
3336 switch_mutex_lock(event_channel_manager.lamutex);
3337 switch_core_hash_insert(event_channel_manager.lahash, node->key, la)switch_core_hash_insert_destructor(event_channel_manager.lahash
, node->key, la, ((void*)0))
;
3338 switch_mutex_unlock(event_channel_manager.lamutex);
3339 }
3340
3341
3342 return !exist;
3343}
3344
3345SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_live_array_create(const char *event_channel, const char *name,
3346 switch_event_channel_id_t channel_id, switch_live_array_t **live_arrayP)
3347{
3348 switch_live_array_t *la = NULL((void*)0);
3349 switch_memory_pool_t *pool;
3350 char *key = NULL((void*)0);
3351
3352 switch_core_new_memory_pool(&pool)switch_core_perform_new_memory_pool(&pool, "src/switch_event.c"
, (const char *)__func__, 3352)
;
3353 key = switch_core_sprintf(pool, "%s.%s", event_channel, name);
3354
3355 switch_mutex_lock(event_channel_manager.lamutex);
3356 la = switch_core_hash_find(event_channel_manager.lahash, key);
3357 switch_mutex_unlock(event_channel_manager.lamutex);
3358
3359 if (la) {
3360 la->new = SWITCH_FALSE;
3361 } else {
3362 la = switch_core_alloc(pool, sizeof(*la))switch_core_perform_alloc(pool, sizeof(*la), "src/switch_event.c"
, (const char *)__func__, 3362)
;
3363 la->pool = pool;
3364 la->serno = 1;
3365 la->visible = SWITCH_TRUE;
3366 la->event_channel = switch_core_strdup(la->pool, event_channel)switch_core_perform_strdup(la->pool, event_channel, "src/switch_event.c"
, (const char *)__func__, 3366)
;
3367 la->name = switch_core_strdup(la->pool, name)switch_core_perform_strdup(la->pool, name, "src/switch_event.c"
, (const char *)__func__, 3367)
;
3368 la->key = key;
3369 la->new = SWITCH_TRUE;
3370 la->channel_id = channel_id;
3371 switch_core_hash_init(&la->hash)switch_core_hash_init_case(&la->hash, SWITCH_TRUE);
3372 switch_mutex_init(&la->mutex, SWITCH_MUTEX_NESTED0x1, la->pool);
3373
3374 switch_mutex_lock(event_channel_manager.lamutex);
3375 switch_core_hash_insert(event_channel_manager.lahash, la->key, la)switch_core_hash_insert_destructor(event_channel_manager.lahash
, la->key, la, ((void*)0))
;
3376 switch_mutex_unlock(event_channel_manager.lamutex);
3377 }
3378
3379 switch_mutex_lock(la->mutex);
3380 la->refs++;
3381 switch_mutex_unlock(la->mutex);
3382
3383 *live_arrayP = la;
3384
3385 return SWITCH_STATUS_SUCCESS;
3386}
3387
3388SWITCH_DECLARE(cJSON *)__attribute__((visibility("default"))) cJSON * switch_live_array_get(switch_live_array_t *la, const char *name)
3389{
3390 la_node_t *node;
3391 cJSON *dup = NULL((void*)0);
3392
3393 switch_mutex_lock(la->mutex);
3394 if ((node = switch_core_hash_find(la->hash, name))) {
3395 dup = cJSON_Duplicate(node->obj, 1);
3396 }
3397 switch_mutex_unlock(la->mutex);
3398
3399 return dup;
3400}
3401
3402SWITCH_DECLARE(cJSON *)__attribute__((visibility("default"))) cJSON * switch_live_array_get_idx(switch_live_array_t *la, int idx)
3403{
3404 la_node_t *node;
3405 cJSON *dup = NULL((void*)0);
3406
3407 switch_mutex_lock(la->mutex);
3408 for (node = la->head; node; node = node->next) {
3409 if (node->pos == idx) {
3410 dup = cJSON_Duplicate(node->obj, 1);
3411 break;
3412 }
3413 }
3414 switch_mutex_unlock(la->mutex);
3415
3416 return dup;
3417}
3418
3419SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_live_array_lock(switch_live_array_t *la)
3420{
3421 switch_mutex_lock(la->mutex);
3422}
3423
3424SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_live_array_unlock(switch_live_array_t *la)
3425{
3426 switch_mutex_unlock(la->mutex);
3427}
3428
3429SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_live_array_del(switch_live_array_t *la, const char *name)
3430{
3431 switch_status_t status = SWITCH_STATUS_FALSE;
3432 la_node_t *node, *cur, *np, *last = NULL((void*)0);
3433 cJSON *msg, *data = NULL((void*)0);
3434
3435 switch_mutex_lock(la->mutex);
3436 if ((node = switch_core_hash_find(la->hash, name))) {
3437 np = la->head;
3438
3439 while(np) {
3440 cur = np;
3441 np = np->next;
3442
3443 if (cur == node) {
3444 if (last) {
3445 last->next = cur->next;
3446 } else {
3447 la->head = cur->next;
3448 }
3449 switch_core_hash_delete(la->hash, name);
3450
3451 msg = cJSON_CreateObject();
3452 data = json_add_child_obj(msg, "data", NULL((void*)0));
3453
3454 cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
3455 cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
3456 cJSON_AddItemToObject(data, "action", cJSON_CreateString("del"));
3457 cJSON_AddItemToObject(data, "hashKey", cJSON_CreateString(cur->name));
3458 cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(la->serno++));
3459 cJSON_AddItemToObject(data, "data", cur->obj);
3460 cur->obj = NULL((void*)0);
3461
3462 la_broadcast(la, &msg);
3463 free(cur->name);
3464 free(cur);
3465 } else {
3466 cur->pos = la->pos++;
3467 la->tail = cur;
3468 last = cur;
3469 }
3470 }
3471 }
3472 switch_mutex_unlock(la->mutex);
3473
3474 return status;
3475}
3476
3477SWITCH_DECLARE(switch_status_t)__attribute__((visibility("default"))) switch_status_t switch_live_array_add(switch_live_array_t *la, const char *name, int index, cJSON **obj, switch_bool_t duplicate)
3478{
3479 la_node_t *node;
3480 switch_status_t status = SWITCH_STATUS_SUCCESS;
3481 const char *action = "add";
3482 cJSON *msg = NULL((void*)0), *data = NULL((void*)0);
3483
3484 switch_mutex_lock(la->mutex);
3485
3486 if ((node = switch_core_hash_find(la->hash, name))) {
3487
3488 action = "modify";
3489
3490 if (node->obj) {
3491 if (duplicate) {
3492 cJSON_Delete(node->obj);
3493 node->obj = NULL((void*)0);
3494 }
3495 }
3496 } else {
3497 switch_zmalloc(node, sizeof(*node))(void)((((node = calloc(1, (sizeof(*node))))) ? (void) (0) : __assert_fail
("(node = calloc(1, (sizeof(*node))))", "src/switch_event.c"
, 3497, __PRETTY_FUNCTION__)),node)
;
3498
3499 node->name = strdup(name)(__extension__ (__builtin_constant_p (name) && ((size_t
)(const void *)((name) + 1) - (size_t)(const void *)(name) ==
1) ? (((const char *) (name))[0] == '\0' ? (char *) calloc (
(size_t) 1, (size_t) 1) : ({ size_t __len = strlen (name) + 1
; char *__retval = (char *) malloc (__len); if (__retval != (
(void*)0)) __retval = (char *) memcpy (__retval, name, __len)
; __retval; })) : __strdup (name)))
;
3500 switch_core_hash_insert(la->hash, name, node)switch_core_hash_insert_destructor(la->hash, name, node, (
(void*)0))
;
3501
3502 if (index > -1 && index < la->pos && la->head) {
3503 la_node_t *np, *last = NULL((void*)0);
3504 int i = 0;
3505
3506 for(np = la->head; np; np = np->next) {
3507
3508 if (i == index) {
3509 if (last) {
3510 node->next = last->next;
3511 last->next = node;
3512 np = node;
3513 } else {
3514 node->next = la->head;
3515 la->head = node;
3516 np = node;
3517 }
3518 }
3519
3520 np->pos = i;
3521 la->tail = np;
3522 last = np;
3523 i++;
3524 }
3525
3526
3527 } else {
3528
3529 node->pos = la->pos++;
3530 index = node->pos;
3531
3532 if (!la->head) {
3533 la->head = node;
3534 } else {
3535 la->tail->next = node;
3536 }
3537
3538 la->tail = node;
3539 }
3540 }
3541
3542 if (duplicate) {
3543 node->obj = cJSON_Duplicate(*obj, 1);
3544 } else {
3545 node->obj = *obj;
3546 }
3547
3548 msg = cJSON_CreateObject();
3549 data = json_add_child_obj(msg, "data", NULL((void*)0));
3550
3551 cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(la->event_channel));
3552 cJSON_AddItemToObject(data, "action", cJSON_CreateString(action));
3553
3554 if (index > -1) {
3555 cJSON_AddItemToObject(data, "arrIndex", cJSON_CreateNumber(index));
3556 }
3557
3558 cJSON_AddItemToObject(data, "name", cJSON_CreateString(la->name));
3559 cJSON_AddItemToObject(data, "hashKey", cJSON_CreateString(node->name));
3560 cJSON_AddItemToObject(data, "wireSerno", cJSON_CreateNumber(la->serno++));
3561 cJSON_AddItemToObject(data, "data", cJSON_Duplicate(node->obj, 1));
3562
3563 la_broadcast(la, &msg);
3564
3565 switch_mutex_unlock(la->mutex);
3566
3567 return status;
3568}
3569
3570SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_live_array_set_user_data(switch_live_array_t *la, void *user_data)
3571{
3572 switch_assert(la)((la) ? (void) (0) : __assert_fail ("la", "src/switch_event.c"
, 3572, __PRETTY_FUNCTION__))
;
3573 la->user_data = user_data;
3574}
3575
3576SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_live_array_set_command_handler(switch_live_array_t *la, switch_live_array_command_handler_t command_handler)
3577{
3578 switch_assert(la)((la) ? (void) (0) : __assert_fail ("la", "src/switch_event.c"
, 3578, __PRETTY_FUNCTION__))
;
3579 la->command_handler = command_handler;
3580}
3581
3582
3583SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_live_array_parse_json(cJSON *json, switch_event_channel_id_t channel_id)
3584{
3585 const char *context = NULL((void*)0), *name = NULL((void*)0);
3586 switch_live_array_t *la = NULL((void*)0);
3587 cJSON *jla = NULL((void*)0);
3588
3589 if ((jla = cJSON_GetObjectItem(json, "data")) && (jla = cJSON_GetObjectItem(jla, "liveArray"))) {
3590
3591 if ((context = cJSON_GetObjectCstr(jla, "context")) && (name = cJSON_GetObjectCstr(jla, "name"))) {
3592 const char *command = cJSON_GetObjectCstr(jla, "command");
3593 const char *sessid = cJSON_GetObjectCstr(json, "sessid");
3594
3595 if (command) {
3596 if (switch_live_array_create(context, name, channel_id, &la) == SWITCH_STATUS_SUCCESS) {
3597
3598 if (!strcasecmp(command, "bootstrap")) {
3599 switch_live_array_bootstrap(la, sessid, channel_id);
3600 } else {
3601 if (la->command_handler) {
3602 la->command_handler(la, command, sessid, jla, la->user_data);
3603 }
3604 }
3605 switch_live_array_destroy(&la);
3606 }
3607 }
3608 }
3609 }
3610
3611}
3612
3613/* For Emacs:
3614 * Local Variables:
3615 * mode:c
3616 * indent-tabs-mode:t
3617 * tab-width:4
3618 * c-basic-offset:4
3619 * End:
3620 * For VIM:
3621 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3622 */