@ -519,11 +519,13 @@ struct sip_request {
int len ; /*!< Length */
int headers ; /*!< # of SIP Headers */
int method ; /*!< Method of this request */
int lines ; /*!< SDP Content */
int lines ; /*!< Body Content */
unsigned int flags ; /*!< SIP_PKT Flags for this packet */
char * header [ SIP_MAX_HEADERS ] ;
char * line [ SIP_MAX_LINES ] ;
char data [ SIP_MAX_PACKET ] ;
unsigned int sdp_start ; /*!< the line number where the SDP begins */
unsigned int sdp_end ; /*!< the line number where the SDP ends */
} ;
/*
@ -1091,9 +1093,9 @@ static struct sip_pvt *find_call(struct sip_request *req, struct sockaddr_in *si
/*--- Codec handling / SDP */
static void try_suggested_sip_codec ( struct sip_pvt * p ) ;
static const char * get_sdp_by_line ( const char * line , const char * name , int nameLen ) ;
static const char * get_sdp_iterate ( int * start , struct sip_request * req , const char * name ) ;
static const char * get_sdp ( struct sip_request * req , const char * name ) ;
static int find_sdp ( struct sip_request * req ) ;
static int process_sdp ( struct sip_pvt * p , struct sip_request * req ) ;
static void add_codec_to_sdp ( const struct sip_pvt * p , int codec , int sample_rate ,
char * * m_buf , size_t * m_size , char * * a_buf , size_t * a_size ,
@ -3270,37 +3272,55 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
}
/*! \brief Reads one line of SIP message body */
static const char * get_sdp_by_line ( const char * line , const char * name , int nameLen )
static char * get_body_by_line ( const char * line , const char * name , int nameLen )
{
if ( strncasecmp ( line , name , nameLen ) = = 0 & & line [ nameLen ] = = ' = ' )
return ast_skip_blanks ( line + nameLen + 1 ) ;
return " " ;
}
/*! \brief get_sdp_iterate: lookup 'name' in the request starting
/*! \brief Lookup 'name' in the SDP starting
* at the ' start ' line . Returns the matching line , and ' start '
* is updated with the next line number .
*/
static const char * get_sdp_iterate ( int * start , struct sip_request * req , const char * name )
static const char * get_sdp_iterate ( int * start , struct sip_request * req , const char * name )
{
int len = strlen ( name ) ;
while ( * start < req - > line s) {
const char * r = get_ sdp _by_line( req - > line [ ( * start ) + + ] , name , len ) ;
while ( * start < req - > sdp_end ) {
const char * r = get_ body _by_line( req - > line [ ( * start ) + + ] , name , len ) ;
if ( r [ 0 ] ! = ' \0 ' )
return r ;
}
return " " ;
}
/*! \brief get_sdp: Gets all kind of SIP message bodies, including SDP,
but the name wrongly applies _only_ sdp */
/*! \brief Get a line from an SDP message body */
static const char * get_sdp ( struct sip_request * req , const char * name )
{
int dummy = 0 ;
return get_sdp_iterate ( & dummy , req , name ) ;
}
/*! \brief Get a specific line from the message body */
static char * get_body ( struct sip_request * req , char * name )
{
int x ;
int len = strlen ( name ) ;
char * r ;
for ( x = 0 ; x < req - > lines ; x + + ) {
r = get_body_by_line ( req - > line [ x ] , name , len ) ;
if ( r [ 0 ] ! = ' \0 ' )
return r ;
}
return " " ;
}
/*! \brief Find compressed SIP alias */
static const char * find_alias ( const char * name , const char * _default )
{
@ -3329,9 +3349,11 @@ static const char *find_alias(const char *name, const char *_default)
{ " Session-Expires " , " x " } ,
} ;
int x ;
for ( x = 0 ; x < sizeof ( aliases ) / sizeof ( aliases [ 0 ] ) ; x + + )
if ( ! strcasecmp ( aliases [ x ] . fullname , name ) )
return aliases [ x ] . shortname ;
return _default ;
}
@ -3860,7 +3882,69 @@ static void parse_request(struct sip_request *req)
determine_firstline_parts ( req ) ;
}
/*! \brief Process SIP SDP and activate RTP channels*/
/*!
\ brief Determine whether a SIP message contains an SDP in its body
\ param req the SIP request to process
\ return 1 if SDP found , 0 if not found
Also updates req - > sdp_start and req - > sdp_end to indicate where the SDP
lives in the message body .
*/
static int find_sdp ( struct sip_request * req )
{
const char * content_type ;
const char * search ;
char * boundary ;
unsigned int x ;
content_type = get_header ( req , " Content-Type " ) ;
/* if the body contains only SDP, this is easy */
if ( ! strcasecmp ( content_type , " application/sdp " ) ) {
req - > sdp_start = 0 ;
req - > sdp_end = req - > lines ;
return 1 ;
}
/* if it's not multipart/mixed, there cannot be an SDP */
if ( strncasecmp ( content_type , " multipart/mixed " , 15 ) )
return 0 ;
/* if there is no boundary marker, it's invalid */
if ( ! ( search = strcasestr ( content_type , " ;boundary= " ) ) )
return 0 ;
search + = 10 ;
if ( ast_strlen_zero ( search ) )
return 0 ;
/* make a duplicate of the string, with two extra characters
at the beginning */
boundary = ast_strdupa ( search - 2 ) ;
boundary [ 0 ] = boundary [ 1 ] = ' - ' ;
/* search for the boundary marker, but stop when there are not enough
lines left for it , the Content - Type header and at least one line of
body */
for ( x = 0 ; x < ( req - > lines - 2 ) ; x + + ) {
if ( ! strncasecmp ( req - > line [ x ] , boundary , strlen ( boundary ) ) & &
! strcasecmp ( req - > line [ x + 1 ] , " Content-Type: application/sdp " ) ) {
req - > sdp_start = x + 2 ;
/* search for the end of the body part */
for ( ; x < req - > lines ; x + + ) {
if ( ! strncasecmp ( req - > line [ x ] , boundary , strlen ( boundary ) ) )
break ;
}
req - > sdp_end = x ;
return 1 ;
}
}
return 0 ;
}
/*! \brief Process SIP SDP and activate RTP channels---*/
static int process_sdp ( struct sip_pvt * p , struct sip_request * req )
{
const char * m ;
@ -3894,13 +3978,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
time ( & p - > lastrtprx ) ;
time ( & p - > lastrtptx ) ;
/* 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 " ) ) ;
return - 1 ;
}
m = get_sdp ( req , " m " ) ;
destiterator = 0 ;
destiterator = req - > sdp_start ;
c = get_sdp_iterate ( & destiterator , req , " c " ) ;
if ( ast_strlen_zero ( m ) | | ast_strlen_zero ( c ) ) {
ast_log ( LOG_WARNING , " Insufficient information for SDP (m = '%s', c = '%s') \n " , m , c ) ;
@ -3916,7 +3995,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
ast_log ( LOG_WARNING , " Unable to lookup host in c= line, '%s' \n " , c ) ;
return - 1 ;
}
iterator = 0 ;
iterator = req - > sdp_start ;
ast_set_flag ( & p - > flags [ 0 ] , SIP_NOVIDEO ) ;
while ( ( m = get_sdp_iterate ( & iterator , req , " m " ) ) [ 0 ] ! = ' \0 ' ) {
int found = 0 ;
@ -4015,7 +4094,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
/* Next, scan through each "a=rtpmap:" line, noting each
* specified RTP payload type ( with corresponding MIME subtype ) :
*/
iterator = 0 ;
iterator = req - > sdp_start ;
while ( ( a = get_sdp_iterate ( & iterator , req , " a " ) ) [ 0 ] ! = ' \0 ' ) {
char * mimeSubtype = ast_strdupa ( a ) ; /* ensures we have enough space */
if ( ! strcasecmp ( a , " sendonly " ) ) {
@ -9142,7 +9221,7 @@ static void handle_request_info(struct sip_pvt *p, struct sip_request *req)
! strcasecmp ( c , " application/vnd.nortelnetworks.digits " ) ) {
/* Try getting the "signal=" part */
if ( ast_strlen_zero ( c = get_ sdp ( req , " Signal " ) ) & & ast_strlen_zero ( c = get_ sdp ( req , " d " ) ) ) {
if ( ast_strlen_zero ( c = get_ body ( req , " Signal " ) ) & & ast_strlen_zero ( c = get_ body ( req , " d " ) ) ) {
ast_log ( LOG_WARNING , " Unable to retrieve DTMF signal from INFO message from %s \n " , p - > callid ) ;
transmit_response ( p , " 200 OK " , req ) ; /* Should return error */
return ;
@ -10002,7 +10081,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if ( p - > owner - > _state ! = AST_STATE_UP )
ast_setstate ( p - > owner , AST_STATE_RINGING ) ;
}
if ( ! strcasecmp ( get_header ( req , " Content-Type " ) , " application/sdp " ) ) {
if ( find_sdp ( req ) ) {
process_sdp ( p , req ) ;
if ( ! ast_test_flag ( req , SIP_PKT_IGNORE ) & & p - > owner ) {
/* Queue a progress frame only if we have SDP in 180 */
@ -10014,7 +10093,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if ( ! ast_test_flag ( req , SIP_PKT_IGNORE ) )
sip_cancel_destroy ( p ) ;
/* Ignore 183 Session progress without SDP */
if ( ! strcasecmp ( get_header ( req , " Content-Type " ) , " application/sdp " ) ) {
if ( find_sdp ( req ) ) {
process_sdp ( p , req ) ;
if ( ! ast_test_flag ( req , SIP_PKT_IGNORE ) & & p - > owner ) {
/* Queue a progress frame */
@ -10026,7 +10105,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
if ( ! ast_test_flag ( req , SIP_PKT_IGNORE ) )
sip_cancel_destroy ( p ) ;
p - > authtries = 0 ;
if ( ! strcasecmp ( get_header ( req , " Content-Type " ) , " application/sdp " ) )
if ( find_sdp ( req ) )
process_sdp ( p , req ) ;
/* Parse contact header for continued conversation */
@ -10594,7 +10673,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
} else if ( ( resp > = 100 ) & & ( resp < 200 ) ) {
if ( sipmethod = = SIP_INVITE ) {
sip_cancel_destroy ( p ) ;
if ( ! ast_strlen_zero ( get_header ( req , " Content-Type " ) ) )
if ( find_sdp ( req ) )
process_sdp ( p , req ) ;
if ( p - > owner ) {
/* Queue a progress frame */
@ -11155,7 +11234,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
parse_ok_contact ( p , req ) ;
} else { /* Re-invite on existing call */
/* Handle SDP here if we already have an owner */
if ( ! strcasecmp ( get_header ( req , " Content-Type " ) , " application/sdp " ) ) {
if ( find_sdp ( req ) ) {
if ( process_sdp ( p , req ) ) {
transmit_response ( p , " 488 Not acceptable here " , req ) ;
if ( ! p - > lastinvite )
@ -11186,7 +11265,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
}
/* We have a succesful authentication, process the SDP portion if there is one */
if ( ! strcasecmp ( get_header ( req , " Content-Type " ) , " application/sdp " ) ) {
if ( find_sdp ( req ) ) {
if ( process_sdp ( p , req ) ) {
/* Unacceptable codecs */
transmit_response_reliable ( p , " 488 Not acceptable here " , req ) ;
@ -11986,7 +12065,7 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
if ( seqno = = p - > pendinginvite ) {
p - > pendinginvite = 0 ;
__sip_ack ( p , seqno , FLAG_RESPONSE , 0 , FALSE ) ;
if ( ! ast_strlen_zero ( get_header ( req , " Content-Type " ) ) ) {
if ( find_sdp ( req ) ) {
if ( process_sdp ( p , req ) )
return - 1 ;
}