File: | src/switch_event.c |
Location: | line 1547, column 5 |
Description: | Value stored to 'buf' is never read |
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; |
Value stored to 'buf' is never read | |
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 | */ |