From e446f4ca814d2832f66b6ef63a33859b3e024918 Mon Sep 17 00:00:00 2001 From: Mark Spencer <markster@digium.com> Date: Thu, 27 May 2004 22:12:55 +0000 Subject: [PATCH] Merge OSS fixes for FreeBSD, implement rtptimeout and rtpholdtimeout git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3097 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/Makefile | 2 - apps/app_intercom.c | 2 +- channels/Makefile | 3 +- channels/chan_oss.c | 2 +- channels/chan_sip.c | 98 +++++++++++++++++++++++++++++++++++------ configs/sip.conf.sample | 8 +++- 6 files changed, 93 insertions(+), 22 deletions(-) diff --git a/apps/Makefile b/apps/Makefile index 708ac94cc4..e10209ec79 100755 --- a/apps/Makefile +++ b/apps/Makefile @@ -30,10 +30,8 @@ APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\ app_groupcount.so app_txtcidname.so app_controlplayback.so ifneq (${OSARCH},Darwin) -ifneq (${OSARCH},FreeBSD) APPS+=app_intercom.so endif -endif #APPS+=app_sql_postgres.so #APPS+=app_sql_odbc.so diff --git a/apps/app_intercom.c b/apps/app_intercom.c index 925ea37c25..1652aaa0bd 100755 --- a/apps/app_intercom.c +++ b/apps/app_intercom.c @@ -29,7 +29,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/Makefile b/channels/Makefile index 32f611c92a..40f5024f24 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 89eec2e7c9..731ae30eea 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 8968ea839e..14abfcf1dc 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")) { diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index c314b70990..ddd3354196 100755 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -48,7 +48,10 @@ bindaddr=0.0.0.0 ; IP address to bind to (0.0.0.0 binds to all) ;language=en ; Default language setting for all users/peers ; This may also be set for individual users/peers ;relaxdtmf=yes ; Relax dtmf handling - +;rtptimeout=60 ; Terminate call if 60 seconds of no RTP activity + ; when we're not on hold +;rtpholdtimeout=300 ; Terminate call if 300 seconds of no RTP activity + ; when we're on hold (must be > rtptimeout) ; Asterisk can register as a SIP user agent to a SIP proxy (provider) ; Format for the register statement is: @@ -128,7 +131,8 @@ bindaddr=0.0.0.0 ; IP address to bind to (0.0.0.0 binds to all) ; port ; qualify ; defaultip - +; rtptimeout +; rtpholdtimeout ;[sip_proxy] ; For incoming calls only. Example: FWD (Free World Dialup) -- GitLab