diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-01-07 07:11:40 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-01-07 07:11:40 +0000 |
commit | 9685e2fb7a7cae5cfa812ccbba53f9c37fda1433 (patch) | |
tree | f57ec6973fb479564d4e7221ca33babd6802d40a | |
parent | 3e4e6e77b828c666b15da4556bcf298339a70b8e (diff) |
Support CNG transmission when on hold (bug #2904)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@4704 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-x | channels/chan_sip.c | 32 | ||||
-rwxr-xr-x | include/asterisk/rtp.h | 2 | ||||
-rwxr-xr-x | rtp.c | 40 |
3 files changed, 72 insertions, 2 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index fa0f63214..e2a3c7778 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -151,6 +151,8 @@ static int global_rtptimeout = 0; static int global_rtpholdtimeout = 0; +static int global_rtpkeepalive = 0; + static int global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT; /* Object counters */ @@ -379,8 +381,10 @@ static struct sip_pvt { int initid; /* Auto-congest ID if appropriate */ int autokillid; /* Auto-kill ID */ time_t lastrtprx; /* Last RTP received */ + time_t lastrtptx; /* Last RTP sent */ int rtptimeout; /* RTP timeout time */ int rtpholdtimeout; /* RTP timeout when on hold */ + int rtpkeepalive; /* Send RTP packets for keepalive */ int subscribed; /* Is this call a subscription? */ int stateid; @@ -468,6 +472,7 @@ struct sip_peer { int capability; /* Codec capability */ int rtptimeout; int rtpholdtimeout; + int rtpkeepalive; /* Send RTP packets for keepalive */ unsigned int callgroup; /* Call group */ unsigned int pickupgroup; /* Pickup group */ struct sockaddr_in addr; /* IP address of peer */ @@ -1821,6 +1826,7 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame) transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0); ast_set_flag(p, SIP_PROGRESS_SENT); } + time(&p->lastrtptx); res = ast_rtp_write(p->rtp, frame); } ast_mutex_unlock(&p->lock); @@ -1833,6 +1839,7 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame) transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0); ast_set_flag(p, SIP_PROGRESS_SENT); } + time(&p->lastrtptx); res = ast_rtp_write(p->vrtp, frame); } ast_mutex_unlock(&p->lock); @@ -2346,6 +2353,7 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg strncpy(p->musicclass, global_musicclass, sizeof(p->musicclass) - 1); p->rtptimeout = global_rtptimeout; p->rtpholdtimeout = global_rtpholdtimeout; + p->rtpkeepalive = global_rtpkeepalive; p->capability = global_capability; if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833) p->noncodeccapability |= AST_RTP_DTMF; @@ -2637,6 +2645,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req) /* Update our last rtprx when we receive an SDP, too */ time(&p->lastrtprx); + time(&p->lastrtptx); /* Get codec and RTP info from SDP */ if (strcasecmp(get_header(req, "Content-Type"), "application/sdp")) { @@ -3550,6 +3559,7 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p) } /* Update lastrtprx when we send our SDP */ time(&p->lastrtprx); + time(&p->lastrtptx); return 0; } @@ -8192,8 +8202,13 @@ restartsearch: sip = iflist; while(sip) { ast_mutex_lock(&sip->lock); - if (sip->rtp && sip->owner && (sip->owner->_state == AST_STATE_UP) && sip->lastrtprx && (sip->rtptimeout || sip->rtpholdtimeout) && !sip->redirip.sin_addr.s_addr) { - if (t > sip->lastrtprx + sip->rtptimeout) { + if (sip->rtp && sip->owner && (sip->owner->_state == AST_STATE_UP) && !sip->redirip.sin_addr.s_addr) { + if (sip->lastrtptx && sip->rtpkeepalive && t > sip->lastrtptx + sip->rtpkeepalive) { + /* Need to send an empty RTP packet */ + time(&sip->lastrtptx); + ast_rtp_sendcng(sip->rtp, 0); + } + if (sip->lastrtprx && (sip->rtptimeout || sip->rtpholdtimeout) && 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); @@ -8718,6 +8733,7 @@ static struct sip_peer *temp_peer(char *name) peer->capability = global_capability; peer->rtptimeout = global_rtptimeout; peer->rtpholdtimeout = global_rtpholdtimeout; + peer->rtpkeepalive = global_rtpkeepalive; ast_set_flag(peer, SIP_SELFDESTRUCT); ast_set_flag(peer, SIP_DYNAMIC); peer->prefs = prefs; @@ -8883,6 +8899,11 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); peer->rtpholdtimeout = global_rtpholdtimeout; } + } else if (!strcasecmp(v->name, "rtpkeepalive")) { + if ((sscanf(v->value, "%d", &peer->rtpkeepalive) != 1) || (peer->rtpkeepalive < 0)) { + ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); + peer->rtpkeepalive = global_rtpkeepalive; + } } else if (!strcasecmp(v->name, "qualify")) { if (!strcasecmp(v->value, "no")) { peer->maxms = 0; @@ -8968,6 +8989,7 @@ static int reload_config(void) ourport = DEFAULT_SIP_PORT; global_rtptimeout = 0; global_rtpholdtimeout = 0; + global_rtpkeepalive = 0; pedanticsipchecking = 0; ast_clear_flag(&global_flags, AST_FLAGS_ALL); ast_set_flag(&global_flags, SIP_DTMF_RFC2833); @@ -9018,6 +9040,11 @@ static int reload_config(void) ast_log(LOG_WARNING, "'%s' is not a valid RTP hold time at line %d. Using default.\n", v->value, v->lineno); global_rtpholdtimeout = 0; } + } else if (!strcasecmp(v->name, "rtpkeepalive")) { + if ((sscanf(v->value, "%d", &global_rtpkeepalive) != 1) || (global_rtpkeepalive < 0)) { + ast_log(LOG_WARNING, "'%s' is not a valid RTP keepalive time at line %d. Using default.\n", v->value, v->lineno); + global_rtpkeepalive = 0; + } } else if (!strcasecmp(v->name, "videosupport")) { videosupport = ast_true(v->value); } else if (!strcasecmp(v->name, "compactheaders")) { @@ -9276,6 +9303,7 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struc } /* Reset lastrtprx timer */ time(&p->lastrtprx); + time(&p->lastrtptx); ast_mutex_unlock(&p->lock); return 0; } diff --git a/include/asterisk/rtp.h b/include/asterisk/rtp.h index 6b2df7c02..0fc653e59 100755 --- a/include/asterisk/rtp.h +++ b/include/asterisk/rtp.h @@ -78,6 +78,8 @@ int ast_rtcp_fd(struct ast_rtp *rtp); int ast_rtp_senddigit(struct ast_rtp *rtp, char digit); +int ast_rtp_sendcng(struct ast_rtp *rtp, int level); + int ast_rtp_settos(struct ast_rtp *rtp, int tos); // Setting RTP payload types from lines in a SDP description: @@ -1129,6 +1129,46 @@ int ast_rtp_senddigit(struct ast_rtp *rtp, char digit) return 0; } +int ast_rtp_sendcng(struct ast_rtp *rtp, int level) +{ + unsigned int *rtpheader; + int hdrlen = 12; + int res; + int payload; + char data[256]; + char iabuf[INET_ADDRSTRLEN]; + level = 127 - (level & 0x7f); + payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN); + + /* If we have no peer, return immediately */ + if (!rtp->them.sin_addr.s_addr) + return 0; + + gettimeofday(&rtp->dtmfmute, NULL); + rtp->dtmfmute.tv_usec += (500 * 1000); + if (rtp->dtmfmute.tv_usec > 1000000) { + rtp->dtmfmute.tv_usec -= 1000000; + rtp->dtmfmute.tv_sec += 1; + } + + /* Get a pointer to the header */ + rtpheader = (unsigned int *)data; + rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++)); + rtpheader[1] = htonl(rtp->lastts); + rtpheader[2] = htonl(rtp->ssrc); + data[12] = level; + if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) { + res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them)); + if (res <0) + ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno)); + if(rtp_debug_test_addr(&rtp->them)) + ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %d)\n" + , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen); + + } + return 0; +} + #ifdef SOLARIS static void put_uint32(unsigned char *buf, int i) { |