Asterisk - The Open Source Telephony Project  21.4.1
Enumerations | Functions
stasis_app_snoop.h File Reference

Stasis Application Snoop API. See StasisApplication API" for detailed documentation. More...

#include "asterisk/stasis_app.h"

Go to the source code of this file.

Enumerations

enum  stasis_app_snoop_direction { STASIS_SNOOP_DIRECTION_NONE = 0, STASIS_SNOOP_DIRECTION_OUT, STASIS_SNOOP_DIRECTION_IN, STASIS_SNOOP_DIRECTION_BOTH }
 Directions for audio stream flow. More...
 

Functions

struct ast_channelstasis_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. More...
 

Detailed Description

Stasis Application Snoop API. See StasisApplication API" for detailed documentation.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om
Since
12

Definition in file stasis_app_snoop.h.

Enumeration Type Documentation

Directions for audio stream flow.

Enumerator
STASIS_SNOOP_DIRECTION_NONE 

No direction.

STASIS_SNOOP_DIRECTION_OUT 

Audio stream out to the channel.

STASIS_SNOOP_DIRECTION_IN 

Audio stream in from the channel.

STASIS_SNOOP_DIRECTION_BOTH 

Audio stream to AND from the channel.

Definition at line 34 of file stasis_app_snoop.h.

34  {
35  /*! \brief No direction */
37  /*! \brief Audio stream out to the channel */
39  /*! \brief Audio stream in from the channel */
41  /*! \brief Audio stream to AND from the channel */
43 };
Audio stream in from the channel.
Audio stream to AND from the channel.
Audio stream out to the channel.

Function Documentation

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.

Parameters
chanChannel to snoop on.
spyDirection of media that should be spied on.
whisperDirection of media that should be whispered into.
appStasis application to execute on the snoop channel.
app_argsStasis application arguments.
snoop_id
Returns
ast_channel ast_channel_unref() when done.
Return values
NULLif snoop channel couldn't be created.

Definition at line 303 of file res_stasis_snoop.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_ref, stasis_app_snoop::app, ast_atomic_fetchadd_int(), AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_calloc, ast_channel_alloc, ast_channel_ref, ast_channel_set_fd(), ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_get_sample_rate(), AST_FRAME_VOICE, ast_hangup(), AST_STATE_UP, ast_str_append(), ast_str_create, ast_str_set(), ast_timer_fd(), ast_timer_open(), ast_timer_set_rate(), stasis_app_snoop::chan, chan_idx, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, ast_frame::frametype, ast_frame::mallocd, ast_frame::offset, RAII_VAR, ast_frame::samples, stasis_app_snoop::silence, snoop_destroy(), snoop_determine_format(), SNOOP_INTERVAL, snoop_setup_audiohook(), snoop_stasis_thread(), stasis_app_snoop::spy, stasis_app_snoop::spy_active, stasis_app_snoop::spy_direction, stasis_app_snoop::spy_format, stasis_app_snoop::spy_samples, stasis_app_snoop::spyee_chan, ast_frame::src, STASIS_SNOOP_DIRECTION_NONE, ast_frame::subclass, thread, stasis_app_snoop::timer, stasis_app_snoop::whisper, stasis_app_snoop::whisper_active, and stasis_app_snoop::whisper_direction.

306 {
307  RAII_VAR(struct stasis_app_snoop *, snoop, NULL, ao2_cleanup);
308  struct ast_format_cap *caps;
309  pthread_t thread;
310  struct ast_assigned_ids assignedids = {
311  .uniqueid = snoop_id,
312  };
313 
314  if (spy == STASIS_SNOOP_DIRECTION_NONE &&
315  whisper == STASIS_SNOOP_DIRECTION_NONE) {
316  return NULL;
317  }
318 
319  snoop = ao2_alloc_options(sizeof(*snoop), snoop_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
320  if (!snoop) {
321  return NULL;
322  }
323 
324  /* Allocate a buffer to store the Stasis application and arguments in */
325  snoop->app = ast_str_create(64);
326  if (!snoop->app) {
327  return NULL;
328  }
329 
330  ast_str_set(&snoop->app, 0, "%s", app);
331  if (!ast_strlen_zero(app_args)) {
332  ast_str_append(&snoop->app, 0, ",%s", app_args);
333  }
334 
335  /* Set up a timer for the Snoop channel so it wakes up at a specific interval */
336  snoop->timer = ast_timer_open();
337  if (!snoop->timer) {
338  return NULL;
339  }
340  ast_timer_set_rate(snoop->timer, 1000 / SNOOP_INTERVAL);
341 
342  /* Determine which signed linear format should be used */
343  snoop_determine_format(chan, snoop);
344 
345  /* Allocate a Snoop channel and set up various parameters */
346  snoop->chan = ast_channel_alloc(1, AST_STATE_UP, "", "", "", "", "", &assignedids, NULL, 0, "Snoop/%s-%08x", ast_channel_uniqueid(chan),
347  (unsigned)ast_atomic_fetchadd_int((int *)&chan_idx, +1));
348  if (!snoop->chan) {
349  return NULL;
350  }
351 
352  /* To keep the channel valid on the Snoop structure until it is destroyed we bump the ref up here */
353  ast_channel_ref(snoop->chan);
354 
355  ast_channel_tech_set(snoop->chan, &snoop_tech);
356  ao2_ref(snoop, +1);
357  ast_channel_tech_pvt_set(snoop->chan, snoop);
358  ast_channel_set_fd(snoop->chan, 0, ast_timer_fd(snoop->timer));
359 
360  /* The format on the Snoop channel will be this signed linear format, and it will never change */
362  if (!caps) {
363  ast_channel_unlock(snoop->chan);
364  ast_hangup(snoop->chan);
365  return NULL;
366  }
367  ast_format_cap_append(caps, snoop->spy_format, 0);
368  ast_channel_nativeformats_set(snoop->chan, caps);
369  ao2_ref(caps, -1);
370 
371  ast_channel_set_writeformat(snoop->chan, snoop->spy_format);
372  ast_channel_set_rawwriteformat(snoop->chan, snoop->spy_format);
373  ast_channel_set_readformat(snoop->chan, snoop->spy_format);
374  ast_channel_set_rawreadformat(snoop->chan, snoop->spy_format);
375 
376  ast_channel_unlock(snoop->chan);
377 
378  if (spy != STASIS_SNOOP_DIRECTION_NONE) {
379  if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_SPY, spy, &snoop->spy_direction, &snoop->spy)) {
380  ast_hangup(snoop->chan);
381  return NULL;
382  }
383 
384  snoop->spy_samples = ast_format_get_sample_rate(snoop->spy_format) / (1000 / SNOOP_INTERVAL);
385  snoop->spy_active = 1;
386 
387  snoop->silence.frametype = AST_FRAME_VOICE,
388  snoop->silence.datalen = snoop->spy_samples * sizeof(uint16_t),
389  snoop->silence.samples = snoop->spy_samples,
390  snoop->silence.mallocd = 0,
391  snoop->silence.offset = 0,
392  snoop->silence.src = __PRETTY_FUNCTION__,
393  snoop->silence.subclass.format = snoop->spy_format,
394  snoop->silence.data.ptr = ast_calloc(snoop->spy_samples, sizeof(uint16_t));
395  if (!snoop->silence.data.ptr) {
396  ast_hangup(snoop->chan);
397  return NULL;
398  }
399  }
400 
401  /* If whispering is enabled set up the audiohook */
402  if (whisper != STASIS_SNOOP_DIRECTION_NONE) {
403  if (snoop_setup_audiohook(chan, AST_AUDIOHOOK_TYPE_WHISPER, whisper, &snoop->whisper_direction, &snoop->whisper)) {
404  ast_hangup(snoop->chan);
405  return NULL;
406  }
407 
408  snoop->whisper_active = 1;
409  }
410 
411  /* Create the thread which services the Snoop channel */
412  ao2_ref(snoop, +1);
413  if (ast_pthread_create_detached_background(&thread, NULL, snoop_stasis_thread, snoop)) {
414  ao2_cleanup(snoop);
415 
416  /* No other thread is servicing this channel so we can immediately hang it up */
417  ast_hangup(snoop->chan);
418  return NULL;
419  }
420 
421  /* Keep a reference to the channel we are spying on */
422  snoop->spyee_chan = ast_channel_ref(chan);
423 
424  publish_chanspy_message(snoop, 1);
425 
426  /* The caller of this has a reference as well */
427  return ast_channel_ref(snoop->chan);
428 }
pthread_t thread
Definition: app_sla.c:329
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:604
struct ast_timer * ast_timer_open(void)
Open a timer.
Definition: timing.c:122
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:1139
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:757
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
Structure which contains all of the snoop information.
static unsigned int chan_idx
Index used to keep Snoop channel names unique.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static void * snoop_stasis_thread(void *obj)
Thread used for running the Stasis application.
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
static struct ast_channel_tech snoop_tech
Channel interface declaration.
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
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...
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
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...
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2426
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
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.
#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:941
static void snoop_destroy(void *obj)
Destructor for snoop structure.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659