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)) return; // determine session interval string sess_expires_hdr = getHeader(reply.hdrs, "Session-Expires"); if (sess_expires_hdr.empty()) sess_expires_hdr = getHeader(reply.hdrs, "x"); // compact form session_interval = session_timer_conf.getSessionExpires(); session_refresher = refresh_local; session_refresher_role = UAC; if (!sess_expires_hdr.empty()) { //session_interval = get_session_interval_from(req); unsigned int sess_i_tmp = 0; if (str2i(strip_header_params(sess_expires_hdr), sess_i_tmp)) { WARN("error while parsing Session-Expires header value '%s'\n", strip_header_params(sess_expires_hdr).c_str()); // exception? } else { // this is forbidden by rfc, but to be sure against 'rogue' proxy/uas if (sess_i_tmp < session_timer_conf.getMinimumTimer()) { session_interval = session_timer_conf.getMinimumTimer(); } else { session_interval = sess_i_tmp; } } if (get_header_param(sess_expires_hdr, "refresher") == "uas") { session_refresher = refresh_remote; session_refresher_role = UAS; } } removeTimers(s); setTimers(s); }
void AmSession::onSipRequest(const AmSipRequest& req) { CALL_EVENT_H(onSipRequest,req); dlg.updateStatus(req); DBG("onSipRequest: method = %s\n",req.method.c_str()); if(req.method == "INVITE"){ onInvite(req); if(detached.get() && !getStopped()){ onSessionStart(req); if(input || output) AmMediaProcessor::instance()->addSession(this, callgroup); else { ERROR("missing audio input and/or ouput.\n"); } } } else if( req.method == "BYE" ){ dlg.reply(req,200,"OK"); onBye(req); } else if( req.method == "CANCEL" ){ dlg.reply(req,200,"OK"); onCancel(); } else if( req.method == "INFO" ){ if ((strip_header_params(getHeader(req.hdrs, "Content-Type")) =="application/dtmf-relay")|| (strip_header_params(getHeader(req.hdrs, "c")) =="application/dtmf-relay")){ postDtmfEvent(new AmSipDtmfEvent(req.body)); dlg.reply(req, 200, "OK"); } } }
/** * check if UAC requests too low Session-Expires * (<locally configured Min-SE) * Throws SessionIntervalTooSmallException if too low */ bool SessionTimerFactory::checkSessionExpires(const AmSipRequest& req) { //if (session_timer_conf.getEnableSessionTimer()) { string session_expires = getHeader(req.hdrs, "Session-Expires", "x"); if (session_expires.length()) { unsigned int i_se; if (!str2i(strip_header_params(session_expires), i_se)) { //if (i_se < session_timer_conf.getMinimumTimer()) { //TODO: reply_error... //throw SessionTimerException(session_timer_conf.getMinimumTimer()); //} } else throw AmSession::Exception(500,"internal error"); // malformed request? } //} return true; }
void AmB2BSession::onSipRequest(const AmSipRequest& req) { bool fwd = sip_relay_only && (req.method != SIP_METH_CANCEL); if( ((req.method == SIP_METH_SUBSCRIBE) || (req.method == SIP_METH_NOTIFY) || (req.method == SIP_METH_REFER)) && !subs->onRequestIn(req) ) { return; } if(!fwd) AmSession::onSipRequest(req); else { updateRefreshMethod(req.hdrs); if(req.method == SIP_METH_BYE) onBye(req); } B2BSipRequestEvent* r_ev = new B2BSipRequestEvent(req,fwd); if (fwd) { DBG("relaying B2B SIP request (fwd) %s %s\n", r_ev->req.method.c_str(), r_ev->req.r_uri.c_str()); if(r_ev->req.method == SIP_METH_NOTIFY) { string event = getHeader(r_ev->req.hdrs,SIP_HDR_EVENT,true); string id = get_header_param(event,"id"); event = strip_header_params(event); if(event == "refer" && !id.empty()) { int id_int=0; if(str2int(id,id_int)) { unsigned int mapped_id=0; if(getMappedReferID(id_int,mapped_id)) { removeHeader(r_ev->req.hdrs,SIP_HDR_EVENT); r_ev->req.hdrs += SIP_HDR_COLSP(SIP_HDR_EVENT) "refer;id=" + int2str(mapped_id) + CRLF; } } } } int res = relayEvent(r_ev); if (res == 0) { // successfuly relayed, store the request if(req.method != SIP_METH_ACK) recvd_req.insert(std::make_pair(req.cseq,req)); } else { // relay failed, generate error reply DBG("relay failed, replying error\n"); AmSipReply n_reply; errCode2RelayedReply(n_reply, res, 500); dlg->reply(req, n_reply.code, n_reply.reason); } return; } DBG("relaying B2B SIP request %s %s\n", r_ev->req.method.c_str(), r_ev->req.r_uri.c_str()); relayEvent(r_ev); }
void SessionTimer::updateTimer(AmSession* s, const AmSipRequest& req) { if((req.method == "INVITE")||(req.method == "UPDATE")){ remote_timer_aware = key_in_list(getHeader(req.hdrs, SIP_HDR_SUPPORTED),"timer"); // determine session interval string sess_expires_hdr = getHeader(req.hdrs, "Session-Expires", "x"); //session_interval = get_session_interval_from(req); if (!sess_expires_hdr.empty()) { if (str2i(strip_header_params(sess_expires_hdr), session_interval)) { WARN("error while parsing Session-Expires header value '%s'\n", strip_header_params(sess_expires_hdr).c_str()); // exception? session_interval = session_timer_conf.getSessionExpires(); } } else { session_interval = session_timer_conf.getSessionExpires(); } // get Min-SE unsigned int i_minse = session_timer_conf.getMinimumTimer(); string min_se_hdr = getHeader(req.hdrs, "Min-SE"); if (!min_se_hdr.empty()) { if (str2i(strip_header_params(min_se_hdr), i_minse)) { WARN("error while parsing Min-SE header value '%s'\n", strip_header_params(min_se_hdr).c_str()); // exception? } } // calculate actual se unsigned int min = session_timer_conf.getMinimumTimer(); if (i_minse > min) min = i_minse; if ((session_timer_conf.getSessionExpires() < min)|| (session_interval<min)) { session_interval = min; } else { if (session_timer_conf.getSessionExpires() < session_interval) session_interval = session_timer_conf.getSessionExpires(); } // determine session refresher -- cf rfc4028 Table 2 // only if the remote party supports timer and asks // to be refresher we will let the remote party do it. // if remote supports timer and does not specify, // could also be refresher=uac if ((remote_timer_aware) && (!sess_expires_hdr.empty()) && (get_header_param(sess_expires_hdr, "refresher") == "uac")) { DBG("session refresher will be remote UAC.\n"); session_refresher = refresh_remote; session_refresher_role = UAC; } else { DBG("session refresher will be local UAS.\n"); session_refresher = refresh_local; session_refresher_role = UAS; } removeTimers(s); setTimers(s); } else if (req.method == "BYE") { // remove all timers? removeTimers(s); } }