mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
Sat Mar 8 07:00:00 CET 2003
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -1,3 +1,4 @@
|
|||||||
|
-- Allow selection of in-band, out-of-band, or INFO based DTMF
|
||||||
-- Add contributed "*80" support to blacklist numbers (Thanks James!)
|
-- Add contributed "*80" support to blacklist numbers (Thanks James!)
|
||||||
-- Add "NAT" option to sip user, peer, friend
|
-- Add "NAT" option to sip user, peer, friend
|
||||||
-- Add experimental "IAX2" protocol
|
-- Add experimental "IAX2" protocol
|
||||||
|
2
CREDITS
2
CREDITS
@@ -33,7 +33,7 @@ James Golovch - Various contributions
|
|||||||
Steven Critchfield - Seek and Trunc functions for playback and recording
|
Steven Critchfield - Seek and Trunc functions for playback and recording
|
||||||
critch@basesys.com
|
critch@basesys.com
|
||||||
Jefferson Noxon - app_lookupcidname, app_db, and various other contributions
|
Jefferson Noxon - app_lookupcidname, app_db, and various other contributions
|
||||||
|
Klaus-Peter Junghanns - in-band DTMF on SIP and MGCP
|
||||||
=== OTHER SOURCE CODE IN ASTERISK ===
|
=== OTHER SOURCE CODE IN ASTERISK ===
|
||||||
|
|
||||||
I did not implement the codecs in asterisk. Here is the copyright on the
|
I did not implement the codecs in asterisk. Here is the copyright on the
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#include <asterisk/pbx.h>
|
#include <asterisk/pbx.h>
|
||||||
#include <asterisk/module.h>
|
#include <asterisk/module.h>
|
||||||
#include <asterisk/pbx.h>
|
#include <asterisk/pbx.h>
|
||||||
|
#include <asterisk/astdb.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -76,7 +77,7 @@ deltree_exec (struct ast_channel *chan, void *data)
|
|||||||
}
|
}
|
||||||
memcpy (argv, data, arglen + 1);
|
memcpy (argv, data, arglen + 1);
|
||||||
|
|
||||||
if (strchr (argv, '/'))
|
if (strchr (argv, '/')) {
|
||||||
{
|
{
|
||||||
family = strsep (&argv, "/");
|
family = strsep (&argv, "/");
|
||||||
keytree = strsep (&argv, "\0");
|
keytree = strsep (&argv, "\0");
|
||||||
@@ -88,7 +89,7 @@ deltree_exec (struct ast_channel *chan, void *data)
|
|||||||
if (!strlen (keytree))
|
if (!strlen (keytree))
|
||||||
keytree = 0;
|
keytree = 0;
|
||||||
}
|
}
|
||||||
else
|
} else
|
||||||
{
|
{
|
||||||
family = argv;
|
family = argv;
|
||||||
keytree = 0;
|
keytree = 0;
|
||||||
|
@@ -184,7 +184,7 @@ out:
|
|||||||
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
|
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
|
||||||
if (save_macro_priority) free(save_macro_priority);
|
if (save_macro_priority) free(save_macro_priority);
|
||||||
|
|
||||||
if (!strcasecmp(chan->context, fullmacro)) {
|
if (!strcasecmp(chan->context, fullmacro) && !chan->_softhangup) {
|
||||||
/* If we're leaving the macro normally, restore original information */
|
/* If we're leaving the macro normally, restore original information */
|
||||||
chan->priority = oldpriority;
|
chan->priority = oldpriority;
|
||||||
strncpy(chan->exten, oldexten, sizeof(chan->exten) - 1);
|
strncpy(chan->exten, oldexten, sizeof(chan->exten) - 1);
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
#include <asterisk/md5.h>
|
#include <asterisk/md5.h>
|
||||||
#include <asterisk/app.h>
|
#include <asterisk/app.h>
|
||||||
#include <asterisk/musiconhold.h>
|
#include <asterisk/musiconhold.h>
|
||||||
|
#include <asterisk/dsp.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
@@ -51,6 +52,10 @@
|
|||||||
#define DEFAULT_DEFAULT_EXPIREY 120
|
#define DEFAULT_DEFAULT_EXPIREY 120
|
||||||
#define DEFAULT_MAX_EXPIREY 3600
|
#define DEFAULT_MAX_EXPIREY 3600
|
||||||
|
|
||||||
|
#define SIP_DTMF_RFC2833 (1 << 0)
|
||||||
|
#define SIP_DTMF_INBAND (1 << 1)
|
||||||
|
#define SIP_DTMF_INFO (1 << 2)
|
||||||
|
|
||||||
static int max_expirey = DEFAULT_MAX_EXPIREY;
|
static int max_expirey = DEFAULT_MAX_EXPIREY;
|
||||||
static int default_expirey = DEFAULT_DEFAULT_EXPIREY;
|
static int default_expirey = DEFAULT_DEFAULT_EXPIREY;
|
||||||
|
|
||||||
@@ -172,6 +177,9 @@ static struct sip_pvt {
|
|||||||
|
|
||||||
int maxtime; /* Max time for first response */
|
int maxtime; /* Max time for first response */
|
||||||
int initid; /* Auto-congest ID if appropriate */
|
int initid; /* Auto-congest ID if appropriate */
|
||||||
|
|
||||||
|
int dtmfmode;
|
||||||
|
struct ast_dsp *vad;
|
||||||
|
|
||||||
struct sip_peer *peerpoke; /* If this calls is to poke a peer, which one */
|
struct sip_peer *peerpoke; /* If this calls is to poke a peer, which one */
|
||||||
struct sip_registry *registry; /* If this is a REGISTER call, to which registry */
|
struct sip_registry *registry; /* If this is a REGISTER call, to which registry */
|
||||||
@@ -200,6 +208,7 @@ struct sip_user {
|
|||||||
int amaflags;
|
int amaflags;
|
||||||
int insecure;
|
int insecure;
|
||||||
int canreinvite;
|
int canreinvite;
|
||||||
|
int dtmfmode;
|
||||||
struct ast_ha *ha;
|
struct ast_ha *ha;
|
||||||
struct sip_user *next;
|
struct sip_user *next;
|
||||||
};
|
};
|
||||||
@@ -220,6 +229,7 @@ struct sip_peer {
|
|||||||
int insecure;
|
int insecure;
|
||||||
int nat;
|
int nat;
|
||||||
int canreinvite;
|
int canreinvite;
|
||||||
|
int dtmfmode;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
struct in_addr mask;
|
struct in_addr mask;
|
||||||
|
|
||||||
@@ -383,6 +393,7 @@ static int create_addr(struct sip_pvt *r, char *peer)
|
|||||||
r->insecure = p->insecure;
|
r->insecure = p->insecure;
|
||||||
r->canreinvite = p->canreinvite;
|
r->canreinvite = p->canreinvite;
|
||||||
r->maxtime = p->maxms;
|
r->maxtime = p->maxms;
|
||||||
|
r->dtmfmode = p->dtmfmode;
|
||||||
strncpy(r->context, p->context,sizeof(r->context)-1);
|
strncpy(r->context, p->context,sizeof(r->context)-1);
|
||||||
if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
|
if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
|
||||||
(!p->maxms || ((p->lastms > 0) && (p->lastms <= p->maxms)))) {
|
(!p->maxms || ((p->lastms > 0) && (p->lastms <= p->maxms)))) {
|
||||||
@@ -688,6 +699,9 @@ static int sip_hangup(struct ast_channel *ast)
|
|||||||
needcancel = 1;
|
needcancel = 1;
|
||||||
/* Disconnect */
|
/* Disconnect */
|
||||||
p = ast->pvt->pvt;
|
p = ast->pvt->pvt;
|
||||||
|
if (p->vad) {
|
||||||
|
ast_dsp_free(p->vad);
|
||||||
|
}
|
||||||
p->owner = NULL;
|
p->owner = NULL;
|
||||||
ast->pvt->pvt = NULL;
|
ast->pvt->pvt = NULL;
|
||||||
|
|
||||||
@@ -800,11 +814,13 @@ static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
|
|||||||
static int sip_senddigit(struct ast_channel *ast, char digit)
|
static int sip_senddigit(struct ast_channel *ast, char digit)
|
||||||
{
|
{
|
||||||
struct sip_pvt *p = ast->pvt->pvt;
|
struct sip_pvt *p = ast->pvt->pvt;
|
||||||
if (p && p->rtp) {
|
if (p && p->rtp && (p->dtmfmode & SIP_DTMF_RFC2833)) {
|
||||||
ast_rtp_senddigit(p->rtp, digit);
|
ast_rtp_senddigit(p->rtp, digit);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return -1;
|
/* If in-band DTMF is desired, send that */
|
||||||
|
if (p->dtmfmode & SIP_DTMF_INBAND)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sip_indicate(struct ast_channel *ast, int condition)
|
static int sip_indicate(struct ast_channel *ast, int condition)
|
||||||
@@ -933,6 +949,10 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
|
|||||||
else
|
else
|
||||||
snprintf(tmp->name, sizeof(tmp->name), "SIP/%s:%d", inet_ntoa(i->sa.sin_addr), ntohs(i->sa.sin_port));
|
snprintf(tmp->name, sizeof(tmp->name), "SIP/%s:%d", inet_ntoa(i->sa.sin_addr), ntohs(i->sa.sin_port));
|
||||||
tmp->type = type;
|
tmp->type = type;
|
||||||
|
if (i->dtmfmode & SIP_DTMF_INBAND) {
|
||||||
|
i->vad = ast_dsp_new();
|
||||||
|
ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT);
|
||||||
|
}
|
||||||
tmp->fds[0] = ast_rtp_fd(i->rtp);
|
tmp->fds[0] = ast_rtp_fd(i->rtp);
|
||||||
ast_setstate(tmp, state);
|
ast_setstate(tmp, state);
|
||||||
if (state == AST_STATE_RING)
|
if (state == AST_STATE_RING)
|
||||||
@@ -1043,7 +1063,11 @@ static struct ast_frame *sip_rtp_read(struct sip_pvt *p)
|
|||||||
{
|
{
|
||||||
/* Retrieve audio/etc from channel. Assumes p->lock is already held. */
|
/* Retrieve audio/etc from channel. Assumes p->lock is already held. */
|
||||||
struct ast_frame *f;
|
struct ast_frame *f;
|
||||||
|
static struct ast_frame null_frame = { AST_FRAME_NULL, };
|
||||||
f = ast_rtp_read(p->rtp);
|
f = ast_rtp_read(p->rtp);
|
||||||
|
/* Don't send RFC2833 if we're not supposed to */
|
||||||
|
if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & SIP_DTMF_RFC2833))
|
||||||
|
return &null_frame;
|
||||||
if (p->owner) {
|
if (p->owner) {
|
||||||
/* We already hold the channel lock */
|
/* We already hold the channel lock */
|
||||||
if (f->frametype == AST_FRAME_VOICE) {
|
if (f->frametype == AST_FRAME_VOICE) {
|
||||||
@@ -1053,6 +1077,9 @@ static struct ast_frame *sip_rtp_read(struct sip_pvt *p)
|
|||||||
ast_set_read_format(p->owner, p->owner->readformat);
|
ast_set_read_format(p->owner, p->owner->readformat);
|
||||||
ast_set_write_format(p->owner, p->owner->writeformat);
|
ast_set_write_format(p->owner, p->owner->writeformat);
|
||||||
}
|
}
|
||||||
|
if (p->dtmfmode & SIP_DTMF_INBAND) {
|
||||||
|
f = ast_dsp_process(p->owner,p->vad,f,0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
@@ -1122,6 +1149,7 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin)
|
|||||||
strncpy(p->callid, callid, sizeof(p->callid) - 1);
|
strncpy(p->callid, callid, sizeof(p->callid) - 1);
|
||||||
/* Assume reinvite OK */
|
/* Assume reinvite OK */
|
||||||
p->canreinvite = 1;
|
p->canreinvite = 1;
|
||||||
|
p->dtmfmode = SIP_DTMF_RFC2833;
|
||||||
/* Add to list */
|
/* Add to list */
|
||||||
ast_pthread_mutex_lock(&iflock);
|
ast_pthread_mutex_lock(&iflock);
|
||||||
p->next = iflist;
|
p->next = iflist;
|
||||||
@@ -1839,7 +1867,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, char *cmd, c
|
|||||||
l = "asterisk";
|
l = "asterisk";
|
||||||
}
|
}
|
||||||
if (!n)
|
if (!n)
|
||||||
n = "asterisk";
|
n = l;
|
||||||
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%08x", n, l, inet_ntoa(p->ourip), p->tag);
|
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%08x", n, l, inet_ntoa(p->ourip), p->tag);
|
||||||
if (strlen(p->username)) {
|
if (strlen(p->username)) {
|
||||||
if (ntohs(p->sa.sin_port) != DEFAULT_SIP_PORT) {
|
if (ntohs(p->sa.sin_port) != DEFAULT_SIP_PORT) {
|
||||||
@@ -2119,16 +2147,22 @@ static int parse_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_req
|
|||||||
port = atoi(pt);
|
port = atoi(pt);
|
||||||
} else
|
} else
|
||||||
port = DEFAULT_SIP_PORT;
|
port = DEFAULT_SIP_PORT;
|
||||||
/* XXX This could block for a long time XXX */
|
if (!p->nat) {
|
||||||
hp = gethostbyname(n);
|
/* XXX This could block for a long time XXX */
|
||||||
if (!hp) {
|
hp = gethostbyname(n);
|
||||||
ast_log(LOG_WARNING, "Invalid host '%s'\n", n);
|
if (!hp) {
|
||||||
return -1;
|
ast_log(LOG_WARNING, "Invalid host '%s'\n", n);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(&oldsin, &p->addr, sizeof(oldsin));
|
||||||
|
p->addr.sin_family = AF_INET;
|
||||||
|
memcpy(&p->addr.sin_addr, hp->h_addr, sizeof(p->addr.sin_addr));
|
||||||
|
p->addr.sin_port = htons(port);
|
||||||
|
} else {
|
||||||
|
/* Don't trust the contact field. Just use what they came to us
|
||||||
|
with */
|
||||||
|
memcpy(&p->addr, &pvt->recv, sizeof(p->addr));
|
||||||
}
|
}
|
||||||
memcpy(&oldsin, &p->addr, sizeof(oldsin));
|
|
||||||
p->addr.sin_family = AF_INET;
|
|
||||||
memcpy(&p->addr.sin_addr, hp->h_addr, sizeof(p->addr.sin_addr));
|
|
||||||
p->addr.sin_port = htons(port);
|
|
||||||
if (c)
|
if (c)
|
||||||
strncpy(p->username, c, sizeof(p->username) - 1);
|
strncpy(p->username, c, sizeof(p->username) - 1);
|
||||||
else
|
else
|
||||||
@@ -2526,6 +2560,7 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha
|
|||||||
strncpy(p->accountcode, user->accountcode, sizeof(p->accountcode) -1);
|
strncpy(p->accountcode, user->accountcode, sizeof(p->accountcode) -1);
|
||||||
p->canreinvite = user->canreinvite;
|
p->canreinvite = user->canreinvite;
|
||||||
p->amaflags = user->amaflags;
|
p->amaflags = user->amaflags;
|
||||||
|
p->dtmfmode = user->dtmfmode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2557,13 +2592,13 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req)
|
|||||||
if (p->owner) {
|
if (p->owner) {
|
||||||
if (sipdebug)
|
if (sipdebug)
|
||||||
ast_verbose("Message received: '%s'\n", buf);
|
ast_verbose("Message received: '%s'\n", buf);
|
||||||
memset(&f, 0, sizeof(f));
|
memset(&f, 0, sizeof(f));
|
||||||
f.frametype = AST_FRAME_TEXT;
|
f.frametype = AST_FRAME_TEXT;
|
||||||
f.subclass = 0;
|
f.subclass = 0;
|
||||||
f.offset = 0;
|
f.offset = 0;
|
||||||
f.data = buf;
|
f.data = buf;
|
||||||
f.datalen = strlen(buf);
|
f.datalen = strlen(buf);
|
||||||
ast_queue_frame(p->owner, &f, 1);
|
ast_queue_frame(p->owner, &f, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3740,7 +3775,18 @@ static struct sip_user *build_user(char *name, struct ast_variable *v)
|
|||||||
} else if (!strcasecmp(v->name, "auth")) {
|
} else if (!strcasecmp(v->name, "auth")) {
|
||||||
strncpy(user->methods, v->value, sizeof(user->methods)-1);
|
strncpy(user->methods, v->value, sizeof(user->methods)-1);
|
||||||
} else if (!strcasecmp(v->name, "secret")) {
|
} else if (!strcasecmp(v->name, "secret")) {
|
||||||
strncpy(user->secret, v->value, sizeof(user->secret)-1);
|
strncpy(user->secret, v->value, sizeof(user->secret)-1);
|
||||||
|
} else if (!strcasecmp(v->name, "dtmfmode")) {
|
||||||
|
if (!strcasecmp(v->value, "inband"))
|
||||||
|
user->dtmfmode=SIP_DTMF_INBAND;
|
||||||
|
else if (!strcasecmp(v->value, "rfc2833"))
|
||||||
|
user->dtmfmode = SIP_DTMF_RFC2833;
|
||||||
|
else if (!strcasecmp(v->value, "info"))
|
||||||
|
user->dtmfmode = SIP_DTMF_INFO;
|
||||||
|
else {
|
||||||
|
ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
|
||||||
|
user->dtmfmode = SIP_DTMF_RFC2833;
|
||||||
|
}
|
||||||
} else if (!strcasecmp(v->name, "canreinvite")) {
|
} else if (!strcasecmp(v->name, "canreinvite")) {
|
||||||
user->canreinvite = ast_true(v->value);
|
user->canreinvite = ast_true(v->value);
|
||||||
} else if (!strcasecmp(v->name, "nat")) {
|
} else if (!strcasecmp(v->name, "nat")) {
|
||||||
@@ -3814,6 +3860,7 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v)
|
|||||||
peer->capability = capability;
|
peer->capability = capability;
|
||||||
/* Assume can reinvite */
|
/* Assume can reinvite */
|
||||||
peer->canreinvite = 1;
|
peer->canreinvite = 1;
|
||||||
|
peer->dtmfmode = SIP_DTMF_RFC2833;
|
||||||
while(v) {
|
while(v) {
|
||||||
if (!strcasecmp(v->name, "secret"))
|
if (!strcasecmp(v->name, "secret"))
|
||||||
strncpy(peer->secret, v->value, sizeof(peer->secret)-1);
|
strncpy(peer->secret, v->value, sizeof(peer->secret)-1);
|
||||||
@@ -3825,7 +3872,18 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v)
|
|||||||
peer->nat = ast_true(v->value);
|
peer->nat = ast_true(v->value);
|
||||||
else if (!strcasecmp(v->name, "context"))
|
else if (!strcasecmp(v->name, "context"))
|
||||||
strncpy(peer->context, v->value, sizeof(peer->context)-1);
|
strncpy(peer->context, v->value, sizeof(peer->context)-1);
|
||||||
else if (!strcasecmp(v->name, "host")) {
|
else if (!strcasecmp(v->name, "dtmfmode")) {
|
||||||
|
if (!strcasecmp(v->value, "inband"))
|
||||||
|
peer->dtmfmode=SIP_DTMF_INBAND;
|
||||||
|
else if (!strcasecmp(v->value, "rfc2833"))
|
||||||
|
peer->dtmfmode = SIP_DTMF_RFC2833;
|
||||||
|
else if (!strcasecmp(v->value, "info"))
|
||||||
|
peer->dtmfmode = SIP_DTMF_INFO;
|
||||||
|
else {
|
||||||
|
ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
|
||||||
|
peer->dtmfmode = SIP_DTMF_RFC2833;
|
||||||
|
}
|
||||||
|
} else if (!strcasecmp(v->name, "host")) {
|
||||||
if (!strcasecmp(v->value, "dynamic")) {
|
if (!strcasecmp(v->value, "dynamic")) {
|
||||||
/* They'll register with us */
|
/* They'll register with us */
|
||||||
peer->dynamic = 1;
|
peer->dynamic = 1;
|
||||||
|
@@ -17,6 +17,7 @@ context = default ; Default for incoming calls
|
|||||||
;type=friend
|
;type=friend
|
||||||
;secret=blah
|
;secret=blah
|
||||||
;host=dynamic
|
;host=dynamic
|
||||||
|
;dtmf=inband ; Choices are inband, rfc2833, or info
|
||||||
;defaultip=192.168.0.59
|
;defaultip=192.168.0.59
|
||||||
|
|
||||||
;[pingtel]
|
;[pingtel]
|
||||||
|
Reference in New Issue
Block a user