SST: retry INV/UPD on 422 Session Interval to low

sayer/1.4-spce2.6
Stefan Sayer 16 years ago
parent c0fd38d998
commit f2c6964550

@ -50,6 +50,10 @@ playout_type=adaptive_playout
#
# minimum_timer=90
# - maximum Timer value we want to accept
#
#maximum_timer=900
# session refresh (Session Timer, RFC4028) method
#
# INVITE - use re-INVITE

@ -18,6 +18,10 @@ script_path=/usr/local/lib/sems/ivr/
#
# minimum_timer=90
# - maximum Timer value we want to accept
#
#maximum_timer=900
# session refresh (Session Timer, RFC4028) method
#
# INVITE - use re-INVITE

@ -58,6 +58,7 @@ prepaid_acc_dest=$H(P-Acc-Dest)
# default values
#session_expires=120
#minimum_timer=90
#maximum_timer=900
#session_refresh_method=UPDATE_FALLBACK_INVITE
#accept_501_reply=yes

@ -47,9 +47,11 @@ enable_session_timer=yes
# default values
#session_expires=120
#minimum_timer=90
#maximum_timer=900
#session_refresh_method=UPDATE_FALLBACK_INVITE
#accept_501_reply=yes
#
#This application can be routed through for achieving
#two things:

@ -157,6 +157,10 @@ stats_dir=/var/log/sems-webconference/
#
# minimum_timer=90
# - maximum Timer value we want to accept
#
#maximum_timer=900
# session refresh (Session Timer, RFC4028) method
#
# INVITE - use re-INVITE

@ -387,6 +387,17 @@ bool AmB2BSession::replaceConnectionAddress(const string& content_type,
return true;
}
void AmB2BSession::updateUACTransCSeq(unsigned int old_cseq, unsigned int new_cseq) {
TransMap::iterator t = relayed_req.find(old_cseq);
if (t != relayed_req.end()) {
AmSipTransaction trans = t->second;
relayed_req.erase(t);
relayed_req[new_cseq] = trans;
DBG("updated relayed_req (UAC trans): CSeq %u -> %u\n", old_cseq, new_cseq);
}
}
void AmB2BSession::onSipReply(const AmSipReply& reply,
int old_dlg_status,
const string& trans_method)
@ -437,6 +448,7 @@ void AmB2BSession::onInvite2xx(const AmSipReply& reply)
TransMap::iterator it = relayed_req.find(reply.cseq);
bool req_fwded = it != relayed_req.end();
if(!req_fwded) {
DBG("req not fwded\n");
AmSession::onInvite2xx(reply);
} else {
DBG("no 200 ACK now: waiting for the 200 ACK from the other side...\n");

@ -175,7 +175,10 @@ class AmB2BSession: public AmSession
/** Terminate the other leg and forget it.*/
virtual void terminateOtherLeg();
/** @see AmSession */
virtual void updateUACTransCSeq(unsigned int old_cseq, unsigned int new_cseq);
void onSipRequest(const AmSipRequest& req);
void onSipReply(const AmSipReply& reply,
int old_dlg_status, const string& trans_method);

@ -376,6 +376,11 @@ public:
/** set the session on/off hold */
virtual void setOnHold(bool hold);
/** update UAC trans state reference from old_cseq to new_cseq
e.g. if uac_auth or session_timer have resent a UAC request
*/
virtual void updateUACTransCSeq(unsigned int old_cseq, unsigned int new_cseq) { }
/**
* Destroy the session.
* It causes the session to be erased from the active session list

@ -185,6 +185,7 @@ int AmSipDialog::rel100OnRequestIn(const AmSipRequest& req)
SIP_HDR_COLSP(SIP_HDR_UNSUPPORTED) SIP_EXT_100REL CRLF,
next_hop_for_replies ? next_hop_ip : "",
next_hop_for_replies ? next_hop_port : 0);
return 0;
break;
default:

@ -16,6 +16,10 @@
#
# minimum_timer=90
# - maximum Timer value we want to accept
#
#maximum_timer=900
# session refresh (Session Timer, RFC4028) method
#
# INVITE - use re-INVITE

@ -80,6 +80,52 @@ bool SessionTimer::onSipRequest(const AmSipRequest& req)
bool SessionTimer::onSipReply(const AmSipReply& reply, int old_dlg_status,
const string& trans_method)
{
if (session_timer_conf.getEnableSessionTimer() &&
(reply.code == 422) &&
((trans_method == SIP_METH_INVITE) || (trans_method == SIP_METH_UPDATE))) {
std::map<unsigned int, SIPRequestInfo >::iterator ri =
sent_requests.find(reply.cseq);
if (ri != sent_requests.end()) {
SIPRequestInfo& orig_req = ri->second;
// get Min-SE
unsigned int i_minse;
string min_se_hdr = getHeader(reply.hdrs, SIP_HDR_MIN_SE, true);
if (!min_se_hdr.empty()) {
if (str2i(strip_header_params(min_se_hdr), i_minse)) {
WARN("error while parsing " SIP_HDR_MIN_SE " header value '%s'\n",
strip_header_params(min_se_hdr).c_str());
} else {
if (i_minse <= session_timer_conf.getMaximumTimer()) {
session_interval = i_minse;
unsigned int new_cseq = s->dlg.cseq;
// resend request with interval i_minse
if (s->dlg.sendRequest(orig_req.method,orig_req.content_type,
orig_req.body, orig_req.hdrs) == 0) {
DBG("request with new Session Interval %u successfully sent.\n", i_minse);
// undo SIP dialog status change
if (s->dlg.getStatus() != old_dlg_status)
s->dlg.setStatus(old_dlg_status);
s->updateUACTransCSeq(reply.cseq, new_cseq);
// processed
return true;
} else {
ERROR("failed to send request with new Session Interval.\n");
}
} else {
DBG("other side requests too high Min-SE: %u (our limit %u)\n",
i_minse, session_timer_conf.getMaximumTimer());
}
}
}
} else {
WARN("request CSeq %u not found in sent requests; unable to retry after 422\n",
reply.cseq);
}
}
updateTimer(s,reply);
return false;
}
@ -96,10 +142,22 @@ bool SessionTimer::onSendRequest(const string& method,
return false;
}
if (session_timer_conf.getEnableSessionTimer() &&
((method == SIP_METH_INVITE) || (method == SIP_METH_UPDATE))) {
// save INVITE and UPDATE so we can resend on 422 reply
DBG("adding %d to list of sent requests.\n", cseq);
sent_requests[cseq] = SIPRequestInfo(method,
content_type,
body,
hdrs);
}
string m_hdrs = SIP_HDR_COLSP(SIP_HDR_SUPPORTED) "timer" CRLF;
if ((method != SIP_METH_INVITE) && (method != SIP_METH_UPDATE))
goto end;
removeHeader(hdrs, SIP_HDR_SESSION_EXPIRES);
removeHeader(hdrs, SIP_HDR_MIN_SE);
m_hdrs += SIP_HDR_COLSP(SIP_HDR_SESSION_EXPIRES) + int2str(session_interval) +CRLF
+ SIP_HDR_COLSP(SIP_HDR_MIN_SE) + int2str(min_se) + CRLF;
@ -372,10 +430,11 @@ void SessionTimer::onTimeoutEvent(AmTimeoutEvent* timeout_ev)
AmSessionTimerConfig::AmSessionTimerConfig()
: EnableSessionTimer(DEFAULT_ENABLE_SESSION_TIMER),
SessionExpires(SESSION_EXPIRES),
MinimumTimer(MINIMUM_TIMER)
MinimumTimer(MINIMUM_TIMER),
MaximumTimer(MAXIMUM_TIMER)
{
}
AmSessionTimerConfig::~AmSessionTimerConfig()
{
}
@ -405,6 +464,18 @@ int AmSessionTimerConfig::readFromConfig(AmConfigReader& cfg)
return -1;
}
}
if (cfg.hasParameter("maximum_timer")){
int maximum_timer = 0;
if (!str2int(cfg.getParameter("maximum_timer"), maximum_timer) ||
maximum_timer<=0) {
ERROR("invalid value for maximum_timer '%s'\n",
cfg.getParameter("maximum_timer").c_str());
return -1;
}
MaximumTimer = (unsigned int) maximum_timer;
}
return 0;
}

@ -40,11 +40,12 @@ class AmTimeoutEvent;
#define ID_SESSION_INTERVAL_TIMER -1
#define ID_SESSION_REFRESH_TIMER -2
/* Session Timer defaul configuration: */
/* Session Timer default configuration: */
#define DEFAULT_ENABLE_SESSION_TIMER 1
#define SESSION_EXPIRES 120 // seconds
#define MINIMUM_TIMER 90 //seconds
#define MINIMUM_TIMER 90 // seconds
#define MAXIMUM_TIMER 900 // seconds - 15 min
/** \brief Factory of the session timer event handler */
class SessionTimerFactory: public AmSessionEventHandlerFactory
@ -71,7 +72,9 @@ class AmSessionTimerConfig
unsigned int SessionExpires;
/** Session Timer: Minimum Session-Expires */
unsigned int MinimumTimer;
unsigned int MaximumTimer;
public:
AmSessionTimerConfig();
~AmSessionTimerConfig();
@ -90,16 +93,22 @@ public:
bool getEnableSessionTimer() { return EnableSessionTimer; }
unsigned int getSessionExpires() { return SessionExpires; }
unsigned int getMinimumTimer() { return MinimumTimer; }
unsigned int getMaximumTimer() { return MaximumTimer; }
int readFromConfig(AmConfigReader& cfg);
};
struct SIPRequestInfo;
/** \brief SessionEventHandler for implementing session timer logic for a session */
class SessionTimer: public AmSessionEventHandler
{
AmSessionTimerConfig session_timer_conf;
AmSession* s;
// map to save sent requests, so we can resent in case of 422
std::map<unsigned int, SIPRequestInfo> sent_requests;
enum SessionRefresher {
refresh_local,
refresh_remote
@ -161,4 +170,22 @@ class SessionTimer: public AmSessionEventHandler
};
/** \brief contains necessary information for UAC auth of a SIP request */
struct SIPRequestInfo {
string method;
string content_type;
string body;
string hdrs;
SIPRequestInfo(const string& method,
const string& content_type,
const string& body,
const string& hdrs)
: method(method), content_type(content_type),
body(body), hdrs(hdrs) { }
SIPRequestInfo() {}
};
#endif

Loading…
Cancel
Save