mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-15 22:38:08 +00:00
Support CNG transmission when on hold (bug #2904)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4704 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -151,6 +151,8 @@ static int global_rtptimeout = 0;
|
|||||||
|
|
||||||
static int global_rtpholdtimeout = 0;
|
static int global_rtpholdtimeout = 0;
|
||||||
|
|
||||||
|
static int global_rtpkeepalive = 0;
|
||||||
|
|
||||||
static int global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
|
static int global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
|
||||||
|
|
||||||
/* Object counters */
|
/* Object counters */
|
||||||
@@ -379,8 +381,10 @@ static struct sip_pvt {
|
|||||||
int initid; /* Auto-congest ID if appropriate */
|
int initid; /* Auto-congest ID if appropriate */
|
||||||
int autokillid; /* Auto-kill ID */
|
int autokillid; /* Auto-kill ID */
|
||||||
time_t lastrtprx; /* Last RTP received */
|
time_t lastrtprx; /* Last RTP received */
|
||||||
|
time_t lastrtptx; /* Last RTP sent */
|
||||||
int rtptimeout; /* RTP timeout time */
|
int rtptimeout; /* RTP timeout time */
|
||||||
int rtpholdtimeout; /* RTP timeout when on hold */
|
int rtpholdtimeout; /* RTP timeout when on hold */
|
||||||
|
int rtpkeepalive; /* Send RTP packets for keepalive */
|
||||||
|
|
||||||
int subscribed; /* Is this call a subscription? */
|
int subscribed; /* Is this call a subscription? */
|
||||||
int stateid;
|
int stateid;
|
||||||
@@ -468,6 +472,7 @@ struct sip_peer {
|
|||||||
int capability; /* Codec capability */
|
int capability; /* Codec capability */
|
||||||
int rtptimeout;
|
int rtptimeout;
|
||||||
int rtpholdtimeout;
|
int rtpholdtimeout;
|
||||||
|
int rtpkeepalive; /* Send RTP packets for keepalive */
|
||||||
unsigned int callgroup; /* Call group */
|
unsigned int callgroup; /* Call group */
|
||||||
unsigned int pickupgroup; /* Pickup group */
|
unsigned int pickupgroup; /* Pickup group */
|
||||||
struct sockaddr_in addr; /* IP address of peer */
|
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);
|
transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0);
|
||||||
ast_set_flag(p, SIP_PROGRESS_SENT);
|
ast_set_flag(p, SIP_PROGRESS_SENT);
|
||||||
}
|
}
|
||||||
|
time(&p->lastrtptx);
|
||||||
res = ast_rtp_write(p->rtp, frame);
|
res = ast_rtp_write(p->rtp, frame);
|
||||||
}
|
}
|
||||||
ast_mutex_unlock(&p->lock);
|
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);
|
transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0);
|
||||||
ast_set_flag(p, SIP_PROGRESS_SENT);
|
ast_set_flag(p, SIP_PROGRESS_SENT);
|
||||||
}
|
}
|
||||||
|
time(&p->lastrtptx);
|
||||||
res = ast_rtp_write(p->vrtp, frame);
|
res = ast_rtp_write(p->vrtp, frame);
|
||||||
}
|
}
|
||||||
ast_mutex_unlock(&p->lock);
|
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);
|
strncpy(p->musicclass, global_musicclass, sizeof(p->musicclass) - 1);
|
||||||
p->rtptimeout = global_rtptimeout;
|
p->rtptimeout = global_rtptimeout;
|
||||||
p->rtpholdtimeout = global_rtpholdtimeout;
|
p->rtpholdtimeout = global_rtpholdtimeout;
|
||||||
|
p->rtpkeepalive = global_rtpkeepalive;
|
||||||
p->capability = global_capability;
|
p->capability = global_capability;
|
||||||
if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833)
|
if (ast_test_flag(p, SIP_DTMF) == SIP_DTMF_RFC2833)
|
||||||
p->noncodeccapability |= AST_RTP_DTMF;
|
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 */
|
/* Update our last rtprx when we receive an SDP, too */
|
||||||
time(&p->lastrtprx);
|
time(&p->lastrtprx);
|
||||||
|
time(&p->lastrtptx);
|
||||||
|
|
||||||
/* Get codec and RTP info from SDP */
|
/* Get codec and RTP info from SDP */
|
||||||
if (strcasecmp(get_header(req, "Content-Type"), "application/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 */
|
/* Update lastrtprx when we send our SDP */
|
||||||
time(&p->lastrtprx);
|
time(&p->lastrtprx);
|
||||||
|
time(&p->lastrtptx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8192,8 +8202,13 @@ restartsearch:
|
|||||||
sip = iflist;
|
sip = iflist;
|
||||||
while(sip) {
|
while(sip) {
|
||||||
ast_mutex_lock(&sip->lock);
|
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 (sip->rtp && sip->owner && (sip->owner->_state == AST_STATE_UP) && !sip->redirip.sin_addr.s_addr) {
|
||||||
if (t > sip->lastrtprx + sip->rtptimeout) {
|
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 */
|
/* Might be a timeout now -- see if we're on hold */
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
ast_rtp_get_peer(sip->rtp, &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->capability = global_capability;
|
||||||
peer->rtptimeout = global_rtptimeout;
|
peer->rtptimeout = global_rtptimeout;
|
||||||
peer->rtpholdtimeout = global_rtpholdtimeout;
|
peer->rtpholdtimeout = global_rtpholdtimeout;
|
||||||
|
peer->rtpkeepalive = global_rtpkeepalive;
|
||||||
ast_set_flag(peer, SIP_SELFDESTRUCT);
|
ast_set_flag(peer, SIP_SELFDESTRUCT);
|
||||||
ast_set_flag(peer, SIP_DYNAMIC);
|
ast_set_flag(peer, SIP_DYNAMIC);
|
||||||
peer->prefs = prefs;
|
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);
|
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;
|
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")) {
|
} else if (!strcasecmp(v->name, "qualify")) {
|
||||||
if (!strcasecmp(v->value, "no")) {
|
if (!strcasecmp(v->value, "no")) {
|
||||||
peer->maxms = 0;
|
peer->maxms = 0;
|
||||||
@@ -8968,6 +8989,7 @@ static int reload_config(void)
|
|||||||
ourport = DEFAULT_SIP_PORT;
|
ourport = DEFAULT_SIP_PORT;
|
||||||
global_rtptimeout = 0;
|
global_rtptimeout = 0;
|
||||||
global_rtpholdtimeout = 0;
|
global_rtpholdtimeout = 0;
|
||||||
|
global_rtpkeepalive = 0;
|
||||||
pedanticsipchecking = 0;
|
pedanticsipchecking = 0;
|
||||||
ast_clear_flag(&global_flags, AST_FLAGS_ALL);
|
ast_clear_flag(&global_flags, AST_FLAGS_ALL);
|
||||||
ast_set_flag(&global_flags, SIP_DTMF_RFC2833);
|
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);
|
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;
|
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")) {
|
} else if (!strcasecmp(v->name, "videosupport")) {
|
||||||
videosupport = ast_true(v->value);
|
videosupport = ast_true(v->value);
|
||||||
} else if (!strcasecmp(v->name, "compactheaders")) {
|
} 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 */
|
/* Reset lastrtprx timer */
|
||||||
time(&p->lastrtprx);
|
time(&p->lastrtprx);
|
||||||
|
time(&p->lastrtptx);
|
||||||
ast_mutex_unlock(&p->lock);
|
ast_mutex_unlock(&p->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_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);
|
int ast_rtp_settos(struct ast_rtp *rtp, int tos);
|
||||||
|
|
||||||
// Setting RTP payload types from lines in a SDP description:
|
// Setting RTP payload types from lines in a SDP description:
|
||||||
|
|||||||
40
rtp.c
40
rtp.c
@@ -1129,6 +1129,46 @@ int ast_rtp_senddigit(struct ast_rtp *rtp, char digit)
|
|||||||
return 0;
|
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
|
#ifdef SOLARIS
|
||||||
static void put_uint32(unsigned char *buf, int i)
|
static void put_uint32(unsigned char *buf, int i)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user