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