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); }
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; }
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"); }
void AmB2BCallerSession::onCancel(const AmSipRequest& req) { terminateOtherLeg(); terminateLeg(); }
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; }