00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00035
00036 #include <fcntl.h>
00037 #include <sys/signal.h>
00038
00039 #include "asterisk/lock.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/config.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/pbx.h"
00044 #include "asterisk/sched.h"
00045 #include "asterisk/io.h"
00046 #include "asterisk/acl.h"
00047 #include "asterisk/callerid.h"
00048 #include "asterisk/file.h"
00049 #include "asterisk/cli.h"
00050 #include "asterisk/app.h"
00051 #include "asterisk/bridging.h"
00052
00053 static struct ast_channel *bridge_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
00054 static int bridge_call(struct ast_channel *ast, char *dest, int timeout);
00055 static int bridge_hangup(struct ast_channel *ast);
00056 static struct ast_frame *bridge_read(struct ast_channel *ast);
00057 static int bridge_write(struct ast_channel *ast, struct ast_frame *f);
00058 static struct ast_channel *bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
00059
00060 static const struct ast_channel_tech bridge_tech = {
00061 .type = "Bridge",
00062 .description = "Bridge Interaction Channel",
00063 .capabilities = -1,
00064 .requester = bridge_request,
00065 .call = bridge_call,
00066 .hangup = bridge_hangup,
00067 .read = bridge_read,
00068 .write = bridge_write,
00069 .write_video = bridge_write,
00070 .exception = bridge_read,
00071 .bridged_channel = bridge_bridgedchannel,
00072 };
00073
00074 struct bridge_pvt {
00075 ast_mutex_t lock;
00076 struct ast_channel *input;
00077 struct ast_channel *output;
00078 };
00079
00080
00081 static struct ast_channel *bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
00082 {
00083 struct bridge_pvt *p = chan->tech_pvt;
00084 return (chan == p->input) ? p->output : bridge;
00085 }
00086
00087
00088 static struct ast_frame *bridge_read(struct ast_channel *ast)
00089 {
00090 return &ast_null_frame;
00091 }
00092
00093
00094 static int bridge_write(struct ast_channel *ast, struct ast_frame *f)
00095 {
00096 struct bridge_pvt *p = ast->tech_pvt;
00097 struct ast_channel *other;
00098
00099 ast_mutex_lock(&p->lock);
00100
00101 other = (p->input == ast ? p->output : p->input);
00102
00103 while (other && ast_channel_trylock(other)) {
00104 ast_mutex_unlock(&p->lock);
00105 do {
00106 CHANNEL_DEADLOCK_AVOIDANCE(ast);
00107 } while (ast_mutex_trylock(&p->lock));
00108 other = (p->input == ast ? p->output : p->input);
00109 }
00110
00111
00112 if (other) {
00113 ast_queue_frame(other, f);
00114 ast_channel_unlock(other);
00115 }
00116
00117 ast_mutex_unlock(&p->lock);
00118
00119 return 0;
00120 }
00121
00122
00123 static int bridge_call(struct ast_channel *ast, char *dest, int timeout)
00124 {
00125 struct bridge_pvt *p = ast->tech_pvt;
00126
00127
00128 if (!ast->bridge) {
00129 return -1;
00130 }
00131
00132
00133 ast_bridge_impart(p->input->bridge, p->output, NULL, NULL);
00134
00135 return 0;
00136 }
00137
00138
00139 static void bridge_queue_hangup(struct bridge_pvt *p, struct ast_channel *us)
00140 {
00141 struct ast_channel *other = (p->input == us ? p->output : p->input);
00142
00143 while (other && ast_channel_trylock(other)) {
00144 ast_mutex_unlock(&p->lock);
00145 do {
00146 CHANNEL_DEADLOCK_AVOIDANCE(us);
00147 } while (ast_mutex_trylock(&p->lock));
00148 other = (p->input == us ? p->output : p->input);
00149 }
00150
00151
00152 if (other) {
00153 ast_queue_hangup(other);
00154 ast_channel_unlock(other);
00155 }
00156
00157 return;
00158 }
00159
00160
00161 static int bridge_hangup(struct ast_channel *ast)
00162 {
00163 struct bridge_pvt *p = ast->tech_pvt;
00164
00165 ast_mutex_lock(&p->lock);
00166
00167
00168 if (p->input == ast) {
00169 if (p->output) {
00170 bridge_queue_hangup(p, ast);
00171 }
00172 p->input = NULL;
00173 } else if (p->output == ast) {
00174 if (p->input) {
00175 bridge_queue_hangup(p, ast);
00176 }
00177 p->output = NULL;
00178 }
00179
00180
00181 ast->tech_pvt = NULL;
00182
00183
00184 if (!p->input && !p->output) {
00185 ast_mutex_unlock(&p->lock);
00186 ast_mutex_destroy(&p->lock);
00187 ast_free(p);
00188 } else {
00189 ast_mutex_unlock(&p->lock);
00190 }
00191
00192 return 0;
00193 }
00194
00195
00196 static struct ast_channel *bridge_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
00197 {
00198 struct bridge_pvt *p = NULL;
00199
00200
00201 if (!(p = ast_calloc(1, sizeof(*p)))) {
00202 return NULL;
00203 }
00204
00205
00206 if (!(p->input = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? requestor->linkedid : NULL, 0, "Bridge/%p-input", p))) {
00207 ast_free(p);
00208 return NULL;
00209 }
00210 if (!(p->output = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? requestor->linkedid : NULL, 0, "Bridge/%p-output", p))) {
00211 p->input = ast_channel_release(p->input);
00212 ast_free(p);
00213 return NULL;
00214 }
00215
00216
00217 ast_mutex_init(&p->lock);
00218
00219
00220 p->input->tech = p->output->tech = &bridge_tech;
00221 p->input->tech_pvt = p->output->tech_pvt = p;
00222 p->input->nativeformats = p->output->nativeformats = AST_FORMAT_SLINEAR;
00223 p->input->readformat = p->output->readformat = AST_FORMAT_SLINEAR;
00224 p->input->rawreadformat = p->output->rawreadformat = AST_FORMAT_SLINEAR;
00225 p->input->writeformat = p->output->writeformat = AST_FORMAT_SLINEAR;
00226 p->input->rawwriteformat = p->output->rawwriteformat = AST_FORMAT_SLINEAR;
00227
00228 return p->input;
00229 }
00230
00231
00232 static int load_module(void)
00233 {
00234
00235 if (ast_channel_register(&bridge_tech)) {
00236 ast_log(LOG_ERROR, "Unable to register channel class 'Bridge'\n");
00237 return AST_MODULE_LOAD_FAILURE;
00238 }
00239 return AST_MODULE_LOAD_SUCCESS;
00240 }
00241
00242
00243 static int unload_module(void)
00244 {
00245 ast_channel_unregister(&bridge_tech);
00246 return 0;
00247 }
00248
00249 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Bridge Interaction Channel",
00250 .load = load_module,
00251 .unload = unload_module,
00252 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
00253 );