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