Wed Jan 8 2020 09:49:43

Asterisk developer's documentation


chan_bridge.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \author Joshua Colp <jcolp@digium.com>
22  *
23  * \brief Bridge Interaction Channel
24  *
25  * \ingroup channel_drivers
26  */
27 
28 /*** MODULEINFO
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
35 
36 #include <fcntl.h>
37 #include <sys/signal.h>
38 
39 #include "asterisk/lock.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/config.h"
42 #include "asterisk/module.h"
43 #include "asterisk/pbx.h"
44 #include "asterisk/sched.h"
45 #include "asterisk/io.h"
46 #include "asterisk/acl.h"
47 #include "asterisk/callerid.h"
48 #include "asterisk/file.h"
49 #include "asterisk/cli.h"
50 #include "asterisk/app.h"
51 #include "asterisk/bridging.h"
52 
53 static struct ast_channel *bridge_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
54 static int bridge_call(struct ast_channel *ast, char *dest, int timeout);
55 static int bridge_hangup(struct ast_channel *ast);
56 static struct ast_frame *bridge_read(struct ast_channel *ast);
57 static int bridge_write(struct ast_channel *ast, struct ast_frame *f);
58 static struct ast_channel *bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
59 
60 static const struct ast_channel_tech bridge_tech = {
61  .type = "Bridge",
62  .description = "Bridge Interaction Channel",
63  .capabilities = -1,
64  .requester = bridge_request,
65  .call = bridge_call,
66  .hangup = bridge_hangup,
67  .read = bridge_read,
68  .write = bridge_write,
69  .write_video = bridge_write,
70  .exception = bridge_read,
71  .bridged_channel = bridge_bridgedchannel,
72 };
73 
74 struct bridge_pvt {
75  ast_mutex_t lock; /*!< Lock that protects this structure */
76  struct ast_channel *input; /*!< Input channel - talking to source */
77  struct ast_channel *output; /*!< Output channel - talking to bridge */
78 };
79 
80 /*! \brief Called when the user of this channel wants to get the actual channel in the bridge */
81 static struct ast_channel *bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
82 {
83  struct bridge_pvt *p = chan->tech_pvt;
84  return (chan == p->input) ? p->output : bridge;
85 }
86 
87 /*! \brief Called when a frame should be read from the channel */
88 static struct ast_frame *bridge_read(struct ast_channel *ast)
89 {
90  return &ast_null_frame;
91 }
92 
93 /*! \brief Called when a frame should be written out to a channel */
94 static int bridge_write(struct ast_channel *ast, struct ast_frame *f)
95 {
96  struct bridge_pvt *p = ast->tech_pvt;
97  struct ast_channel *other;
98 
99  ast_mutex_lock(&p->lock);
100 
101  other = (p->input == ast ? p->output : p->input);
102 
103  while (other && ast_channel_trylock(other)) {
104  ast_mutex_unlock(&p->lock);
105  do {
107  } while (ast_mutex_trylock(&p->lock));
108  other = (p->input == ast ? p->output : p->input);
109  }
110 
111  /* We basically queue the frame up on the other channel if present */
112  if (other) {
113  ast_queue_frame(other, f);
114  ast_channel_unlock(other);
115  }
116 
117  ast_mutex_unlock(&p->lock);
118 
119  return 0;
120 }
121 
122 /*! \brief Called when the channel should actually be dialed */
123 static int bridge_call(struct ast_channel *ast, char *dest, int timeout)
124 {
125  struct bridge_pvt *p = ast->tech_pvt;
126 
127  /* If no bridge has been provided on the input channel, bail out */
128  if (!ast->bridge) {
129  return -1;
130  }
131 
132  /* Impart the output channel upon the given bridge of the input channel */
133  ast_bridge_impart(p->input->bridge, p->output, NULL, NULL);
134 
135  return 0;
136 }
137 
138 /*! \brief Helper function to not deadlock when queueing the hangup frame */
139 static void bridge_queue_hangup(struct bridge_pvt *p, struct ast_channel *us)
140 {
141  struct ast_channel *other = (p->input == us ? p->output : p->input);
142 
143  while (other && ast_channel_trylock(other)) {
144  ast_mutex_unlock(&p->lock);
145  do {
147  } while (ast_mutex_trylock(&p->lock));
148  other = (p->input == us ? p->output : p->input);
149  }
150 
151  /* We basically queue the frame up on the other channel if present */
152  if (other) {
153  ast_queue_hangup(other);
154  ast_channel_unlock(other);
155  }
156 
157  return;
158 }
159 
160 /*! \brief Called when a channel should be hung up */
161 static int bridge_hangup(struct ast_channel *ast)
162 {
163  struct bridge_pvt *p = ast->tech_pvt;
164 
165  ast_mutex_lock(&p->lock);
166 
167  /* Figure out which channel this is... and set it to NULL as it has gone, but also queue up a hangup frame. */
168  if (p->input == ast) {
169  if (p->output) {
170  bridge_queue_hangup(p, ast);
171  }
172  p->input = NULL;
173  } else if (p->output == ast) {
174  if (p->input) {
175  bridge_queue_hangup(p, ast);
176  }
177  p->output = NULL;
178  }
179 
180  /* Deal with the Asterisk portion of it */
181  ast->tech_pvt = NULL;
182 
183  /* If both sides have been terminated free the structure and be done with things */
184  if (!p->input && !p->output) {
185  ast_mutex_unlock(&p->lock);
186  ast_mutex_destroy(&p->lock);
187  ast_free(p);
188  } else {
189  ast_mutex_unlock(&p->lock);
190  }
191 
192  return 0;
193 }
194 
195 /*! \brief Called when we want to place a call somewhere, but not actually call it... yet */
196 static struct ast_channel *bridge_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
197 {
198  struct bridge_pvt *p = NULL;
199 
200  /* Try to allocate memory for our very minimal pvt structure */
201  if (!(p = ast_calloc(1, sizeof(*p)))) {
202  return NULL;
203  }
204 
205  /* Try to grab two Asterisk channels to use as input and output channels */
206  if (!(p->input = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? requestor->linkedid : NULL, 0, "Bridge/%p-input", p))) {
207  ast_free(p);
208  return NULL;
209  }
210  if (!(p->output = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? requestor->linkedid : NULL, 0, "Bridge/%p-output", p))) {
212  ast_free(p);
213  return NULL;
214  }
215 
216  /* Setup the lock on the pvt structure, we will need that */
217  ast_mutex_init(&p->lock);
218 
219  /* Setup parameters on both new channels */
220  p->input->tech = p->output->tech = &bridge_tech;
221  p->input->tech_pvt = p->output->tech_pvt = p;
227 
228  return p->input;
229 }
230 
231 /*! \brief Load module into PBX, register channel */
232 static int load_module(void)
233 {
234  /* Make sure we can register our channel type */
235  if (ast_channel_register(&bridge_tech)) {
236  ast_log(LOG_ERROR, "Unable to register channel class 'Bridge'\n");
238  }
240 }
241 
242 /*! \brief Unload the bridge interaction channel from Asterisk */
243 static int unload_module(void)
244 {
245  ast_channel_unregister(&bridge_tech);
246  return 0;
247 }
248 
249 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Bridge Interaction Channel",
250  .load = load_module,
251  .unload = unload_module,
252  .load_pri = AST_MODPRI_CHANNEL_DRIVER,
253 );
static int load_module(void)
Load module into PBX, register channel.
Definition: chan_bridge.c:232
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1569
Main Channel structure associated with a channel.
Definition: channel.h:742
static struct ast_channel * bridge_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
Called when we want to place a call somewhere, but not actually call it... yet.
Definition: chan_bridge.c:196
const char *const type
Definition: channel.h:508
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
struct ast_frame ast_null_frame
Definition: frame.c:131
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
format_t writeformat
Definition: channel.h:854
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:938
void * tech_pvt
Definition: channel.h:744
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1921
static int bridge_hangup(struct ast_channel *ast)
Called when a channel should be hung up.
Definition: chan_bridge.c:161
format_t rawwriteformat
Definition: channel.h:856
Configuration File Parser.
static int bridge_write(struct ast_channel *ast, struct ast_frame *f)
Called when a frame should be written out to a channel.
Definition: chan_bridge.c:94
static int bridge_call(struct ast_channel *ast, char *dest, int timeout)
Called when the channel should actually be dialed.
Definition: chan_bridge.c:123
ast_mutex_t lock
Definition: chan_bridge.c:75
#define ast_mutex_lock(a)
Definition: lock.h:155
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:907
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
format_t nativeformats
Definition: channel.h:852
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
const char * data
Definition: channel.h:755
I/O Management (derived from Cheops-NG)
static struct ast_channel_tech bridge_tech
Definition: chan_bridge.c:60
const ast_string_field linkedid
Definition: channel.h:787
format_t rawreadformat
Definition: channel.h:855
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
static void bridge_queue_hangup(struct bridge_pvt *p, struct ast_channel *us)
Helper function to not deadlock when queueing the hangup frame.
Definition: chan_bridge.c:139
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features)
Impart (non-blocking) a channel on a bridge.
Definition: bridging.c:1043
General Asterisk PBX channel definitions.
#define ast_mutex_trylock(a)
Definition: lock.h:157
Access Control of various sorts.
Channel Bridging API.
Scheduler Routines (derived from cheops)
Structure to describe a channel &quot;technology&quot;, ie a channel driver See for examples: ...
Definition: channel.h:507
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1558
static struct ast_frame * bridge_read(struct ast_channel *ast)
Called when a frame should be read from the channel.
Definition: chan_bridge.c:88
#define LOG_ERROR
Definition: logger.h:155
int64_t format_t
Definition: frame_defs.h:32
static struct ast_channel * bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
Called when the user of this channel wants to get the actual channel in the bridge.
Definition: chan_bridge.c:81
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_bridge * bridge
Definition: channel.h:865
static int unload_module(void)
Unload the bridge interaction channel from Asterisk.
Definition: chan_bridge.c:243
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_free(a)
Definition: astmm.h:97
struct ast_channel * output
Definition: chan_bridge.c:77
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
Definition: lock.h:480
static struct ast_format f[]
Definition: format_g726.c:181
static const char type[]
Definition: chan_nbs.c:57
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
Standard Command Line Interface.
format_t readformat
Definition: channel.h:853
#define ast_calloc(a, b)
Definition: astmm.h:82
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
Data structure associated with a single frame of data.
Definition: frame.h:142
#define ast_mutex_init(pmutex)
Definition: lock.h:152
#define ast_channel_trylock(chan)
Definition: channel.h:2468
#define ast_mutex_destroy(a)
Definition: lock.h:154
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
static snd_pcm_format_t format
Definition: chan_alsa.c:93
struct ast_channel_tech * tech
Definition: channel.h:743
struct ast_channel * input
Definition: chan_bridge.c:76
Structure for mutex and tracking information.
Definition: lock.h:121
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define ast_mutex_unlock(a)
Definition: lock.h:156