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