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 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 40722 $")
00033
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <string.h>
00037 #include <unistd.h>
00038
00039 #include "asterisk/lock.h"
00040 #include "asterisk/file.h"
00041 #include "asterisk/logger.h"
00042 #include "asterisk/channel.h"
00043 #include "asterisk/pbx.h"
00044 #include "asterisk/module.h"
00045 #include "asterisk/options.h"
00046 #include "asterisk/app.h"
00047
00048
00049 static const char *app = "Transfer";
00050
00051 static const char *synopsis = "Transfer caller to remote extension";
00052
00053 static const char *descrip =
00054 " Transfer([Tech/]dest[|options]): Requests the remote caller be transferred\n"
00055 "to a given destination. If TECH (SIP, IAX2, LOCAL etc) is used, only\n"
00056 "an incoming call with the same channel technology will be transfered.\n"
00057 "Note that for SIP, if you transfer before call is setup, a 302 redirect\n"
00058 "SIP message will be returned to the caller.\n"
00059 "\nThe result of the application will be reported in the TRANSFERSTATUS\n"
00060 "channel variable:\n"
00061 " SUCCESS Transfer succeeded\n"
00062 " FAILURE Transfer failed\n"
00063 " UNSUPPORTED Transfer unsupported by channel driver\n"
00064 "The option string many contain the following character:\n"
00065 "'j' -- jump to n+101 priority if the channel transfer attempt\n"
00066 " fails\n";
00067
00068 static int transfer_exec(struct ast_channel *chan, void *data)
00069 {
00070 int res;
00071 int len;
00072 struct ast_module_user *u;
00073 char *slash;
00074 char *tech = NULL;
00075 char *dest = NULL;
00076 char *status;
00077 char *parse;
00078 int priority_jump = 0;
00079 AST_DECLARE_APP_ARGS(args,
00080 AST_APP_ARG(dest);
00081 AST_APP_ARG(options);
00082 );
00083
00084 u = ast_module_user_add(chan);
00085
00086 if (ast_strlen_zero((char *)data)) {
00087 ast_log(LOG_WARNING, "Transfer requires an argument ([Tech/]destination[|options])\n");
00088 ast_module_user_remove(u);
00089 pbx_builtin_setvar_helper(chan, "TRANSFERSTATUS", "FAILURE");
00090 return 0;
00091 } else
00092 parse = ast_strdupa(data);
00093
00094 AST_STANDARD_APP_ARGS(args, parse);
00095
00096 if (args.options) {
00097 if (strchr(args.options, 'j'))
00098 priority_jump = 1;
00099 }
00100
00101 dest = args.dest;
00102
00103 if ((slash = strchr(dest, '/')) && (len = (slash - dest))) {
00104 tech = dest;
00105 dest = slash + 1;
00106
00107 if (strncasecmp(chan->tech->type, tech, len)) {
00108 pbx_builtin_setvar_helper(chan, "TRANSFERSTATUS", "FAILURE");
00109 ast_module_user_remove(u);
00110 return 0;
00111 }
00112 }
00113
00114
00115 if (!chan->tech->transfer) {
00116 pbx_builtin_setvar_helper(chan, "TRANSFERSTATUS", "UNSUPPORTED");
00117 ast_module_user_remove(u);
00118 return 0;
00119 }
00120
00121 res = ast_transfer(chan, dest);
00122
00123 if (res < 0) {
00124 status = "FAILURE";
00125 if (priority_jump || ast_opt_priority_jumping)
00126 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
00127 res = 0;
00128 } else {
00129 status = "SUCCESS";
00130 res = 0;
00131 }
00132
00133 pbx_builtin_setvar_helper(chan, "TRANSFERSTATUS", status);
00134
00135 ast_module_user_remove(u);
00136
00137 return res;
00138 }
00139
00140 static int unload_module(void)
00141 {
00142 int res;
00143
00144 res = ast_unregister_application(app);
00145
00146 ast_module_user_hangup_all();
00147
00148 return res;
00149 }
00150
00151 static int load_module(void)
00152 {
00153 return ast_register_application(app, transfer_exec, synopsis, descrip);
00154 }
00155
00156 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Transfer");