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

Reply via email to