@ -1691,8 +1691,10 @@ struct sip_st_cfg {
int st_max_se ; /*!< Highest threshold for session refresh interval */
} ;
struct offered_media {
int offered ;
char text [ 128 ] ;
} ;
/*! \brief Structure used for each SIP dialog, ie. a call, a registration, a subscribe.
* Created and initialized by sip_alloc ( ) , the descriptor goes into the list of
@ -1856,6 +1858,21 @@ struct sip_pvt {
* have with this peer to determine its allowed methods .
*/
unsigned int allowed_methods ;
/*! When receiving an SDP offer, it is important to take note of what media types were offered.
* By doing this , even if we don ' t want to answer a particular media stream with something meaningful , we can
* still put an m = line in our answer with the port set to 0.
*
* The reason for the length being 4 is that in this branch of Asterisk , the only media types supported are
* image , audio , text , and video . Therefore we need to keep track of which types of media were offered .
*
* Note that if we wanted to be 100 % correct , we would keep a list of all media streams offered . That way we could respond
* even to unknown media types , and we could respond to multiple streams of the same type . Such large - scale changes
* are not a good idea for released branches , though , so we ' re compromising by just making sure that for the common cases :
* audio and video , audio and T .38 , and audio and text , we give the appropriate response to both media streams .
*
* The large - scale changes would be a good idea for implementing during an SDP rewrite .
*/
struct offered_media offered_media [ 4 ] ;
} ;
@ -7947,6 +7964,8 @@ static int find_sdp(struct sip_request *req)
enum media_type {
SDP_AUDIO ,
SDP_VIDEO ,
SDP_IMAGE ,
SDP_TEXT ,
} ;
static int get_ip_and_port_from_sdp ( struct sip_request * req , const enum media_type media , struct sockaddr_in * sin )
@ -8077,6 +8096,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
/* Update our last rtprx when we receive an SDP, too */
p - > lastrtprx = p - > lastrtptx = time ( NULL ) ; /* XXX why both ? */
memset ( p - > offered_media , 0 , sizeof ( p - > offered_media ) ) ;
/* Store the SDP version number of remote UA. This will allow us to
distinguish between session modifications and session refreshes . If
the remote UA does not send an incremented SDP version number in a
@ -8197,11 +8218,14 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
if ( ( 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 ) ) {
audio = TRUE ;
p - > offered_media [ SDP_AUDIO ] . offered = TRUE ;
numberofmediastreams + + ;
/* Found audio stream in this media definition */
portno = x ;
/* Scan through the RTP payload types specified in a "m=" line: */
for ( codecs = m + len ; ! ast_strlen_zero ( codecs ) ; codecs = ast_skip_blanks ( codecs + len ) ) {
codecs = m + len ;
ast_copy_string ( p - > offered_media [ SDP_AUDIO ] . text , codecs , sizeof ( p - > offered_media [ SDP_AUDIO ] . text ) ) ;
for ( ; ! ast_strlen_zero ( codecs ) ; codecs = ast_skip_blanks ( codecs + len ) ) {
if ( sscanf ( codecs , " %d%n " , & codec , & len ) ! = 1 ) {
ast_log ( LOG_WARNING , " Error in codec string '%s' \n " , codecs ) ;
return - 1 ;
@ -8215,10 +8239,13 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
( sscanf ( m , " video %d RTP/AVP %n " , & x , & len ) = = 1 & & len > = 0 ) ) {
video = TRUE ;
p - > novideo = FALSE ;
p - > offered_media [ SDP_VIDEO ] . offered = TRUE ;
numberofmediastreams + + ;
vportno = x ;
/* Scan through the RTP payload types specified in a "m=" line: */
for ( codecs = m + len ; ! ast_strlen_zero ( codecs ) ; codecs = ast_skip_blanks ( codecs + len ) ) {
codecs = m + len ;
ast_copy_string ( p - > offered_media [ SDP_VIDEO ] . text , codecs , sizeof ( p - > offered_media [ SDP_VIDEO ] . text ) ) ;
for ( ; ! ast_strlen_zero ( codecs ) ; codecs = ast_skip_blanks ( codecs + len ) ) {
if ( sscanf ( codecs , " %d%n " , & codec , & len ) ! = 1 ) {
ast_log ( LOG_WARNING , " Error in codec string '%s' \n " , codecs ) ;
return - 1 ;
@ -8230,11 +8257,14 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
} else if ( ( sscanf ( m , " text %d/%d RTP/AVP %n " , & x , & numberofports , & len ) = = 2 & & len > 0 ) | |
( sscanf ( m , " text %d RTP/AVP %n " , & x , & len ) = = 1 & & len > 0 ) ) {
text = TRUE ;
p - > offered_media [ SDP_TEXT ] . offered = TRUE ;
p - > notext = FALSE ;
numberofmediastreams + + ;
tportno = x ;
/* Scan through the RTP payload types specified in a "m=" line: */
for ( codecs = m + len ; ! ast_strlen_zero ( codecs ) ; codecs = ast_skip_blanks ( codecs + len ) ) {
codecs = m + len ;
ast_copy_string ( p - > offered_media [ SDP_TEXT ] . text , codecs , sizeof ( p - > offered_media [ SDP_TEXT ] . text ) ) ;
for ( ; ! ast_strlen_zero ( codecs ) ; codecs = ast_skip_blanks ( codecs + len ) ) {
if ( sscanf ( codecs , " %d%n " , & codec , & len ) ! = 1 ) {
ast_log ( LOG_WARNING , " Error in codec string '%s' \n " , codecs ) ;
return - 1 ;
@ -8247,6 +8277,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
( sscanf ( m , " image %d UDPTL t38%n " , & x , & len ) = = 1 & & len > 0 ) ) ) {
if ( debug )
ast_verbose ( " Got T.38 offer in SDP in dialog %s \n " , p - > callid ) ;
p - > offered_media [ SDP_IMAGE ] . offered = TRUE ;
udptlportno = x ;
numberofmediastreams + + ;
} else
@ -9192,7 +9223,6 @@ static inline int resp_needs_contact(const char *msg, enum sipmethod method) {
return 0 ;
}
/*! \brief Prepare SIP response packet */
static int respprep ( struct sip_request * resp , struct sip_pvt * p , const char * msg , const struct sip_request * req )
{
@ -9977,6 +10007,7 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
char codecbuf [ SIPBUFSIZE ] ;
char buf [ SIPBUFSIZE ] ;
char dummy_answer [ 256 ] ;
/* Set the SDP session name */
snprintf ( subject , sizeof ( subject ) , " s=%s \r \n " , ast_strlen_zero ( global_sdpsession ) ? " - " : global_sdpsession ) ;
@ -10246,20 +10277,31 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int
add_line ( resp , m_audio - > str ) ;
add_line ( resp , a_audio - > str ) ;
add_line ( resp , hold ) ;
} else if ( p - > offered_media [ SDP_AUDIO ] . offered ) {
snprintf ( dummy_answer , sizeof ( dummy_answer ) , " m=audio 0 RTP/AVP %s \r \n " , p - > offered_media [ SDP_AUDIO ] . text ) ;
add_line ( resp , dummy_answer ) ;
}
if ( needvideo ) { /* only if video response is appropriate */
add_line ( resp , m_video - > str ) ;
add_line ( resp , a_video - > str ) ;
add_line ( resp , hold ) ; /* Repeat hold for the video stream */
} else if ( p - > offered_media [ SDP_VIDEO ] . offered ) {
snprintf ( dummy_answer , sizeof ( dummy_answer ) , " m=video 0 RTP/AVP %s \r \n " , p - > offered_media [ SDP_VIDEO ] . text ) ;
add_line ( resp , dummy_answer ) ;
}
if ( needtext ) { /* only if text response is appropriate */
add_line ( resp , m_text - > str ) ;
add_line ( resp , a_text - > str ) ;
add_line ( resp , hold ) ; /* Repeat hold for the text stream */
} else if ( p - > offered_media [ SDP_TEXT ] . offered ) {
snprintf ( dummy_answer , sizeof ( dummy_answer ) , " m=text 0 RTP/AVP %s \r \n " , p - > offered_media [ SDP_TEXT ] . text ) ;
add_line ( resp , dummy_answer ) ;
}
if ( add_t38 ) {
add_line ( resp , m_modem - > str ) ;
add_line ( resp , a_modem - > str ) ;
} else if ( p - > offered_media [ SDP_IMAGE ] . offered ) {
add_line ( resp , " m=image 0 udptl t38 \r \n " ) ;
}
/* Update lastrtprx when we send our SDP */
@ -10424,6 +10466,7 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, int t38version, int old
if ( p - > do_history )
append_history ( p , " ReInv " , " Re-invite sent " ) ;
memset ( p - > offered_media , 0 , sizeof ( p - > offered_media ) ) ;
try_suggested_sip_codec ( p ) ;
if ( t38version )
@ -10806,6 +10849,7 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
add_diversion_header ( & req , p ) ;
}
if ( sdp ) {
memset ( p - > offered_media , 0 , sizeof ( p - > offered_media ) ) ;
if ( p - > udptl & & p - > t38 . state = = T38_LOCAL_REINVITE ) {
ast_udptl_offered_from_local ( p - > udptl , 1 ) ;
ast_debug ( 1 , " T38 is in state %d on channel %s \n " , p - > t38 . state , p - > owner ? p - > owner - > name : " <none> " ) ;