Asterisk - The Open Source Telephony Project  18.5.0
stasis_channels.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013, Digium, Inc.
5  *
6  * Matt Jordan <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Stasis Messages and Data Types for Channel Objects
22  *
23  * \author \verbatim Matt Jordan <[email protected]> \endverbatim
24  *
25  */
26 
27 /*** MODULEINFO
28  <support_level>core</support_level>
29  ***/
30 
31 #include "asterisk.h"
32 
33 #include "asterisk/astobj2.h"
34 #include "asterisk/json.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/bridge.h"
37 #include "asterisk/translate.h"
38 #include "asterisk/stasis.h"
40 #include "asterisk/dial.h"
41 #include "asterisk/linkedlists.h"
42 
43 /*** DOCUMENTATION
44  <managerEvent language="en_US" name="VarSet">
45  <managerEventInstance class="EVENT_FLAG_DIALPLAN">
46  <synopsis>Raised when a variable is set to a particular value.</synopsis>
47  <syntax>
48  <channel_snapshot/>
49  <parameter name="Variable">
50  <para>The variable being set.</para>
51  </parameter>
52  <parameter name="Value">
53  <para>The new value of the variable.</para>
54  </parameter>
55  </syntax>
56  </managerEventInstance>
57  </managerEvent>
58  <managerEvent language="en_US" name="AgentLogin">
59  <managerEventInstance class="EVENT_FLAG_AGENT">
60  <synopsis>Raised when an Agent has logged in.</synopsis>
61  <syntax>
62  <channel_snapshot/>
63  <parameter name="Agent">
64  <para>Agent ID of the agent.</para>
65  </parameter>
66  </syntax>
67  <see-also>
68  <ref type="application">AgentLogin</ref>
69  <ref type="managerEvent">AgentLogoff</ref>
70  </see-also>
71  </managerEventInstance>
72  </managerEvent>
73  <managerEvent language="en_US" name="AgentLogoff">
74  <managerEventInstance class="EVENT_FLAG_AGENT">
75  <synopsis>Raised when an Agent has logged off.</synopsis>
76  <syntax>
77  <xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentLogin']/managerEventInstance/syntax/parameter)" />
78  <parameter name="Logintime">
79  <para>The number of seconds the agent was logged in.</para>
80  </parameter>
81  </syntax>
82  <see-also>
83  <ref type="managerEvent">AgentLogin</ref>
84  </see-also>
85  </managerEventInstance>
86  </managerEvent>
87  <managerEvent language="en_US" name="ChannelTalkingStart">
88  <managerEventInstance class="EVENT_FLAG_CLASS">
89  <synopsis>Raised when talking is detected on a channel.</synopsis>
90  <syntax>
91  <channel_snapshot/>
92  </syntax>
93  <see-also>
94  <ref type="function">TALK_DETECT</ref>
95  <ref type="managerEvent">ChannelTalkingStop</ref>
96  </see-also>
97  </managerEventInstance>
98  </managerEvent>
99  <managerEvent language="en_US" name="ChannelTalkingStop">
100  <managerEventInstance class="EVENT_FLAG_CLASS">
101  <synopsis>Raised when talking is no longer detected on a channel.</synopsis>
102  <syntax>
103  <channel_snapshot/>
104  <parameter name="Duration">
105  <para>The length in time, in milliseconds, that talking was
106  detected on the channel.</para>
107  </parameter>
108  </syntax>
109  <see-also>
110  <ref type="function">TALK_DETECT</ref>
111  <ref type="managerEvent">ChannelTalkingStart</ref>
112  </see-also>
113  </managerEventInstance>
114  </managerEvent>
115 ***/
116 
117 #define NUM_MULTI_CHANNEL_BLOB_BUCKETS 7
118 
122 
124 {
125  return ao2_bump(channel_cache);
126 }
127 
129 {
130  return channel_topic_all;
131 }
132 
134 {
135  return ao2_bump(channel_cache_by_name);
136 }
137 
138 /*!
139  * \internal
140  * \brief Hash function for \ref ast_channel_snapshot objects
141  */
142 static int channel_snapshot_hash_cb(const void *obj, const int flags)
143 {
144  const struct ast_channel_snapshot *object = obj;
145  const char *key;
146 
147  switch (flags & OBJ_SEARCH_MASK) {
148  case OBJ_SEARCH_KEY:
149  key = obj;
150  break;
151  case OBJ_SEARCH_OBJECT:
152  key = object->base->name;
153  break;
154  default:
155  ast_assert(0);
156  return 0;
157  }
158  return ast_str_case_hash(key);
159 }
160 
161 /*!
162  * \internal
163  * \brief Comparison function for \ref ast_channel_snapshot objects
164  */
165 static int channel_snapshot_cmp_cb(void *obj, void *arg, int flags)
166 {
167  const struct ast_channel_snapshot *object_left = obj;
168  const struct ast_channel_snapshot *object_right = arg;
169  const char *right_key = arg;
170  int cmp;
171 
172  switch (flags & OBJ_SEARCH_MASK) {
173  case OBJ_SEARCH_OBJECT:
174  right_key = object_right->base->name;
175  case OBJ_SEARCH_KEY:
176  cmp = strcasecmp(object_left->base->name, right_key);
177  break;
179  cmp = strncasecmp(object_left->base->name, right_key, strlen(right_key));
180  break;
181  default:
182  cmp = 0;
183  break;
184  }
185  if (cmp) {
186  return 0;
187  }
188  return CMP_MATCH;
189 }
190 
191 /*!
192  * \internal
193  * \brief Hash function (using uniqueid) for \ref ast_channel_snapshot objects
194  */
195 static int channel_snapshot_uniqueid_hash_cb(const void *obj, const int flags)
196 {
197  const struct ast_channel_snapshot *object = obj;
198  const char *key;
199 
200  switch (flags & OBJ_SEARCH_MASK) {
201  case OBJ_SEARCH_KEY:
202  key = obj;
203  break;
204  case OBJ_SEARCH_OBJECT:
205  key = object->base->uniqueid;
206  break;
207  default:
208  ast_assert(0);
209  return 0;
210  }
211  return ast_str_case_hash(key);
212 }
213 
214 /*!
215  * \internal
216  * \brief Comparison function (using uniqueid) for \ref ast_channel_snapshot objects
217  */
218 static int channel_snapshot_uniqueid_cmp_cb(void *obj, void *arg, int flags)
219 {
220  const struct ast_channel_snapshot *object_left = obj;
221  const struct ast_channel_snapshot *object_right = arg;
222  const char *right_key = arg;
223  int cmp;
224 
225  switch (flags & OBJ_SEARCH_MASK) {
226  case OBJ_SEARCH_OBJECT:
227  right_key = object_right->base->uniqueid;
228  case OBJ_SEARCH_KEY:
229  cmp = strcasecmp(object_left->base->uniqueid, right_key);
230  break;
232  cmp = strncasecmp(object_left->base->uniqueid, right_key, strlen(right_key));
233  break;
234  default:
235  cmp = 0;
236  break;
237  }
238  if (cmp) {
239  return 0;
240  }
241  return CMP_MATCH;
242 }
243 
244 static void channel_snapshot_dtor(void *obj)
245 {
246  struct ast_channel_snapshot *snapshot = obj;
247 
248  ao2_cleanup(snapshot->base);
249  ao2_cleanup(snapshot->peer);
250  ao2_cleanup(snapshot->caller);
251  ao2_cleanup(snapshot->connected);
252  ao2_cleanup(snapshot->bridge);
253  ao2_cleanup(snapshot->dialplan);
254  ao2_cleanup(snapshot->hangup);
255  ao2_cleanup(snapshot->manager_vars);
256  ao2_cleanup(snapshot->ari_vars);
257 }
258 
259 static void channel_snapshot_base_dtor(void *obj)
260 {
261  struct ast_channel_snapshot_base *snapshot = obj;
262 
264 }
265 
267 {
268  struct ast_channel_snapshot_base *snapshot;
269 
270  snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_base_dtor,
272  if (!snapshot) {
273  return NULL;
274  }
275 
276  if (ast_string_field_init(snapshot, 256)) {
277  ao2_ref(snapshot, -1);
278  return NULL;
279  }
280 
281  ast_string_field_set(snapshot, name, ast_channel_name(chan));
282  ast_string_field_set(snapshot, type, ast_channel_tech(chan)->type);
287 
288  snapshot->creationtime = ast_channel_creationtime(chan);
289  snapshot->tech_properties = ast_channel_tech(chan)->properties;
290 
291  return snapshot;
292 }
293 
295 {
296  const char *linkedid = S_OR(ast_channel_linkedid(chan), "");
297  const char *peeraccount = S_OR(ast_channel_peeraccount(chan), "");
298  size_t linkedid_len = strlen(linkedid) + 1;
299  size_t peeraccount_len = strlen(peeraccount) + 1;
300  struct ast_channel_snapshot_peer *snapshot;
301 
302  snapshot = ao2_alloc_options(sizeof(*snapshot) + linkedid_len + peeraccount_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
303  if (!snapshot) {
304  return NULL;
305  }
306 
307  strcpy(snapshot->account, peeraccount); /* Safe */
308  snapshot->linkedid = snapshot->account + peeraccount_len;
309  ast_copy_string(snapshot->linkedid, linkedid, linkedid_len); /* Safe */
310 
311  return snapshot;
312 }
313 
314 static void channel_snapshot_caller_dtor(void *obj)
315 {
316  struct ast_channel_snapshot_caller *snapshot = obj;
317 
319 }
320 
322 {
323  struct ast_channel_snapshot_caller *snapshot;
324 
325  snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_caller_dtor,
327  if (!snapshot) {
328  return NULL;
329  }
330 
331  if (ast_string_field_init(snapshot, 256)) {
332  ao2_ref(snapshot, -1);
333  return NULL;
334  }
335 
336  ast_string_field_set(snapshot, name,
337  S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));
338  ast_string_field_set(snapshot, number,
339  S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));
340  ast_string_field_set(snapshot, subaddr,
341  S_COR(ast_channel_caller(chan)->id.subaddress.valid, ast_channel_caller(chan)->id.subaddress.str, ""));
342  ast_string_field_set(snapshot, ani,
343  S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""));
344 
345  ast_string_field_set(snapshot, rdnis,
346  S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""));
347 
348  ast_string_field_set(snapshot, dnid,
349  S_OR(ast_channel_dialed(chan)->number.str, ""));
351  S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, ""));
352 
353  snapshot->pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
354 
355  return snapshot;
356 }
357 
359 {
360  const char *name = S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, "");
361  const char *number = S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, "");
362  size_t name_len = strlen(name) + 1;
363  size_t number_len = strlen(number) + 1;
364  struct ast_channel_snapshot_connected *snapshot;
365 
366  snapshot = ao2_alloc_options(sizeof(*snapshot) + name_len + number_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
367  if (!snapshot) {
368  return NULL;
369  }
370 
371  strcpy(snapshot->name, name); /* Safe */
372  snapshot->number = snapshot->name + name_len;
373  ast_copy_string(snapshot->number, number, number_len); /* Safe */
374 
375  return snapshot;
376 }
377 
379 {
380  const char *uniqueid = "";
381  struct ast_bridge *bridge;
382  struct ast_channel_snapshot_bridge *snapshot;
383 
384  bridge = ast_channel_get_bridge(chan);
385  if (bridge && !ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_INVISIBLE)) {
386  uniqueid = bridge->uniqueid;
387  }
388  ao2_cleanup(bridge);
389 
390  snapshot = ao2_alloc_options(sizeof(*snapshot) + strlen(uniqueid) + 1, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
391  if (!snapshot) {
392  return NULL;
393  }
394 
395  strcpy(snapshot->id, uniqueid); /* Safe */
396 
397  return snapshot;
398 }
399 
400 static void channel_snapshot_dialplan_dtor(void *obj)
401 {
402  struct ast_channel_snapshot_dialplan *snapshot = obj;
403 
405 }
406 
408 {
409  struct ast_channel_snapshot_dialplan *snapshot;
410 
411  snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_dialplan_dtor,
413  if (!snapshot) {
414  return NULL;
415  }
416 
417  if (ast_string_field_init(snapshot, 256)) {
418  ao2_ref(snapshot, -1);
419  return NULL;
420  }
421 
422  if (ast_channel_appl(chan)) {
423  ast_string_field_set(snapshot, appl, ast_channel_appl(chan));
424  }
425  if (ast_channel_data(chan)) {
426  ast_string_field_set(snapshot, data, ast_channel_data(chan));
427  }
429  ast_string_field_set(snapshot, exten, ast_channel_exten(chan));
430  snapshot->priority = ast_channel_priority(chan);
431 
432  return snapshot;
433 }
434 
436 {
437  const char *hangupsource = S_OR(ast_channel_hangupsource(chan), "");
438  struct ast_channel_snapshot_hangup *snapshot;
439 
440  snapshot = ao2_alloc_options(sizeof(*snapshot) + strlen(hangupsource) + 1, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
441  if (!snapshot) {
442  return NULL;
443  }
444 
445  snapshot->cause = ast_channel_hangupcause(chan);
446  strcpy(snapshot->source, hangupsource); /* Safe */
447 
448  return snapshot;
449 }
450 
452 {
453  struct ast_channel_snapshot *old_snapshot;
454  struct ast_channel_snapshot *snapshot;
455 
456  /* no snapshots for dummy channels */
457  if (!ast_channel_tech(chan)) {
458  return NULL;
459  }
460 
461  snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_dtor,
463  if (!snapshot) {
464  return NULL;
465  }
466 
467  old_snapshot = ast_channel_snapshot(chan);
468 
469  /* Channels automatically have all segments invalidated on them initially so a check for an old
470  * snapshot existing before usage is not done here, as it can not happen. If the stored snapshot
471  * on the channel is updated as a result of this then all segments marked as invalidated will be
472  * cleared.
473  */
475  /* The base information has changed so update our snapshot */
476  snapshot->base = channel_snapshot_base_create(chan);
477  if (!snapshot->base) {
478  ao2_ref(snapshot, -1);
479  return NULL;
480  }
481  } else {
482  snapshot->base = ao2_bump(old_snapshot->base);
483  }
484 
486  /* The peer information has changed so update our snapshot */
487  snapshot->peer = channel_snapshot_peer_create(chan);
488  if (!snapshot->peer) {
489  ao2_ref(snapshot, -1);
490  return NULL;
491  }
492  } else {
493  snapshot->peer = ao2_bump(old_snapshot->peer);
494  }
495 
496  /* Unfortunately both caller and connected information do not have an enforced contract with
497  * the channel API. This has allowed consumers to directly get the caller or connected structure
498  * and manipulate it. Until such time as there is an enforced contract (which is being tracked under
499  * ASTERISK-28164) they are each regenerated every time a channel snapshot is created.
500  */
501  snapshot->caller = channel_snapshot_caller_create(chan);
502  if (!snapshot->caller) {
503  ao2_ref(snapshot, -1);
504  return NULL;
505  }
506 
508  if (!snapshot->connected) {
509  ao2_ref(snapshot, -1);
510  return NULL;
511  }
512 
514  /* The bridge has changed so update our snapshot */
515  snapshot->bridge = channel_snapshot_bridge_create(chan);
516  if (!snapshot->bridge) {
517  ao2_ref(snapshot, -1);
518  return NULL;
519  }
520  } else {
521  snapshot->bridge = ao2_bump(old_snapshot->bridge);
522  }
523 
525  /* The dialplan information has changed so update our snapshot */
526  snapshot->dialplan = channel_snapshot_dialplan_create(chan);
527  if (!snapshot->dialplan) {
528  ao2_ref(snapshot, -1);
529  return NULL;
530  }
531  } else {
532  snapshot->dialplan = ao2_bump(old_snapshot->dialplan);
533  }
534 
536  /* The hangup information has changed so update our snapshot */
537  snapshot->hangup = channel_snapshot_hangup_create(chan);
538  if (!snapshot->hangup) {
539  ao2_ref(snapshot, -1);
540  return NULL;
541  }
542  } else {
543  snapshot->hangup = ao2_bump(old_snapshot->hangup);
544  }
545 
546  snapshot->state = ast_channel_state(chan);
547  snapshot->amaflags = ast_channel_amaflags(chan);
548  ast_copy_flags(&snapshot->flags, ast_channel_flags(chan), 0xFFFFFFFF);
550 
551  /* These have to be recreated as they may have changed, unfortunately */
552  snapshot->manager_vars = ast_channel_get_manager_vars(chan);
553  snapshot->ari_vars = ast_channel_get_ari_vars(chan);
554 
555  return snapshot;
556 }
557 
558 static void channel_snapshot_update_dtor(void *obj)
559 {
560  struct ast_channel_snapshot_update *update = obj;
561 
562  ao2_cleanup(update->old_snapshot);
563  ao2_cleanup(update->new_snapshot);
564 }
565 
567 {
569 
570  update = ao2_alloc_options(sizeof(*update), channel_snapshot_update_dtor,
572  if (!update) {
573  return NULL;
574  }
575 
576  update->old_snapshot = ao2_bump(ast_channel_snapshot(chan));
578  if (!update->new_snapshot) {
579  ao2_ref(update, -1);
580  return NULL;
581  }
582 
583  return update;
584 }
585 
587 {
588  if (chan) {
589  stasis_publish(ast_channel_topic(chan), message);
590  } else {
592  }
593 }
594 
595 static void channel_blob_dtor(void *obj)
596 {
597  struct ast_channel_blob *event = obj;
598  ao2_cleanup(event->snapshot);
599  ast_json_unref(event->blob);
600 }
601 
603  struct ast_channel *peer, struct ast_channel *forwarded, const char *dialstring,
604  const char *dialstatus, const char *forward)
605 {
606  struct ast_multi_channel_blob *payload;
607  struct stasis_message *msg;
608  struct ast_json *blob;
609  struct ast_channel_snapshot *peer_snapshot;
610 
611  if (!ast_channel_dial_type()) {
612  return;
613  }
614 
615  ast_assert(peer != NULL);
616 
617  blob = ast_json_pack("{s: s, s: s, s: s}",
618  "dialstatus", S_OR(dialstatus, ""),
619  "forward", S_OR(forward, ""),
620  "dialstring", S_OR(dialstring, ""));
621  if (!blob) {
622  return;
623  }
624  payload = ast_multi_channel_blob_create(blob);
625  ast_json_unref(blob);
626  if (!payload) {
627  return;
628  }
629 
630  if (caller) {
631  struct ast_channel_snapshot *caller_snapshot;
632 
633  ast_channel_lock(caller);
634  if (ast_strlen_zero(dialstatus)) {
635  caller_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(caller));
636  } else {
637  caller_snapshot = ast_channel_snapshot_create(caller);
638  }
639  ast_channel_unlock(caller);
640  if (!caller_snapshot) {
641  ao2_ref(payload, -1);
642  return;
643  }
644  ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot);
645  ao2_ref(caller_snapshot, -1);
646  }
647 
648  ast_channel_lock(peer);
649  if (ast_strlen_zero(dialstatus)) {
651  } else {
652  peer_snapshot = ast_channel_snapshot_create(peer);
653  }
654  ast_channel_unlock(peer);
655  if (!peer_snapshot) {
656  ao2_ref(payload, -1);
657  return;
658  }
659  ast_multi_channel_blob_add_channel(payload, "peer", peer_snapshot);
660  ao2_ref(peer_snapshot, -1);
661 
662  if (forwarded) {
663  struct ast_channel_snapshot *forwarded_snapshot;
664 
665  ast_channel_lock(forwarded);
666  forwarded_snapshot = ast_channel_snapshot_create(forwarded);
667  ast_channel_unlock(forwarded);
668  if (!forwarded_snapshot) {
669  ao2_ref(payload, -1);
670  return;
671  }
672  ast_multi_channel_blob_add_channel(payload, "forwarded", forwarded_snapshot);
673  ao2_ref(forwarded_snapshot, -1);
674  }
675 
677  ao2_ref(payload, -1);
678  if (msg) {
679  publish_message_for_channel_topics(msg, caller ?: peer);
680  ao2_ref(msg, -1);
681  }
682 }
683 
684 static void remove_dial_masquerade(struct ast_channel *peer);
686 static int set_dial_masquerade(struct ast_channel *caller,
687  struct ast_channel *peer, const char *dialstring);
688 
689 void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer,
690  struct ast_channel *forwarded, const char *dialstring, const char *dialstatus,
691  const char *forward)
692 {
693  ast_assert(peer != NULL);
694 
695  /* XXX With an early bridge the below dial masquerade datastore code could, theoretically,
696  * go away as the act of changing the channel during dialing would be done using the bridge
697  * API itself and not a masquerade.
698  */
699 
700  if (caller) {
701  /*
702  * Lock two or three channels.
703  *
704  * We need to hold the locks to hold off a potential masquerade
705  * messing up the stasis dial event ordering.
706  */
707  for (;; ast_channel_unlock(caller), sched_yield()) {
708  ast_channel_lock(caller);
709  if (ast_channel_trylock(peer)) {
710  continue;
711  }
712  if (forwarded && ast_channel_trylock(forwarded)) {
713  ast_channel_unlock(peer);
714  continue;
715  }
716  break;
717  }
718 
719  if (ast_strlen_zero(dialstatus)) {
720  set_dial_masquerade(caller, peer, dialstring);
721  } else {
723  }
724  }
725 
726  ast_channel_publish_dial_internal(caller, peer, forwarded, dialstring, dialstatus,
727  forward);
728 
729  if (caller) {
730  if (forwarded) {
731  ast_channel_unlock(forwarded);
732  }
733  ast_channel_unlock(peer);
735  ast_channel_unlock(caller);
736  }
737 }
738 
739 void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer,
740  const char *dialstring, const char *dialstatus)
741 {
742  ast_channel_publish_dial_forward(caller, peer, NULL, dialstring, dialstatus, NULL);
743 }
744 
746  struct stasis_message_type *type,
747  struct ast_json *blob)
748 {
749  struct stasis_message *msg;
750  struct ast_channel_blob *obj;
751 
752  obj = ao2_alloc(sizeof(*obj), channel_blob_dtor);
753  if (!obj) {
754  return NULL;
755  }
756 
757  if (snapshot) {
758  obj->snapshot = snapshot;
759  ao2_ref(obj->snapshot, +1);
760  }
761  if (!blob) {
762  blob = ast_json_null();
763  }
764  obj->blob = ast_json_ref(blob);
765 
766  msg = stasis_message_create(type, obj);
767  ao2_cleanup(obj);
768  return msg;
769 }
770 
771 struct stasis_message *ast_channel_blob_create_from_cache(const char *channel_id,
772  struct stasis_message_type *type,
773  struct ast_json *blob)
774 {
775  struct ast_channel_snapshot *snapshot;
776  struct stasis_message *msg;
777 
778  if (!type) {
779  return NULL;
780  }
781 
782  snapshot = ast_channel_snapshot_get_latest(channel_id);
783  msg = create_channel_blob_message(snapshot, type, blob);
784  ao2_cleanup(snapshot);
785  return msg;
786 }
787 
789  struct stasis_message_type *type, struct ast_json *blob)
790 {
791  struct ast_channel_snapshot *snapshot;
792  struct stasis_message *msg;
793 
794  if (!type) {
795  return NULL;
796  }
797 
798  snapshot = chan ? ao2_bump(ast_channel_snapshot(chan)) : NULL;
799  msg = create_channel_blob_message(snapshot, type, blob);
800  ao2_cleanup(snapshot);
801  return msg;
802 }
803 
804 /*! \brief A channel snapshot wrapper object used in \ref ast_multi_channel_blob objects */
806  struct ast_channel_snapshot *snapshot; /*!< A channel snapshot */
807  char role[0]; /*!< The role assigned to the channel */
808 };
809 
810 /*! \brief A multi channel blob data structure for multi_channel_blob stasis messages */
812  struct ao2_container *channel_snapshots; /*!< A container holding the snapshots */
813  struct ast_json *blob; /*!< A blob of JSON data */
814 };
815 
816 /*!
817  * \internal
818  * \brief Comparison function for \ref channel_role_snapshot objects
819  */
820 static int channel_role_cmp_cb(void *obj, void *arg, int flags)
821 {
822  const struct channel_role_snapshot *object_left = obj;
823  const struct channel_role_snapshot *object_right = arg;
824  const char *right_key = arg;
825  int cmp;
826 
827  switch (flags & OBJ_SEARCH_MASK) {
828  case OBJ_SEARCH_OBJECT:
829  right_key = object_right->role;
830  case OBJ_SEARCH_KEY:
831  cmp = strcasecmp(object_left->role, right_key);
832  break;
834  cmp = strncasecmp(object_left->role, right_key, strlen(right_key));
835  break;
836  default:
837  cmp = 0;
838  break;
839  }
840  if (cmp) {
841  return 0;
842  }
843  return CMP_MATCH;
844 }
845 
846 /*!
847  * \internal
848  * \brief Hash function for \ref channel_role_snapshot objects
849  */
850 static int channel_role_hash_cb(const void *obj, const int flags)
851 {
852  const struct channel_role_snapshot *object = obj;
853  const char *key;
854 
855  switch (flags & OBJ_SEARCH_MASK) {
856  case OBJ_SEARCH_KEY:
857  key = obj;
858  break;
859  case OBJ_SEARCH_OBJECT:
860  key = object->role;
861  break;
862  default:
863  ast_assert(0);
864  return 0;
865  }
866  return ast_str_case_hash(key);
867 }
868 
869 /*!
870  * \internal
871  * \brief Destructor for \ref ast_multi_channel_blob objects
872  */
873 static void multi_channel_blob_dtor(void *obj)
874 {
875  struct ast_multi_channel_blob *multi_blob = obj;
876 
877  ao2_cleanup(multi_blob->channel_snapshots);
878  ast_json_unref(multi_blob->blob);
879 }
880 
882 {
883  struct ast_multi_channel_blob *obj;
884 
885  ast_assert(blob != NULL);
886 
887  obj = ao2_alloc(sizeof(*obj), multi_channel_blob_dtor);
888  if (!obj) {
889  return NULL;
890  }
891 
894  if (!obj->channel_snapshots) {
895  ao2_ref(obj, -1);
896  return NULL;
897  }
898 
899  obj->blob = ast_json_ref(blob);
900  return obj;
901 }
902 
904 {
905  ast_assert(!ast_strlen_zero(uniqueid));
906 
907  return ao2_find(channel_cache, uniqueid, OBJ_SEARCH_KEY);
908 }
909 
911 {
912  ast_assert(!ast_strlen_zero(name));
913 
914  return ao2_find(channel_cache_by_name, name, OBJ_SEARCH_KEY);
915 }
916 
918 {
920  struct stasis_message *message;
921 
922  if (!ast_channel_snapshot_type()) {
923  return;
924  }
925 
926  update = channel_snapshot_update_create(chan);
927  if (!update) {
928  return;
929  }
930 
932  /* In the success path message holds a reference to update so it will be valid
933  * for the lifetime of this function until the end.
934  */
935  ao2_ref(update, -1);
936  if (!message) {
937  return;
938  }
939 
940  ao2_unlink(channel_cache, update->old_snapshot);
941  ao2_unlink(channel_cache_by_name, update->old_snapshot);
942 
944 
945  stasis_publish(ast_channel_topic(chan), message);
946  ao2_ref(message, -1);
947 }
948 
949 static void channel_role_snapshot_dtor(void *obj)
950 {
951  struct channel_role_snapshot *role_snapshot = obj;
952 
953  ao2_cleanup(role_snapshot->snapshot);
954 }
955 
957 {
958  struct channel_role_snapshot *role_snapshot;
959  int role_len = strlen(role) + 1;
960 
961  if (!obj || ast_strlen_zero(role) || !snapshot) {
962  return;
963  }
964 
965  role_snapshot = ao2_alloc_options(sizeof(*role_snapshot) + role_len,
967  if (!role_snapshot) {
968  return;
969  }
970  ast_copy_string(role_snapshot->role, role, role_len);
971  role_snapshot->snapshot = snapshot;
972  ao2_ref(role_snapshot->snapshot, +1);
973  ao2_link(obj->channel_snapshots, role_snapshot);
974  ao2_ref(role_snapshot, -1);
975 }
976 
978 {
979  struct channel_role_snapshot *role_snapshot;
981 
982  if (!obj || ast_strlen_zero(role)) {
983  return NULL;
984  }
985  role_snapshot = ao2_find(obj->channel_snapshots, role, OBJ_SEARCH_KEY);
986  /* Note that this function does not increase the ref count on snapshot */
987  if (!role_snapshot) {
988  return NULL;
989  }
990  snapshot = role_snapshot->snapshot;
991  ao2_ref(role_snapshot, -1);
992  return snapshot;
993 }
994 
996 {
997  struct ao2_container *ret_container;
998  struct ao2_iterator *it_role_snapshots;
999  struct channel_role_snapshot *role_snapshot;
1000  char *arg;
1001 
1002  if (!obj || ast_strlen_zero(role)) {
1003  return NULL;
1004  }
1005 
1009  if (!ret_container) {
1010  return NULL;
1011  }
1012 
1013  arg = ast_strdupa(role);
1014  it_role_snapshots = ao2_callback(obj->channel_snapshots,
1016  if (!it_role_snapshots) {
1017  ao2_ref(ret_container, -1);
1018  return NULL;
1019  }
1020 
1021  while ((role_snapshot = ao2_iterator_next(it_role_snapshots))) {
1022  ao2_link(ret_container, role_snapshot->snapshot);
1023  ao2_ref(role_snapshot, -1);
1024  }
1025  ao2_iterator_destroy(it_role_snapshots);
1026 
1027  return ret_container;
1028 }
1029 
1031 {
1032  if (!obj) {
1033  return NULL;
1034  }
1035  return obj->blob;
1036 }
1037 
1039 {
1041 }
1042 
1044 {
1047 }
1048 
1051 {
1053 }
1054 
1056 {
1058  struct stasis_message *message;
1059 
1060  if (!ast_channel_snapshot_type()) {
1061  return;
1062  }
1063 
1065  return;
1066  }
1067 
1068  update = channel_snapshot_update_create(chan);
1069  if (!update) {
1070  return;
1071  }
1072 
1073  /* If an old snapshot exists and is the same as this newly created one don't bother
1074  * raising a message as it hasn't changed.
1075  */
1076  if (update->old_snapshot && !memcmp(update->old_snapshot, update->new_snapshot, sizeof(struct ast_channel_snapshot))) {
1077  ao2_ref(update, -1);
1078  return;
1079  }
1080 
1081  message = stasis_message_create(ast_channel_snapshot_type(), update);
1082  /* In the success path message holds a reference to update so it will be valid
1083  * for the lifetime of this function until the end.
1084  */
1085  ao2_ref(update, -1);
1086  if (!message) {
1087  return;
1088  }
1089 
1090  /* We lock these ourselves so that the update is atomic and there isn't time where a
1091  * snapshot is not in the cache.
1092  */
1093  ao2_wrlock(channel_cache);
1094  if (update->old_snapshot) {
1095  ao2_unlink_flags(channel_cache, update->old_snapshot, OBJ_NOLOCK);
1096  }
1097  ao2_link_flags(channel_cache, update->new_snapshot, OBJ_NOLOCK);
1098  ao2_unlock(channel_cache);
1099 
1100  /* The same applies here. */
1101  ao2_wrlock(channel_cache_by_name);
1102  if (update->old_snapshot) {
1103  ao2_unlink_flags(channel_cache_by_name, update->old_snapshot, OBJ_NOLOCK);
1104  }
1105  ao2_link_flags(channel_cache_by_name, update->new_snapshot, OBJ_NOLOCK);
1106  ao2_unlock(channel_cache_by_name);
1107 
1108  ast_channel_snapshot_set(chan, update->new_snapshot);
1109 
1110  /* As this is now the new snapshot any existing invalidated segments have been
1111  * created fresh and are up to date.
1112  */
1114 
1115  ast_assert(ast_channel_topic(chan) != NULL);
1116  stasis_publish(ast_channel_topic(chan), message);
1117  ao2_ref(message, -1);
1118 }
1119 
1121 {
1122  struct stasis_message *message;
1123 
1124  if (!blob) {
1125  blob = ast_json_null();
1126  }
1127 
1128  message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), type, blob);
1129  if (message) {
1130  stasis_publish(ast_channel_topic(chan), message);
1131  ao2_ref(message, -1);
1132  }
1133 }
1134 
1135 void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
1136 {
1137  struct stasis_message *message;
1138 
1139  if (!blob) {
1140  blob = ast_json_null();
1141  }
1142 
1143  message = ast_channel_blob_create(chan, type, blob);
1144  if (message) {
1145  stasis_publish(ast_channel_topic(chan), message);
1146  ao2_ref(message, -1);
1147  }
1148 }
1149 
1150 void ast_channel_publish_varset(struct ast_channel *chan, const char *name, const char *value)
1151 {
1152  struct ast_json *blob;
1153 
1154  ast_assert(name != NULL);
1155  ast_assert(value != NULL);
1156 
1157  blob = ast_json_pack("{s: s, s: s}",
1158  "variable", name,
1159  "value", value);
1160  if (!blob) {
1161  ast_log(LOG_ERROR, "Error creating message\n");
1162  return;
1163  }
1164 
1165  /*! If there are manager variables, force a cache update */
1166  if (chan && ast_channel_has_manager_vars()) {
1168  }
1169 
1170  /* This function is NULL safe for global variables */
1172  ast_json_unref(blob);
1173 }
1174 
1176 {
1177  struct ast_str *channel_event_string;
1178  struct ast_channel_blob *obj = stasis_message_data(msg);
1179  const char *variable =
1180  ast_json_string_get(ast_json_object_get(obj->blob, "variable"));
1181  char *value;
1182  struct ast_manager_event_blob *ev;
1183 
1185  "value")));
1186  if (!value) {
1187  return NULL;
1188  }
1189 
1190  if (obj->snapshot) {
1191  channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
1192  } else {
1193  channel_event_string = ast_str_create(35);
1194  ast_str_set(&channel_event_string, 0,
1195  "Channel: none\r\n"
1196  "Uniqueid: none\r\n");
1197  }
1198  if (!channel_event_string) {
1199  ast_free(value);
1200  return NULL;
1201  }
1202 
1204  "%s"
1205  "Variable: %s\r\n"
1206  "Value: %s\r\n",
1207  ast_str_buffer(channel_event_string), variable, value);
1208  ast_free(channel_event_string);
1209  ast_free(value);
1210  return ev;
1211 }
1212 
1214 {
1215  struct ast_str *channel_string;
1216  struct ast_channel_blob *obj = stasis_message_data(msg);
1217  const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
1218  struct ast_manager_event_blob *ev;
1219 
1220  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1221  if (!channel_string) {
1222  return NULL;
1223  }
1224 
1226  "%s"
1227  "Agent: %s\r\n",
1228  ast_str_buffer(channel_string), agent);
1229  ast_free(channel_string);
1230  return ev;
1231 }
1232 
1234 {
1235  struct ast_str *channel_string;
1236  struct ast_channel_blob *obj = stasis_message_data(msg);
1237  const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
1238  long logintime = ast_json_integer_get(ast_json_object_get(obj->blob, "logintime"));
1239  struct ast_manager_event_blob *ev;
1240 
1241  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1242  if (!channel_string) {
1243  return NULL;
1244  }
1245 
1246  ev = ast_manager_event_blob_create(EVENT_FLAG_AGENT, "AgentLogoff",
1247  "%s"
1248  "Agent: %s\r\n"
1249  "Logintime: %ld\r\n",
1250  ast_str_buffer(channel_string), agent, logintime);
1251  ast_free(channel_string);
1252  return ev;
1253 }
1254 
1256  const struct ast_channel_snapshot *snapshot,
1257  const struct stasis_message_sanitizer *sanitize)
1258 {
1259  struct ast_json *json_chan;
1260 
1261  if (snapshot == NULL
1262  || (sanitize
1263  && sanitize->channel_snapshot
1264  && sanitize->channel_snapshot(snapshot))) {
1265  return NULL;
1266  }
1267 
1268  json_chan = ast_json_pack(
1269  /* Broken up into groups of three for readability */
1270  "{ s: s, s: s, s: s,"
1271  " s: o, s: o, s: s,"
1272  " s: o, s: o, s: s }",
1273  /* First line */
1274  "id", snapshot->base->uniqueid,
1275  "name", snapshot->base->name,
1276  "state", ast_state2str(snapshot->state),
1277  /* Second line */
1278  "caller", ast_json_name_number(
1279  snapshot->caller->name, snapshot->caller->number),
1280  "connected", ast_json_name_number(
1281  snapshot->connected->name, snapshot->connected->number),
1282  "accountcode", snapshot->base->accountcode,
1283  /* Third line */
1284  "dialplan", ast_json_dialplan_cep_app(
1285  snapshot->dialplan->context, snapshot->dialplan->exten, snapshot->dialplan->priority,
1286  snapshot->dialplan->appl, snapshot->dialplan->data),
1287  "creationtime", ast_json_timeval(snapshot->base->creationtime, NULL),
1288  "language", snapshot->base->language);
1289 
1290  if (snapshot->ari_vars && !AST_LIST_EMPTY(snapshot->ari_vars)) {
1291  ast_json_object_set(json_chan, "channelvars", ast_json_channel_vars(snapshot->ari_vars));
1292  }
1293 
1294  return json_chan;
1295 }
1296 
1298  const struct ast_channel_snapshot *old_snapshot,
1299  const struct ast_channel_snapshot *new_snapshot)
1300 {
1301  ast_assert(old_snapshot != NULL);
1302  ast_assert(new_snapshot != NULL);
1303 
1304  /* We actually get some snapshots with CEP set, but before the
1305  * application is set. Since empty application is invalid, we treat
1306  * setting the application from nothing as a CEP change.
1307  */
1308  if (ast_strlen_zero(old_snapshot->dialplan->appl) &&
1309  !ast_strlen_zero(new_snapshot->dialplan->appl)) {
1310  return 0;
1311  }
1312 
1313  return old_snapshot->dialplan->priority == new_snapshot->dialplan->priority &&
1314  strcmp(old_snapshot->dialplan->context, new_snapshot->dialplan->context) == 0 &&
1315  strcmp(old_snapshot->dialplan->exten, new_snapshot->dialplan->exten) == 0;
1316 }
1317 
1319  const struct ast_channel_snapshot *old_snapshot,
1320  const struct ast_channel_snapshot *new_snapshot)
1321 {
1322  ast_assert(old_snapshot != NULL);
1323  ast_assert(new_snapshot != NULL);
1324  return strcmp(old_snapshot->caller->number, new_snapshot->caller->number) == 0 &&
1325  strcmp(old_snapshot->caller->name, new_snapshot->caller->name) == 0;
1326 }
1327 
1329  const struct ast_channel_snapshot *old_snapshot,
1330  const struct ast_channel_snapshot *new_snapshot)
1331 {
1332  ast_assert(old_snapshot != NULL);
1333  ast_assert(new_snapshot != NULL);
1334  return strcmp(old_snapshot->connected->number, new_snapshot->connected->number) == 0 &&
1335  strcmp(old_snapshot->connected->name, new_snapshot->connected->name) == 0;
1336 }
1337 
1339  struct stasis_message *message,
1340  const char *type,
1341  const struct stasis_message_sanitizer *sanitize)
1342 {
1343  struct ast_json *to_json;
1344  struct ast_channel_blob *channel_blob = stasis_message_data(message);
1345  struct ast_json *blob = channel_blob->blob;
1346  struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
1347  const struct timeval *tv = stasis_message_timestamp(message);
1348  int res = 0;
1349 
1350  if (blob == NULL || ast_json_is_null(blob)) {
1351  to_json = ast_json_object_create();
1352  } else {
1353  /* blobs are immutable, so shallow copies are fine */
1354  to_json = ast_json_copy(blob);
1355  }
1356  if (!to_json) {
1357  return NULL;
1358  }
1359 
1360  res |= ast_json_object_set(to_json, "type", ast_json_string_create(type));
1361  res |= ast_json_object_set(to_json, "timestamp",
1362  ast_json_timeval(*tv, NULL));
1363 
1364  /* For global channel messages, the snapshot is optional */
1365  if (snapshot) {
1366  struct ast_json *json_channel;
1367 
1368  json_channel = ast_channel_snapshot_to_json(snapshot, sanitize);
1369  if (!json_channel) {
1370  ast_json_unref(to_json);
1371  return NULL;
1372  }
1373 
1374  res |= ast_json_object_set(to_json, "channel", json_channel);
1375  }
1376 
1377  if (res != 0) {
1378  ast_json_unref(to_json);
1379  return NULL;
1380  }
1381 
1382  return to_json;
1383 }
1384 
1386  struct stasis_message *message,
1387  const struct stasis_message_sanitizer *sanitize)
1388 {
1389  struct ast_channel_blob *channel_blob = stasis_message_data(message);
1390  struct ast_json *blob = channel_blob->blob;
1391  struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
1392  const char *direction =
1393  ast_json_string_get(ast_json_object_get(blob, "direction"));
1394  const char *digit =
1395  ast_json_string_get(ast_json_object_get(blob, "digit"));
1396  long duration_ms =
1397  ast_json_integer_get(ast_json_object_get(blob, "duration_ms"));
1398  const struct timeval *tv = stasis_message_timestamp(message);
1399  struct ast_json *json_channel;
1400 
1401  /* Only present received DTMF end events as JSON */
1402  if (strcasecmp("Received", direction) != 0) {
1403  return NULL;
1404  }
1405 
1406  json_channel = ast_channel_snapshot_to_json(snapshot, sanitize);
1407  if (!json_channel) {
1408  return NULL;
1409  }
1410 
1411  return ast_json_pack("{s: s, s: o, s: s, s: I, s: o}",
1412  "type", "ChannelDtmfReceived",
1413  "timestamp", ast_json_timeval(*tv, NULL),
1414  "digit", digit,
1415  "duration_ms", (ast_json_int_t)duration_ms,
1416  "channel", json_channel);
1417 }
1418 
1419 static struct ast_json *varset_to_json(
1420  struct stasis_message *message,
1421  const struct stasis_message_sanitizer *sanitize)
1422 {
1423  return channel_blob_to_json(message, "ChannelVarset", sanitize);
1424 }
1425 
1427  struct stasis_message *message,
1428  const struct stasis_message_sanitizer *sanitize)
1429 {
1430  return channel_blob_to_json(message, "ChannelHangupRequest", sanitize);
1431 }
1432 
1433 static struct ast_json *dial_to_json(
1434  struct stasis_message *message,
1435  const struct stasis_message_sanitizer *sanitize)
1436 {
1437  struct ast_multi_channel_blob *payload = stasis_message_data(message);
1438  struct ast_json *blob = ast_multi_channel_blob_get_json(payload);
1439  const char *dialstatus =
1440  ast_json_string_get(ast_json_object_get(blob, "dialstatus"));
1441  const char *forward =
1442  ast_json_string_get(ast_json_object_get(blob, "forward"));
1443  const char *dialstring =
1444  ast_json_string_get(ast_json_object_get(blob, "dialstring"));
1445  struct ast_json *caller_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "caller"), sanitize);
1446  struct ast_json *peer_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "peer"), sanitize);
1447  struct ast_json *forwarded_json = ast_channel_snapshot_to_json(ast_multi_channel_blob_get_channel(payload, "forwarded"), sanitize);
1448  struct ast_json *json;
1449  const struct timeval *tv = stasis_message_timestamp(message);
1450  int res = 0;
1451 
1452  json = ast_json_pack("{s: s, s: o, s: s, s: s, s: s}",
1453  "type", "Dial",
1454  "timestamp", ast_json_timeval(*tv, NULL),
1455  "dialstatus", dialstatus,
1456  "forward", forward,
1457  "dialstring", dialstring);
1458  if (!json) {
1459  ast_json_unref(caller_json);
1460  ast_json_unref(peer_json);
1461  ast_json_unref(forwarded_json);
1462  return NULL;
1463  }
1464 
1465  if (caller_json) {
1466  res |= ast_json_object_set(json, "caller", caller_json);
1467  }
1468  if (peer_json) {
1469  res |= ast_json_object_set(json, "peer", peer_json);
1470  }
1471  if (forwarded_json) {
1472  res |= ast_json_object_set(json, "forwarded", forwarded_json);
1473  }
1474 
1475  if (res) {
1476  ast_json_unref(json);
1477  return NULL;
1478  }
1479 
1480  return json;
1481 }
1482 
1484 {
1485  struct ast_str *channel_string;
1486  struct ast_channel_blob *obj = stasis_message_data(msg);
1487  struct ast_manager_event_blob *blob;
1488 
1489  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1490  if (!channel_string) {
1491  return NULL;
1492  }
1493 
1494  blob = ast_manager_event_blob_create(EVENT_FLAG_CALL, "ChannelTalkingStart",
1495  "%s", ast_str_buffer(channel_string));
1496  ast_free(channel_string);
1497 
1498  return blob;
1499 }
1500 
1502  const struct stasis_message_sanitizer *sanitize)
1503 {
1504  return channel_blob_to_json(message, "ChannelTalkingStarted", sanitize);
1505 }
1506 
1508 {
1509  struct ast_str *channel_string;
1510  struct ast_channel_blob *obj = stasis_message_data(msg);
1511  int duration = ast_json_integer_get(ast_json_object_get(obj->blob, "duration"));
1512  struct ast_manager_event_blob *blob;
1513 
1514  channel_string = ast_manager_build_channel_state_string(obj->snapshot);
1515  if (!channel_string) {
1516  return NULL;
1517  }
1518 
1519  blob = ast_manager_event_blob_create(EVENT_FLAG_CALL, "ChannelTalkingStop",
1520  "%s"
1521  "Duration: %d\r\n",
1522  ast_str_buffer(channel_string),
1523  duration);
1524  ast_free(channel_string);
1525 
1526  return blob;
1527 }
1528 
1530  const struct stasis_message_sanitizer *sanitize)
1531 {
1532  return channel_blob_to_json(message, "ChannelTalkingFinished", sanitize);
1533 }
1534 
1536  const struct stasis_message_sanitizer *sanitize)
1537 {
1538  struct ast_channel_blob *channel_blob = stasis_message_data(message);
1539  struct ast_json *blob = channel_blob->blob;
1540  struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
1541  const char *musicclass = ast_json_string_get(ast_json_object_get(blob, "musicclass"));
1542  const struct timeval *tv = stasis_message_timestamp(message);
1543  struct ast_json *json_channel;
1544 
1545  json_channel = ast_channel_snapshot_to_json(snapshot, sanitize);
1546  if (!json_channel) {
1547  return NULL;
1548  }
1549 
1550  return ast_json_pack("{s: s, s: o, s: s, s: o}",
1551  "type", "ChannelHold",
1552  "timestamp", ast_json_timeval(*tv, NULL),
1553  "musicclass", S_OR(musicclass, "N/A"),
1554  "channel", json_channel);
1555 }
1556 
1558  const struct stasis_message_sanitizer *sanitize)
1559 {
1560  struct ast_channel_blob *channel_blob = stasis_message_data(message);
1561  struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
1562  const struct timeval *tv = stasis_message_timestamp(message);
1563  struct ast_json *json_channel;
1564 
1565  json_channel = ast_channel_snapshot_to_json(snapshot, sanitize);
1566  if (!json_channel) {
1567  return NULL;
1568  }
1569 
1570  return ast_json_pack("{s: s, s: o, s: o}",
1571  "type", "ChannelUnhold",
1572  "timestamp", ast_json_timeval(*tv, NULL),
1573  "channel", json_channel);
1574 }
1575 
1576 /*!
1577  * @{ \brief Define channel message types.
1578  */
1581  .to_json = dial_to_json,
1582  );
1584  .to_ami = varset_to_ami,
1585  .to_json = varset_to_json,
1586  );
1588  .to_json = hangup_request_to_json,
1589  );
1593  .to_json = dtmf_end_to_json,
1594  );
1596  .to_json = hold_to_json,
1597  );
1599  .to_json = unhold_to_json,
1600  );
1615  );
1618  );
1621  .to_json = talking_start_to_json,
1622  );
1625  .to_json = talking_stop_to_json,
1626  );
1627 
1628 /*! @} */
1629 
1630 static void stasis_channels_cleanup(void)
1631 {
1632  ao2_cleanup(channel_topic_all);
1633  channel_topic_all = NULL;
1634  ao2_cleanup(channel_cache);
1635  channel_cache = NULL;
1636  ao2_cleanup(channel_cache_by_name);
1637  channel_cache_by_name = NULL;
1638 
1664 }
1665 
1667 {
1668  int res = 0;
1669 
1671 
1672  channel_topic_all = stasis_topic_create("channel:all");
1673  if (!channel_topic_all) {
1674  return -1;
1675  }
1676 
1680  if (!channel_cache) {
1681  return -1;
1682  }
1683 
1684  channel_cache_by_name = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_RWLOCK,
1687  if (!channel_cache_by_name) {
1688  return -1;
1689  }
1690 
1716 
1717  return res;
1718 }
1719 
1720 /*!
1721  * \internal
1722  * \brief A list element for the dial_masquerade_datastore -- stores data about a dialed peer
1723  */
1724 struct dial_target {
1725  /*! Called party channel. */
1727  /*! Dialstring used to call the peer. */
1728  char *dialstring;
1729  /*! Next entry in the list. */
1731 };
1732 
1733 static void dial_target_free(struct dial_target *doomed)
1734 {
1735  if (!doomed) {
1736  return;
1737  }
1738  ast_free(doomed->dialstring);
1739  ast_channel_cleanup(doomed->peer);
1740  ast_free(doomed);
1741 }
1742 
1743 /*!
1744  * \internal
1745  * \brief Datastore used for advancing dial state in the case of a masquerade
1746  * against a channel in the process of dialing.
1747  */
1749  /*! Calling party channel. */
1751  /*! List of called peers. */
1753 };
1754 
1756 {
1757  struct dial_target *cur;
1758 
1759  while ((cur = AST_LIST_REMOVE_HEAD(&masq_data->dialed_peers, list))) {
1760  dial_target_free(cur);
1761  }
1762 }
1763 
1765 {
1766  struct dial_target *cur;
1767 
1768  ao2_lock(masq_data);
1769  if (masq_data->caller == chan) {
1771  } else {
1772  AST_LIST_TRAVERSE_SAFE_BEGIN(&masq_data->dialed_peers, cur, list) {
1773  if (cur->peer == chan) {
1775  dial_target_free(cur);
1776  break;
1777  }
1778  }
1780  }
1781  ao2_unlock(masq_data);
1782 }
1783 
1784 static void dial_masquerade_datastore_dtor(void *vdoomed)
1785 {
1787 }
1788 
1790 {
1791  struct dial_masquerade_datastore *masq_data;
1792 
1793  masq_data = ao2_alloc(sizeof(struct dial_masquerade_datastore),
1795  if (!masq_data) {
1796  return NULL;
1797  }
1799  return masq_data;
1800 }
1801 
1802 /*!
1803  * \internal
1804  * \brief Datastore destructor for dial_masquerade_datastore
1805  */
1806 static void dial_masquerade_datastore_destroy(void *data)
1807 {
1808  ao2_ref(data, -1);
1809 }
1810 
1811 /*!
1812  * \internal
1813  * \brief Datastore destructor for dial_masquerade_datastore
1814  */
1816 {
1818  ao2_ref(data, -1);
1819 }
1820 
1821 static struct ast_datastore *dial_masquerade_datastore_find(struct ast_channel *chan);
1822 
1823 static void dial_masquerade_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
1824 {
1825  struct dial_masquerade_datastore *masq_data = data;
1826  struct dial_target *cur;
1827  struct ast_datastore *datastore;
1828 
1829  ao2_lock(masq_data);
1830  if (!masq_data->caller) {
1831  /* Nothing to do but remove the datastore */
1832  } else if (masq_data->caller == old_chan) {
1833  /* The caller channel is being masqueraded out. */
1834  ast_debug(1, "Caller channel %s being masqueraded out to %s (is_empty:%d)\n",
1835  ast_channel_name(new_chan), ast_channel_name(old_chan),
1836  AST_LIST_EMPTY(&masq_data->dialed_peers));
1837  AST_LIST_TRAVERSE(&masq_data->dialed_peers, cur, list) {
1839  cur->dialstring, "NOANSWER", NULL);
1841  cur->dialstring, NULL, NULL);
1842  }
1844  } else {
1845  /* One of the peer channels is being masqueraded out. */
1846  AST_LIST_TRAVERSE_SAFE_BEGIN(&masq_data->dialed_peers, cur, list) {
1847  if (cur->peer == old_chan) {
1848  ast_debug(1, "Peer channel %s being masqueraded out to %s\n",
1849  ast_channel_name(new_chan), ast_channel_name(old_chan));
1850  ast_channel_publish_dial_internal(masq_data->caller, new_chan, NULL,
1851  cur->dialstring, "CANCEL", NULL);
1852  ast_channel_publish_dial_internal(masq_data->caller, old_chan, NULL,
1853  cur->dialstring, NULL, NULL);
1854 
1856  dial_target_free(cur);
1857  break;
1858  }
1859  }
1861  }
1862  ao2_unlock(masq_data);
1863 
1864  /* Remove the datastore from the channel. */
1865  datastore = dial_masquerade_datastore_find(old_chan);
1866  if (!datastore) {
1867  return;
1868  }
1869  ast_channel_datastore_remove(old_chan, datastore);
1870  ast_datastore_free(datastore);
1871 }
1872 
1873 /*!
1874  * \internal
1875  * \brief Primary purpose for dial_masquerade_datastore, publishes
1876  * the channel dial event needed to set the incoming channel into the
1877  * dial state during a masquerade.
1878  * \param data pointer to the dial_masquerade_datastore
1879  * \param old_chan Channel being replaced
1880  * \param new_chan Channel being pushed to dial mode
1881  */
1882 static void dial_masquerade_breakdown(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
1883 {
1884  struct dial_masquerade_datastore *masq_data = data;
1885  struct dial_target *cur;
1886 
1887  ao2_lock(masq_data);
1888 
1889  if (!masq_data->caller) {
1890  ao2_unlock(masq_data);
1891  return;
1892  }
1893 
1894  if (masq_data->caller == new_chan) {
1895  /*
1896  * The caller channel is being masqueraded into.
1897  * The masquerade is likely because of a blonde transfer.
1898  */
1899  ast_debug(1, "Caller channel %s being masqueraded into by %s (is_empty:%d)\n",
1900  ast_channel_name(old_chan), ast_channel_name(new_chan),
1901  AST_LIST_EMPTY(&masq_data->dialed_peers));
1902  AST_LIST_TRAVERSE(&masq_data->dialed_peers, cur, list) {
1904  cur->dialstring, "NOANSWER", NULL);
1906  cur->dialstring, NULL, NULL);
1907  }
1908 
1909  ao2_unlock(masq_data);
1910  return;
1911  }
1912 
1913  /*
1914  * One of the peer channels is being masqueraded into.
1915  * The masquerade is likely because of a call pickup.
1916  */
1917  AST_LIST_TRAVERSE(&masq_data->dialed_peers, cur, list) {
1918  if (cur->peer == new_chan) {
1919  ast_debug(1, "Peer channel %s being masqueraded into by %s\n",
1920  ast_channel_name(old_chan), ast_channel_name(new_chan));
1921  ast_channel_publish_dial_internal(masq_data->caller, old_chan, NULL,
1922  cur->dialstring, "CANCEL", NULL);
1923  ast_channel_publish_dial_internal(masq_data->caller, new_chan, NULL,
1924  cur->dialstring, NULL, NULL);
1925  break;
1926  }
1927  }
1928 
1929  ao2_unlock(masq_data);
1930 }
1931 
1933  .type = "stasis-chan-dial-masq",
1935  .chan_fixup = dial_masquerade_fixup,
1936  .chan_breakdown = dial_masquerade_breakdown,
1937 };
1938 
1940  .type = "stasis-chan-dial-masq",
1942  .chan_fixup = dial_masquerade_fixup,
1943  .chan_breakdown = dial_masquerade_breakdown,
1944 };
1945 
1946 /*!
1947  * \internal
1948  * \brief Find the dial masquerade datastore on the given channel.
1949  *
1950  * \param chan Channel a datastore data is wanted from
1951  *
1952  * \return A pointer to the datastore if it exists.
1953  */
1955 {
1956  struct ast_datastore *datastore;
1957 
1958  datastore = ast_channel_datastore_find(chan, &dial_masquerade_info, NULL);
1959  if (!datastore) {
1960  datastore = ast_channel_datastore_find(chan, &dial_masquerade_caller_info, NULL);
1961  }
1962 
1963  return datastore;
1964 }
1965 
1966 /*!
1967  * \internal
1968  * \brief Add the dial masquerade datastore to a channel.
1969  *
1970  * \param chan Channel to setup dial masquerade datastore on.
1971  * \param masq_data NULL to setup caller datastore otherwise steals the ref on success.
1972  *
1973  * \retval masq_data given or created on success.
1974  * (A ref is not returned but can be obtained before chan is unlocked.)
1975  * \retval NULL on error. masq_data ref is not stolen.
1976  */
1978  struct ast_channel *chan, struct dial_masquerade_datastore *masq_data)
1979 {
1980  struct ast_datastore *datastore;
1981 
1982  datastore = ast_datastore_alloc(!masq_data ? &dial_masquerade_caller_info : &dial_masquerade_info, NULL);
1983  if (!datastore) {
1984  return NULL;
1985  }
1986 
1987  if (!masq_data) {
1988  masq_data = dial_masquerade_datastore_alloc();
1989  if (!masq_data) {
1990  ast_datastore_free(datastore);
1991  return NULL;
1992  }
1993  masq_data->caller = chan;
1994  }
1995 
1996  datastore->data = masq_data;
1997  ast_channel_datastore_add(chan, datastore);
1998 
1999  return masq_data;
2000 }
2001 
2002 static int set_dial_masquerade(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring)
2003 {
2004  struct ast_datastore *datastore;
2005  struct dial_masquerade_datastore *masq_data;
2006  struct dial_target *target;
2007 
2008  /* Find or create caller datastore */
2009  datastore = dial_masquerade_datastore_find(caller);
2010  if (!datastore) {
2011  masq_data = dial_masquerade_datastore_add(caller, NULL);
2012  } else {
2013  masq_data = datastore->data;
2014  }
2015  if (!masq_data) {
2016  return -1;
2017  }
2018  ao2_ref(masq_data, +1);
2019 
2020  /*
2021  * Someone likely forgot to do an ast_channel_publish_dial()
2022  * or ast_channel_publish_dial_forward() with a final dial
2023  * status on the channel.
2024  */
2025  ast_assert(masq_data->caller == caller);
2026 
2027  /* Create peer target to put into datastore */
2028  target = ast_calloc(1, sizeof(*target));
2029  if (!target) {
2030  ao2_ref(masq_data, -1);
2031  return -1;
2032  }
2033  if (dialstring) {
2034  target->dialstring = ast_strdup(dialstring);
2035  if (!target->dialstring) {
2036  ast_free(target);
2037  ao2_ref(masq_data, -1);
2038  return -1;
2039  }
2040  }
2041  target->peer = ast_channel_ref(peer);
2042 
2043  /* Put peer target into datastore */
2044  ao2_lock(masq_data);
2045  dial_masquerade_datastore_remove_chan(masq_data, peer);
2046  AST_LIST_INSERT_HEAD(&masq_data->dialed_peers, target, list);
2047  ao2_unlock(masq_data);
2048 
2049  datastore = dial_masquerade_datastore_find(peer);
2050  if (datastore) {
2051  if (datastore->data == masq_data) {
2052  /*
2053  * Peer already had the datastore for this dial masquerade.
2054  * This was a redundant peer dial masquerade setup.
2055  */
2056  ao2_ref(masq_data, -1);
2057  return 0;
2058  }
2059 
2060  /* Something is wrong. Try to fix if the assert doesn't abort. */
2061  ast_assert(0);
2062 
2063  /* Remove the stale dial masquerade datastore */
2064  dial_masquerade_datastore_remove_chan(datastore->data, peer);
2065  ast_channel_datastore_remove(peer, datastore);
2066  ast_datastore_free(datastore);
2067  }
2068 
2069  /* Create the peer dial masquerade datastore */
2070  if (dial_masquerade_datastore_add(peer, masq_data)) {
2071  /* Success */
2072  return 0;
2073  }
2074 
2075  /* Failed to create the peer datastore */
2076  dial_masquerade_datastore_remove_chan(masq_data, peer);
2077  ao2_ref(masq_data, -1);
2078  return -1;
2079 }
2080 
2081 static void remove_dial_masquerade(struct ast_channel *peer)
2082 {
2083  struct ast_datastore *datastore;
2084  struct dial_masquerade_datastore *masq_data;
2085 
2086  datastore = dial_masquerade_datastore_find(peer);
2087  if (!datastore) {
2088  return;
2089  }
2090 
2091  masq_data = datastore->data;
2092  if (masq_data) {
2093  dial_masquerade_datastore_remove_chan(masq_data, peer);
2094  }
2095 
2096  ast_channel_datastore_remove(peer, datastore);
2097  ast_datastore_free(datastore);
2098 }
2099 
2100 static void remove_dial_masquerade_caller(struct ast_channel *caller)
2101 {
2102  struct ast_datastore *datastore;
2103  struct dial_masquerade_datastore *masq_data;
2104 
2105  datastore = dial_masquerade_datastore_find(caller);
2106  if (!datastore) {
2107  return;
2108  }
2109 
2110  masq_data = datastore->data;
2111  if (!masq_data || !AST_LIST_EMPTY(&masq_data->dialed_peers)) {
2112  return;
2113  }
2114 
2115  dial_masquerade_datastore_remove_chan(masq_data, caller);
2116 
2117  ast_channel_datastore_remove(caller, datastore);
2118  ast_datastore_free(datastore);
2119 }
struct stasis_message_type * ast_channel_hold_type(void)
Message type for when a channel is placed on hold.
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * type
Definition: datastore.h:32
static char musicclass[MAX_MUSICCLASS]
Definition: chan_mgcp.c:162
struct ao2_container * ast_channel_cache_by_name(void)
Secondary channel cache, indexed by name.
struct stasis_message_type * ast_channel_talking_stop(void)
Message type for a channel stopping talking.
static const char type[]
Definition: chan_ooh323.c:109
const ast_string_field data
void ast_channel_snapshot_set(struct ast_channel *chan, struct ast_channel_snapshot *snapshot)
Struct containing info for an AMI event to send out.
Definition: manager.h:491
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:428
static void multi_channel_blob_dtor(void *obj)
char digit
#define ast_channel_lock(chan)
Definition: channel.h:2945
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Main Channel structure associated with a channel.
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
static void channel_snapshot_base_dtor(void *obj)
struct ast_channel_snapshot_base * base
struct stasis_message_type * ast_channel_dtmf_end_type(void)
Message type for when DTMF ends on a channel.
Asterisk main include file. File version handling, generic pbx functions.
struct ast_flags feature_flags
Definition: bridge.h:377
const ast_string_field uniqueid
Definition: bridge.h:409
char * str
Subscriber phone number (Malloced)
Definition: channel.h:387
struct stasis_message_type * ast_channel_unhold_type(void)
Message type for when a channel is removed from hold.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
struct ast_json * blob
int ast_channel_snapshot_cep_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the context, exten and priority of two snapshots.
void ast_channel_snapshot_invalidate_segment(struct ast_channel *chan, enum ast_channel_snapshot_segment_invalidation segment)
Invalidate a channel snapshot segment from being reused.
static void remove_dial_masquerade_caller(struct ast_channel *caller)
const ast_string_field name
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1105
static struct ast_channel_snapshot_hangup * channel_snapshot_hangup_create(struct ast_channel *chan)
#define ast_test_flag(p, flag)
Definition: utils.h:63
int(* channel_snapshot)(const struct ast_channel_snapshot *snapshot)
Callback which determines whether a channel should be sanitized from a message based on the channel&#39;s...
Definition: stasis.h:221
static int set_dial_masquerade(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring)
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition: codec_g726.c:367
Support for translation of data formats. translate.c.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message using the latest snapshot from the cache.
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
struct ast_json * blob
static struct dial_masquerade_datastore * dial_masquerade_datastore_add(struct ast_channel *chan, struct dial_masquerade_datastore *masq_data)
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
static void ast_channel_publish_dial_internal(struct ast_channel *caller, struct ast_channel *peer, struct ast_channel *forwarded, const char *dialstring, const char *dialstatus, const char *forward)
struct ast_channel_snapshot * snapshot
struct stasis_message_type * ast_channel_moh_start_type(void)
Message type for starting music on hold on a channel.
#define ast_set_flag(p, flag)
Definition: utils.h:70
struct varshead * ast_channel_get_manager_vars(struct ast_channel *chan)
Gets the variables for a given channel, as specified by ast_channel_set_manager_vars().
Definition: channel.c:8085
static struct ast_channel_snapshot_dialplan * channel_snapshot_dialplan_create(struct ast_channel *chan)
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
const ast_string_field rdnis
struct ast_channel_snapshot * ast_channel_snapshot(const struct ast_channel *chan)
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:1821
struct dial_masquerade_datastore::@422 dialed_peers
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
static int channel_snapshot_uniqueid_cmp_cb(void *obj, void *arg, int flags)
static struct ast_json * varset_to_json(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
static void dial_masquerade_caller_datastore_destroy(void *data)
Structure representing a snapshot of channel state.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
static int channel_role_cmp_cb(void *obj, void *arg, int flags)
static struct ast_manager_event_blob * agent_logoff_to_ami(struct stasis_message *msg)
#define EVENT_FLAG_CALL
Definition: manager.h:72
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
static void channel_snapshot_dialplan_dtor(void *obj)
static struct dial_masquerade_datastore * dial_masquerade_datastore_alloc(void)
Structure for a data store type.
Definition: datastore.h:31
ast_channel_state
ast_channel states
Definition: channelstate.h:35
const ast_string_field accountcode
struct stasis_message_type * ast_channel_flash_type(void)
Message type for when a hook flash occurs on a channel.
Definition: astman.c:222
#define AST_NUM_CHANNEL_BUCKETS
Definition: channel.h:156
Dialing API.
static struct ast_json * hold_to_json(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
const ast_string_field uniqueid
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static struct ast_manager_event_blob * agent_login_to_ami(struct stasis_message *msg)
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define ast_assert(a)
Definition: utils.h:695
#define ao2_link_flags(container, obj, flags)
Definition: astobj2.h:1572
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
const char * ast_state2str(enum ast_channel_state)
Gives the string form of a given channel state.
Definition: channel.c:642
struct stasis_message_type * ast_channel_varset_type(void)
Message type for when a variable is set on a channel.
struct stasis_message_type * ast_channel_chanspy_start_type(void)
Message type for when a channel starts spying on another channel.
Structure containing connected information for a channel snapshot.
#define NULL
Definition: resample.c:96
static void channel_role_snapshot_dtor(void *obj)
struct stasis_message_type * ast_channel_monitor_start_type(void)
Message type for starting monitor on a channel.
int ast_json_is_null(const struct ast_json *value)
Check if value is JSON null.
Definition: json.c:263
#define ao2_wrlock(a)
Definition: astobj2.h:720
static struct ast_channel_snapshot_base * channel_snapshot_base_create(struct ast_channel *chan)
int value
Definition: syslog.c:37
Structure representing a change of snapshot of channel state.
struct stasis_message_type * ast_channel_talking_start(void)
Message type for a channel starting talking.
#define EVENT_FLAG_DIALPLAN
Definition: manager.h:82
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
int ast_channel_priority(const struct ast_channel *chan)
struct ast_channel_snapshot_dialplan * dialplan
const char * ast_channel_linkedid(const struct ast_channel *chan)
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Definition: manager.c:9727
Structure containing callbacks for Stasis message sanitization.
Definition: stasis.h:200
static const struct ast_datastore_info dial_masquerade_info
struct ast_channel_snapshot * ast_channel_snapshot_create(struct ast_channel *chan)
Generate a snapshot of the channel state. This is an ao2 object, so ao2_cleanup() to deallocate...
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
struct ast_json * ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
Retrieve the JSON blob from a ast_multi_channel_blob. Returned ast_json is still owned by obj...
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:404
Blob of data associated with a channel.
static void dial_masquerade_datastore_dtor(void *vdoomed)
#define NUM_MULTI_CHANNEL_BLOB_BUCKETS
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_channel_snapshot_caller_id_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the callerid info of two snapshots.
struct ast_json * ast_json_dialplan_cep_app(const char *context, const char *exten, int priority, const char *app_name, const char *app_data)
Construct a context/exten/priority/application/application_data as JSON.
Definition: json.c:632
Number structure.
Definition: app_followme.c:154
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
#define ao2_bump(obj)
Definition: astobj2.h:491
struct ast_json * ast_json_channel_vars(struct varshead *channelvars)
Construct a JSON object from a ast_var_t list.
Definition: json.c:843
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
const ast_string_field dialed_subaddr
ast_channel_snapshot_segment_invalidation
Channel snapshot invalidation flags, used to force generation of segments.
static void dial_masquerade_datastore_destroy(void *data)
static struct ast_json * talking_stop_to_json(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
const ast_string_field context
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static struct ast_json * dial_to_json(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
Definition: channel.c:10735
struct varshead * ari_vars
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1120
struct ast_channel_snapshot * ast_channel_snapshot_get_latest_by_name(const char *name)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
Structure containing hangup information for a channel snapshot.
struct ast_json * ast_json_name_number(const char *name, const char *number)
Common JSON rendering functions for common &#39;objects&#39;.
Definition: json.c:625
static void dial_masquerade_breakdown(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
Asterisk JSON abstraction layer.
static int channel_snapshot_uniqueid_hash_cb(const void *obj, const int flags)
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
const char * ast_channel_accountcode(const struct ast_channel *chan)
static struct ast_json * unhold_to_json(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
const ast_string_field appl
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:268
static void channel_snapshot_caller_dtor(void *obj)
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
int ast_stasis_channels_init(void)
Initialize the stasis channel topic and message types.
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
static struct ast_manager_event_blob * varset_to_ami(struct stasis_message *msg)
void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
Add a ast_channel_snapshot to a ast_multi_channel_blob object.
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
static int channel_snapshot_cmp_cb(void *obj, void *arg, int flags)
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
Structure containing dialplan information for a channel snapshot.
struct stasis_message_type * ast_channel_monitor_stop_type(void)
Message type for stopping monitor on a channel.
const ast_string_field subaddr
#define ao2_lock(a)
Definition: astobj2.h:718
static struct stasis_topic * channel_topic_all
const ast_string_field exten
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct varshead * ast_channel_get_ari_vars(struct ast_channel *chan)
Gets the variables for a given channel, as specified by ast_channel_set_ari_vars().
Definition: channel.c:8090
struct ast_channel_snapshot_hangup * hangup
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
static struct stasis_message * create_channel_blob_message(struct ast_channel_snapshot *snapshot, struct stasis_message_type *type, struct ast_json *blob)
A set of macros to manage forward-linked lists.
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:117
struct stasis_message_type * ast_channel_agent_login_type(void)
Message type for agent login on a channel.
static struct ast_channel_snapshot_bridge * channel_snapshot_bridge_create(struct ast_channel *chan)
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition: stasis.c:618
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
AST_LIST_HEAD_NOLOCK(contactliststruct, contact)
struct stasis_message_type * ast_channel_agent_logoff_type(void)
Message type for agent logoff on a channel.
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
static struct ao2_container * channel_cache_by_name
const char * ast_channel_exten(const struct ast_channel *chan)
struct ao2_container * ast_channel_cache_all(void)
Core PBX routines and definitions.
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:649
static int channel_snapshot_hash_cb(const void *obj, const int flags)
struct ao2_container * ast_multi_channel_blob_get_channels(struct ast_multi_channel_blob *obj, const char *role)
Retrieve all channel snapshots associated with a specific role from a ast_multi_channel_blob.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_channel_snapshot_caller * caller
static void dial_masquerade_datastore_cleanup(struct dial_masquerade_datastore *masq_data)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
static void dial_masquerade_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
struct ast_flags softhangup_flags
struct stasis_message_type * ast_channel_mixmonitor_start_type(void)
Message type for starting mixmonitor on a channel.
Structure that contains information about a bridge.
Definition: bridge.h:357
const char * ast_channel_userfield(const struct ast_channel *chan)
#define LOG_ERROR
Definition: logger.h:285
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Definition: astobj2.h:1310
static void dial_masquerade_datastore_remove_chan(struct dial_masquerade_datastore *masq_data, struct ast_channel *chan)
struct varshead * manager_vars
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
struct stasis_message_type * ast_channel_mixmonitor_stop_type(void)
Message type for stopping mixmonitor on a channel.
const ast_string_field dnid
#define ao2_unlink(container, obj)
Definition: astobj2.h:1598
Structure containing peer information for a channel snapshot.
struct ast_channel_snapshot * snapshot
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
void ast_channel_publish_varset(struct ast_channel *chan, const char *name, const char *value)
Publish a ast_channel_varset for a channel.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
static struct ast_channel_snapshot_peer * channel_snapshot_peer_create(struct ast_channel *chan)
void ast_channel_publish_final_snapshot(struct ast_channel *chan)
Send the final channel snapshot for a channel, thus removing it from cache.
Structure containing caller information for a channel snapshot.
struct ast_party_dialed * ast_channel_dialed(struct ast_channel *chan)
#define EVENT_FLAG_AGENT
Definition: manager.h:76
static struct ast_datastore * dial_masquerade_datastore_find(struct ast_channel *chan)
static struct ast_json * dtmf_end_to_json(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
Structure containing base information for a channel snapshot.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct timeval ast_channel_creationtime(struct ast_channel *chan)
static void channel_snapshot_update_dtor(void *obj)
struct stasis_message * ast_channel_blob_create(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Creates a ast_channel_blob message.
const char * ast_channel_appl(const struct ast_channel *chan)
static int channel_role_hash_cb(const void *obj, const int flags)
void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer, struct ast_channel *forwarded, const char *dialstring, const char *dialstatus, const char *forward)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
const ast_string_field userfield
const char * ast_channel_peeraccount(const struct ast_channel *chan)
static void remove_dial_masquerade(struct ast_channel *peer)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
STASIS_MESSAGE_TYPE_DEFN(ast_channel_snapshot_type)
Define channel message types.
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct stasis_message_type * ast_channel_hangup_handler_type(void)
Message type for hangup handler related actions.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
static struct ast_channel_snapshot_update * channel_snapshot_update_create(struct ast_channel *chan)
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
static struct ast_manager_event_blob * talking_start_to_ami(struct stasis_message *msg)
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
char * ast_escape_c_alloc(const char *s)
Escape standard &#39;C&#39; sequences in the given string.
Definition: main/utils.c:1892
#define AST_FLAGS_ALL
Definition: utils.h:196
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
struct ast_channel_snapshot * new_snapshot
enum ast_channel_state state
const char * ast_channel_hangupsource(const struct ast_channel *chan)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
struct ast_channel_snapshot * old_snapshot
struct stasis_message_type * ast_channel_dtmf_begin_type(void)
Message type for when DTMF begins on a channel.
static const struct ast_datastore_info dial_masquerade_caller_info
#define ast_clear_flag(p, flag)
Definition: utils.h:77
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
struct stasis_message * ast_channel_blob_create_from_cache(const char *channel_id, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
const char * ast_channel_data(const struct ast_channel *chan)
const ast_string_field ani
static void publish_message_for_channel_topics(struct stasis_message *message, struct ast_channel *chan)
struct ast_json * ast_json_object_create(void)
Create a new JSON object.
Definition: json.c:389
const ast_string_field language
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
void * data
Definition: datastore.h:70
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:680
struct ao2_container * channel_snapshots
static void channel_blob_dtor(void *obj)
static struct ao2_container * channel_cache
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
static struct ast_channel_snapshot_connected * channel_snapshot_connected_create(struct ast_channel *chan)
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ast_json * talking_start_to_json(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
static struct ast_json * channel_blob_to_json(struct stasis_message *message, const char *type, const struct stasis_message_sanitizer *sanitize)
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
int ast_channel_hangupcause(const struct ast_channel *chan)
const ast_string_field number
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct dial_target::@421 list
struct ast_flags flags
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
static void dial_target_free(struct dial_target *doomed)
struct ast_channel_snapshot_bridge * bridge
A multi channel blob data structure for multi_channel_blob stasis messages.
#define ao2_unlink_flags(container, obj, flags)
Definition: astobj2.h:1622
const char * ast_channel_language(const struct ast_channel *chan)
Abstract JSON element (object, array, string, int, ...).
struct ast_flags * ast_channel_snapshot_segment_flags(struct ast_channel *chan)
static void channel_snapshot_dtor(void *obj)
int ast_channel_has_manager_vars(void)
Return whether or not any manager variables have been set.
Definition: channel.c:7957
const char * ast_channel_context(const struct ast_channel *chan)
struct stasis_message_type * ast_channel_dial_type(void)
Message type for when a channel dials another channel.
void ast_channel_publish_snapshot(struct ast_channel *chan)
Publish a ast_channel_snapshot for a channel.
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
Generic container type.
#define ast_channel_trylock(chan)
Definition: channel.h:2947
int ast_channel_snapshot_connected_line_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the connected line info of two snapshots.
Search option field mask.
Definition: astobj2.h:1076
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
struct ast_channel * caller
struct stasis_message_type * ast_channel_moh_stop_type(void)
Message type for stopping music on hold on a channel.
static void stasis_channels_cleanup(void)
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
struct ast_channel * peer
struct ast_channel_snapshot_peer * peer
struct stasis_message_type * ast_channel_hangup_request_type(void)
Message type for when a hangup is requested on a channel.
direction
Bridging API.
static struct ast_manager_event_blob * talking_stop_to_ami(struct stasis_message *msg)
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:322
struct stasis_message_type * ast_channel_masquerade_type(void)
Message type for when a channel is being masqueraded.
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
static struct ast_channel_snapshot_caller * channel_snapshot_caller_create(struct ast_channel *chan)
enum ama_flags ast_channel_amaflags(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
Structure containing bridge information for a channel snapshot.
struct ast_json * ast_json_copy(const struct ast_json *value)
Copy a JSON value, but not its children.
Definition: json.c:616
A channel snapshot wrapper object used in ast_multi_channel_blob objects.
const struct ast_channel_tech * ast_channel_tech(const struct ast_channel *chan)
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2399
struct ast_channel_snapshot_connected * connected
struct ast_multi_channel_blob * ast_multi_channel_blob_create(struct ast_json *blob)
Create a ast_multi_channel_blob suitable for a stasis_message.
struct stasis_message_type * ast_channel_chanspy_stop_type(void)
Message type for when a channel stops spying on another channel.
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1250
const ast_string_field name
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
static struct ast_json * hangup_request_to_json(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)
struct stasis_message_type * ast_channel_mixmonitor_mute_type(void)
Message type for muting or unmuting mixmonitor on a channel.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
#define ao2_link(container, obj)
Definition: astobj2.h:1549