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