dect
/
asterisk
Archived
13
0
Fork 0

Add transfer to IAX2, and transfer application

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@1016 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
markster 2003-05-14 05:33:06 +00:00
parent 1fbfb13dba
commit 67b5919a15
10 changed files with 164 additions and 4 deletions

View File

@ -20,7 +20,7 @@ APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_intercom.
app_setcidname.so app_lookupcidname.so app_substring.so app_macro.so \
app_authenticate.so app_softhangup.so app_lookupblacklist.so \
app_waitforring.so app_privacy.so app_db.so app_chanisavail.so \
app_enumlookup.so app_voicemail2.so
app_enumlookup.so app_voicemail2.so app_transfer.so
#APPS+=app_sql_postgres.so
#APPS+=app_sql_odbc.so

View File

@ -26,11 +26,11 @@
#include <pthread.h>
static char *tdesc = "Date and Time";
static char *tdesc = "ENUM Lookup";
static char *app = "EnumLookup";
static char *synopsis = "Say the date and time";
static char *synopsis = "Lookup number in ENUM";
static char *descrip =
" EnumLookup(exten): Looks up an extension via ENUM and sets\n"

94
apps/app_transfer.c Executable file
View File

@ -0,0 +1,94 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Time of day - Report the time of day
*
* Copyright (C) 1999, Mark Spencer
*
* Mark Spencer <markster@linux-support.net>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/logger.h>
#include <asterisk/channel.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
static char *tdesc = "Transfer";
static char *app = "Transfer";
static char *synopsis = "Transfer caller to remote extension";
static char *descrip =
" Transfer(exten): Requests the remote caller be transferred to\n"
"a given Returns -1 on hangup, or 0 on completion\n"
"regardless of whether the transfer was successful. If the transfer\n"
"was *not* supported or successful and there exists a priority n + 101,\n"
"then that priority will be taken next.\n" ;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int transfer_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
if (!data || !strlen(data)) {
ast_log(LOG_WARNING, "Transfer requires an argument (destination)\n");
res = 1;
}
LOCAL_USER_ADD(u);
if (!res) {
res = ast_transfer(chan, data);
}
if (!res) {
/* Look for a "busy" place */
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
chan->priority += 100;
}
if (res > 0)
res = 0;
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
return ast_register_application(app, transfer_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@ -1568,6 +1568,26 @@ int ast_call(struct ast_channel *chan, char *addr, int timeout)
return res;
}
int ast_transfer(struct ast_channel *chan, char *dest)
{
/* Place an outgoing call, but don't wait any longer than timeout ms before returning.
If the remote end does not answer within the timeout, then do NOT hang up, but
return anyway. */
int res = -1;
/* Stop if we're a zombie or need a soft hangup */
ast_pthread_mutex_lock(&chan->lock);
if (!chan->zombie && !ast_check_hangup(chan)) {
if (chan->pvt->transfer) {
res = chan->pvt->transfer(chan, dest);
if (!res)
res = 1;
} else
res = 0;
}
pthread_mutex_unlock(&chan->lock);
return res;
}
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
{
int pos=0;

View File

@ -994,7 +994,6 @@ static void iax2_destroy(int callno)
retry:
ast_pthread_mutex_lock(&iaxsl[callno]);
pvt = iaxs[callno];
iaxs[callno] = NULL;
gettimeofday(&lastused[callno], NULL);
if (pvt)
@ -1009,6 +1008,7 @@ retry:
goto retry;
}
}
iaxs[callno] = NULL;
if (pvt) {
pvt->owner = NULL;
/* No more pings or lagrq's */
@ -1918,6 +1918,26 @@ static int iax2_indicate(struct ast_channel *c, int condition)
return send_command(pvt, AST_FRAME_CONTROL, condition, 0, NULL, 0, -1);
}
static int iax2_transfer(struct ast_channel *c, char *dest)
{
struct chan_iax2_pvt *pvt = c->pvt->pvt;
struct iax_ie_data ied;
char tmp[256] = "", *context;
strncpy(tmp, dest, sizeof(tmp) - 1);
context = strchr(tmp, '@');
if (context) {
*context = '\0';
context++;
}
memset(&ied, 0, sizeof(ied));
iax_ie_append_str(&ied, IAX_IE_CALLED_NUMBER, tmp);
if (context)
iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
if (option_debug)
ast_log(LOG_DEBUG, "Transferring '%s' to '%s'\n", c->name, dest);
return send_command(pvt, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
}
static int iax2_write(struct ast_channel *c, struct ast_frame *f);
@ -1966,6 +1986,7 @@ static struct ast_channel *ast_iax2_new(struct chan_iax2_pvt *i, int state, int
tmp->pvt->indicate = iax2_indicate;
tmp->pvt->setoption = iax2_setoption;
tmp->pvt->bridge = iax2_bridge;
tmp->pvt->transfer = iax2_transfer;
if (strlen(i->callerid))
tmp->callerid = strdup(i->callerid);
if (strlen(i->ani))
@ -3973,6 +3994,17 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
send_command_immediate(iaxs[fr.callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr.ts, NULL, 0,fr.iseqno);
iax2_destroy_nolock(fr.callno);
break;
case IAX_COMMAND_TRANSFER:
if (iaxs[fr.callno]->owner && iaxs[fr.callno]->owner->bridge && ies.called_number) {
if (ast_async_goto(iaxs[fr.callno]->owner->bridge, iaxs[fr.callno]->context, ies.called_number, 1, 1))
ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", iaxs[fr.callno]->owner->bridge->name,
ies.called_number, iaxs[fr.callno]->context);
else
ast_log(LOG_DEBUG, "Async goto of '%s' to '%s@%s' started\n", iaxs[fr.callno]->owner->bridge->name,
ies.called_number, iaxs[fr.callno]->context);
} else
ast_log(LOG_DEBUG, "Async goto not applicable on call %d\n", fr.callno);
break;
case IAX_COMMAND_ACCEPT:
/* Ignore if call is already up or needs authentication or is a TBD */
if (iaxs[fr.callno]->state & (IAX_STATE_STARTED | IAX_STATE_TBD | IAX_STATE_AUTHENTICATED))

View File

@ -116,6 +116,7 @@ static struct iax2_ie {
{ IAX_IE_MSGCOUNT, "MESSAGE COUNT", dump_short },
{ IAX_IE_AUTOANSWER, "AUTO ANSWER REQ" },
{ IAX_IE_TRANSFERID, "TRANSFER ID", dump_int },
{ IAX_IE_RDNIS, "REFERRING DNIS", dump_string },
};
const char *iax_ie2str(int ie)
@ -217,6 +218,7 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
"PAGE",
"MWI",
"UNSUPPORTED",
"TRANSFER",
};
char *cmds[] = {
"(0?)",
@ -420,6 +422,9 @@ int iax_parse_ies(struct iax_ies *ies, unsigned char *data, int datalen)
case IAX_IE_DNID:
ies->dnid = data + 2;
break;
case IAX_IE_RDNIS:
ies->rdnis = data + 2;
break;
case IAX_IE_AUTHMETHODS:
if (len != sizeof(unsigned short)) {
snprintf(tmp, sizeof(tmp), "Expecting authmethods to be %d bytes long but was %d\n", sizeof(unsigned short), len);

View File

@ -28,6 +28,7 @@ struct iax_ies {
int version;
unsigned short adsicpe;
char *dnid;
char *rdnis;
unsigned int authmethods;
char *challenge;
char *md5_result;

View File

@ -63,6 +63,7 @@
#define IAX_COMMAND_PAGE 31 /* Paging description */
#define IAX_COMMAND_MWI 32 /* Stand-alone message waiting indicator */
#define IAX_COMMAND_UNSUPPORT 33 /* Unsupported message received */
#define IAX_COMMAND_TRANSFER 34 /* Request remote transfer */
#define IAX_DEFAULT_REG_EXPIRE 60 /* By default require re-registration once per minute */
@ -98,6 +99,7 @@
#define IAX_IE_AUTOANSWER 25 /* Request auto-answering -- none */
#define IAX_IE_MUSICONHOLD 26 /* Request musiconhold with QUELCH -- none or string */
#define IAX_IE_TRANSFERID 27 /* Transfer Request Identifier -- int */
#define IAX_IE_RDNIS 28 /* Referring DNIS -- string */
#define IAX_AUTH_PLAINTEXT (1 << 0)
#define IAX_AUTH_MD5 (1 << 1)

View File

@ -676,6 +676,10 @@ int ast_autoservice_stop(struct ast_channel *chan);
timer fd */
int ast_settimeout(struct ast_channel *c, int ms);
/* Transfer a channel (if supported). Returns -1 on error, 0 if not supported
and 1 if supported and requested */
int ast_transfer(struct ast_channel *chan, char *dest);
/* Misc. functions below */
//! Waits for activity on a group of channels

View File

@ -65,6 +65,8 @@ struct ast_channel_pvt {
int (*setoption)(struct ast_channel *chan, int option, void *data, int datalen);
/*! Query a given option */
int (*queryoption)(struct ast_channel *chan, int option, void *data, int *datalen);
/*! Blind transfer other side */
int (*transfer)(struct ast_channel *chan, char *newdest);
};
//! Create a channel structure