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
