Module: sems
Branch: master
Commit: 9e1ec3433c48e4dce9b714a0c0c326efcfb7ccad
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=9e1ec3433c48e4dce9b714a0c0c326efcfb7ccad

Author: bpintea <[email protected]>
Committer: bpintea <[email protected]>
Date:   Sat Nov 20 18:24:27 2010 +0100

100rel enhancements

- change the way RSeq accounting is done: changed signed data type to
  unsigned, at expense of adding two more vars to AmSipDialog; this
  should make AmSipDialog more replication friendly.
- b/f: if 100rel is disabled and an inbound request asks support for it,
  reply with 420.

---

 core/AmSession.cpp   |    1 +
 core/AmSession.h     |    7 -----
 core/AmSipDialog.cpp |   71 +++++++++++++++++++++++--------------------------
 core/AmSipDialog.h   |    6 ++++
 core/AmSipHeaders.h  |    2 +
 5 files changed, 42 insertions(+), 45 deletions(-)

diff --git a/core/AmSession.cpp b/core/AmSession.cpp
index dbe9002..b0f1a0c 100644
--- a/core/AmSession.cpp
+++ b/core/AmSession.cpp
@@ -731,6 +731,7 @@ void AmSession::onSipRequest(const AmSipRequest& req)
   } else if (req.method == SIP_METH_PRACK) {
     // TODO: SDP
     dlg.reply(req, 200, "OK");
+    // TODO: WARN: only include latest SDP if req.rseq == dlg.rseq (latest 1xx)
   }
 }
 
diff --git a/core/AmSession.h b/core/AmSession.h
index ab3eec6..ae6b76d 100644
--- a/core/AmSession.h
+++ b/core/AmSession.h
@@ -63,13 +63,6 @@ class AmDtmfEvent;
 #define AM_AUDIO_OUT 1
 
 
-/* maximum number of reliable 1xx supported; needed for marking first 1xx
- * (which can not be followed by subsequent ones w/o being PRACKed), as
- * opposed to having another value storing it's value. */
-#define MAX_RSEQ_BITS           24
-#define LOC_RSEQ_ORDER(_rseq)   (_rseq & ((1 << MAX_RSEQ_BITS) - 1))
-
-
 /**
  * \brief Implements the default behavior of one session
  * 
diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp
index 5d41eaa..a10f347 100644
--- a/core/AmSipDialog.cpp
+++ b/core/AmSipDialog.cpp
@@ -152,6 +152,7 @@ int AmSipDialog::rel100OnRequestIn(const AmSipRequest& req)
           DBG(SIP_EXT_100REL " now active.\n");
         }
         break;
+
       case REL100_REQUIRE: /* if support is required, reject if UAC doesn't */
         if (! (key_in_list(getHeader(req.hdrs,SIP_HDR_SUPPORTED), 
               SIP_EXT_100REL) ||
@@ -163,30 +164,31 @@ int AmSipDialog::rel100OnRequestIn(const AmSipRequest& 
req)
           return 0; // has been replied
         }
         break; // 100rel required
+
+      case REL100_DISABLED:
+        // TODO: shouldn't this be part of a more general check in SEMS?
+        if (key_in_list(getHeader(req.hdrs,SIP_HDR_SUPPORTED),SIP_EXT_100REL))
+          reply_error(req, 420, SIP_REPLY_BAD_EXTENSION, 
+              SIP_HDR_COLSP(SIP_HDR_UNSUPPORTED) SIP_EXT_100REL CRLF);
+        break;
+
       default:
         ERROR("BUG: unexpected value `%d' for '" SIP_EXT_100REL "' switch.", 
           reliable_1xx);
 #ifndef NDEBUG
         abort();
 #endif
-      case 0: /* support disabled */
-        break;
     } // switch reliable_1xx
   } else if (req.method == SIP_METH_PRACK) {
     if (reliable_1xx != REL100_REQUIRE) {
       WARN("unexpected PRACK received while " SIP_EXT_100REL " not active.\n");
       // let if float up
-    } else if ((1<<MAX_RSEQ_BITS)<=req.rseq && 
-        req.rseq<=(unsigned)abs(rseq)) {
-      // reply generation will be done by the onSipRequest()
-      if (req.rseq == (unsigned)-rseq) {
-        rseq = -rseq; // confirmed
-        DBG("latest RSeq (%u) confirmed.\n", rseq);
+    } else if (rseq_1st<=req.rseq && req.rseq<=rseq) {
+      if (req.rseq == rseq) {
+        rseq_confirmed = true; // confirmed
       }
-    } else {
-      WARN("no matching RAck value in PRACK (%s).\n", req.hdrs.c_str());
-      // just drop it, either a retransmission or some bogus
-      return 0;
+      // else: confirmation for one of the pending 1xx
+      DBG("%sRSeq (%u) confirmed.\n", (req.rseq==rseq) ? "latest " : "", rseq);
     }
   }
 
@@ -385,8 +387,10 @@ int AmSipDialog::rel100OnReplyIn(const AmSipReply &reply)
         break;
 
     case REL100_REQUIRE:
-      if (! reply.rseq) {
-        ERROR("no RSeq value (or unsupported 0) in reliable 1xx.\n");
+      if (!key_in_list(getHeader(reply.hdrs,SIP_HDR_REQUIRE),SIP_EXT_100REL) ||
+          !reply.rseq) {
+        ERROR(SIP_EXT_100REL " not supported or no positive RSeq value in "
+            "(reliable) 1xx.\n");
         if (hdl) hdl->onFailure(FAIL_REL100, 0, &reply);
       } else {
         DBG(SIP_EXT_100REL " now active.\n");
@@ -394,7 +398,7 @@ int AmSipDialog::rel100OnReplyIn(const AmSipReply &reply)
       }
       break;
 
-    case 0:
+    case REL100_DISABLED:
       // 100rel support disabled
       break;
     default:
@@ -448,7 +452,7 @@ void AmSipDialog::rel100OnTimeout(const AmSipRequest &req,
 {
   INFO("reply <%s> timed out (not PRACKed).\n", rpl.print().c_str());
   if (100 < rpl.code && rpl.code < 200 && reliable_1xx == REL100_REQUIRE &&
-      (unsigned)rseq == rpl.rseq && rpl.method == SIP_METH_INVITE) {
+      rseq == rpl.rseq && rpl.method == SIP_METH_INVITE) {
     INFO("reliable %d reply timed out; rejecting request.\n", rpl.code);
     if(hdl) hdl->onNoPrack(req, rpl);
   } else {
@@ -562,34 +566,25 @@ void AmSipDialog::rel100OnReplyOut(const AmSipRequest 
&req, unsigned int code,
           if (getHeader(hdrs, SIP_HDR_RSEQ).length())
             // already added (by app?)
             break;
-#ifndef NDEBUG
-          if ((abs(rseq) & ((1 << MAX_RSEQ_BITS) - 1)) == 
-              ((1 << MAX_RSEQ_BITS) - 1)) {
-            ERROR("CRITICAL: RSeq value too high: increase MAX_RSEQ_BITS "
-              "(now %d) and recompile.\n", MAX_RSEQ_BITS);
-            abort();
-          }
-#endif
-          if (rseq < 0) { // RSeq not yet PRACKed
-            // refuse subsequent 1xx if first isn't yet PRACKed
-            if ((((unsigned)-rseq) & ((1 << MAX_RSEQ_BITS) - 1)) == 0)
-              throw AmSession::Exception(491, "last reliable 1xx not yet "
-                  "PRACKed");
-            rseq --;
-          } else if (! rseq) { // only init rseq if 1xx is used
-            unsigned rseq_1st = (get_random() + 1) << MAX_RSEQ_BITS;
-            rseq_1st &= 0x7fffffff;
-            rseq = -((signed)rseq_1st);
+          if (! rseq) { // only init rseq if 1xx is used
+            rseq = (get_random() & 0x3ff) + 1; // start small (<1024) and non-0
+            rseq_confirmed = false;
+            rseq_1st = rseq;
           } else {
-            rseq = -(++rseq);
+            if ((! rseq_confirmed) && (rseq_1st == rseq))
+              // refuse subsequent 1xx if first isn't yet PRACKed
+              throw AmSession::Exception(491, "first reliable 1xx not yet "
+                  "PRACKed");
+            rseq ++;
           }
-          hdrs += SIP_HDR_COLSP(SIP_HDR_RSEQ) + int2str(-rseq) + CRLF;
+          hdrs += SIP_HDR_COLSP(SIP_HDR_RSEQ) + int2str(rseq) + CRLF;
           break;
         default:
           break;
       }
-    } else if (code < 300 && reliable_1xx == REL100_REQUIRE) {
-      if (rseq < 0) // reliable 1xx is pending
+    } else if (code < 300 && reliable_1xx == REL100_REQUIRE) { //code = 2xx
+      if (rseq && !rseq_confirmed) 
+        // reliable 1xx is pending, 2xx'ing not allowed yet
         throw AmSession::Exception(491, "last reliable 1xx not yet PRACKed");
     }
   }
diff --git a/core/AmSipDialog.h b/core/AmSipDialog.h
index a95f359..db05754 100644
--- a/core/AmSipDialog.h
+++ b/core/AmSipDialog.h
@@ -191,7 +191,13 @@ class AmSipDialog
   };
   enum provisional_100rel reliable_1xx;
 
+#if 0
   int rseq;          // RSeq for next request (NOTE: keep it signed!)
+#else
+  unsigned rseq;          // RSeq for next request (NOTE: keep it signed!)
+  bool rseq_confirmed;    // latest RSeq is confirmed
+  unsigned rseq_1st;      // value of first RSeq (init value)
+#endif
   unsigned int cseq; // Local CSeq for next request
   bool r_cseq_i;
   unsigned int r_cseq; // last remote CSeq  
diff --git a/core/AmSipHeaders.h b/core/AmSipHeaders.h
index c33eb05..6845d26 100644
--- a/core/AmSipHeaders.h
+++ b/core/AmSipHeaders.h
@@ -16,6 +16,7 @@
 #define SIP_HDR_CONTENT_TYPE    "Content-Type"
 #define SIP_HDR_CONTACT         "Contact"
 #define SIP_HDR_SUPPORTED       "Supported"
+#define SIP_HDR_UNSUPPORTED     "Unsupported"
 #define SIP_HDR_REQUIRE         "Require"
 #define SIP_HDR_SERVER          "Server"
 #define SIP_HDR_USER_AGENT      "User-Agent"
@@ -49,4 +50,5 @@
 #define SIP_APPLICATION_SDP     "application/sdp"
 
 #define SIP_REPLY_SERVER_INTERNAL_ERROR "Server Internal Error"
+#define SIP_REPLY_BAD_EXTENSION         "Bad Extension"
 #endif /* __AMSIPHEADERS_H__ */

_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev

Reply via email to