Example #1
0
void CallTimerDialog::process(AmEvent* ev)
{
  AmPluginEvent* plugin_event = dynamic_cast<AmPluginEvent*>(ev);
  if(plugin_event && plugin_event->name == "timer_timeout") {
    int timer_id = plugin_event->data.get(0).asInt();
    if (timer_id == TIMERID_CALL_TIMER) {
      DBG("timer timeout.\n");
      terminateOtherLeg();
      dlg.bye();
      terminateLeg();
      ev->processed = true;
      return;
    }
  }
  
  AmB2BCallerSession::process(ev);
}
Example #2
0
bool CallTimerDialog::onOtherReply(const AmSipReply& reply)
{
  bool ret = false;

  if (m_state == BB_Dialing) {
    if (reply.code < 200) {
      DBG("Callee is trying... code %d\n", reply.code);
    }
    else if(reply.code < 300) {
      if(getCalleeStatus()  == Connected) {
        m_state = BB_Connected;
        setInOut(NULL, NULL);
	// startAccounting();
	// set the call timer
	AmArg di_args,ret;
	di_args.push(TIMERID_CALL_TIMER);
	di_args.push((int)call_time);  // in seconds
	di_args.push(dlg.local_tag.c_str());
        m_user_timer->invoke("setTimer", di_args, ret);
      }
    }
    else if(reply.code == 487 && dlg.getStatus() == AmSipDialog::Pending) {
      DBG("Stopping leg A on 487 from B with 487\n");
      dlg.reply(invite_req, 487, "Request terminated");
      setStopped();
      ret = true;
    }
    else if (reply.code >= 300 && dlg.getStatus() == AmSipDialog::Connected) {
      DBG("Callee final error in connected state with code %d\n",reply.code);
      terminateLeg();
    }
    else if (reply.code >= 300 && m_state == BB_Dialing) {
      DBG("Callee final error with code %d\n",reply.code);
      AmB2BCallerSession::onOtherReply(reply);
      // reset into non-b2b mode to get possible INVITE again
      sip_relay_only = false;
    } else {
      DBG("Callee final error with code %d\n",reply.code);
      AmB2BCallerSession::onOtherReply(reply);
    }
  }
  return ret;
}
bool SWPrepaidSIPDialog::onOtherReply(const AmSipReply& reply)
{
  bool ret = false;

  if (m_state == CC_Dialing) {
    if (reply.code < 200) {
      DBG("Callee is trying... code %d\n", reply.code);
    }
    else if(reply.code < 300) {
      if(getCalleeStatus()  == Connected) {
        m_state = CC_Connected;
        startAccounting();
        setInOut(NULL, NULL);

        // set the call timer
        AmArg di_args,ret;
        di_args.push(TIMERID_CREDIT_TIMEOUT);
        di_args.push(m_credit);  // in seconds
        di_args.push(dlg.local_tag.c_str());
        m_user_timer->invoke("setTimer", di_args, ret);
      }
    }
    else if(reply.code == 487 && dlg.getStatus() == AmSipDialog::Pending) {
      DBG("Canceling leg A on 487 from B");
      dlg.reply(m_localreq, 487, "Call terminated");
      setStopped();
      ret = true;
    }
    else if (reply.code >= 300 && dlg.getStatus() == AmSipDialog::Connected) {
      DBG("Callee final error in connected state with code %d\n",reply.code);
      terminateLeg();
    }
    else {
      DBG("Callee final error with code %d\n",reply.code);
      AmB2BCallerSession::onOtherReply(reply);
    }
  }
  return ret;
}
Example #4
0
void AmB2BSession::onB2BEvent(B2BEvent* ev)
{
  DBG("AmB2BSession::onB2BEvent\n");
  switch(ev->event_id){

  case B2BSipRequest:
    {   
      B2BSipRequestEvent* req_ev = dynamic_cast<B2BSipRequestEvent*>(ev);
      assert(req_ev);

      DBG("B2BSipRequest: %s (fwd=%s)\n",
	  req_ev->req.method.c_str(),
	  req_ev->forward?"true":"false");

      if(req_ev->forward){

	// Check Max-Forwards first
	if(req_ev->req.max_forwards == 0) {
	  relayError(req_ev->req.method,req_ev->req.cseq,
		     true,483,SIP_REPLY_TOO_MANY_HOPS);
	  return;
	}

	if (req_ev->req.method == SIP_METH_INVITE &&
	    dlg->getUACInvTransPending()) {
	  // don't relay INVITE if INV trans pending
	  DBG("not sip-relaying INVITE with pending INV transaction, "
	      "b2b-relaying 491 pending\n");
          relayError(req_ev->req.method, req_ev->req.cseq,
		     true, 491, SIP_REPLY_PENDING);
	  return;
	}

	if (req_ev->req.method == SIP_METH_BYE &&
	    dlg->getStatus() != AmBasicSipDialog::Connected) {
	  DBG("not sip-relaying BYE in not connected dlg, b2b-relaying 200 OK\n");
          relayError(req_ev->req.method, req_ev->req.cseq,
		     true, 200, "OK");
	  return;
	}
      }

       if( (req_ev->req.method == SIP_METH_BYE)
	  // CANCEL is handled differently: other side has already 
	  // sent a terminate event.
	  //|| (req_ev->req.method == SIP_METH_CANCEL)
	  ) {
	
	 if (onOtherBye(req_ev->req))
	   req_ev->processed = true; // app should have relayed 200 to BYE
      }

      if(req_ev->forward && !req_ev->processed){
        int res = relaySip(req_ev->req);
	if(res < 0) {
	  // reply relayed request internally
          relayError(req_ev->req.method, req_ev->req.cseq, true, res);
	  return;
	}
      }
      
    }
    return;

  case B2BSipReply:
    {
      B2BSipReplyEvent* reply_ev = dynamic_cast<B2BSipReplyEvent*>(ev);
      assert(reply_ev);

      DBG("B2BSipReply: %i %s (fwd=%s)\n",reply_ev->reply.code,
	  reply_ev->reply.reason.c_str(),reply_ev->forward?"true":"false");
      DBG("B2BSipReply: content-type = %s\n",
	  reply_ev->reply.body.getCTStr().c_str());

      if(reply_ev->forward){

        std::map<int,AmSipRequest>::iterator t_req =
	  recvd_req.find(reply_ev->reply.cseq);

	if (t_req != recvd_req.end()) {
	  if ((reply_ev->reply.code >= 300) && (reply_ev->reply.code <= 305) &&
	      !reply_ev->reply.contact.empty()) {
	    // relay with Contact in 300 - 305 redirect messages
	    AmSipReply n_reply(reply_ev->reply);
	    n_reply.hdrs+=SIP_HDR_COLSP(SIP_HDR_CONTACT) +
	      reply_ev->reply.contact+ CRLF;

	    if(relaySip(t_req->second,n_reply) < 0) {
	      terminateOtherLeg();
	      terminateLeg();
	    }
	  } else {
	    // relay response
	    if(relaySip(t_req->second,reply_ev->reply) < 0) {
	      terminateOtherLeg();
	      terminateLeg();
	    }
	  }
		
	} else {
	  DBG("Cannot relay reply: request already replied"
	      " (code=%u;cseq=%u;call-id=%s)",
	      reply_ev->reply.code, reply_ev->reply.cseq,
	      reply_ev->reply.callid.c_str());
	}
      } else {
	// check whether not-forwarded (locally initiated)
	// INV/UPD transaction changed session in other leg
	if (SIP_IS_200_CLASS(reply_ev->reply.code) &&
	    (!reply_ev->reply.body.empty()) &&
	    (reply_ev->reply.cseq_method == SIP_METH_INVITE ||
	     reply_ev->reply.cseq_method == SIP_METH_UPDATE)) {
	  if (updateSessionDescription(reply_ev->reply.body)) {
	    if (reply_ev->reply.cseq != est_invite_cseq) {
	      if (dlg->getUACInvTransPending()) {
		DBG("changed session, but UAC INVITE trans pending\n");
		// todo(?): save until trans is finished?
		return;
	      }
	      DBG("session description changed - refreshing\n");
	      sendEstablishedReInvite();
	    } else {
	      DBG("reply to establishing INVITE request - not refreshing\n");
	    }
	  }
	}
      }
    }
    return;

  case B2BTerminateLeg:
    DBG("terminateLeg()\n");
    terminateLeg();
    break;
  }

  //ERROR("unknown event caught\n");
}
Example #5
0
void AmB2BCallerSession::onCancel(const AmSipRequest& req)
{
  terminateOtherLeg();
  terminateLeg();
}
Example #6
0
void AmB2BCallerSession::onB2BEvent(B2BEvent* ev)
{
  bool processed = false;

  if(ev->event_id == B2BSipReply){

    AmSipReply& reply = ((B2BSipReplyEvent*)ev)->reply;

    if(getOtherId().empty()){
      //DBG("Discarding B2BSipReply from other leg (other_id empty)\n");
      DBG("B2BSipReply: other_id empty ("
	  "reply code=%i; method=%s; callid=%s; from_tag=%s; "
	  "to_tag=%s; cseq=%i)\n",
	  reply.code,reply.cseq_method.c_str(),reply.callid.c_str(),reply.from_tag.c_str(),
	  reply.to_tag.c_str(),reply.cseq);
      //return;
    }
    else if(getOtherId() != reply.from_tag){// was: local_tag
      DBG("Dialog mismatch! (oi=%s;ft=%s)\n",
	  getOtherId().c_str(),reply.from_tag.c_str());
      return;
    }

    DBG("%u %s reply received from other leg\n", reply.code, reply.reason.c_str());
      
    switch(callee_status){
    case NoReply:
    case Ringing:
      if (reply.cseq == invite_req.cseq) {

	if (reply.code < 200) {

	  if ((!sip_relay_only) &&
	      (reply.code>=180 && reply.code<=183 && (!reply.body.empty()))) {
	    // save early media SDP
	    updateSessionDescription(reply.body);

	    if (sip_relay_early_media_sdp) {
	      if (reinviteCaller(reply)) {
		ERROR("re-INVITEing caller for early session failed - "
		      "stopping this and other leg\n");
		terminateOtherLeg();
		terminateLeg();
		break;
	      }
	    }

	  }

	  callee_status = Ringing;

	} else if(reply.code < 300){
	  
	  callee_status  = Connected;
	  DBG("setting callee status to connected\n");
	  if (!sip_relay_only) {
	    DBG("received 200 class reply to establishing INVITE: "
		"switching to SIP relay only mode, sending re-INVITE to caller\n");
	    sip_relay_only = true;
	    AmSipReply n_reply = reply;

	    if (n_reply.body.empty() && !established_body.empty()) {
	      DBG("callee FR without SDP, using provisional response's (18x) one\n");
	      n_reply.body = established_body;
	    }

	    if (reinviteCaller(n_reply)) {
	      ERROR("re-INVITEing caller failed - stopping this and other leg\n");
	      terminateOtherLeg();
	      terminateLeg();
	    }
	  }
	} else {
	  // 	DBG("received %i from other leg: other_id=%s; reply.local_tag=%s\n",
	  // 	    reply.code,other_id.c_str(),reply.local_tag.c_str());
	  
	  // TODO: terminated my own leg instead? (+ clear_other())
	  terminateOtherLeg();
	}

	processed = onOtherReply(reply);
      }
	
      break;
	
    default:
      DBG("reply from callee: %u %s\n",reply.code,reply.reason.c_str());
      break;
    }
  }
   
  if (!processed)
    AmB2BSession::onB2BEvent(ev);
}
void AmB2BSession::onOtherBye(const AmSipRequest& req)
{
  DBG("onOtherBye()\n");
  terminateLeg();
}
bool AmB2BSession::onOtherReply(const AmSipReply& reply)
{
  if(reply.code >= 300)
    terminateLeg();
  return false;
}