Ejemplo n.º 1
0
void AmB2BSession::onB2BEvent(B2BEvent* ev)
{
  switch(ev->event_id){

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

      if(req_ev->forward){

	relaySip(req_ev->req);
      }
      else if( (req_ev->req.method == "BYE") ||
	       (req_ev->req.method == "CANCEL") ) {
		
	onOtherBye(req_ev->req);
      }
    }
    return;

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

      DBG("B2BSipReply: %i %s (fwd=%i)\n",reply_ev->reply.code,
	  reply_ev->reply.reason.c_str(),reply_ev->forward);
      DBG("B2BSipReply: content-type = %s\n",reply_ev->reply.content_type.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()) {
	  relaySip(t_req->second,reply_ev->reply);
		
	  if(reply_ev->reply.code >= 200){

	    if( (t_req->second.method == "INVITE") &&
		(reply_ev->reply.code == 487)){
	      
	      terminateLeg();
	    }
	    recvd_req.erase(t_req);
	  } 
	} else {
	  ERROR("Request with CSeq %u not found in recvd_req.\n",
	      reply_ev->reply.cseq);
	}
      }
    }
    return;

  case B2BTerminateLeg:
    terminateLeg();
    break;
  }

  //ERROR("unknown event caught\n");
}
Ejemplo n.º 2
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");
}