Merged revisions 323370 via svnmerge from

https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r323370 | twilson | 2011-06-14 09:33:55 -0700 (Tue, 14 Jun 2011) | 10 lines
  
  Add rtpkeepalives back to 1.8
  
  The RTP-engine conversion left out support for handling rtpkeepalives.
  This patch adds them back.
  
  (closes issue ASTERISK-17304)
  Reported by: lmadsen
  
  Review: https://reviewboard.asterisk.org/r/1226/
........


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@323374 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Terry Wilson
2011-06-14 17:03:37 +00:00
parent 00181729b4
commit abd7ef817e
4 changed files with 131 additions and 1 deletions

View File

@@ -5061,6 +5061,7 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
} }
ast_rtp_instance_set_timeout(dialog->vrtp, global_rtptimeout); ast_rtp_instance_set_timeout(dialog->vrtp, global_rtptimeout);
ast_rtp_instance_set_hold_timeout(dialog->vrtp, global_rtpholdtimeout); ast_rtp_instance_set_hold_timeout(dialog->vrtp, global_rtpholdtimeout);
ast_rtp_instance_set_keepalive(dialog->vrtp, global_rtpholdtimeout);
ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, 1);
} }
@@ -5071,12 +5072,14 @@ static int dialog_initialize_rtp(struct sip_pvt *dialog)
} }
ast_rtp_instance_set_timeout(dialog->trtp, global_rtptimeout); ast_rtp_instance_set_timeout(dialog->trtp, global_rtptimeout);
ast_rtp_instance_set_hold_timeout(dialog->trtp, global_rtpholdtimeout); ast_rtp_instance_set_hold_timeout(dialog->trtp, global_rtpholdtimeout);
ast_rtp_instance_set_keepalive(dialog->trtp, global_rtpholdtimeout);
ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, 1);
} }
ast_rtp_instance_set_timeout(dialog->rtp, global_rtptimeout); ast_rtp_instance_set_timeout(dialog->rtp, global_rtptimeout);
ast_rtp_instance_set_hold_timeout(dialog->rtp, global_rtpholdtimeout); ast_rtp_instance_set_hold_timeout(dialog->rtp, global_rtpholdtimeout);
ast_rtp_instance_set_keepalive(dialog->rtp, global_rtpkeepalive);
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, 1); ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, 1);
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833); ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
@@ -5144,6 +5147,7 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
ast_rtp_instance_set_timeout(dialog->rtp, peer->rtptimeout); ast_rtp_instance_set_timeout(dialog->rtp, peer->rtptimeout);
ast_rtp_instance_set_hold_timeout(dialog->rtp, peer->rtpholdtimeout); ast_rtp_instance_set_hold_timeout(dialog->rtp, peer->rtpholdtimeout);
ast_rtp_instance_set_keepalive(dialog->rtp, peer->rtpkeepalive);
/* Set Frame packetization */ /* Set Frame packetization */
ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs); ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(dialog->rtp), dialog->rtp, &dialog->prefs);
dialog->autoframing = peer->autoframing; dialog->autoframing = peer->autoframing;
@@ -5151,10 +5155,12 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
if (dialog->vrtp) { /* Video */ if (dialog->vrtp) { /* Video */
ast_rtp_instance_set_timeout(dialog->vrtp, peer->rtptimeout); ast_rtp_instance_set_timeout(dialog->vrtp, peer->rtptimeout);
ast_rtp_instance_set_hold_timeout(dialog->vrtp, peer->rtpholdtimeout); ast_rtp_instance_set_hold_timeout(dialog->vrtp, peer->rtpholdtimeout);
ast_rtp_instance_set_keepalive(dialog->vrtp, peer->rtpkeepalive);
} }
if (dialog->trtp) { /* Realtime text */ if (dialog->trtp) { /* Realtime text */
ast_rtp_instance_set_timeout(dialog->trtp, peer->rtptimeout); ast_rtp_instance_set_timeout(dialog->trtp, peer->rtptimeout);
ast_rtp_instance_set_hold_timeout(dialog->trtp, peer->rtpholdtimeout); ast_rtp_instance_set_hold_timeout(dialog->trtp, peer->rtpholdtimeout);
ast_rtp_instance_set_keepalive(dialog->trtp, peer->rtpkeepalive);
} }
/* XXX TODO: get fields directly from peer only as they are needed using dialog->relatedpeer */ /* XXX TODO: get fields directly from peer only as they are needed using dialog->relatedpeer */
@@ -25396,11 +25402,19 @@ static void check_rtp_timeout(struct sip_pvt *dialog, time_t t)
} }
/* If we have no timers set, return now */ /* If we have no timers set, return now */
if (!ast_rtp_instance_get_timeout(dialog->rtp) && !ast_rtp_instance_get_hold_timeout(dialog->rtp)) { if (!ast_rtp_instance_get_keepalive(dialog->rtp) && !ast_rtp_instance_get_timeout(dialog->rtp) && !ast_rtp_instance_get_hold_timeout(dialog->rtp)) {
dialog_unlink_rtpcheck(dialog); dialog_unlink_rtpcheck(dialog);
return; return;
} }
/* Check AUDIO RTP keepalives */
if (dialog->lastrtptx && ast_rtp_instance_get_keepalive(dialog->rtp) &&
(t > dialog->lastrtptx + ast_rtp_instance_get_keepalive(dialog->rtp))) {
/* Need to send an empty RTP packet */
dialog->lastrtptx = time(NULL);
ast_rtp_instance_sendcng(dialog->rtp, 0);
}
/*! \todo Check video RTP keepalives /*! \todo Check video RTP keepalives
Do we need to move the lastrtptx to the RTP structure to have one for audio and one Do we need to move the lastrtptx to the RTP structure to have one for audio and one

View File

@@ -377,6 +377,8 @@ struct ast_rtp_engine {
void (*stun_request)(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username); void (*stun_request)(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username);
/*! Callback to get the transcodeable formats supported. result returned in ast_format_cap *result */ /*! Callback to get the transcodeable formats supported. result returned in ast_format_cap *result */
void (*available_formats)(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result); void (*available_formats)(struct ast_rtp_instance *instance, struct ast_format_cap *to_endpoint, struct ast_format_cap *to_asterisk, struct ast_format_cap *result);
/*! Callback to send CNG */
int (*sendcng)(struct ast_rtp_instance *instance, int level);
/*! Linked list information */ /*! Linked list information */
AST_RWLIST_ENTRY(ast_rtp_engine) entry; AST_RWLIST_ENTRY(ast_rtp_engine) entry;
}; };
@@ -1712,6 +1714,24 @@ void ast_rtp_instance_set_timeout(struct ast_rtp_instance *instance, int timeout
*/ */
void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int timeout); void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int timeout);
/*!
* \brief Set the RTP keepalive interval
*
* \param instance The RTP instance
* \param period Value to set the keepalive interval to
*
* Example usage:
*
* \code
* ast_rtp_instance_set_keepalive(instance, 5000);
* \endcode
*
* This sets the RTP keepalive interval on 'instance' to be 5000.
*
* \since 1.8
*/
void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int timeout);
/*! /*!
* \brief Get the RTP timeout value * \brief Get the RTP timeout value
* *
@@ -1750,6 +1770,25 @@ int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance);
*/ */
int ast_rtp_instance_get_hold_timeout(struct ast_rtp_instance *instance); int ast_rtp_instance_get_hold_timeout(struct ast_rtp_instance *instance);
/*!
* \brief Get the RTP keepalive interval
*
* \param instance The RTP instance
*
* \retval period Keepalive interval value
*
* Example usage:
*
* \code
* int interval = ast_rtp_instance_get_keepalive(instance);
* \endcode
*
* This gets the RTP keepalive interval value for the RTP instance pointed to by 'instance'.
*
* \since 1.8
*/
int ast_rtp_instance_get_keepalive(struct ast_rtp_instance *instance);
/*! /*!
* \brief Get the RTP engine in use on an RTP instance * \brief Get the RTP engine in use on an RTP instance
* *
@@ -1809,6 +1848,17 @@ struct ast_rtp_glue *ast_rtp_instance_get_active_glue(struct ast_rtp_instance *i
*/ */
struct ast_channel *ast_rtp_instance_get_chan(struct ast_rtp_instance *instance); struct ast_channel *ast_rtp_instance_get_chan(struct ast_rtp_instance *instance);
/*!
* \brief Send a comfort noise packet to the RTP instance
*
* \param instance The RTP instance
* \param level Magnitude of the noise level
*
* \retval 0 Success
* \retval non-zero Failure
*/
int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level);
int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct ast_srtp_policy *policy); int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct ast_srtp_policy *policy);
struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance); struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance);

View File

@@ -66,6 +66,8 @@ struct ast_rtp_instance {
int timeout; int timeout;
/*! RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */ /*! RTP timeout when on hold (negative or zero means disabled, negative value means temporarily disabled). */
int holdtimeout; int holdtimeout;
/*! RTP keepalive interval */
int keepalive;
/*! DTMF mode in use */ /*! DTMF mode in use */
enum ast_rtp_dtmf_mode dtmf_mode; enum ast_rtp_dtmf_mode dtmf_mode;
/*! Glue currently in use */ /*! Glue currently in use */
@@ -1781,6 +1783,11 @@ void ast_rtp_instance_set_hold_timeout(struct ast_rtp_instance *instance, int ti
instance->holdtimeout = timeout; instance->holdtimeout = timeout;
} }
void ast_rtp_instance_set_keepalive(struct ast_rtp_instance *instance, int interval)
{
instance->keepalive = interval;
}
int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance) int ast_rtp_instance_get_timeout(struct ast_rtp_instance *instance)
{ {
return instance->timeout; return instance->timeout;
@@ -1791,6 +1798,11 @@ int ast_rtp_instance_get_hold_timeout(struct ast_rtp_instance *instance)
return instance->holdtimeout; return instance->holdtimeout;
} }
int ast_rtp_instance_get_keepalive(struct ast_rtp_instance *instance)
{
return instance->keepalive;
}
struct ast_rtp_engine *ast_rtp_instance_get_engine(struct ast_rtp_instance *instance) struct ast_rtp_engine *ast_rtp_instance_get_engine(struct ast_rtp_instance *instance)
{ {
return instance->engine; return instance->engine;
@@ -1850,6 +1862,15 @@ struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance)
return instance->srtp; return instance->srtp;
} }
int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level)
{
if (instance->engine->sendcng) {
return instance->engine->sendcng(instance, level);
}
return -1;
}
static void set_next_mime_type(const struct ast_format *format, int rtp_code, char *type, char *subtype, unsigned int sample_rate) static void set_next_mime_type(const struct ast_format *format, int rtp_code, char *type, char *subtype, unsigned int sample_rate)
{ {
int x = mime_types_len; int x = mime_types_len;

View File

@@ -272,6 +272,7 @@ static int ast_rtp_dtmf_compatible(struct ast_channel *chan0, struct ast_rtp_ins
static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username); static void ast_rtp_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username);
static void ast_rtp_stop(struct ast_rtp_instance *instance); static void ast_rtp_stop(struct ast_rtp_instance *instance);
static int ast_rtp_qos_set(struct ast_rtp_instance *instance, int tos, int cos, const char* desc); static int ast_rtp_qos_set(struct ast_rtp_instance *instance, int tos, int cos, const char* desc);
static int ast_rtp_sendcng(struct ast_rtp_instance *instance, int level);
/* RTP Engine Declaration */ /* RTP Engine Declaration */
static struct ast_rtp_engine asterisk_rtp_engine = { static struct ast_rtp_engine asterisk_rtp_engine = {
@@ -297,6 +298,7 @@ static struct ast_rtp_engine asterisk_rtp_engine = {
.stun_request = ast_rtp_stun_request, .stun_request = ast_rtp_stun_request,
.stop = ast_rtp_stop, .stop = ast_rtp_stop,
.qos = ast_rtp_qos_set, .qos = ast_rtp_qos_set,
.sendcng = ast_rtp_sendcng,
}; };
static inline int rtp_debug_test_addr(struct ast_sockaddr *addr) static inline int rtp_debug_test_addr(struct ast_sockaddr *addr)
@@ -2591,6 +2593,49 @@ static int ast_rtp_qos_set(struct ast_rtp_instance *instance, int tos, int cos,
return ast_set_qos(rtp->s, tos, cos, desc); return ast_set_qos(rtp->s, tos, cos, desc);
} }
/*! \brief generate comfort noice (CNG) */
static int ast_rtp_sendcng(struct ast_rtp_instance *instance, int level)
{
unsigned int *rtpheader;
int hdrlen = 12;
int res;
int payload;
char data[256];
struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
struct ast_sockaddr remote_address = { {0,} };
ast_rtp_instance_get_remote_address(instance, &remote_address);
if (ast_sockaddr_isnull(&remote_address)) {
return -1;
}
payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_CN);
level = 127 - (level & 0x7f);
rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
/* 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;
res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address);
if (res < 0) {
ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno));
} else if (rtp_debug_test_addr(&remote_address)) {
ast_verbose("Sent Comfort Noise RTP packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
ast_sockaddr_stringify(&remote_address),
AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen);
}
return res;
}
static char *rtp_do_debug_ip(struct ast_cli_args *a) static char *rtp_do_debug_ip(struct ast_cli_args *a)
{ {
char *arg = ast_strdupa(a->argv[4]); char *arg = ast_strdupa(a->argv[4]);