@ -1751,6 +1751,15 @@ static int __sip_xmit(struct sip_pvt *p, char *data, int len)
const struct sockaddr_in * dst = sip_real_dst ( p ) ;
res = sendto ( sipsock , data , len , 0 , ( const struct sockaddr * ) dst , sizeof ( struct sockaddr_in ) ) ;
if ( res = = - 1 ) {
switch ( errno ) {
case EBADF : /* Bad file descriptor - seems like this is generated when the host exist, but doesn't accept the UDP packet */
case EHOSTUNREACH : /* Host can't be reached */
case ENETDOWN : /* Inteface down */
case ENETUNREACH : /* Network failure */
res = - 2 ; /* Don't bother with trying to transmit again */
}
}
if ( res ! = len )
ast_log ( LOG_WARNING , " sip_xmit of %p (len %d) to %s:%d returned %d: %s \n " , data , len , ast_inet_ntoa ( dst - > sin_addr ) , ntohs ( dst - > sin_port ) , res , strerror ( errno ) ) ;
return res ;
@ -1852,6 +1861,7 @@ static int retrans_pkt(void *data)
{
struct sip_pkt * pkt = data , * prev , * cur = NULL ;
int reschedule = DEFAULT_RETRANS ;
int xmitres = 0 ;
/* Lock channel PVT */
ast_mutex_lock ( & pkt - > owner - > lock ) ;
@ -1891,19 +1901,25 @@ static int retrans_pkt(void *data)
}
append_history ( pkt - > owner , " ReTx " , " %d %s " , reschedule , pkt - > data ) ;
__sip_xmit ( pkt - > owner , pkt - > data , pkt - > packetlen ) ;
xmitres = __sip_xmit ( pkt - > owner , pkt - > data , pkt - > packetlen ) ;
ast_mutex_unlock ( & pkt - > owner - > lock ) ;
return reschedule ;
if ( xmitres = = - 2 )
ast_log ( LOG_WARNING , " Network error on retransmit in dialog %s \n " , pkt - > owner - > callid ) ;
else
return reschedule ;
}
/* Too many retries */
if ( pkt - > owner & & pkt - > method ! = SIP_OPTIONS ) {
if ( pkt - > owner & & pkt - > method ! = SIP_OPTIONS & & xmitres = = 0 ) {
if ( ast_test_flag ( pkt , FLAG_FATAL ) | | sipdebug ) /* Tell us if it's critical or if we're debugging */
ast_log ( LOG_WARNING , " Maximum retries exceeded on transmission %s for seqno %d (%s %s) \n " , pkt - > owner - > callid , pkt - > seqno , ( ast_test_flag ( pkt , FLAG_FATAL ) ) ? " Critical " : " Non-critical " , ( ast_test_flag ( pkt , FLAG_RESPONSE ) ) ? " Response " : " Request " ) ;
} else {
if ( ( pkt - > method = = SIP_OPTIONS ) & & sipdebug )
} else if ( ( pkt - > method = = SIP_OPTIONS ) & & sipdebug ) {
ast_log ( LOG_WARNING , " Cancelling retransmit of OPTIONs (call id %s) \n " , pkt - > owner - > callid ) ;
}
append_history ( pkt - > owner , " MaxRetries " , " %s " , ( ast_test_flag ( pkt , FLAG_FATAL ) ) ? " (Critical) " : " (Non-critical) " ) ;
if ( xmitres = = - 2 ) {
ast_log ( LOG_WARNING , " Transmit error :: Cancelling transmission of transaction in call id %s \n " , pkt - > owner - > callid ) ;
append_history ( pkt - > owner , " XmitErr " , " %s " , ( ast_test_flag ( pkt , FLAG_FATAL ) ) ? " (Critical) " : " (Non-critical) " ) ;
} else
append_history ( pkt - > owner , " MaxRetries " , " %s " , ( ast_test_flag ( pkt , FLAG_FATAL ) ) ? " (Critical) " : " (Non-critical) " ) ;
pkt - > retransid = - 1 ;
@ -1953,6 +1969,7 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int res
{
struct sip_pkt * pkt ;
int siptimer_a = DEFAULT_RETRANS ;
int xmitres = 0 ;
if ( ! ( pkt = ast_calloc ( 1 , sizeof ( * pkt ) + len + 1 ) ) )
return AST_FAILURE ;
@ -1977,13 +1994,20 @@ static enum sip_result __sip_reliable_xmit(struct sip_pvt *p, int seqno, int res
ast_log ( LOG_DEBUG , " *** SIP TIMER: Initalizing retransmit timer on packet: Id #%d \n " , pkt - > retransid ) ;
pkt - > next = p - > packets ;
p - > packets = pkt ;
__sip_xmit ( pkt - > owner , pkt - > data , pkt - > packetlen ) ; /* Send packet */
if ( sipmethod = = SIP_INVITE ) {
/* Note this is a pending invite */
p - > pendinginvite = seqno ;
}
return AST_SUCCESS ;
xmitres = __sip_xmit ( pkt - > owner , pkt - > data , pkt - > packetlen ) ; /* Send packet */
if ( xmitres = = - 2 ) { /* Serious network trouble, no need to try again */
append_history ( pkt - > owner , " XmitErr " , " %s " , ( ast_test_flag ( pkt , FLAG_FATAL ) ) ? " (Critical) " : " (Non-critical) " ) ;
ast_sched_del ( sched , pkt - > retransid ) ; /* No more retransmission */
pkt - > retransid = - 1 ;
return AST_FAILURE ;
} else
return AST_SUCCESS ;
}
/*! \brief Kill a SIP dialog (called by scheduler) */
@ -2175,7 +2199,7 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty
( tmp . method = = SIP_RESPONSE | | tmp . method = = SIP_UNKNOWN ) ? tmp . rlPart2 : sip_methods [ tmp . method ] . text ) ;
}
res = ( reliable ) ?
__sip_reliable_xmit ( p , seqno , 1 , req - > data , req - > len , ( reliable = = XMIT_CRITICAL ) , req - > method ) :
__sip_reliable_xmit ( p , seqno , 1 , req - > data , req - > len , ( reliable = = XMIT_CRITICAL ) , req - > method ) :
__sip_xmit ( p , req - > data , req - > len ) ;
if ( res > 0 )
return 0 ;
@ -2771,7 +2795,7 @@ static int auto_congest(void *nothing)
* used from the dial ( ) application */
static int sip_call ( struct ast_channel * ast , char * dest , int timeout )
{
int res ;
int res , xmitres = 0 ;
struct sip_pvt * p ;
struct varshead * headp ;
struct ast_var_t * current ;
@ -2845,7 +2869,10 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
p - > t38 . jointcapability = p - > t38 . capability ;
if ( option_debug > 1 )
ast_log ( LOG_DEBUG , " Our T38 capability (%d), joint T38 capability (%d) \n " , p - > t38 . capability , p - > t38 . jointcapability ) ;
transmit_invite ( p , SIP_INVITE , 1 , 2 ) ;
xmitres = transmit_invite ( p , SIP_INVITE , 1 , 2 ) ;
if ( xmitres = = - 2 )
return - 1 ; /* Transmission error */
p - > invitestate = INV_CALLING ;
/* Initialize auto-congest time */
@ -6417,7 +6444,9 @@ static void copy_request(struct sip_request *dst, const struct sip_request *src)
dst - > rlPart2 + = offset ;
}
/*! \brief Used for 200 OK and 183 early media */
/*! \brief Used for 200 OK and 183 early media
\ return Will return - 2 for network errors .
*/
static int transmit_response_with_sdp ( struct sip_pvt * p , const char * msg , const struct sip_request * req , enum xmittype reliable )
{
struct sip_request resp ;
@ -7510,7 +7539,9 @@ static int transmit_info_with_vidupdate(struct sip_pvt *p)
return send_request ( p , & req , XMIT_RELIABLE , p - > ocseq ) ;
}
/*! \brief Transmit generic SIP request */
/*! \brief Transmit generic SIP request
returns - 2 if transmit failed with a critical error ( don ' t retry )
*/
static int transmit_request ( struct sip_pvt * p , int sipmethod , int seqno , enum xmittype reliable , int newbranch )
{
struct sip_request resp ;
@ -11587,16 +11618,16 @@ static struct ast_custom_function sipchaninfo_function = {
static void parse_moved_contact ( struct sip_pvt * p , struct sip_request * req )
{
char tmp [ BUFSIZ ] ;
char * s , * e ;
char * s , * e , * uri ;
char * domain ;
ast_copy_string ( tmp , get_header ( req , " Contact " ) , sizeof ( tmp ) ) ;
s = get_in_brackets ( tmp ) ;
s = strsep ( & s , " ; " ) ; /* strip ; and beyond */
uri = ast_strdupa ( s ) ;
if ( ast_test_flag ( & p - > flags [ 0 ] , SIP_PROMISCREDIR ) ) {
if ( ! strncasecmp ( s , " sip: " , 4 ) )
s + = 4 ;
e = strchr ( s , ' / ' ) ;
e = strchr ( s , ' ; ' ) ;
if ( e )
* e = ' \0 ' ;
if ( option_debug )
@ -11612,14 +11643,19 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req)
/* No username part */
domain = tmp ;
}
e = strchr ( tmp, ' / ' ) ;
e = strchr ( s, ' ; ' ) ; /* Strip of parameters in the username part */
if ( e )
* e = ' \0 ' ;
e = strchr ( domain , ' ; ' ) ; /* Strip of parameters in the domain part */
if ( e )
* e = ' \0 ' ;
if ( ! strncasecmp ( s , " sip: " , 4 ) )
s + = 4 ;
if ( option_debug > 1 )
ast_log ( LOG_DEBUG , " Received 302 Redirect to extension '%s' (domain %s) \n " , s , domain ) ;
if ( p - > owner ) {
pbx_builtin_setvar_helper ( p - > owner , " SIPREDIRECTURI " , uri ) ;
pbx_builtin_setvar_helper ( p - > owner , " SIPDOMAIN " , domain ) ;
ast_string_field_set ( p - > owner , call_forward , s ) ;
}
@ -11653,6 +11689,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
{
int outgoing = ast_test_flag ( & p - > flags [ 0 ] , SIP_OUTGOING ) ;
int res = 0 ;
int xmitres = 0 ;
int reinvite = ( p - > owner & & p - > owner - > _state = = AST_STATE_UP ) ;
struct ast_channel * bridgepeer = NULL ;
@ -11832,13 +11869,13 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
}
/* If I understand this right, the branch is different for a non-200 ACK only */
p - > invitestate = INV_TERMINATED ;
transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , TRUE ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , TRUE ) ;
check_pendings ( p ) ;
break ;
case 407 : /* Proxy authentication */
case 401 : /* Www auth */
/* First we ACK */
transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
if ( p - > options )
p - > options - > auth_type = ( resp = = 401 ? WWW_AUTH : PROXY_AUTH ) ;
@ -11861,7 +11898,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
case 403 : /* Forbidden */
/* First we ACK */
transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
ast_log ( LOG_WARNING , " Received response: \" Forbidden \" from '%s' \n " , get_header ( & p - > initreq , " From " ) ) ;
if ( ! ast_test_flag ( req , SIP_PKT_IGNORE ) & & p - > owner )
ast_queue_control ( p - > owner , AST_CONTROL_CONGESTION ) ;
@ -11870,7 +11907,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
break ;
case 404 : /* Not found */
transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
if ( p - > owner & & ! ast_test_flag ( req , SIP_PKT_IGNORE ) )
ast_queue_control ( p - > owner , AST_CONTROL_CONGESTION ) ;
sip_alreadygone ( p ) ;
@ -11879,7 +11916,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
case 481 : /* Call leg does not exist */
/* Could be REFER caused INVITE with replaces */
ast_log ( LOG_WARNING , " Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up. \n " , p - > callid ) ;
transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
if ( p - > owner )
ast_queue_control ( p - > owner , AST_CONTROL_CONGESTION ) ;
sip_scheddestroy ( p , DEFAULT_TRANS_TIMEOUT ) ;
@ -11888,14 +11925,14 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
/* We have sent CANCEL on an outbound INVITE
This transaction is already scheduled to be killed by sip_hangup ( ) .
*/
transmit_request ( p , SIP_ACK , seqno , 0 , 0 ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
if ( p - > owner & & ! ast_test_flag ( req , SIP_PKT_IGNORE ) )
ast_queue_hangup ( p - > owner ) ;
else if ( ! ast_test_flag ( req , SIP_PKT_IGNORE ) )
update_call_counter ( p , DEC_CALL_LIMIT ) ;
break ;
case 488 : /* Not acceptable here */
transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
if ( reinvite & & p - > udptl ) {
/* If this is a T.38 call, we should go back to
audio . If this is an audio call - something went
@ -11925,18 +11962,20 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru
/* we really should have to wait a while, then retransmit */
/* We should support the retry-after at some point */
/* At this point, we treat this as a congestion */
transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
if ( p - > owner & & ! ast_test_flag ( req , SIP_PKT_IGNORE ) )
ast_queue_control ( p - > owner , AST_CONTROL_CONGESTION ) ;
ast_set_flag ( & p - > flags [ 0 ] , SIP_NEEDDESTROY ) ;
break ;
case 501 : /* Not implemented */
transmit_request ( p , SIP_ACK , seqno , 0 , 0 ) ;
xmitres = transmit_request ( p , SIP_ACK , seqno , XMIT_UNRELIABLE , FALSE ) ;
if ( p - > owner )
ast_queue_control ( p - > owner , AST_CONTROL_CONGESTION ) ;
break ;
}
if ( xmitres = = - 2 )
ast_log ( LOG_WARNING , " Could not transmit message in dialog %s \n " , p - > callid ) ;
}
/* \brief Handle SIP response in REFER transaction
@ -13078,6 +13117,7 @@ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, in
/* Answer the incoming call and set channel to UP state */
transmit_response_with_sdp ( p , " 200 OK " , req , XMIT_RELIABLE ) ;
ast_setstate ( c , AST_STATE_UP ) ;
/* Stop music on hold and other generators */
@ -15220,6 +15260,7 @@ static int sip_poke_noanswer(void *data)
static int sip_poke_peer ( struct sip_peer * peer )
{
struct sip_pvt * p ;
int xmitres = 0 ;
if ( ! peer - > maxms | | ! peer - > addr . sin_addr . s_addr ) {
/* IF we have no IP, or this isn't to be monitored, return
@ -15265,12 +15306,15 @@ static int sip_poke_peer(struct sip_peer *peer)
ast_set_flag ( & p - > flags [ 0 ] , SIP_OUTGOING ) ;
# ifdef VOCAL_DATA_HACK
ast_copy_string ( p - > username , " __VOCAL_DATA_SHOULD_READ_THE_SIP_SPEC__ " , sizeof ( p - > username ) ) ;
transmit_invite ( p , SIP_INVITE , 0 , 2 ) ;
xmitres = transmit_invite ( p , SIP_INVITE , 0 , 2 ) ;
# else
transmit_invite ( p , SIP_OPTIONS , 0 , 2 ) ;
xmitres = transmit_invite ( p , SIP_OPTIONS , 0 , 2 ) ;
# endif
gettimeofday ( & peer - > ps , NULL ) ;
peer - > pokeexpire = ast_sched_add ( sched , DEFAULT_MAXMS * 2 , sip_poke_noanswer , peer ) ;
if ( xmitres = = - 2 )
sip_poke_noanswer ( peer ) ; /* Immediately unreachable, network problems */
else
peer - > pokeexpire = ast_sched_add ( sched , DEFAULT_MAXMS * 2 , sip_poke_noanswer , peer ) ;
return 0 ;
}