File: | src/switch_event.c |
Location: | line 1906, column 17 |
Description: | Potential leak of memory pointed to by '__retval' |
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 | */ |