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$")
00035
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041
00042 #include "asterisk/module.h"
00043 #include "asterisk/channel.h"
00044 #include "asterisk/bridging.h"
00045 #include "asterisk/bridging_technology.h"
00046 #include "asterisk/frame.h"
00047 #include "asterisk/file.h"
00048 #include "asterisk/app.h"
00049 #include "asterisk/astobj2.h"
00050
00051
00052 static int grab_transfer(struct ast_channel *chan, char *exten, size_t exten_len, const char *context)
00053 {
00054 int res;
00055
00056
00057 res = ast_stream_and_wait(chan, "pbx-transfer", AST_DIGIT_ANY);
00058 ast_stopstream(chan);
00059
00060
00061 if (res) {
00062 exten[0] = (char)res;
00063 }
00064
00065
00066 res = ast_app_dtget(chan, context, exten, exten_len, 100, 1000);
00067
00068 return res;
00069 }
00070
00071
00072 static struct ast_channel *dial_transfer(const struct ast_channel *caller, const char *exten, const char *context)
00073 {
00074 char destination[AST_MAX_EXTENSION+AST_MAX_CONTEXT+1] = "";
00075 struct ast_channel *chan = NULL;
00076 int cause;
00077
00078
00079 snprintf(destination, sizeof(destination), "%s@%s", exten, context);
00080
00081
00082 if (!(chan = ast_request("Local", caller->nativeformats, caller, destination, &cause))) {
00083 return NULL;
00084 }
00085
00086
00087 ast_channel_inherit_variables(caller, chan);
00088
00089
00090 if (ast_call(chan, destination, 0)) {
00091 ast_hangup(chan);
00092 return NULL;
00093 }
00094
00095 return chan;
00096 }
00097
00098
00099 static int feature_blind_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
00100 {
00101 char exten[AST_MAX_EXTENSION] = "";
00102 struct ast_channel *chan = NULL;
00103 struct ast_bridge_features_blind_transfer *blind_transfer = hook_pvt;
00104 const char *context = (blind_transfer && !ast_strlen_zero(blind_transfer->context) ? blind_transfer->context : bridge_channel->chan->context);
00105
00106
00107 if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
00108 ast_stream_and_wait(bridge_channel->chan, "pbx-invalid", AST_DIGIT_ANY);
00109 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00110 return 0;
00111 }
00112
00113
00114 if (!(chan = dial_transfer(bridge_channel->chan, exten, context))) {
00115 ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
00116 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00117 return 0;
00118 }
00119
00120
00121 ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL);
00122
00123 return 0;
00124 }
00125
00126
00127 static int attended_threeway_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
00128 {
00129
00130 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
00131 return 0;
00132 }
00133
00134
00135 static int attended_abort_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
00136 {
00137 struct ast_bridge_channel *called_bridge_channel = NULL;
00138
00139
00140 ao2_lock(bridge);
00141
00142 if (AST_LIST_FIRST(&bridge->channels) != bridge_channel) {
00143 called_bridge_channel = AST_LIST_FIRST(&bridge->channels);
00144 } else {
00145 called_bridge_channel = AST_LIST_LAST(&bridge->channels);
00146 }
00147
00148
00149 if (called_bridge_channel) {
00150 ast_bridge_change_state(called_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
00151 }
00152
00153 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00154
00155 ao2_unlock(bridge);
00156
00157 return 0;
00158 }
00159
00160
00161 static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
00162 {
00163 char exten[AST_MAX_EXTENSION] = "";
00164 struct ast_channel *chan = NULL;
00165 struct ast_bridge *attended_bridge = NULL;
00166 struct ast_bridge_features caller_features, called_features;
00167 enum ast_bridge_channel_state attended_bridge_result;
00168 struct ast_bridge_features_attended_transfer *attended_transfer = hook_pvt;
00169 const char *context = (attended_transfer && !ast_strlen_zero(attended_transfer->context) ? attended_transfer->context : bridge_channel->chan->context);
00170
00171
00172 if (!grab_transfer(bridge_channel->chan, exten, sizeof(exten), context)) {
00173 ast_stream_and_wait(bridge_channel->chan, "pbx-invalid", AST_DIGIT_ANY);
00174 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00175 return 0;
00176 }
00177
00178
00179 if (!(chan = dial_transfer(bridge_channel->chan, exten, context))) {
00180 ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
00181 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00182 return 0;
00183 }
00184
00185
00186 if (!(attended_bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_1TO1MIX, 0))) {
00187 ast_hangup(chan);
00188 ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
00189 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00190 return 0;
00191 }
00192
00193
00194 ast_bridge_features_init(&called_features);
00195 ast_bridge_features_set_flag(&called_features, AST_BRIDGE_FLAG_DISSOLVE);
00196
00197
00198 ast_bridge_impart(attended_bridge, chan, NULL, &called_features);
00199
00200
00201 ast_bridge_features_init(&caller_features);
00202 ast_bridge_features_enable(&caller_features, AST_BRIDGE_BUILTIN_HANGUP,
00203 (attended_transfer && !ast_strlen_zero(attended_transfer->complete) ? attended_transfer->complete : "*1"), NULL);
00204 ast_bridge_features_hook(&caller_features, (attended_transfer && !ast_strlen_zero(attended_transfer->threeway) ? attended_transfer->threeway : "*2"),
00205 attended_threeway_transfer, NULL);
00206 ast_bridge_features_hook(&caller_features, (attended_transfer && !ast_strlen_zero(attended_transfer->abort) ? attended_transfer->abort : "*3"),
00207 attended_abort_transfer, NULL);
00208
00209
00210 attended_bridge_result = ast_bridge_join(attended_bridge, bridge_channel->chan, NULL, &caller_features);
00211
00212
00213 ast_bridge_features_cleanup(&caller_features);
00214
00215
00216 if ((attended_bridge_result != AST_BRIDGE_CHANNEL_STATE_HANGUP) && !ast_bridge_depart(attended_bridge, chan)) {
00217
00218 if (attended_bridge_result == AST_BRIDGE_CHANNEL_STATE_DEPART) {
00219
00220 ast_bridge_impart(bridge, chan, NULL, NULL);
00221 } else {
00222 ast_bridge_impart(bridge, chan, bridge_channel->chan, NULL);
00223 }
00224 } else {
00225 ast_stream_and_wait(bridge_channel->chan, "beeperr", AST_DIGIT_ANY);
00226 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00227 }
00228
00229
00230 ast_bridge_features_cleanup(&called_features);
00231 ast_bridge_destroy(attended_bridge);
00232
00233 return 0;
00234 }
00235
00236
00237 static int feature_hangup(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
00238 {
00239
00240 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00241 return 0;
00242 }
00243
00244 static int unload_module(void)
00245 {
00246 return 0;
00247 }
00248
00249 static int load_module(void)
00250 {
00251 ast_bridge_features_register(AST_BRIDGE_BUILTIN_BLINDTRANSFER, feature_blind_transfer, NULL);
00252 ast_bridge_features_register(AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER, feature_attended_transfer, NULL);
00253 ast_bridge_features_register(AST_BRIDGE_BUILTIN_HANGUP, feature_hangup, NULL);
00254
00255
00256 ast_module_ref(ast_module_info->self);
00257
00258 return AST_MODULE_LOAD_SUCCESS;
00259 }
00260
00261 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Built in bridging features");