Module: sems Branch: master Commit: 03f617af0a21bd2158d178b45ac5fd617c51238b URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=03f617af0a21bd2158d178b45ac5fd617c51238b
Author: Raphael Coeffic <[email protected]> Committer: Raphael Coeffic <[email protected]> Date: Mon Jun 18 15:17:18 2012 +0200 add support for 503 replies. When 503 is replied, SEMS will re-send the request to the next destination IP according to SRV records, or whatever destination IP list we might have. --- core/sip/trans_layer.cpp | 89 +++++++++++++++++++++++++++------------------- core/sip/trans_layer.h | 9 +++++ 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/core/sip/trans_layer.cpp b/core/sip/trans_layer.cpp index 009d0db..e106ca3 100644 --- a/core/sip/trans_layer.cpp +++ b/core/sip/trans_layer.cpp @@ -1383,7 +1383,12 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg* if(t->msg->u.request->method == sip_request::INVITE){ if(reply_code >= 300){ - + + if(reply_code == 503) { + if(!try_next_ip(bucket,t)) + goto end; + } + // Final error reply switch(t->state){ @@ -1478,6 +1483,11 @@ int _trans_layer::update_uac_reply(trans_bucket* bucket, sip_trans* t, sip_msg* } else { // non-INVITE transaction + if(reply_code == 503) { + if(!try_next_ip(bucket,t)) + goto end; + } + // Final reply switch(t->state){ @@ -1864,42 +1874,7 @@ void _trans_layer::timer_expired(timer* t, trans_bucket* bucket, sip_trans* tr) } break; case STIMER_M: - { - sockaddr_storage sa; - memset(&sa,0,sizeof(sockaddr_storage)); - - // get the next ip - if(tr->msg->h_dns.next_ip(&sa) < 0){ - tr->clear_timer(STIMER_M); - break; - } - - //If a SRV record is involved, the port number - // should have been set by h_dns.next_ip(...). - if(!((sockaddr_in*)&sa)->sin_port){ - //Else, we copy the old port number - ((sockaddr_in*)&sa)->sin_port = ((sockaddr_in*)&tr->msg->remote_ip)->sin_port; - } - - // copy the new address back - memcpy(&tr->msg->remote_ip,&sa,sizeof(sockaddr_storage)); - - // create new branch tag - compute_branch((char*)(tr->msg->via_p1->branch.s+MAGIC_BRANCH_LEN), - tr->msg->callid->value,tr->msg->cseq->value); - - // and re-send - tr->msg->send(); - - // reset counter for timer A & E - timer* A_E_timer = tr->get_timer(STIMER_A); - tr->reset_timer(A_E_timer->type & 0xFFFF,A_TIMER,bucket->get_id()); - - if(!tr->msg->h_dns.eoip()) - tr->reset_timer(STIMER_M,M_TIMER,bucket->get_id()); - else - tr->clear_timer(STIMER_M); - } + try_next_ip(bucket,tr); break; default: @@ -1984,6 +1959,46 @@ trsp_socket* _trans_layer::find_transport(sockaddr_storage* remote_ip) return NULL; } +int _trans_layer::try_next_ip(trans_bucket* bucket, sip_trans* tr) +{ + sockaddr_storage sa; + memset(&sa,0,sizeof(sockaddr_storage)); + + // get the next ip + if(tr->msg->h_dns.next_ip(&sa) < 0){ + tr->clear_timer(STIMER_M); + return -1; + } + + //If a SRV record is involved, the port number + // should have been set by h_dns.next_ip(...). + if(!((sockaddr_in*)&sa)->sin_port){ + //Else, we copy the old port number + ((sockaddr_in*)&sa)->sin_port = ((sockaddr_in*)&tr->msg->remote_ip)->sin_port; + } + + // copy the new address back + memcpy(&tr->msg->remote_ip,&sa,sizeof(sockaddr_storage)); + + // create new branch tag + compute_branch((char*)(tr->msg->via_p1->branch.s+MAGIC_BRANCH_LEN), + tr->msg->callid->value,tr->msg->cseq->value); + + // and re-send + tr->msg->send(); + + // reset counter for timer A & E + timer* A_E_timer = tr->get_timer(STIMER_A); + tr->reset_timer(A_E_timer->type & 0xFFFF,A_TIMER,bucket->get_id()); + + if(!tr->msg->h_dns.eoip()) + tr->reset_timer(STIMER_M,M_TIMER,bucket->get_id()); + else + tr->clear_timer(STIMER_M); + + return 0; +} + /** EMACS ** * Local variables: * mode: c++ diff --git a/core/sip/trans_layer.h b/core/sip/trans_layer.h index a9e77af..fceeeb0 100644 --- a/core/sip/trans_layer.h +++ b/core/sip/trans_layer.h @@ -182,6 +182,15 @@ protected: */ int set_destination_ip(sip_msg* msg, cstring* next_hop, unsigned short next_port); + /** + * If the destination has multiple IPs (SRV records), + * try the next destination IP. + * @return 0 if the message has been re-sent. + * -1 if no additional destination has been found. + */ + int try_next_ip(trans_bucket* bucket, sip_trans* tr); + + /** Avoid external instantiation. @see singleton. */ _trans_layer(); ~_trans_layer(); _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
