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

Author: Stefan Sayer <[email protected]>
Committer: Stefan Sayer <[email protected]>
Date:   Thu Sep 16 21:11:14 2010 +0200

UPDATE support for Session Timer

- configured via app config file
- so far only for one-legged calls (no sst_b2b support)

---

 core/AmSession.cpp                          |   31 +++++++++++++++++++-
 core/AmSession.h                            |   13 ++++++++-
 core/AmSipHeaders.h                         |    1 +
 core/plug-in/echo/etc/echo.conf             |   20 ++++++++++++-
 core/plug-in/session_timer/SessionTimer.cpp |   41 ++++++++++++++++++++------
 core/plug-in/session_timer/SessionTimer.h   |    1 +
 6 files changed, 94 insertions(+), 13 deletions(-)

diff --git a/core/AmSession.cpp b/core/AmSession.cpp
index 50fdf19..8b0a9a7 100644
--- a/core/AmSession.cpp
+++ b/core/AmSession.cpp
@@ -68,6 +68,7 @@ AmSession::AmSession()
     m_dtmfDetectionEnabled(true),
     accept_early_session(false),
     reliable_1xx(AmConfig::rel100),
+    refresh_method(REFRESH_UPDATE_FB_REINV),
     processing_status(SESSION_PROCESSING_EVENTS)
 #ifdef WITH_ZRTP
   ,  zrtp_session(NULL), zrtp_audio(NULL), enable_zrtp(true)
@@ -682,6 +683,15 @@ void AmSession::onSipRequest(const AmSipRequest& req)
   CALL_EVENT_H(onSipRequest,req);
 
   DBG("onSipRequest: method = %s\n",req.method.c_str());
+
+  if (refresh_method == REFRESH_UPDATE_FB_REINV) {
+    if (key_in_list(getHeader(req.hdrs, SIP_HDR_ALLOW),
+                   SIP_METH_UPDATE)) {
+      DBG("remote allows UPDATE, using UPDATE for session refresh.\n");
+      refresh_method = REFRESH_UPDATE;
+    }
+  }
+
   if(req.method == SIP_METH_INVITE){
 
     switch(reliable_1xx) {
@@ -774,6 +784,14 @@ void AmSession::onSipReply(const AmSipReply& reply, int 
old_dlg_status)
 {
   CALL_EVENT_H(onSipReply,reply,old_dlg_status);
 
+  if (refresh_method == REFRESH_UPDATE_FB_REINV) {
+    if (key_in_list(getHeader(reply.hdrs, SIP_HDR_ALLOW),
+                   SIP_METH_UPDATE)) {
+      DBG("remote allows UPDATE, using UPDATE for session refresh.\n");
+      refresh_method = REFRESH_UPDATE;
+    }
+  }
+
   if (old_dlg_status != dlg.getStatus())
     DBG("Dialog status changed %s -> %s (stopped=%s) \n", 
        AmSipDialog::status2str[old_dlg_status], 
@@ -1081,7 +1099,18 @@ void AmSession::onRtpTimeout()
   setStopped();
 }
 
-void AmSession::sendUpdate(string &cont_type, string &body, string &hdrs)
+void AmSession::refresh() {
+  if (refresh_method == REFRESH_UPDATE) {
+    DBG("Refreshing session with UPDATE\n");
+    sendUpdate("", "", "");
+  } else {
+    DBG("Refreshing session with re-INVITE\n");
+    sendReinvite(true);
+  }
+}
+
+void AmSession::sendUpdate(const string &cont_type, const string &body,
+                          const string &hdrs)
 {
   dlg.update(cont_type, body, hdrs);
 }
diff --git a/core/AmSession.h b/core/AmSession.h
index 20c6d1f..620fe8c 100644
--- a/core/AmSession.h
+++ b/core/AmSession.h
@@ -164,6 +164,7 @@ protected:
 
   /** do accept early session? */
   bool accept_early_session;
+
   /** enable the reliability of provisional replies? */
   unsigned char reliable_1xx;
 #define REL100_DISABLED         0
@@ -175,6 +176,13 @@ protected:
 
 public:
 
+  enum SessionRefreshMethod {
+    REFRESH_REINVITE = 0,      // use reinvite
+    REFRESH_UPDATE,            // use update
+    REFRESH_UPDATE_FB_REINV    // use update or fallback to reinvite
+  };
+  SessionRefreshMethod refresh_method;
+
   AmRtpAudio* RTPStream();
 
 #ifdef WITH_ZRTP
@@ -347,8 +355,11 @@ public:
                         bool force_symmetric_rtp,
                         string* sdp_reply);
 
+  /** refresh the session - re-INVITE or UPDATE*/
+  virtual void refresh();
+
   /** send an UPDATE in the session */
-  virtual void sendUpdate(string &cont_type, string &body, string &hdrs);
+  virtual void sendUpdate(const string &cont_type, const string &body, const 
string &hdrs);
 
   /** send a Re-INVITE (if connected) */
   virtual void sendReinvite(bool updateSDP = true, const string& headers = "");
diff --git a/core/AmSipHeaders.h b/core/AmSipHeaders.h
index e8e4880..cdc3d31 100644
--- a/core/AmSipHeaders.h
+++ b/core/AmSipHeaders.h
@@ -30,6 +30,7 @@
 #define SIP_HDR_PROXY_AUTHORIZATION "Proxy-Authorization"
 #define SIP_HDR_PROXY_AUTHENTICATE "Proxy-Authenticate"
 #define SIP_HDR_WWW_AUTHENTICATE "WWW-Authenticate"
+#define SIP_HDR_ALLOW            "Allow"
 
 #define SIP_HDR_COL(_hdr)       _hdr ":"
 #define SIP_HDR_COLSP(_hdr)     SIP_HDR_COL(_hdr) " "
diff --git a/core/plug-in/echo/etc/echo.conf b/core/plug-in/echo/etc/echo.conf
index 0f93230..b87edc4 100644
--- a/core/plug-in/echo/etc/echo.conf
+++ b/core/plug-in/echo/etc/echo.conf
@@ -1,7 +1,7 @@
 # Echo plug-in configuration file
 #
 
-# Session timer ([yes,no]; default: no)
+# RFC4028 Session Timer  ([yes,no]; default: no)
 #
 
 # - enables the session timer.
@@ -15,3 +15,21 @@
 # - set the "Min-SE" parameter for the session timer.
 #
 # minimum_timer=90
+
+# session refresh (Session Timer, RFC4028) method
+#
+# INVITE                 - use re-INVITE
+# UPDATE                 - use UPDATE
+# UPDATE_FALLBACK_INVITE - use UPDATE if indicated in Allow, re-INVITE 
otherwise
+#
+# Default: UPDATE_FALLBACK_INVITE
+#
+# Note: Session Timers are only supported in some applications
+#
+#session_refresh_method=UPDATE
+
+# accept_501_reply - accept 501 reply as successful refresh? [yes|no]
+#
+# Default: yes
+#
+#accept_501_reply=no
diff --git a/core/plug-in/session_timer/SessionTimer.cpp 
b/core/plug-in/session_timer/SessionTimer.cpp
index 6c35f11..e36dd48 100644
--- a/core/plug-in/session_timer/SessionTimer.cpp
+++ b/core/plug-in/session_timer/SessionTimer.cpp
@@ -53,8 +53,10 @@ SessionTimer::SessionTimer(AmSession* s)
   :AmSessionEventHandler(),
    s(s),
    session_interval(0), 
-   session_refresher(refresh_remote)
-{}
+   session_refresher(refresh_remote),
+   accept_501_reply(true)
+{
+}
 
 bool SessionTimer::process(AmEvent* ev)
 {
@@ -140,6 +142,24 @@ int SessionTimer::configure(AmConfigReader& conf)
       session_timer_conf.getMinimumTimer()
       );
 
+  if (conf.hasParameter("session_refresh_method")) {
+    string refresh_method_s = conf.getParameter("session_refresh_method");
+    if (refresh_method_s == "UPDATE") {
+      s->refresh_method = AmSession::REFRESH_UPDATE;
+    } else if (refresh_method_s == "UPDATE_FALLBACK_INVITE") {
+      s->refresh_method = AmSession::REFRESH_UPDATE_FB_REINV;
+    } else if (refresh_method_s == "INVITE") {
+      s->refresh_method = AmSession::REFRESH_REINVITE;
+    } else {
+      ERROR("unknown setting for 'session_refresh_method' config option.\n");
+      return -1;
+    }
+    DBG("set session refresh method: %d.\n", s->refresh_method);
+  }
+
+  if (conf.getParameter("accept_501_reply")=="no")
+    accept_501_reply = false;
+
   return 0;
 }
 
@@ -253,8 +273,9 @@ void SessionTimer::updateTimer(AmSession* s, const 
AmSipReply& reply)
   if (!session_timer_conf.getEnableSessionTimer())
     return;
 
-  // only update timer on positive reply
-  if ((reply.code < 200) || (reply.code >= 300))
+  // only update timer on positive reply, or 501 if config'd
+  if (((reply.code < 200) || (reply.code >= 300)) &&
+      (!(accept_501_reply && reply.code == 501)))
     return;
   
   // determine session interval
@@ -319,12 +340,12 @@ void SessionTimer::onTimeoutEvent(AmTimeoutEvent* 
timeout_ev)
   int timer_id = timeout_ev->data.get(0).asInt();
 
   if (timer_id == ID_SESSION_REFRESH_TIMER) {
-    DBG("Session Timer: initiating refresh (Re-Invite)\n");
-    if (session_refresher == refresh_local) 
-      // send reinvite with SDP
-      s->sendReinvite(true);
-    else
-      WARN("need session refresh but remote session is refresher\n");
+    if (session_refresher == refresh_local) {
+      DBG("Session Timer: initiating session refresh\n");
+      s->refresh();
+    } else {
+      DBG("need session refresh but remote session is refresher\n");
+    }
   } else if (timer_id == ID_SESSION_INTERVAL_TIMER) {
     //     // let the session know it got timeout
     //     onTimeout();
diff --git a/core/plug-in/session_timer/SessionTimer.h 
b/core/plug-in/session_timer/SessionTimer.h
index 1ca75f9..0b179e8 100644
--- a/core/plug-in/session_timer/SessionTimer.h
+++ b/core/plug-in/session_timer/SessionTimer.h
@@ -114,6 +114,7 @@ class SessionTimer: public AmSessionEventHandler
   unsigned int         session_interval;  
   SessionRefresher     session_refresher;
   SessionRefresherRole session_refresher_role;
+  bool                 accept_501_reply;
 
   void updateTimer(AmSession* s,const AmSipRequest& req);
   void updateTimer(AmSession* s,const AmSipReply& reply);

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

Reply via email to