Asterisk - The Open Source Telephony Project  18.5.0
res_stasis_snoop.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  * Joshua Colp <[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 application snoop control support.
22  *
23  * \author Joshua Colp <[email protected]>
24  */
25 
26 /*** MODULEINFO
27  <depend type="module">res_stasis</depend>
28  <support_level>core</support_level>
29  ***/
30 
31 #include "asterisk.h"
32 
33 #include "asterisk/module.h"
36 #include "asterisk/audiohook.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/timing.h"
40 #include "asterisk/json.h"
41 #include "asterisk/format_cache.h"
42 
43 /*! \brief The interval (in milliseconds) that the Snoop timer is triggered, also controls length of audio within frames */
44 #define SNOOP_INTERVAL 20
45 
46 /*! \brief Index used to keep Snoop channel names unique */
47 static unsigned int chan_idx;
48 
49 /*! \brief Structure which contains all of the snoop information */
51  /*! \brief Timer used for waking up Stasis thread */
52  struct ast_timer *timer;
53  /*! \brief Audiohook used to spy on the channel */
55  /*! \brief Direction for spying */
57  /*! \brief Number of samples to be read in when spying */
58  unsigned int spy_samples;
59  /*! \brief Format in use by the spy audiohook */
61  /*! \brief Audiohook used to whisper on the channel */
63  /*! \brief Direction for whispering */
65  /*! \brief Stasis application and arguments */
66  struct ast_str *app;
67  /*! \brief Snoop channel */
68  struct ast_channel *chan;
69  /*! \brief The channel that the Snoop channel is snooping on */
71  /*! \brief Whether the spy capability is active or not */
72  unsigned int spy_active:1;
73  /*! \brief Whether the whisper capability is active or not */
74  unsigned int whisper_active:1;
75  /*! \brief A frame of silence to use when the audiohook returns null */
77 };
78 
79 /*! \brief Destructor for snoop structure */
80 static void snoop_destroy(void *obj)
81 {
82  struct stasis_app_snoop *snoop = obj;
83 
84  if (snoop->timer) {
85  ast_timer_close(snoop->timer);
86  }
87 
88  if (snoop->spy_active) {
89  ast_audiohook_destroy(&snoop->spy);
90  }
91 
92  if (snoop->whisper_active) {
94  }
95 
96  if (snoop->silence.data.ptr) {
97  ast_free(snoop->silence.data.ptr);
98  snoop->silence.data.ptr = NULL;
99  }
100 
101  ast_free(snoop->app);
102 
104  ast_channel_cleanup(snoop->chan);
105 }
106 
107 /*! \internal
108  * \brief Publish the chanspy message over Stasis-Core
109  * \param snoop The snoop structure
110  * \start start If non-zero, the spying is starting. Otherwise, the spyer is
111  * finishing
112  */
113 static void publish_chanspy_message(struct stasis_app_snoop *snoop, int start)
114 {
115  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
116  RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
118  RAII_VAR(struct ast_channel_snapshot *, snoop_snapshot, NULL, ao2_cleanup);
119  RAII_VAR(struct ast_channel_snapshot *, spyee_snapshot, NULL, ao2_cleanup);
121 
122  blob = ast_json_null();
123  if (!blob || !type) {
124  return;
125  }
126 
127  payload = ast_multi_channel_blob_create(blob);
128  if (!payload) {
129  return;
130  }
131 
133  if (!snoop_snapshot) {
134  return;
135  }
136  ast_multi_channel_blob_add_channel(payload, "spyer_channel", snoop_snapshot);
137 
139  if (spyee_snapshot) {
140  ast_multi_channel_blob_add_channel(payload, "spyee_channel", spyee_snapshot);
141  }
142 
143  message = stasis_message_create(type, payload);
144  if (!message) {
145  return;
146  }
147 
149 }
150 
151 /*! \brief Callback function for writing to a Snoop whisper audiohook */
152 static int snoop_write(struct ast_channel *chan, struct ast_frame *frame)
153 {
154  struct stasis_app_snoop *snoop = ast_channel_tech_pvt(chan);
155 
156  if (!snoop->whisper_active) {
157  return 0;
158  }
159 
160  ast_audiohook_lock(&snoop->whisper);
164  } else {
165  ast_audiohook_write_frame(&snoop->whisper, snoop->whisper_direction, frame);
166  }
167  ast_audiohook_unlock(&snoop->whisper);
168 
169  return 0;
170 }
171 
172 /*! \brief Callback function for reading from a Snoop channel */
173 static struct ast_frame *snoop_read(struct ast_channel *chan)
174 {
175  struct stasis_app_snoop *snoop = ast_channel_tech_pvt(chan);
176  struct ast_frame *frame = NULL;
177 
178  /* If we fail to ack the timer OR if any active audiohooks are done hangup */
179  if ((ast_timer_ack(snoop->timer, 1) < 0) ||
180  (snoop->spy_active && snoop->spy.status != AST_AUDIOHOOK_STATUS_RUNNING) ||
182  return NULL;
183  }
184 
185  /* Only get audio from the spy audiohook if it is active */
186  if (!snoop->spy_active) {
187  return &ast_null_frame;
188  }
189 
190  ast_audiohook_lock(&snoop->spy);
192  /*
193  * When a singular direction is chosen frames are still written to the
194  * opposing direction's queue. Those frames must be read so the queue
195  * does not continue to grow, however since they are not needed for the
196  * selected direction they can be dropped.
197  */
198  enum ast_audiohook_direction opposing_direction =
202  opposing_direction, snoop->spy_format));
203  }
204 
205  frame = ast_audiohook_read_frame(&snoop->spy, snoop->spy_samples, snoop->spy_direction, snoop->spy_format);
206  ast_audiohook_unlock(&snoop->spy);
207 
208  return frame ? frame : &snoop->silence;
209 }
210 
211 /*! \brief Callback function for hanging up a Snoop channel */
212 static int snoop_hangup(struct ast_channel *chan)
213 {
214  struct stasis_app_snoop *snoop = ast_channel_tech_pvt(chan);
215 
216  if (snoop->spy_active) {
217  ast_audiohook_lock(&snoop->spy);
218  ast_audiohook_detach(&snoop->spy);
219  ast_audiohook_unlock(&snoop->spy);
220  }
221 
222  if (snoop->whisper_active) {
223  ast_audiohook_lock(&snoop->whisper);
224  ast_audiohook_detach(&snoop->whisper);
225  ast_audiohook_unlock(&snoop->whisper);
226  }
227 
228  publish_chanspy_message(snoop, 0);
229 
230  ao2_cleanup(snoop);
231 
233 
234  return 0;
235 }
236 
237 static int snoop_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
238 {
239  struct stasis_app_snoop *snoop = ast_channel_tech_pvt(oldchan);
240 
241  if (snoop->chan != oldchan) {
242  return -1;
243  }
244 
245  ast_channel_unref(snoop->chan);
246  ast_channel_ref(newchan);
247  snoop->chan = newchan;
248 
249  return 0;
250 }
251 
252 /*! \brief Channel interface declaration */
253 static struct ast_channel_tech snoop_tech = {
254  .type = "Snoop",
255  .description = "Snoop Channel Driver",
256  .write = snoop_write,
257  .read = snoop_read,
258  .hangup = snoop_hangup,
259  .fixup = snoop_fixup,
260 };
261 
262 /*! \brief Thread used for running the Stasis application */
263 static void *snoop_stasis_thread(void *obj)
264 {
265  RAII_VAR(struct stasis_app_snoop *, snoop, obj, ao2_cleanup);
266  struct ast_app *stasis = pbx_findapp("Stasis");
267 
268  if (!stasis) {
269  ast_hangup(snoop->chan);
270  return NULL;
271  }
272 
273  pbx_exec(snoop->chan, stasis, ast_str_buffer(snoop->app));
274 
275  ast_hangup(snoop->chan);
276 
277  return NULL;
278 }
279 
280 /*! \brief Internal helper function which sets up and attaches a snoop audiohook */
281 static int snoop_setup_audiohook(struct ast_channel *chan, enum ast_audiohook_type type, enum stasis_app_snoop_direction requested_direction,
282  enum ast_audiohook_direction *direction, struct ast_audiohook *audiohook)
283 {
284  ast_audiohook_init(audiohook, type, "Snoop", 0);
285 
286  if (requested_direction == STASIS_SNOOP_DIRECTION_OUT) {
287  *direction = AST_AUDIOHOOK_DIRECTION_WRITE;
288  } else if (requested_direction == STASIS_SNOOP_DIRECTION_IN) {
289  *direction = AST_AUDIOHOOK_DIRECTION_READ;
290  } else if (requested_direction == STASIS_SNOOP_DIRECTION_BOTH) {
291  *direction = AST_AUDIOHOOK_DIRECTION_BOTH;
292  } else {
293  return -1;
294  }
295 
296  return ast_audiohook_attach(chan, audiohook);
297 }
298 
299 /*! \brief Helper function which gets the format for a Snoop channel based on the channel being snooped on */
300 static void snoop_determine_format(struct ast_channel *chan, struct stasis_app_snoop *snoop)
301 {
302  SCOPED_CHANNELLOCK(lock, chan);
303  unsigned int rate = MAX(ast_format_get_sample_rate(ast_channel_rawwriteformat(chan)),
305 
307 }
308 
311  const char *app, const char *app_args, const char *snoop_id)
312 {
313  RAII_VAR(struct stasis_app_snoop *, snoop, NULL, ao2_cleanup);
314  struct ast_format_cap *caps;
315  pthread_t thread;
316  struct ast_assigned_ids assignedids = {
317  .uniqueid = snoop_id,
318  };
319 
320  if (spy == STASIS_SNOOP_DIRECTION_NONE &&
321  whisper == STASIS_SNOOP_DIRECTION_NONE) {
322  return NULL;
323  }
324 
326  if (!snoop) {
327  return NULL;
328  }
329 
330  /* Allocate a buffer to store the Stasis application and arguments in */
331  snoop->app = ast_str_create(64);
332  if (!snoop->app) {
333  return NULL;
334  }
335 
336  ast_str_set(&snoop->app, 0, "%s", app);
337  if (!ast_strlen_zero(app_args)) {
338  ast_str_append(&snoop->app, 0, ",%s", app_args);
339  }
340 
341  /* Set up a timer for the Snoop channel so it wakes up at a specific interval */
342  snoop->timer = ast_timer_open();
343  if (!snoop->timer) {
344  return NULL;
345  }
346  ast_timer_set_rate(snoop->timer, 1000 / SNOOP_INTERVAL);
347 
348  /* Determine which signed linear format should be used */
349  snoop_determine_format(chan, snoop);
350 
351  /* Allocate a Snoop channel and set up various parameters */
352  snoop->chan = ast_channel_alloc(1, AST_STATE_UP, "", "", "", "", "", &assignedids, NULL, 0, "Snoop/%s-%08x", ast_channel_uniqueid(chan),
353  (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1));
354  if (!snoop->chan) {
355  return NULL;
356  }
357 
358  /* To keep the channel valid on the Snoop structure until it is destroyed we bump the ref up here */
359  ast_channel_ref(snoop->chan);
360 
361  ast_channel_tech_set(snoop->chan, &snoop_tech);
362  ao2_ref(snoop, +1);
363  ast_channel_tech_pvt_set(snoop->chan, snoop);
364  ast_channel_set_fd(snoop->chan, 0, ast_timer_fd(snoop->timer));
365 
366  /* The format on the Snoop channel will be this signed linear format, and it will never change */
368  if (!caps) {
369  ast_channel_unlock(snoop->chan);
370  ast_hangup(snoop->chan);
371  return NULL;
372  }
373  ast_format_cap_append(caps, snoop->spy_format, 0);
374  ast_channel_nativeformats_set(snoop->chan, caps);
375  ao2_ref(caps, -1);
376 
377  ast_channel_set_writeformat(snoop->chan, snoop->spy_format);
378  ast_channel_set_rawwriteformat(snoop->chan, snoop->spy_format);
379  ast_channel_set_readformat(snoop->chan, snoop->spy_format);
380  ast_channel_set_rawreadformat(snoop->chan, snoop->spy_format);
381 
382  ast_channel_unlock(snoop->chan);
383 
384  if (spy != STASIS_SNOOP_DIRECTION_NONE) {
385  if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_SPY, spy, &snoop->spy_direction, &snoop->spy)) {
386  ast_hangup(snoop->chan);
387  return NULL;
388  }
389 
390  snoop->spy_samples = ast_format_get_sample_rate(snoop->spy_format) / (1000 / SNOOP_INTERVAL);
391  snoop->spy_active = 1;
392 
393  snoop->silence.frametype = AST_FRAME_VOICE,
394  snoop->silence.datalen = snoop->spy_samples * sizeof(uint16_t),
395  snoop->silence.samples = snoop->spy_samples,
396  snoop->silence.mallocd = 0,
397  snoop->silence.offset = 0,
398  snoop->silence.src = __PRETTY_FUNCTION__,
399  snoop->silence.subclass.format = snoop->spy_format,
400  snoop->silence.data.ptr = ast_calloc(snoop->spy_samples, sizeof(uint16_t));
401  if (!snoop->silence.data.ptr) {
402  ast_hangup(snoop->chan);
403  return NULL;
404  }
405  }
406 
407  /* If whispering is enabled set up the audiohook */
408  if (whisper != STASIS_SNOOP_DIRECTION_NONE) {
409  if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_WHISPER, whisper, &snoop->whisper_direction, &snoop->whisper)) {
410  ast_hangup(snoop->chan);
411  return NULL;
412  }
413 
414  snoop->whisper_active = 1;
415  }
416 
417  /* Create the thread which services the Snoop channel */
418  ao2_ref(snoop, +1);
420  ao2_cleanup(snoop);
421 
422  /* No other thread is servicing this channel so we can immediately hang it up */
423  ast_hangup(snoop->chan);
424  return NULL;
425  }
426 
427  /* Keep a reference to the channel we are spying on */
428  snoop->spyee_chan = ast_channel_ref(chan);
429 
430  publish_chanspy_message(snoop, 1);
431 
432  /* The caller of this has a reference as well */
433  return ast_channel_ref(snoop->chan);
434 }
435 
436 static int load_module(void)
437 {
439 }
440 
441 static int unload_module(void)
442 {
443  return 0;
444 }
445 
446 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Stasis application snoop support",
447  .support_level = AST_MODULE_SUPPORT_CORE,
448  .load = load_module,
449  .unload = unload_module,
450  .requires = "res_stasis",
451 );
static const char type[]
Definition: chan_ooh323.c:109
pthread_t thread
Definition: app_meetme.c:1089
Main Channel structure associated with a channel.
stasis_app_snoop_direction
Directions for audio stream flow.
const char *const type
Definition: channel.h:630
Asterisk main include file. File version handling, generic pbx functions.
struct ast_audiohook spy
Audiohook used to spy on the channel.
int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, struct ast_frame *frame)
Writes a frame into the audiohook structure.
Definition: audiohook.c:170
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
struct ast_str * app
Stasis application and arguments.
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
Audio stream in from the channel.
static void publish_chanspy_message(struct stasis_app_snoop *snoop, int start)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
Audiohooks Architecture.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
struct ast_audiohook whisper
Audiohook used to whisper on the channel.
Structure representing a snapshot of channel state.
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
Definition: timing.c:154
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:605
struct ast_timer * ast_timer_open(void)
Open a timer.
Definition: timing.c:122
static int snoop_hangup(struct ast_channel *chan)
Callback function for hanging up a Snoop channel.
Definition of a media format.
Definition: format.c:43
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:501
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
const char * uniqueid
Definition: channel.h:606
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
Audio stream to AND from the channel.
struct stasis_message_type * ast_channel_chanspy_start_type(void)
Message type for when a channel starts spying on another channel.
#define NULL
Definition: resample.c:96
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition: audiohook.c:133
struct ast_channel * spyee_chan
The channel that the Snoop channel is snooping on.
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:572
static struct ast_frame * snoop_read(struct ast_channel *chan)
Callback function for reading from a Snoop channel.
static int unload_module(void)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
static int snoop_write(struct ast_channel *chan, struct ast_frame *frame)
Callback function for writing to a Snoop whisper audiohook.
#define ast_strlen_zero(foo)
Definition: strings.h:52
void ast_frame_dtor(struct ast_frame *frame)
NULL-safe wrapper for ast_frfree, good for RAII_VAR.
Definition: main/frame.c:187
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags flags)
Initialize an audiohook structure.
Definition: audiohook.c:108
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
unsigned int spy_samples
Number of samples to be read in when spying.
Structure which contains all of the snoop information.
enum ast_audiohook_direction spy_direction
Direction for spying.
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
Definition: audiohook.h:300
static unsigned int chan_idx
Index used to keep Snoop channel names unique.
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
#define MAX(a, b)
Definition: utils.h:228
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
Asterisk JSON abstraction layer.
struct ast_channel * chan
Snoop channel.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
ast_audiohook_type
Definition: audiohook.h:35
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.
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
Audio stream out to the channel.
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:629
Core PBX routines and definitions.
static void * snoop_stasis_thread(void *obj)
Thread used for running the Stasis application.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
Definition: timing.c:171
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
Definition: audiohook.c:579
Backend API for implementing components of res_stasis.
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
static struct ast_channel_tech snoop_tech
Channel interface declaration.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
static int snoop_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic&#39;s subscribers.
Definition: stasis.c:1511
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static void snoop_determine_format(struct ast_channel *chan, struct stasis_app_snoop *snoop)
Helper function which gets the format for a Snoop channel based on the channel being snooped on...
static const char * stasis
Dialplan application name.
Definition: app_stasis.c:80
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
Definition: timing.c:161
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
Definition: timing.c:166
#define SNOOP_INTERVAL
The interval (in milliseconds) that the Snoop timer is triggered, also controls length of audio withi...
struct ast_channel * stasis_app_control_snoop(struct ast_channel *chan, enum stasis_app_snoop_direction spy, enum stasis_app_snoop_direction whisper, const char *app, const char *app_args, const char *snoop_id)
Create a snoop on the provided channel.
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2431
struct ast_timer * timer
Timer used for waking up Stasis thread.
ast_audiohook_direction
Definition: audiohook.h:48
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
unsigned int whisper_active
Whether the whisper capability is active or not.
struct ast_frame ast_null_frame
Definition: main/frame.c:79
enum ast_audiohook_direction whisper_direction
Direction for whispering.
static int load_module(void)
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
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...
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
ast_app: A registered application
Definition: pbx_app.c:45
Stasis Application Snoop API. See StasisApplication API" for detailed documentation.
A multi channel blob data structure for multi_channel_blob stasis messages.
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
unsigned int spy_active
Whether the spy capability is active or not.
Data structure associated with a single frame of data.
Abstract JSON element (object, array, string, int, ...).
enum ast_audiohook_status status
Definition: audiohook.h:107
union ast_frame::@263 data
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
direction
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition: audiohook.h:295
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
Asterisk module definitions.
struct ast_format * spy_format
Format in use by the spy audiohook.
static int snoop_setup_audiohook(struct ast_channel *chan, enum ast_audiohook_type type, enum stasis_app_snoop_direction requested_direction, enum ast_audiohook_direction *direction, struct ast_audiohook *audiohook)
Internal helper function which sets up and attaches a snoop audiohook.
struct ast_frame silence
A frame of silence to use when the audiohook returns null.
static void snoop_destroy(void *obj)
Destructor for snoop structure.
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
struct ast_format * ast_channel_rawwriteformat(struct ast_channel *chan)
struct ast_frame * ast_audiohook_read_frame(struct ast_audiohook *audiohook, size_t samples, enum ast_audiohook_direction direction, struct ast_format *format)
Reads a frame in from the audiohook structure.
Definition: audiohook.c:449
Timing source management.
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.
struct ast_format * ast_format_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
Definition: format_cache.c:520
Media Format Cache API.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620