aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2004-05-27 22:12:55 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2004-05-27 22:12:55 +0000
commiteadbf9f9ca677d4e199de180018f5bf149338738 (patch)
treeff3e36b608b7a399e59482f7cc4ab5f5d1ee65d1 /channels
parent12ce45cba733f2100d8a3d476f6ed900c5be74c1 (diff)
Merge OSS fixes for FreeBSD, implement rtptimeout and rtpholdtimeout
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@3097 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rwxr-xr-xchannels/Makefile3
-rwxr-xr-xchannels/chan_oss.c2
-rwxr-xr-xchannels/chan_sip.c98
3 files changed, 86 insertions, 17 deletions
diff --git a/channels/Makefile b/channels/Makefile
index 32f611c92..40f5024f2 100755
--- a/channels/Makefile
+++ b/channels/Makefile
@@ -47,10 +47,8 @@ CHANH323LIB=-ldl
endif
ifneq (${OSARCH},Darwin)
-ifneq (${OSARCH},FreeBSD)
CHANNEL_LIBS+=chan_oss.so
endif
-endif
CHANNEL_LIBS+=$(shell [ -f /usr/include/linux/ixjuser.h ] && echo chan_phone.so)
CHANNEL_LIBS+=$(shell [ -f h323/libchanh323.a ] && echo chan_h323.so)
@@ -64,6 +62,7 @@ CFLAGS+=$(shell [ -f alsa-monitor.h ] && echo " -DALSA_MONITOR")
ZAPPRI=$(shell [ -f /usr/lib/libpri.so.1 ] && echo "-lpri")
ZAPR2=$(shell [ -f /usr/lib/libmfcr2.so.1 ] && echo "-lmfcr2")
CFLAGS+=$(shell [ -f /usr/include/linux/zaptel.h ] && echo "-DIAX_TRUNKING")
+# xxx CFLAGS+=$(shell [ -f /usr/local/include/zaptel.h ] && echo "-DIAX_TRUNKING")
CHANNEL_LIBS+=$(shell [ -f /usr/include/vpbapi.h ] && echo "chan_vpb.so" )
CFLAGS+=$(shell [ -f /usr/include/vpbapi.h ] && echo " -DLINUX")
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index 89eec2e7c..731ae30ee 100755
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -36,7 +36,7 @@
#ifdef __linux
#include <linux/soundcard.h>
#elif defined(__FreeBSD__)
-#include <machine/soundcard.h>
+#include <sys/soundcard.h>
#else
#include <soundcard.h>
#endif
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 8968ea839..14abfcf1d 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -150,6 +150,10 @@ static int autocreatepeer = 0;
static int relaxdtmf = 0;
+static int globalrtptimeout = 0;
+
+static int globalrtpholdtimeout = 0;
+
static int usecnt =0;
static ast_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
@@ -314,6 +318,9 @@ static struct sip_pvt {
int maxtime; /* Max time for first response */
int initid; /* Auto-congest ID if appropriate */
int autokillid; /* Auto-kill ID */
+ time_t lastrtprx; /* Last RTP received */
+ int rtptimeout; /* RTP timeout time */
+ int rtpholdtimeout; /* RTP timeout when on hold */
int subscribed;
int stateid;
@@ -396,6 +403,8 @@ struct sip_peer {
int expire;
int expiry;
int capability;
+ int rtptimeout;
+ int rtpholdtimeout;
int insecure;
int nat;
int canreinvite;
@@ -1519,7 +1528,7 @@ static int sip_hangup(struct ast_channel *ast)
ast_mutex_unlock(&usecnt_lock);
ast_update_use_count();
- needdestroy = 1;
+ needdestroy = 1;
/* Start the process if it's not already started */
if (!p->alreadygone && !ast_strlen_zero(p->initreq.data)) {
if (needcancel) {
@@ -1982,6 +1991,7 @@ static struct ast_frame *sip_read(struct ast_channel *ast)
struct sip_pvt *p = ast->pvt->pvt;
ast_mutex_lock(&p->lock);
fr = sip_rtp_read(ast, p);
+ time(&p->lastrtprx);
ast_mutex_unlock(&p->lock);
return fr;
}
@@ -2059,6 +2069,8 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
/* Assign default music on hold class */
strncpy(p->musicclass, globalmusicclass, sizeof(p->musicclass));
p->dtmfmode = globaldtmfmode;
+ p->rtptimeout = globalrtptimeout;
+ p->rtpholdtimeout = globalrtpholdtimeout;
p->capability = capability;
if (p->dtmfmode & SIP_DTMF_RFC2833)
p->noncodeccapability |= AST_RTP_DTMF;
@@ -2360,6 +2372,9 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
int sendonly = 0;
int x;
+ /* Update our last rtprx when we receive an SDP, too */
+ time(&p->lastrtprx);
+
/* Get codec and RTP info from SDP */
if (strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
ast_log(LOG_NOTICE, "Content is '%s', not 'application/sdp'\n", get_header(req, "Content-Type"));
@@ -3181,6 +3196,8 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p)
add_line(resp, m2);
add_line(resp, a2);
}
+ /* Update lastrtprx when we send our SDP */
+ time(&p->lastrtprx);
return 0;
}
@@ -5428,8 +5445,10 @@ static void receive_info(struct sip_pvt *p, struct sip_request *req)
}
transmit_response(p, "200 OK", req);
return;
+ } else {
+ transmit_response(p, "481 Call leg/transaction does not exist", req);
+ p->needdestroy = 1;
}
- transmit_response(p, "481 Call leg/transaction does not exist", req);
return;
}
/* Other type of INFO message, not really understood by Asterisk */
@@ -6353,7 +6372,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
/* This call is no longer outgoing if it ever was */
p->outgoing = 0;
/* This also counts as a pending invite */
- p->pendinginvite = 1;
+ p->pendinginvite = seqno;
copy_request(&p->initreq, req);
check_via(p, req);
if (!ast_strlen_zero(get_header(req, "Content-Type"))) {
@@ -6675,7 +6694,6 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
ast_verbose("Receiving DTMF!\n");
receive_info(p, req);
}
- transmit_response(p, "200 OK", req);
} else if (!strcasecmp(cmd, "REGISTER")) {
/* Use this as the basis */
if (sip_debug_test_pvt(p))
@@ -6690,16 +6708,16 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
sip_scheddestroy(p, 15*1000);
}
} else if (!strcasecmp(cmd, "ACK")) {
- /* Uhm, I haven't figured out the point of the ACK yet. Are we
- supposed to retransmit responses until we get an ack?
- Make sure this is on a valid call */
- p->pendinginvite = 0;
- __sip_ack(p, seqno, FLAG_RESPONSE);
- if (!ast_strlen_zero(get_header(req, "Content-Type"))) {
- if (process_sdp(p, req))
- return -1;
- }
- check_pendings(p);
+ /* Make sure we don't ignore this */
+ if (seqno == p->pendinginvite) {
+ p->pendinginvite = 0;
+ __sip_ack(p, seqno, FLAG_RESPONSE);
+ if (!ast_strlen_zero(get_header(req, "Content-Type"))) {
+ if (process_sdp(p, req))
+ return -1;
+ }
+ check_pendings(p);
+ }
if (!p->lastinvite && ast_strlen_zero(p->randdata))
p->needdestroy = 1;
} else if (!strcasecmp(cmd, "SIP/2.0")) {
@@ -6857,9 +6875,35 @@ static void *do_monitor(void *data)
/* Check for interfaces needing to be killed */
ast_mutex_lock(&iflock);
restartsearch:
+ time(&t);
sip = iflist;
while(sip) {
ast_mutex_lock(&sip->lock);
+ if (sip->rtp && sip->lastrtprx && (sip->rtptimeout || sip->rtpholdtimeout)) {
+ if (t > sip->lastrtprx + sip->rtptimeout) {
+ /* Might be a timeout now -- see if we're on hold */
+ struct sockaddr_in sin;
+ ast_rtp_get_peer(sip->rtp, &sin);
+ if (sin.sin_addr.s_addr ||
+ (sip->rtpholdtimeout &&
+ (t > sip->lastrtprx + sip->rtpholdtimeout))) {
+ /* Needs a hangup */
+ if (sip->rtptimeout) {
+ while(sip->owner && ast_mutex_trylock(&sip->owner->lock)) {
+ ast_mutex_unlock(&sip->lock);
+ usleep(1);
+ ast_mutex_lock(&sip->lock);
+ }
+ if (sip->owner) {
+ ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", sip->owner->name, (long)(t - sip->lastrtprx));
+ /* Issue a softhangup */
+ ast_softhangup(sip->owner, AST_SOFTHANGUP_DEV);
+ ast_mutex_unlock(&sip->owner->lock);
+ }
+ }
+ }
+ }
+ }
if (sip->needdestroy && !sip->packets) {
ast_mutex_unlock(&sip->lock);
__sip_destroy(sip, 1);
@@ -7262,6 +7306,8 @@ static struct sip_peer *temp_peer(char *name)
peer->canreinvite = globalcanreinvite;
peer->dtmfmode = globaldtmfmode;
peer->nat = globalnat;
+ peer->rtptimeout = globalrtptimeout;
+ peer->rtpholdtimeout = globalrtpholdtimeout;
peer->selfdestruct = 1;
peer->dynamic = 1;
reg_source_db(peer);
@@ -7320,6 +7366,8 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v)
peer->capability = capability;
/* Assume can reinvite */
peer->canreinvite = globalcanreinvite;
+ peer->rtptimeout = globalrtptimeout;
+ peer->rtpholdtimeout = globalrtpholdtimeout;
peer->dtmfmode = 0;
while(v) {
if (!strcasecmp(v->name, "secret"))
@@ -7425,6 +7473,16 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v)
peer->insecure = 1;
else
peer->insecure = 0;
+ } else if (!strcasecmp(v->name, "rtptimeout")) {
+ if ((sscanf(v->value, "%d", &peer->rtptimeout) != 1) || (peer->rtptimeout < 0)) {
+ ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno);
+ peer->rtptimeout = globalrtptimeout;
+ }
+ } else if (!strcasecmp(v->name, "rtpholdtimeout")) {
+ if ((sscanf(v->value, "%d", &peer->rtpholdtimeout) != 1) || (peer->rtpholdtimeout < 0)) {
+ ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno);
+ peer->rtpholdtimeout = globalrtpholdtimeout;
+ }
} else if (!strcasecmp(v->name, "qualify")) {
if (!strcasecmp(v->value, "no")) {
peer->maxms = 0;
@@ -7493,6 +7551,8 @@ static int reload_config(void)
globalcanreinvite = REINVITE_INVITE;
videosupport = 0;
relaxdtmf = 0;
+ globalrtptimeout = 0;
+ globalrtpholdtimeout = 0;
pedanticsipchecking=0;
v = ast_variable_browse(cfg, "general");
while(v) {
@@ -7517,6 +7577,16 @@ static int reload_config(void)
ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
globaldtmfmode = SIP_DTMF_RFC2833;
}
+ } else if (!strcasecmp(v->name, "rtptimeout")) {
+ if ((sscanf(v->value, "%d", &globalrtptimeout) != 1) || (globalrtptimeout < 0)) {
+ ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno);
+ globalrtptimeout = 0;
+ }
+ } else if (!strcasecmp(v->name, "rtpholdtimeout")) {
+ if ((sscanf(v->value, "%d", &globalrtpholdtimeout) != 1) || (globalrtpholdtimeout < 0)) {
+ ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno);
+ globalrtpholdtimeout = 0;
+ }
} else if (!strcasecmp(v->name, "videosupport")) {
videosupport = ast_true(v->value);
} else if (!strcasecmp(v->name, "notifymimetype")) {