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