Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
res_stasis_snoop.c File Reference

Stasis application snoop control support. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app_impl.h"
#include "asterisk/stasis_app_snoop.h"
#include "asterisk/audiohook.h"
#include "asterisk/pbx.h"
#include "asterisk/timing.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/json.h"
#include "asterisk/format_cache.h"
Include dependency graph for res_stasis_snoop.c:

Go to the source code of this file.

Data Structures

struct  stasis_app_snoop
 Structure which contains all of the snoop information. More...
 

Macros

#define SNOOP_INTERVAL   20
 The interval (in milliseconds) that the Snoop timer is triggered, also controls length of audio within frames. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int load_module (void)
 
static void publish_chanspy_message (struct stasis_app_snoop *snoop, int start)
 
static void snoop_destroy (void *obj)
 Destructor for snoop structure. More...
 
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. More...
 
static int snoop_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 
static int snoop_hangup (struct ast_channel *chan)
 Callback function for hanging up a Snoop channel. More...
 
static struct ast_framesnoop_read (struct ast_channel *chan)
 Callback function for reading from a Snoop channel. More...
 
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. More...
 
static void * snoop_stasis_thread (void *obj)
 Thread used for running the Stasis application. More...
 
static int snoop_write (struct ast_channel *chan, struct ast_frame *frame)
 Callback function for writing to a Snoop whisper audiohook. More...
 
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...
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Stasis application snoop support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "res_stasis", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static unsigned int chan_idx
 Index used to keep Snoop channel names unique. More...
 
static struct ast_channel_tech snoop_tech
 Channel interface declaration. More...
 

Detailed Description

Stasis application snoop control support.

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

Definition in file res_stasis_snoop.c.

Macro Definition Documentation

◆ SNOOP_INTERVAL

#define SNOOP_INTERVAL   20

The interval (in milliseconds) that the Snoop timer is triggered, also controls length of audio within frames.

Definition at line 44 of file res_stasis_snoop.c.

Referenced by stasis_app_control_snoop().

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 451 of file res_stasis_snoop.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 451 of file res_stasis_snoop.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 451 of file res_stasis_snoop.c.

◆ load_module()

static int load_module ( void  )
static

Definition at line 436 of file res_stasis_snoop.c.

References AST_MODULE_LOAD_SUCCESS.

Referenced by unload_module().

437 {
439 }

◆ publish_chanspy_message()

static void publish_chanspy_message ( struct stasis_app_snoop snoop,
int  start 
)
static

Definition at line 113 of file res_stasis_snoop.c.

References ao2_cleanup, ast_channel_chanspy_start_type(), ast_channel_chanspy_stop_type(), ast_channel_snapshot_get_latest(), ast_channel_topic(), ast_channel_uniqueid(), ast_json_null(), ast_json_unref(), ast_multi_channel_blob_add_channel(), ast_multi_channel_blob_create(), stasis_app_snoop::chan, NULL, RAII_VAR, stasis_app_snoop::spyee_chan, stasis_message_create(), stasis_publish(), and type.

Referenced by snoop_hangup(), and stasis_app_control_snoop().

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 }
static const char type[]
Definition: chan_ooh323.c:109
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
Structure representing a snapshot of channel state.
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
struct ast_channel * spyee_chan
The channel that the Snoop channel is snooping on.
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
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_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 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.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511
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
A multi channel blob data structure for multi_channel_blob stasis messages.
Abstract JSON element (object, array, string, int, ...).
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.

◆ snoop_destroy()

static void snoop_destroy ( void *  obj)
static

Destructor for snoop structure.

Definition at line 80 of file res_stasis_snoop.c.

References stasis_app_snoop::app, ast_audiohook_destroy(), ast_channel_cleanup, ast_free, ast_timer_close(), stasis_app_snoop::chan, ast_frame::data, NULL, ast_frame::ptr, stasis_app_snoop::silence, stasis_app_snoop::spy, stasis_app_snoop::spy_active, stasis_app_snoop::spyee_chan, stasis_app_snoop::timer, stasis_app_snoop::whisper, and stasis_app_snoop::whisper_active.

Referenced by stasis_app_control_snoop().

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 }
struct ast_audiohook spy
Audiohook used to spy on the channel.
struct ast_str * app
Stasis application and arguments.
struct ast_audiohook whisper
Audiohook used to whisper on the channel.
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
Definition: timing.c:154
#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.
Structure which contains all of the snoop information.
struct ast_channel * chan
Snoop channel.
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
#define ast_free(a)
Definition: astmm.h:182
struct ast_timer * timer
Timer used for waking up Stasis thread.
unsigned int whisper_active
Whether the whisper capability is active or not.
unsigned int spy_active
Whether the spy capability is active or not.
union ast_frame::@263 data
struct ast_frame silence
A frame of silence to use when the audiohook returns null.

◆ snoop_determine_format()

static void snoop_determine_format ( struct ast_channel chan,
struct stasis_app_snoop snoop 
)
static

Helper function which gets the format for a Snoop channel based on the channel being snooped on.

Definition at line 300 of file res_stasis_snoop.c.

References ast_channel_rawreadformat(), ast_channel_rawwriteformat(), ast_format_cache_get_slin_by_rate(), ast_format_get_sample_rate(), lock, MAX, SCOPED_CHANNELLOCK, and stasis_app_snoop::spy_format.

Referenced by stasis_app_control_snoop().

301 {
302  SCOPED_CHANNELLOCK(lock, chan);
303  unsigned int rate = MAX(ast_format_get_sample_rate(ast_channel_rawwriteformat(chan)),
305 
307 }
#define MAX(a, b)
Definition: utils.h:228
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
ast_mutex_t lock
Definition: app_meetme.c:1091
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
struct ast_format * spy_format
Format in use by the spy audiohook.
struct ast_format * ast_channel_rawwriteformat(struct ast_channel *chan)
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

◆ snoop_fixup()

static int snoop_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
)
static

Definition at line 237 of file res_stasis_snoop.c.

References ast_channel_ref, ast_channel_tech_pvt(), ast_channel_unref, and stasis_app_snoop::chan.

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 }
void * ast_channel_tech_pvt(const struct ast_channel *chan)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
Structure which contains all of the snoop information.
struct ast_channel * chan
Snoop channel.
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970

◆ snoop_hangup()

static int snoop_hangup ( struct ast_channel chan)
static

Callback function for hanging up a Snoop channel.

Definition at line 212 of file res_stasis_snoop.c.

References ao2_cleanup, ast_audiohook_detach(), ast_audiohook_lock, ast_audiohook_unlock, ast_channel_tech_pvt(), ast_channel_tech_pvt_set(), NULL, publish_chanspy_message(), stasis_app_snoop::spy, stasis_app_snoop::spy_active, stasis_app_snoop::whisper, and stasis_app_snoop::whisper_active.

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 }
struct ast_audiohook spy
Audiohook used to spy on the channel.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
static void publish_chanspy_message(struct stasis_app_snoop *snoop, int start)
struct ast_audiohook whisper
Audiohook used to whisper on the channel.
#define NULL
Definition: resample.c:96
Structure which contains all of the snoop information.
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
Definition: audiohook.h:300
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
Definition: audiohook.c:579
unsigned int whisper_active
Whether the whisper capability is active or not.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
unsigned int spy_active
Whether the spy capability is active or not.
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition: audiohook.h:295
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)

◆ snoop_read()

static struct ast_frame* snoop_read ( struct ast_channel chan)
static

Callback function for reading from a Snoop channel.

Definition at line 173 of file res_stasis_snoop.c.

References AST_AUDIOHOOK_DIRECTION_BOTH, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, ast_audiohook_lock, ast_audiohook_read_frame(), AST_AUDIOHOOK_STATUS_RUNNING, ast_audiohook_unlock, ast_channel_tech_pvt(), ast_frame_dtor(), ast_null_frame, ast_timer_ack(), NULL, stasis_app_snoop::silence, stasis_app_snoop::spy, stasis_app_snoop::spy_active, stasis_app_snoop::spy_direction, stasis_app_snoop::spy_format, stasis_app_snoop::spy_samples, ast_audiohook::status, stasis_app_snoop::timer, stasis_app_snoop::whisper, and stasis_app_snoop::whisper_active.

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 }
struct ast_audiohook spy
Audiohook used to spy on the channel.
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_audiohook whisper
Audiohook used to whisper on the channel.
#define NULL
Definition: resample.c:96
void ast_frame_dtor(struct ast_frame *frame)
NULL-safe wrapper for ast_frfree, good for RAII_VAR.
Definition: main/frame.c:187
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
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
Definition: timing.c:171
struct ast_timer * timer
Timer used for waking up Stasis thread.
ast_audiohook_direction
Definition: audiohook.h:48
unsigned int whisper_active
Whether the whisper capability is active or not.
struct ast_frame ast_null_frame
Definition: main/frame.c:79
unsigned int spy_active
Whether the spy capability is active or not.
Data structure associated with a single frame of data.
enum ast_audiohook_status status
Definition: audiohook.h:107
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition: audiohook.h:295
struct ast_format * spy_format
Format in use by the spy audiohook.
struct ast_frame silence
A frame of silence to use when the audiohook returns null.
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

◆ snoop_setup_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 
)
static

Internal helper function which sets up and attaches a snoop audiohook.

Definition at line 281 of file res_stasis_snoop.c.

References ast_audiohook_attach(), AST_AUDIOHOOK_DIRECTION_BOTH, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, ast_audiohook_init(), STASIS_SNOOP_DIRECTION_BOTH, STASIS_SNOOP_DIRECTION_IN, and STASIS_SNOOP_DIRECTION_OUT.

Referenced by stasis_app_control_snoop().

283 {
284  ast_audiohook_init(audiohook, type, "Snoop", 0);
285 
286  if (requested_direction == STASIS_SNOOP_DIRECTION_OUT) {
288  } else if (requested_direction == STASIS_SNOOP_DIRECTION_IN) {
290  } else if (requested_direction == STASIS_SNOOP_DIRECTION_BOTH) {
292  } else {
293  return -1;
294  }
295 
296  return ast_audiohook_attach(chan, audiohook);
297 }
static const char type[]
Definition: chan_ooh323.c:109
Audio stream in from the channel.
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:501
Audio stream to AND from the channel.
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
Audio stream out to the channel.
direction

◆ snoop_stasis_thread()

static void* snoop_stasis_thread ( void *  obj)
static

Thread used for running the Stasis application.

Definition at line 263 of file res_stasis_snoop.c.

References ao2_cleanup, ast_hangup(), ast_str_buffer(), NULL, pbx_exec(), pbx_findapp(), RAII_VAR, and stasis.

Referenced by stasis_app_control_snoop().

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 }
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define NULL
Definition: resample.c:96
Structure which contains all of the snoop information.
#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
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
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
ast_app: A registered application
Definition: pbx_app.c:45
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165

◆ snoop_write()

static int snoop_write ( struct ast_channel chan,
struct ast_frame frame 
)
static

Callback function for writing to a Snoop whisper audiohook.

Definition at line 152 of file res_stasis_snoop.c.

References AST_AUDIOHOOK_DIRECTION_BOTH, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, ast_audiohook_lock, ast_audiohook_unlock, ast_audiohook_write_frame(), ast_channel_tech_pvt(), stasis_app_snoop::whisper, stasis_app_snoop::whisper_active, and stasis_app_snoop::whisper_direction.

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 }
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
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_audiohook whisper
Audiohook used to whisper on the channel.
Structure which contains all of the snoop information.
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
Definition: audiohook.h:300
unsigned int whisper_active
Whether the whisper capability is active or not.
enum ast_audiohook_direction whisper_direction
Direction for whispering.
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition: audiohook.h:295

◆ stasis_app_control_snoop()

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.
Returns
Snoop channel. ast_channel_unref() when done.
NULL if snoop channel couldn't be created.

Definition at line 309 of file res_stasis_snoop.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_ref, ast_atomic_fetchadd_int(), AST_AUDIOHOOK_TYPE_SPY, AST_AUDIOHOOK_TYPE_WHISPER, ast_calloc, ast_channel_alloc, ast_channel_nativeformats_set(), ast_channel_ref, ast_channel_set_fd(), ast_channel_set_rawreadformat(), ast_channel_set_rawwriteformat(), ast_channel_set_readformat(), ast_channel_set_writeformat(), ast_channel_tech_pvt_set(), ast_channel_tech_set(), ast_channel_uniqueid(), ast_channel_unlock, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_get_sample_rate(), AST_FRAME_VOICE, ast_hangup(), ast_pthread_create_detached_background, AST_STATE_UP, ast_str_append(), ast_str_create, ast_str_set(), ast_strlen_zero, ast_timer_fd(), ast_timer_open(), ast_timer_set_rate(), chan_idx, NULL, publish_chanspy_message(), RAII_VAR, snoop_destroy(), snoop_determine_format(), SNOOP_INTERVAL, snoop_setup_audiohook(), snoop_stasis_thread(), STASIS_SNOOP_DIRECTION_NONE, thread, and ast_assigned_ids::uniqueid.

Referenced by ari_channels_handle_snoop_channel().

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 }
pthread_t thread
Definition: app_meetme.c:1089
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
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)
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
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
#define NULL
Definition: resample.c:96
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:572
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
#define ast_strlen_zero(foo)
Definition: strings.h:52
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
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
Structure which contains all of the snoop information.
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 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)
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
static void * snoop_stasis_thread(void *obj)
Thread used for running the Stasis application.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
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_channel_unlock(chan)
Definition: channel.h:2946
#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...
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...
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
Definition: channel.c:2431
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
static const char app[]
Definition: app_mysql.c:62
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1259
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.
static void snoop_destroy(void *obj)
Destructor for snoop structure.
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 441 of file res_stasis_snoop.c.

References AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, and load_module().

442 {
443  return 0;
444 }

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Stasis application snoop support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "res_stasis", }
static

Definition at line 451 of file res_stasis_snoop.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 451 of file res_stasis_snoop.c.

◆ chan_idx

unsigned int chan_idx
static

Index used to keep Snoop channel names unique.

Definition at line 47 of file res_stasis_snoop.c.

Referenced by stasis_app_control_snoop().

◆ snoop_tech

struct ast_channel_tech snoop_tech
static

Channel interface declaration.

Definition at line 253 of file res_stasis_snoop.c.