Module: sems Branch: sayer/dsm/next_hop_for_replies Commit: 98966f25d86223d8e2f6b5516efe54cf8cba0c3a URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=98966f25d86223d8e2f6b5516efe54cf8cba0c3a
Author: Stefan Sayer <[email protected]> Committer: Stefan Sayer <[email protected]> Date: Wed Jan 19 21:40:07 2011 +0100 if set, use next_hop ip:port for replies, too --- core/AmSession.cpp | 6 +++- core/AmSipDialog.cpp | 17 +++++++++----- core/AmSipDialog.h | 4 ++- core/SipCtrlInterface.cpp | 13 ++++++---- core/SipCtrlInterface.h | 3 +- core/sip/resolver.h | 9 ++++--- core/sip/trans_layer.cpp | 55 +++++++++++++++++++++++++++++++------------- core/sip/trans_layer.h | 3 +- 8 files changed, 74 insertions(+), 36 deletions(-) diff --git a/core/AmSession.cpp b/core/AmSession.cpp index a539a32..1cb1173 100644 --- a/core/AmSession.cpp +++ b/core/AmSession.cpp @@ -691,12 +691,14 @@ void AmSession::onSipRequest(const AmSipRequest& req) catch(const string& s) { ERROR("%s\n",s.c_str()); setStopped(); - AmSipDialog::reply_error(req, 500, SIP_REPLY_SERVER_INTERNAL_ERROR); + AmSipDialog::reply_error(req, 500, SIP_REPLY_SERVER_INTERNAL_ERROR, "", + dlg.next_hop_ip, dlg.next_hop_port); } catch(const AmSession::Exception& e) { ERROR("%i %s\n",e.code,e.reason.c_str()); setStopped(); - AmSipDialog::reply_error(req,e.code,e.reason, e.hdrs); + AmSipDialog::reply_error(req,e.code, e.reason, e.hdrs, + dlg.next_hop_ip, dlg.next_hop_port); } if(detached.get() && !getStopped()){ diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp index 464c3b1..67a1c52 100644 --- a/core/AmSipDialog.cpp +++ b/core/AmSipDialog.cpp @@ -93,14 +93,16 @@ void AmSipDialog::updateStatus(const AmSipRequest& req) if (r_cseq_i && req.cseq <= r_cseq){ INFO("remote cseq lower than previous ones - refusing request\n"); // see 12.2.2 - reply_error(req, 500, SIP_REPLY_SERVER_INTERNAL_ERROR); + reply_error(req, 500, SIP_REPLY_SERVER_INTERNAL_ERROR, "", + next_hop_ip, next_hop_port); return; } if (req.method == "INVITE") { if (pending_invites) { reply_error(req,500, SIP_REPLY_SERVER_INTERNAL_ERROR, - "Retry-After: " + int2str(get_random() % 10) + CRLF); + "Retry-After: " + int2str(get_random() % 10) + CRLF, + next_hop_ip, next_hop_port); return; } @@ -174,7 +176,8 @@ int AmSipDialog::rel100OnRequestIn(const AmSipRequest& req) // TODO: shouldn't this be part of a more general check in SEMS? if (key_in_list(getHeader(req.hdrs,SIP_HDR_REQUIRE),SIP_EXT_100REL)) reply_error(req, 420, SIP_REPLY_BAD_EXTENSION, - SIP_HDR_COLSP(SIP_HDR_UNSUPPORTED) SIP_EXT_100REL CRLF); + SIP_HDR_COLSP(SIP_HDR_UNSUPPORTED) SIP_EXT_100REL CRLF, + next_hop_ip, next_hop_port); break; default: @@ -550,7 +553,7 @@ int AmSipDialog::reply(const AmSipRequest& req, if(updateStatusReply(req,code)) return -1; - int ret = SipCtrlInterface::send(reply); + int ret = SipCtrlInterface::send(reply, next_hop_ip, next_hop_port); if(ret){ ERROR("Could not send reply: code=%i; reason='%s'; method=%s; call-id=%s; cseq=%i\n", reply.code,reply.reason.c_str(),req.method.c_str(),req.callid.c_str(),req.cseq); @@ -606,7 +609,9 @@ void AmSipDialog::rel100OnReplyOut(const AmSipRequest &req, unsigned int code, /* static */ int AmSipDialog::reply_error(const AmSipRequest& req, unsigned int code, - const string& reason, const string& hdrs) + const string& reason, const string& hdrs, + const string& next_hop_ip, + unsigned short next_hop_port) { AmSipReply reply; @@ -620,7 +625,7 @@ int AmSipDialog::reply_error(const AmSipRequest& req, unsigned int code, if (AmConfig::Signature.length()) reply.hdrs += SIP_HDR_COLSP(SIP_HDR_SERVER) + AmConfig::Signature + CRLF; - int ret = SipCtrlInterface::send(reply); + int ret = SipCtrlInterface::send(reply, next_hop_ip, next_hop_port); if(ret){ ERROR("Could not send reply: code=%i; reason='%s'; method=%s; call-id=%s; cseq=%i\n", reply.code,reply.reason.c_str(),req.method.c_str(),req.callid.c_str(),req.cseq); diff --git a/core/AmSipDialog.h b/core/AmSipDialog.h index c741f21..dce3ad0 100644 --- a/core/AmSipDialog.h +++ b/core/AmSipDialog.h @@ -303,7 +303,9 @@ class AmSipDialog static int reply_error(const AmSipRequest& req, unsigned int code, const string& reason, - const string& hdrs = ""); + const string& hdrs = "", + const string& next_hop_ip = "", + unsigned short next_hop_port = 5060); }; diff --git a/core/SipCtrlInterface.cpp b/core/SipCtrlInterface.cpp index 7f8e83c..576e866 100644 --- a/core/SipCtrlInterface.cpp +++ b/core/SipCtrlInterface.cpp @@ -276,7 +276,8 @@ void SipCtrlInterface::cleanup() delete udp_socket; } -int SipCtrlInterface::send(const AmSipReply &rep) +int SipCtrlInterface::send(const AmSipReply &rep, + const string& next_hop_ip, unsigned short next_hop_port) { sip_msg msg; @@ -371,10 +372,12 @@ int SipCtrlInterface::send(const AmSipReply &rep) } } - int ret = trans_layer::instance()->send_reply((trans_ticket*)&rep.tt, - rep.code,stl2cstr(rep.reason), - stl2cstr(rep.local_tag), - cstring(hdrs_buf,hdrs_len), stl2cstr(rep.body)); + int ret = + trans_layer::instance()->send_reply((trans_ticket*)&rep.tt, + rep.code,stl2cstr(rep.reason), + stl2cstr(rep.local_tag), + cstring(hdrs_buf,hdrs_len), stl2cstr(rep.body), + stl2cstr(next_hop_ip),next_hop_port); delete [] hdrs_buf; diff --git a/core/SipCtrlInterface.h b/core/SipCtrlInterface.h index 91d9301..7b3efea 100644 --- a/core/SipCtrlInterface.h +++ b/core/SipCtrlInterface.h @@ -96,7 +96,8 @@ public: * @param rep The reply to be sent. 'rep.tt' should be set to transaction * ticket included in the SIP request. */ - static int send(const AmSipReply &rep); + static int send(const AmSipReply &rep, + const string& next_hop_ip = "", unsigned short next_hop_port = 5060); /** * CANCELs an INVITE transaction. diff --git a/core/sip/resolver.h b/core/sip/resolver.h index c663a8f..857ab8b 100644 --- a/core/sip/resolver.h +++ b/core/sip/resolver.h @@ -138,6 +138,11 @@ public: dns_handle* h, sockaddr_storage* sa, const address_type types); + + int str2ip(const char* name, + sockaddr_storage* sa, + const address_type types); + protected: _resolver(); @@ -147,10 +152,6 @@ protected: dns_entry** e, long now); - int str2ip(const char* name, - sockaddr_storage* sa, - const address_type types); - void run(); void on_stop() {} diff --git a/core/sip/trans_layer.cpp b/core/sip/trans_layer.cpp index 72ea480..f1234ac 100644 --- a/core/sip/trans_layer.cpp +++ b/core/sip/trans_layer.cpp @@ -82,9 +82,10 @@ void _trans_layer::register_transport(trsp_socket* trsp) int _trans_layer::send_reply(trans_ticket* tt, - int reply_code, const cstring& reason, - const cstring& to_tag, const cstring& hdrs, - const cstring& body) + int reply_code, const cstring& reason, + const cstring& to_tag, const cstring& hdrs, + const cstring& body, + const cstring& _next_hop, unsigned short _next_port) { // Ref.: RFC 3261 8.2.6, 12.1.1 // @@ -327,29 +328,51 @@ int _trans_layer::send_reply(trans_ticket* tt, } assert(transport); + + int err = -1; + // TODO: inspect topmost 'Via' and select proper addr (+resolve DNS names) // refs: RFC3261 18.2.2; RFC3581 sockaddr_storage remote_ip; - memcpy(&remote_ip,&req->remote_ip,sizeof(sockaddr_storage)); + if (!_next_hop.len) { + memcpy(&remote_ip,&req->remote_ip,sizeof(sockaddr_storage)); - if(req->via_p1->has_rport){ + if(req->via_p1->has_rport){ - if(req->via_p1->rport_i){ - // use 'rport' - ((sockaddr_in*)&remote_ip)->sin_port = htons(req->via_p1->rport_i); + if(req->via_p1->rport_i){ + // use 'rport' + ((sockaddr_in*)&remote_ip)->sin_port = htons(req->via_p1->rport_i); + } + // else: use the source port from the replied request (from IP hdr) } - // else: use the source port from the replied request (from IP hdr) - } - else { + else { - if(req->via_p1->port_i){ - // use port from 'sent-by' via address - ((sockaddr_in*)&remote_ip)->sin_port = htons(req->via_p1->port_i); + if(req->via_p1->port_i){ + // use port from 'sent-by' via address + ((sockaddr_in*)&remote_ip)->sin_port = htons(req->via_p1->port_i); + } + // else: use the source port from the replied request (from IP hdr) + } + } else { + DBG("setting next hop '%.*s:%u'\n", + _next_hop.len, _next_hop.s, _next_port ? _next_port : 5060); + // use _next_hop:_next_port + if (resolver::instance()->str2ip(_next_hop.s, &remote_ip, + (address_type)(IPv4 | IPv6)) != 1) { + ERROR("Invalid next_hop_ip '%.*s'\n", _next_hop.len, _next_hop.s); + delete [] reply_buf; + goto end; } - // else: use the source port from the replied request (from IP hdr) + // default port to 5060 + ((sockaddr_in*)&remote_ip)->sin_port = htons(_next_port ? _next_port : 5060); } - int err = transport->send(&remote_ip,reply_buf,reply_len); + DBG("Sending to %s:%i <%.*s...>\n", + get_addr_str(((sockaddr_in*)&remote_ip)->sin_addr).c_str(), + ntohs(((sockaddr_in*)&remote_ip)->sin_port), + 50 /* preview - instead of p_msg->len */,reply_buf); + + err = transport->send(&remote_ip,reply_buf,reply_len); if(err < 0){ delete [] reply_buf; goto end; diff --git a/core/sip/trans_layer.h b/core/sip/trans_layer.h index 8f866c8..9308767 100644 --- a/core/sip/trans_layer.h +++ b/core/sip/trans_layer.h @@ -83,7 +83,8 @@ public: int send_reply(trans_ticket* tt, int reply_code, const cstring& reason, const cstring& to_tag, const cstring& hdrs, - const cstring& body); + const cstring& body, + const cstring& _next_hop, unsigned short _next_port); /** * Sends a UAC request. _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
