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