Asterisk - The Open Source Telephony Project  18.5.0
bridge_builtin_features.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009, 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 Built in bridging features
22  *
23  * \author Joshua Colp <[email protected]>
24  *
25  * \ingroup bridges
26  */
27 
28 /*** MODULEINFO
29  <use type="module">res_monitor</use>
30  <support_level>core</support_level>
31  ***/
32 
33 #include "asterisk.h"
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 
41 #include "asterisk/module.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/bridge.h"
45 #include "asterisk/frame.h"
46 #include "asterisk/file.h"
47 #include "asterisk/app.h"
48 #include "asterisk/astobj2.h"
49 #include "asterisk/pbx.h"
50 #include "asterisk/parking.h"
52 #include "asterisk/monitor.h"
53 #include "asterisk/mixmonitor.h"
54 #include "asterisk/audiohook.h"
55 #include "asterisk/causes.h"
56 
61 };
62 
63 static void set_touch_variable(enum set_touch_variables_res *res, struct ast_channel *chan, const char *var_name, char **touch)
64 {
65  const char *c_touch;
66 
67  if (*res == SET_TOUCH_ALLOC_FAILURE) {
68  return;
69  }
70  c_touch = pbx_builtin_getvar_helper(chan, var_name);
71  if (!ast_strlen_zero(c_touch)) {
72  *touch = ast_strdup(c_touch);
73  if (!*touch) {
75  } else {
76  *res = SET_TOUCH_SUCCESS;
77  }
78  }
79 }
80 
81 static enum set_touch_variables_res set_touch_variables(struct ast_channel *chan, int is_mixmonitor, char **touch_format, char **touch_monitor, char **touch_monitor_prefix)
82 {
84  const char *var_format;
85  const char *var_monitor;
86  const char *var_prefix;
87 
88  SCOPED_CHANNELLOCK(lock, chan);
89 
90  if (is_mixmonitor) {
91  var_format = "TOUCH_MIXMONITOR_FORMAT";
92  var_monitor = "TOUCH_MIXMONITOR";
93  var_prefix = "TOUCH_MIXMONITOR_PREFIX";
94  } else {
95  var_format = "TOUCH_MONITOR_FORMAT";
96  var_monitor = "TOUCH_MONITOR";
97  var_prefix = "TOUCH_MONITOR_PREFIX";
98  }
99  set_touch_variable(&res, chan, var_format, touch_format);
100  set_touch_variable(&res, chan, var_monitor, touch_monitor);
101  set_touch_variable(&res, chan, var_prefix, touch_monitor_prefix);
102 
103  return res;
104 }
105 
106 static void stop_automonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *stop_message)
107 {
108  ast_verb(4, "AutoMonitor used to stop recording call.\n");
109 
110  ast_channel_lock(peer_chan);
111  if (ast_channel_monitor(peer_chan)) {
112  if (ast_channel_monitor(peer_chan)->stop(peer_chan, 1)) {
113  ast_verb(4, "Cannot stop AutoMonitor for %s\n", ast_channel_name(bridge_channel->chan));
114  if (features_cfg && !(ast_strlen_zero(features_cfg->recordingfailsound))) {
115  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->recordingfailsound, NULL);
116  }
117  ast_channel_unlock(peer_chan);
118  return;
119  }
120  } else {
121  /* Something else removed the Monitor before we got to it. */
122  ast_channel_unlock(peer_chan);
123  return;
124  }
125 
126  ast_channel_unlock(peer_chan);
127 
128  if (features_cfg && !(ast_strlen_zero(features_cfg->courtesytone))) {
129  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
130  ast_bridge_channel_write_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
131  }
132 
133  if (!ast_strlen_zero(stop_message)) {
134  ast_bridge_channel_queue_playfile(bridge_channel, NULL, stop_message, NULL);
135  ast_bridge_channel_write_playfile(bridge_channel, NULL, stop_message, NULL);
136  }
137 }
138 
139 static void start_automonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *start_message)
140 {
141  char *touch_filename;
142  size_t len;
143  int x;
144  enum set_touch_variables_res set_touch_res;
145 
146  RAII_VAR(char *, touch_format, NULL, ast_free);
147  RAII_VAR(char *, touch_monitor, NULL, ast_free);
148  RAII_VAR(char *, touch_monitor_prefix, NULL, ast_free);
149 
150  set_touch_res = set_touch_variables(bridge_channel->chan, 0, &touch_format,
151  &touch_monitor, &touch_monitor_prefix);
152  switch (set_touch_res) {
153  case SET_TOUCH_SUCCESS:
154  break;
155  case SET_TOUCH_UNSET:
156  set_touch_res = set_touch_variables(peer_chan, 0, &touch_format, &touch_monitor,
157  &touch_monitor_prefix);
158  if (set_touch_res == SET_TOUCH_ALLOC_FAILURE) {
159  return;
160  }
161  break;
163  return;
164  }
165 
166  if (!ast_strlen_zero(touch_monitor)) {
167  len = strlen(touch_monitor) + 50;
168  touch_filename = ast_alloca(len);
169  snprintf(touch_filename, len, "%s-%ld-%s",
170  S_OR(touch_monitor_prefix, "auto"),
171  (long) time(NULL),
172  touch_monitor);
173  } else {
174  char *caller_chan_id;
175  char *peer_chan_id;
176 
177  caller_chan_id = ast_strdupa(S_COR(ast_channel_caller(bridge_channel->chan)->id.number.valid,
178  ast_channel_caller(bridge_channel->chan)->id.number.str, ast_channel_name(bridge_channel->chan)));
179  peer_chan_id = ast_strdupa(S_COR(ast_channel_caller(peer_chan)->id.number.valid,
180  ast_channel_caller(peer_chan)->id.number.str, ast_channel_name(peer_chan)));
181  len = strlen(caller_chan_id) + strlen(peer_chan_id) + 50;
182  touch_filename = ast_alloca(len);
183  snprintf(touch_filename, len, "%s-%ld-%s-%s",
184  S_OR(touch_monitor_prefix, "auto"),
185  (long) time(NULL),
186  caller_chan_id,
187  peer_chan_id);
188  }
189 
190  for (x = 0; x < strlen(touch_filename); x++) {
191  if (touch_filename[x] == '/') {
192  touch_filename[x] = '-';
193  }
194  }
195 
196  ast_verb(4, "AutoMonitor used to record call. Filename: %s\n", touch_filename);
197 
198  if (ast_monitor_start(peer_chan, touch_format, touch_filename, 1, X_REC_IN | X_REC_OUT, NULL)) {
199  ast_verb(4, "AutoMonitor feature was tried by '%s' but monitor failed to start.\n",
200  ast_channel_name(bridge_channel->chan));
201  return;
202  }
203 
204  ast_monitor_setjoinfiles(peer_chan, 1);
205 
206  if (features_cfg && !ast_strlen_zero(features_cfg->courtesytone)) {
207  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
208  ast_bridge_channel_write_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
209  }
210 
211  if (!ast_strlen_zero(start_message)) {
212  ast_bridge_channel_queue_playfile(bridge_channel, NULL, start_message, NULL);
213  ast_bridge_channel_write_playfile(bridge_channel, NULL, start_message, NULL);
214  }
215 
216  pbx_builtin_setvar_helper(bridge_channel->chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
217  pbx_builtin_setvar_helper(peer_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
218 }
219 
220 static int feature_automonitor(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
221 {
222  const char *start_message;
223  const char *stop_message;
224  struct ast_bridge_features_automonitor *options = hook_pvt;
226  int is_monitoring;
227 
228  RAII_VAR(struct ast_channel *, peer_chan, NULL, ast_channel_cleanup);
229  RAII_VAR(struct ast_features_general_config *, features_cfg, NULL, ao2_cleanup);
230 
231  ast_channel_lock(bridge_channel->chan);
232  features_cfg = ast_get_chan_features_general_config(bridge_channel->chan);
233  ast_channel_unlock(bridge_channel->chan);
234  ast_bridge_channel_lock_bridge(bridge_channel);
235  peer_chan = ast_bridge_peer_nolock(bridge_channel->bridge, bridge_channel->chan);
236  ast_bridge_unlock(bridge_channel->bridge);
237 
238  if (!peer_chan) {
239  ast_verb(4, "Cannot start AutoMonitor for %s - can not determine peer in bridge.\n",
240  ast_channel_name(bridge_channel->chan));
241  if (features_cfg && !ast_strlen_zero(features_cfg->recordingfailsound)) {
242  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->recordingfailsound, NULL);
243  }
244  return 0;
245  }
246 
247  ast_channel_lock(bridge_channel->chan);
248  start_message = pbx_builtin_getvar_helper(bridge_channel->chan,
249  "TOUCH_MONITOR_MESSAGE_START");
250  start_message = ast_strdupa(S_OR(start_message, ""));
251  stop_message = pbx_builtin_getvar_helper(bridge_channel->chan,
252  "TOUCH_MONITOR_MESSAGE_STOP");
253  stop_message = ast_strdupa(S_OR(stop_message, ""));
254  ast_channel_unlock(bridge_channel->chan);
255 
256  is_monitoring = ast_channel_monitor(peer_chan) != NULL;
257  switch (start_stop) {
258  case AUTO_MONITOR_TOGGLE:
259  if (is_monitoring) {
260  stop_automonitor(bridge_channel, peer_chan, features_cfg, stop_message);
261  } else {
262  start_automonitor(bridge_channel, peer_chan, features_cfg, start_message);
263  }
264  return 0;
265  case AUTO_MONITOR_START:
266  if (!is_monitoring) {
267  start_automonitor(bridge_channel, peer_chan, features_cfg, start_message);
268  return 0;
269  }
270  ast_verb(4, "AutoMonitor already recording call.\n");
271  break;
272  case AUTO_MONITOR_STOP:
273  if (is_monitoring) {
274  stop_automonitor(bridge_channel, peer_chan, features_cfg, stop_message);
275  return 0;
276  }
277  ast_verb(4, "AutoMonitor already stopped on call.\n");
278  break;
279  }
280 
281  /*
282  * Fake start/stop to invoker so will think it did something but
283  * was already in that mode.
284  */
285  if (features_cfg && !ast_strlen_zero(features_cfg->courtesytone)) {
286  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
287  }
288  if (is_monitoring) {
289  if (!ast_strlen_zero(start_message)) {
290  ast_bridge_channel_queue_playfile(bridge_channel, NULL, start_message, NULL);
291  }
292  } else {
293  if (!ast_strlen_zero(stop_message)) {
294  ast_bridge_channel_queue_playfile(bridge_channel, NULL, stop_message, NULL);
295  }
296  }
297  return 0;
298 }
299 
300 static void stop_automixmonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *stop_message)
301 {
302  ast_verb(4, "AutoMixMonitor used to stop recording call.\n");
303 
304  if (ast_stop_mixmonitor(peer_chan, NULL)) {
305  ast_verb(4, "Failed to stop AutoMixMonitor for %s.\n", ast_channel_name(bridge_channel->chan));
306  if (features_cfg && !(ast_strlen_zero(features_cfg->recordingfailsound))) {
307  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->recordingfailsound, NULL);
308  }
309  return;
310  }
311 
312  if (features_cfg && !ast_strlen_zero(features_cfg->courtesytone)) {
313  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
314  ast_bridge_channel_write_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
315  }
316 
317  if (!ast_strlen_zero(stop_message)) {
318  ast_bridge_channel_queue_playfile(bridge_channel, NULL, stop_message, NULL);
319  ast_bridge_channel_write_playfile(bridge_channel, NULL, stop_message, NULL);
320  }
321 }
322 
323 static void start_automixmonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *start_message)
324 {
325  char *touch_filename;
326  size_t len;
327  int x;
328  enum set_touch_variables_res set_touch_res;
329 
330  RAII_VAR(char *, touch_format, NULL, ast_free);
331  RAII_VAR(char *, touch_monitor, NULL, ast_free);
332  RAII_VAR(char *, touch_monitor_prefix, NULL, ast_free);
333 
334  set_touch_res = set_touch_variables(bridge_channel->chan, 1, &touch_format,
335  &touch_monitor, &touch_monitor_prefix);
336  switch (set_touch_res) {
337  case SET_TOUCH_SUCCESS:
338  break;
339  case SET_TOUCH_UNSET:
340  set_touch_res = set_touch_variables(peer_chan, 1, &touch_format, &touch_monitor,
341  &touch_monitor_prefix);
342  if (set_touch_res == SET_TOUCH_ALLOC_FAILURE) {
343  return;
344  }
345  break;
347  return;
348  }
349 
350  if (!ast_strlen_zero(touch_monitor)) {
351  len = strlen(touch_monitor) + 50;
352  touch_filename = ast_alloca(len);
353  snprintf(touch_filename, len, "%s-%ld-%s.%s",
354  S_OR(touch_monitor_prefix, "auto"),
355  (long) time(NULL),
356  touch_monitor,
357  S_OR(touch_format, "wav"));
358  } else {
359  char *caller_chan_id;
360  char *peer_chan_id;
361 
362  caller_chan_id = ast_strdupa(S_COR(ast_channel_caller(bridge_channel->chan)->id.number.valid,
363  ast_channel_caller(bridge_channel->chan)->id.number.str, ast_channel_name(bridge_channel->chan)));
364  peer_chan_id = ast_strdupa(S_COR(ast_channel_caller(peer_chan)->id.number.valid,
365  ast_channel_caller(peer_chan)->id.number.str, ast_channel_name(peer_chan)));
366  len = strlen(caller_chan_id) + strlen(peer_chan_id) + 50;
367  touch_filename = ast_alloca(len);
368  snprintf(touch_filename, len, "%s-%ld-%s-%s.%s",
369  S_OR(touch_monitor_prefix, "auto"),
370  (long) time(NULL),
371  caller_chan_id,
372  peer_chan_id,
373  S_OR(touch_format, "wav"));
374  }
375 
376  for (x = 0; x < strlen(touch_filename); x++) {
377  if (touch_filename[x] == '/') {
378  touch_filename[x] = '-';
379  }
380  }
381 
382  ast_verb(4, "AutoMixMonitor used to record call. Filename: %s\n", touch_filename);
383 
384  if (ast_start_mixmonitor(peer_chan, touch_filename, "b")) {
385  ast_verb(4, "AutoMixMonitor feature was tried by '%s' but MixMonitor failed to start.\n",
386  ast_channel_name(bridge_channel->chan));
387 
388  if (features_cfg && !ast_strlen_zero(features_cfg->recordingfailsound)) {
389  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->recordingfailsound, NULL);
390  }
391  return;
392  }
393 
394  if (features_cfg && !ast_strlen_zero(features_cfg->courtesytone)) {
395  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
396  ast_bridge_channel_write_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
397  }
398 
399  if (!ast_strlen_zero(start_message)) {
400  ast_bridge_channel_queue_playfile(bridge_channel, NULL, start_message, NULL);
401  ast_bridge_channel_write_playfile(bridge_channel, NULL, start_message, NULL);
402  }
403 
404  pbx_builtin_setvar_helper(bridge_channel->chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
405  pbx_builtin_setvar_helper(peer_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
406 }
407 
408 static int feature_automixmonitor(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
409 {
410  static const char *mixmonitor_spy_type = "MixMonitor";
411  const char *stop_message;
412  const char *start_message;
413  struct ast_bridge_features_automixmonitor *options = hook_pvt;
415  int is_monitoring;
416 
417  RAII_VAR(struct ast_channel *, peer_chan, NULL, ast_channel_cleanup);
418  RAII_VAR(struct ast_features_general_config *, features_cfg, NULL, ao2_cleanup);
419 
420  ast_channel_lock(bridge_channel->chan);
421  features_cfg = ast_get_chan_features_general_config(bridge_channel->chan);
422  ast_channel_unlock(bridge_channel->chan);
423  ast_bridge_channel_lock_bridge(bridge_channel);
424  peer_chan = ast_bridge_peer_nolock(bridge_channel->bridge, bridge_channel->chan);
425  ast_bridge_unlock(bridge_channel->bridge);
426 
427  if (!peer_chan) {
428  ast_verb(4, "Cannot start AutoMixMonitor for %s - cannot determine peer in bridge.\n",
429  ast_channel_name(bridge_channel->chan));
430  if (features_cfg && !ast_strlen_zero(features_cfg->recordingfailsound)) {
431  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->recordingfailsound, NULL);
432  }
433  return 0;
434  }
435 
436  ast_channel_lock(bridge_channel->chan);
437  start_message = pbx_builtin_getvar_helper(bridge_channel->chan,
438  "TOUCH_MIXMONITOR_MESSAGE_START");
439  start_message = ast_strdupa(S_OR(start_message, ""));
440  stop_message = pbx_builtin_getvar_helper(bridge_channel->chan,
441  "TOUCH_MIXMONITOR_MESSAGE_STOP");
442  stop_message = ast_strdupa(S_OR(stop_message, ""));
443  ast_channel_unlock(bridge_channel->chan);
444 
445  is_monitoring =
446  0 < ast_channel_audiohook_count_by_source(peer_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
447  switch (start_stop) {
448  case AUTO_MONITOR_TOGGLE:
449  if (is_monitoring) {
450  stop_automixmonitor(bridge_channel, peer_chan, features_cfg, stop_message);
451  } else {
452  start_automixmonitor(bridge_channel, peer_chan, features_cfg, start_message);
453  }
454  return 0;
455  case AUTO_MONITOR_START:
456  if (!is_monitoring) {
457  start_automixmonitor(bridge_channel, peer_chan, features_cfg, start_message);
458  return 0;
459  }
460  ast_verb(4, "AutoMixMonitor already recording call.\n");
461  break;
462  case AUTO_MONITOR_STOP:
463  if (is_monitoring) {
464  stop_automixmonitor(bridge_channel, peer_chan, features_cfg, stop_message);
465  return 0;
466  }
467  ast_verb(4, "AutoMixMonitor already stopped on call.\n");
468  break;
469  }
470 
471  /*
472  * Fake start/stop to invoker so will think it did something but
473  * was already in that mode.
474  */
475  if (features_cfg && !ast_strlen_zero(features_cfg->courtesytone)) {
476  ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);
477  }
478  if (is_monitoring) {
479  if (!ast_strlen_zero(start_message)) {
480  ast_bridge_channel_queue_playfile(bridge_channel, NULL, start_message, NULL);
481  }
482  } else {
483  if (!ast_strlen_zero(stop_message)) {
484  ast_bridge_channel_queue_playfile(bridge_channel, NULL, stop_message, NULL);
485  }
486  }
487  return 0;
488 }
489 
490 /*! \brief Internal built in feature for hangup */
491 static int feature_hangup(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
492 {
493  /*
494  * This is very simple, we simply change the state on the
495  * bridge_channel to force the channel out of the bridge and the
496  * core takes care of the rest.
497  */
500  return 0;
501 }
502 
503 static int unload_module(void)
504 {
508 
509  return 0;
510 }
511 
512 static int load_module(void)
513 {
517 
518  /* This module cannot be unloaded until shutdown */
520 
522 }
523 
524 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Built in bridging features",
525  .support_level = AST_MODULE_SUPPORT_CORE,
526  .load = load_module,
527  .unload = unload_module,
528  .optional_modules = "res_monitor",
529 );
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define X_REC_IN
Definition: monitor.h:30
Main Channel structure associated with a channel.
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
Asterisk main include file. File version handling, generic pbx functions.
Call Parking API.
enum ast_bridge_features_monitor start_stop
Audiohooks Architecture.
static void start_automixmonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *start_message)
struct ast_channel * ast_bridge_peer_nolock(struct ast_bridge *bridge, struct ast_channel *chan)
Get the channel&#39;s bridge peer only if the bridge is two-party.
Definition: bridge.c:4114
unsigned int stop
Definition: app_meetme.c:1096
General features configuration items.
ast_bridge_features_monitor
int ast_start_mixmonitor(struct ast_channel *chan, const char *filename, const char *options)
Start a mixmonitor on a channel with the given parameters.
Definition: mixmonitor.c:74
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
#define NULL
Definition: resample.c:96
static int load_module(void)
#define ast_verb(level,...)
Definition: logger.h:463
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_bridge * bridge
Bridge this channel is participating in.
#define X_REC_OUT
Definition: monitor.h:31
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature)
Unregister a handler for a built in feature.
Definition: bridge.c:3139
static void set_touch_variable(enum set_touch_variables_res *res, struct ast_channel *chan, const char *var_name, char **touch)
Number structure.
Definition: app_followme.c:154
struct ast_party_id id
Caller party ID.
Definition: channel.h:421
struct ast_features_general_config * ast_get_chan_features_general_config(struct ast_channel *chan)
Get the general configuration options for a channel.
int ast_channel_audiohook_count_by_source(struct ast_channel *chan, const char *source, enum ast_audiohook_type type)
Find out how many audiohooks from a certain source exist on a given channel, regardless of status...
Definition: audiohook.c:1157
struct ast_module * self
Definition: module.h:342
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
Definition: lock.h:617
General Asterisk PBX channel definitions.
static const char *const mixmonitor_spy_type
#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 int feature_hangup(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Internal built in feature for hangup.
ast_mutex_t lock
Definition: app_meetme.c:1091
Channel Bridging API.
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
int AST_OPTIONAL_API_NAME() ast_monitor_start(struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action, const char *beep_id)
Start monitoring a channel.
Definition: res_monitor.c:305
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:2992
Asterisk internal frame definitions.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
Core PBX routines and definitions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
int ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
Write a bridge action play file frame into the bridge.
int ast_stop_mixmonitor(struct ast_channel *chan, const char *mixmon_id)
Stop a mixmonitor on a channel with the given parameters.
Definition: mixmonitor.c:86
#define ast_module_shutdown_ref(mod)
Prevent unload of the module before shutdown.
Definition: module.h:464
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_bridge_hook_callback callback, const char *dtmf)
Register a handler for a built in feature.
Definition: bridge.c:3123
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
#define ast_free(a)
Definition: astmm.h:182
static void stop_automixmonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *stop_message)
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",)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
set_touch_variables_res
static enum set_touch_variables_res set_touch_variables(struct ast_channel *chan, int is_mixmonitor, char **touch_format, char **touch_monitor, char **touch_monitor_prefix)
static int feature_automixmonitor(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void AST_OPTIONAL_API_NAME() ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
Definition: res_monitor.c:926
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_name(const struct ast_channel *chan)
int ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
Queue a bridge action play file frame onto the bridge channel.
Channel monitoring.
static void stop_automonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *stop_message)
Internal Asterisk hangup causes.
static int feature_automonitor(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
loadable MixMonitor functionality
static struct test_options options
static int unload_module(void)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Bridging API.
Asterisk module definitions.
struct ast_channel_monitor * ast_channel_monitor(const struct ast_channel *chan)
enum ast_bridge_features_monitor start_stop
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
static void start_automonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *start_message)
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343