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;
}
Exemple #4
0
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);
  }
}