@ -7781,6 +7781,63 @@ static int find_sdp(struct sip_request *req)
return FALSE ;
}
enum media_type {
SDP_AUDIO ,
SDP_VIDEO ,
} ;
static int get_ip_and_port_from_sdp ( struct sip_request * req , const enum media_type media , struct sockaddr_in * sin )
{
const char * m ;
const char * c ;
int miterator = req - > sdp_start ;
int citerator = req - > sdp_start ;
int x = 0 ;
int numberofports ;
int len ;
char host [ 258 ] = " " ; /*Initialize to empty so we will know if we have any input */
struct ast_hostent audiohp ;
struct hostent * hp ;
c = get_sdp_iterate ( & citerator , req , " c " ) ;
if ( sscanf ( c , " IN IP4 %256s " , host ) ! = 1 ) {
ast_log ( LOG_WARNING , " Invalid host in c= line, '%s' \n " , c ) ;
/* Continue since there may be a valid host in a c= line specific to the audio stream */
}
/* We only want the m and c lines for audio */
while ( ( m = get_sdp_iterate ( & miterator , req , " m " ) ) ) {
if ( ( media = = SDP_AUDIO & & ( ( sscanf ( m , " audio %d/%d RTP/AVP %n " , & x , & numberofports , & len ) = = 2 & & len > 0 ) | |
( sscanf ( m , " audio %d RTP/AVP %n " , & x , & len ) = = 1 & & len > 0 ) ) ) | |
( media = = SDP_VIDEO & & ( ( sscanf ( m , " video %d/%d RTP/AVP %n " , & x , & numberofports , & len ) = = 2 & & len > 0 ) | |
( sscanf ( m , " video %d RTP/AVP %n " , & x , & len ) = = 1 & & len > 0 ) ) ) ) {
/* See if there's a c= line for this media stream.
* XXX There is no guarantee that we ' ll be grabbing the c = line for this
* particular media stream here . However , this is the same logic used in process_sdp .
*/
c = get_sdp_iterate ( & citerator , req , " c " ) ;
if ( ! ast_strlen_zero ( c ) ) {
sscanf ( c , " IN IP4 %256s " , host ) ;
}
break ;
}
}
if ( ast_strlen_zero ( host ) | | x = = 0 ) {
ast_log ( LOG_WARNING , " Failed to read an alternate host or port in SDP. Expect %s problems \n " , media = = SDP_AUDIO ? " audio " : " video " ) ;
return - 1 ;
}
hp = ast_gethostbyname ( host , & audiohp ) ;
if ( ! hp ) {
ast_log ( LOG_WARNING , " Could not look up IP address of alternate hostname. Expect %s problems \n " , media = = SDP_AUDIO ? " audio " : " video " ) ;
return - 1 ;
}
memcpy ( & sin - > sin_addr , hp - > h_addr , sizeof ( sin - > sin_addr ) ) ;
sin - > sin_port = htons ( x ) ;
return 0 ;
}
/*! \brief Process SIP SDP offer, select formats and activate RTP channels
If offer is rejected , we will not change any properties of the call
Return 0 on success , a negative value on errors .
@ -19907,6 +19964,21 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
} else {
/* We already have a pending invite. Sorry. You are on hold. */
p - > glareinvite = seqno ;
if ( p - > rtp & & find_sdp ( req ) ) {
struct sockaddr_in sin ;
if ( get_ip_and_port_from_sdp ( req , SDP_AUDIO , & sin ) ) {
ast_log ( LOG_WARNING , " Failed to set an alternate media source on glared reinvite. Audio may not work properly on this call. \n " ) ;
} else {
ast_rtp_instance_set_alt_remote_address ( p - > rtp , & sin ) ;
}
if ( p - > vrtp ) {
if ( get_ip_and_port_from_sdp ( req , SDP_VIDEO , & sin ) ) {
ast_log ( LOG_WARNING , " Failed to set an alternate media source on glared reinvite. Video may not work properly on this call. \n " ) ;
} else {
ast_rtp_instance_set_alt_remote_address ( p - > vrtp , & sin ) ;
}
}
}
transmit_response_reliable ( p , " 491 Request Pending " , req ) ;
ast_debug ( 1 , " Got INVITE on call where we already have pending INVITE, deferring that - %s \n " , p - > callid ) ;
/* Don't destroy dialog here */