File: | src/switch_event.c |
Location: | line 3561, column 38 |
Description: | Potential leak of memory pointed to by 'node' |
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 */ | |||
46 | struct 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 */ | |||
61 | struct 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 | ||||
71 | static 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 | |||
81 | static unsigned int MAX_DISPATCH = MAX_DISPATCH_VAL64; | |||
82 | static unsigned int SOFT_MAX_DISPATCH = 0; | |||
83 | static char guess_ip_v4[80] = ""; | |||
84 | static char guess_ip_v6[80] = ""; | |||
85 | static switch_event_node_t *EVENT_NODES[SWITCH_EVENT_ALL + 1] = { NULL((void*)0) }; | |||
86 | static switch_thread_rwlock_t *RWLOCK = NULL((void*)0); | |||
87 | static switch_mutex_t *BLOCK = NULL((void*)0); | |||
88 | static switch_mutex_t *POOL_LOCK = NULL((void*)0); | |||
89 | static switch_memory_pool_t *RUNTIME_POOL = NULL((void*)0); | |||
90 | static switch_memory_pool_t *THRUNTIME_POOL = NULL((void*)0); | |||
91 | static switch_thread_t *EVENT_DISPATCH_QUEUE_THREADS[MAX_DISPATCH_VAL64] = { 0 }; | |||
92 | static uint8_t EVENT_DISPATCH_QUEUE_RUNNING[MAX_DISPATCH_VAL64] = { 0 }; | |||
93 | static switch_queue_t *EVENT_DISPATCH_QUEUE = NULL((void*)0); | |||
94 | static switch_queue_t *EVENT_CHANNEL_DISPATCH_QUEUE = NULL((void*)0); | |||
95 | static switch_mutex_t *EVENT_QUEUE_MUTEX = NULL((void*)0); | |||
96 | static switch_hash_t *CUSTOM_HASH = NULL((void*)0); | |||
97 | static int THREAD_COUNT = 0; | |||
98 | static int DISPATCH_THREAD_COUNT = 0; | |||
99 | static int EVENT_CHANNEL_DISPATCH_THREAD_COUNT = 0; | |||
100 | static int EVENT_CHANNEL_DISPATCH_THREAD_STARTING = 0; | |||
101 | static int SYSTEM_RUNNING = 0; | |||
102 | static uint64_t EVENT_SEQUENCE_NR = 0; | |||
103 | #ifdef SWITCH_EVENT_RECYCLE | |||
104 | static switch_queue_t *EVENT_RECYCLE_QUEUE = NULL((void*)0); | |||
105 | static switch_queue_t *EVENT_HEADER_RECYCLE_QUEUE = NULL((void*)0); | |||
106 | #endif | |||
107 | ||||
108 | static void unsub_all_switch_event_channel(void); | |||
109 | ||||
110 | static 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 | */ | |||
132 | static 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 | ||||
225 | static 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 | ||||
264 | static 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 | ||||
273 | static 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 | ||||
291 | static 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 | ||||
348 | static int PENDING = 0; | |||
349 | ||||
350 | static 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 | ||||
392 | SWITCH_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 | ||||
417 | SWITCH_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 | ||||
422 | SWITCH_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 | ||||
430 | SWITCH_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 | ||||
446 | SWITCH_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 | ||||
473 | SWITCH_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 | ||||
499 | SWITCH_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 | ||||
524 | SWITCH_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 | ||||
600 | static 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 | ||||
619 | SWITCH_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 | ||||
660 | SWITCH_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 | ||||
708 | SWITCH_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 | ||||
750 | SWITCH_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 | ||||
757 | SWITCH_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 | ||||
786 | SWITCH_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 | ||||
807 | SWITCH_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 | ||||
828 | SWITCH_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 | ||||
833 | SWITCH_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 | ||||
889 | static 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 | ||||
912 | SWITCH_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 | ||||
958 | static 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 | ||||
1150 | SWITCH_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 | ||||
1167 | SWITCH_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 | ||||
1179 | SWITCH_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 | ||||
1187 | SWITCH_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 | ||||
1198 | SWITCH_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 | ||||
1221 | SWITCH_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 | ||||
1273 | SWITCH_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 | ||||
1292 | SWITCH_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 | ||||
1329 | SWITCH_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 | ||||
1388 | SWITCH_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 | ||||
1436 | SWITCH_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 | ||||
1477 | SWITCH_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 | ||||
1592 | SWITCH_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 | ||||
1614 | SWITCH_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 | ||||
1718 | SWITCH_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 | ||||
1769 | SWITCH_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 | ||||
1807 | SWITCH_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 | ||||
1823 | static 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 | ||||
1842 | SWITCH_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"))) { | |||
1853 | return xml; | |||
1854 | } | |||
1855 | ||||
1856 | if (!zstr(fmt)_zstr(fmt)) { | |||
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) { | |||
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 ))) { | |||
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 | ||||
1919 | SWITCH_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 | ||||
1952 | SWITCH_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 | ||||
1986 | SWITCH_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 | ||||
2044 | SWITCH_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 | ||||
2051 | SWITCH_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 | ||||
2092 | SWITCH_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 | ||||
2130 | SWITCH_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); }} {\ | |||
2159 | char *dp;\ | |||
2160 | olen += (len + l + block);\ | |||
2161 | cpos = c - data;\ | |||
2162 | if ((dp = realloc(data, olen))) {\ | |||
2163 | data = dp;\ | |||
2164 | c = data + cpos;\ | |||
2165 | memset(c, 0, olen - cpos);\ | |||
2166 | }} \ | |||
2167 | ||||
2168 | SWITCH_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 | ||||
2463 | SWITCH_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 | ||||
2548 | SWITCH_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 | ||||
2577 | SWITCH_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 | ||||
2607 | SWITCH_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 | ||||
2636 | struct switch_event_channel_sub_node_head_s; | |||
2637 | ||||
2638 | typedef 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 | ||||
2645 | typedef 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 | ||||
2651 | static 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 | ||||
2688 | static 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 | ||||
2717 | static 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 | ||||
2748 | static 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 | ||||
2804 | typedef 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 | ||||
2813 | static 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 | ||||
2836 | static 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 | ||||
2851 | static 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 | ||||
2872 | static 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 | ||||
2913 | SWITCH_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 | ||||
2971 | SWITCH_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 | ||||
2976 | SWITCH_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 | ||||
2994 | SWITCH_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 | ||||
3008 | SWITCH_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 | ||||
3032 | SWITCH_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 | ||||
3045 | typedef 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 | ||||
3052 | typedef struct la_node_s { | |||
3053 | char *name; | |||
3054 | cJSON *obj; | |||
3055 | struct la_node_s *next; | |||
3056 | int pos; | |||
3057 | } la_node_t; | |||
3058 | ||||
3059 | struct 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 | ||||
3079 | static 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 | ||||
3102 | SWITCH_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 | ||||
3126 | SWITCH_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 | ||||
3160 | SWITCH_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 | ||||
3232 | SWITCH_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 | ||||
3270 | SWITCH_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 | ||||
3275 | SWITCH_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 | ||||
3307 | SWITCH_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 | ||||
3345 | SWITCH_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 | ||||
3388 | SWITCH_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 | ||||
3402 | SWITCH_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 | ||||
3419 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_live_array_lock(switch_live_array_t *la) | |||
3420 | { | |||
3421 | switch_mutex_lock(la->mutex); | |||
3422 | } | |||
3423 | ||||
3424 | SWITCH_DECLARE(void)__attribute__((visibility("default"))) void switch_live_array_unlock(switch_live_array_t *la) | |||
3425 | { | |||
3426 | switch_mutex_unlock(la->mutex); | |||
3427 | } | |||
3428 | ||||
3429 | SWITCH_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 | ||||
3477 | SWITCH_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 | ||||
3570 | SWITCH_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 | ||||
3576 | SWITCH_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 | ||||
3583 | SWITCH_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 | */ |