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