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: 379808 $")
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 #include "asterisk/astobj2.h"
00053
00054 static struct ast_channel *bridge_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
00055 static int bridge_call(struct ast_channel *ast, const char *dest, int timeout);
00056 static int bridge_hangup(struct ast_channel *ast);
00057 static struct ast_frame *bridge_read(struct ast_channel *ast);
00058 static int bridge_write(struct ast_channel *ast, struct ast_frame *f);
00059 static struct ast_channel *bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
00060
00061 static struct ast_channel_tech bridge_tech = {
00062 .type = "Bridge",
00063 .description = "Bridge Interaction Channel",
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 struct ast_channel *input;
00076 struct ast_channel *output;
00077 };
00078
00079
00080 static struct ast_channel *bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
00081 {
00082 struct bridge_pvt *p = ast_channel_tech_pvt(chan);
00083 return (chan == p->input) ? p->output : bridge;
00084 }
00085
00086
00087 static struct ast_frame *bridge_read(struct ast_channel *ast)
00088 {
00089 return &ast_null_frame;
00090 }
00091
00092
00093 static int bridge_write(struct ast_channel *ast, struct ast_frame *f)
00094 {
00095 struct bridge_pvt *p = ast_channel_tech_pvt(ast);
00096 struct ast_channel *other = NULL;
00097
00098 ao2_lock(p);
00099
00100 if (p->input == ast) {
00101 other = p->output;
00102 if (other) {
00103 ast_channel_ref(other);
00104 }
00105 }
00106 ao2_unlock(p);
00107
00108 if (other) {
00109 ast_channel_unlock(ast);
00110 ast_queue_frame(other, f);
00111 ast_channel_lock(ast);
00112 other = ast_channel_unref(other);
00113 }
00114
00115 return 0;
00116 }
00117
00118
00119 static int bridge_call(struct ast_channel *ast, const char *dest, int timeout)
00120 {
00121 struct bridge_pvt *p = ast_channel_tech_pvt(ast);
00122
00123
00124 if (!ast_channel_internal_bridge(ast)) {
00125 return -1;
00126 }
00127
00128
00129 return ast_bridge_impart(ast_channel_internal_bridge(p->input), p->output, NULL, NULL, 0)
00130 ? -1 : 0;
00131 }
00132
00133
00134 static int bridge_hangup(struct ast_channel *ast)
00135 {
00136 struct bridge_pvt *p = ast_channel_tech_pvt(ast);
00137
00138 if (!p) {
00139 return 0;
00140 }
00141
00142 ao2_lock(p);
00143 if (p->input == ast) {
00144 p->input = NULL;
00145 } else if (p->output == ast) {
00146 p->output = NULL;
00147 }
00148 ao2_unlock(p);
00149
00150 ast_channel_tech_pvt_set(ast, NULL);
00151 ao2_ref(p, -1);
00152
00153 return 0;
00154 }
00155
00156
00157 static struct ast_channel *bridge_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
00158 {
00159 struct bridge_pvt *p = NULL;
00160 struct ast_format slin;
00161
00162
00163 if (!(p = ao2_alloc(sizeof(*p), NULL))) {
00164 return NULL;
00165 }
00166
00167
00168 if (!(p->input = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? ast_channel_linkedid(requestor) : NULL, 0, "Bridge/%p-input", p))) {
00169 ao2_ref(p, -1);
00170 return NULL;
00171 }
00172 if (!(p->output = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? ast_channel_linkedid(requestor) : NULL, 0, "Bridge/%p-output", p))) {
00173 p->input = ast_channel_release(p->input);
00174 ao2_ref(p, -1);
00175 return NULL;
00176 }
00177
00178
00179 ast_channel_tech_set(p->input, &bridge_tech);
00180 ast_channel_tech_set(p->output, &bridge_tech);
00181
00182 ao2_ref(p, 2);
00183 ast_channel_tech_pvt_set(p->input, p);
00184 ast_channel_tech_pvt_set(p->output, p);
00185
00186 ast_format_set(&slin, AST_FORMAT_SLINEAR, 0);
00187
00188 ast_format_cap_add(ast_channel_nativeformats(p->input), &slin);
00189 ast_format_cap_add(ast_channel_nativeformats(p->output), &slin);
00190 ast_format_copy(ast_channel_readformat(p->input), &slin);
00191 ast_format_copy(ast_channel_readformat(p->output), &slin);
00192 ast_format_copy(ast_channel_rawreadformat(p->input), &slin);
00193 ast_format_copy(ast_channel_rawreadformat(p->output), &slin);
00194 ast_format_copy(ast_channel_writeformat(p->input), &slin);
00195 ast_format_copy(ast_channel_writeformat(p->output), &slin);
00196 ast_format_copy(ast_channel_rawwriteformat(p->input), &slin);
00197 ast_format_copy(ast_channel_rawwriteformat(p->output), &slin);
00198
00199 ast_answer(p->output);
00200 ast_answer(p->input);
00201
00202
00203 ao2_ref(p, -1);
00204 return p->input;
00205 }
00206
00207
00208 static int load_module(void)
00209 {
00210 if (!(bridge_tech.capabilities = ast_format_cap_alloc())) {
00211 return AST_MODULE_LOAD_FAILURE;
00212 }
00213
00214 ast_format_cap_add_all(bridge_tech.capabilities);
00215
00216 if (ast_channel_register(&bridge_tech)) {
00217 ast_log(LOG_ERROR, "Unable to register channel class 'Bridge'\n");
00218 return AST_MODULE_LOAD_FAILURE;
00219 }
00220 return AST_MODULE_LOAD_SUCCESS;
00221 }
00222
00223
00224 static int unload_module(void)
00225 {
00226 ast_channel_unregister(&bridge_tech);
00227 bridge_tech.capabilities = ast_format_cap_destroy(bridge_tech.capabilities);
00228 return 0;
00229 }
00230
00231 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Bridge Interaction Channel",
00232 .load = load_module,
00233 .unload = unload_module,
00234 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
00235 );