diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp index e14a4587dc2e6a609f83cfe508692935a40492ec..b6fdce7c58be031ce1b334662e5c2bd4cae0f3ef 100644 --- a/src/sip/sipvoiplink.cpp +++ b/src/sip/sipvoiplink.cpp @@ -782,88 +782,98 @@ SIPVoIPLink::requestKeyframe(const std::string &callID) // Private functions /////////////////////////////////////////////////////////////////////////////// +static std::shared_ptr<SIPCall> +getCallFromInvite(pjsip_inv_session* inv) +{ + if (auto call_ptr = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id])) + return std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this()); + return nullptr; +} + static void invite_session_state_changed_cb(pjsip_inv_session *inv, pjsip_event *ev) { - if (!inv) + auto call = getCallFromInvite(inv); + if (not call) return; - auto call_ptr = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id]); - if (!call_ptr) { - RING_WARN("invite_session_state_changed_cb: can't find related call"); + if (ev->type != PJSIP_EVENT_TSX_STATE and ev->type != PJSIP_EVENT_TX_MSG) { + RING_WARN("[call:%s] INVITE@%p state changed to %d (%s): unwaited event type %d", + call->getCallId().c_str(), inv, inv->state, pjsip_inv_state_name(inv->state), + ev->type); return; } - auto call = std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this()); - if (ev and inv->state != PJSIP_INV_STATE_CONFIRMED) { + decltype(pjsip_transaction::status_code) status_code; + + if (ev->type != PJSIP_EVENT_TX_MSG) { const auto tsx = ev->body.tsx_state.tsx; - if (auto status_code = tsx ? tsx->status_code : 404) { - const pj_str_t* description = pjsip_get_status_text(status_code); - RING_DBG("SIP invite session state change: %d %.*s", status_code, description->slen, description->ptr); - } + status_code = tsx ? tsx->status_code : PJSIP_SC_NOT_FOUND; + const pj_str_t* description = pjsip_get_status_text(status_code); + + RING_DBG("[call:%s] INVITE@%p state changed to %d (%s): cause=%d, tsx@%p status %d (%.*s)", + call->getCallId().c_str(), inv, inv->state, pjsip_inv_state_name(inv->state), + inv->cause, tsx, status_code, description->slen, description->ptr); + } else { + status_code = 0; + RING_DBG("[call:%s] INVITE@%p state changed to %d (%s): cause=%d (TX_MSG)", + call->getCallId().c_str(), inv, inv->state, pjsip_inv_state_name(inv->state), + inv->cause); } - if (inv->state == PJSIP_INV_STATE_EARLY and ev and ev->body.tsx_state.tsx and - ev->body.tsx_state.tsx->role == PJSIP_ROLE_UAC) { - call->onPeerRinging(); - } else if (inv->state == PJSIP_INV_STATE_CONFIRMED and ev) { - // After we sent or received a ACK - The connection is established - call->onAnswered(); - } else if (inv->state == PJSIP_INV_STATE_DISCONNECTED) { - switch (inv->cause) { + switch (inv->state) { + case PJSIP_INV_STATE_EARLY: + if (status_code == PJSIP_SC_RINGING) + call->onPeerRinging(); + break; + + case PJSIP_INV_STATE_CONFIRMED: + // After we sent or received a ACK - The connection is established + call->onAnswered(); + break; + + case PJSIP_INV_STATE_DISCONNECTED: + switch (inv->cause) { + // When the peer manually refuse the call + case PJSIP_SC_DECLINE: + case PJSIP_SC_BUSY_EVERYWHERE: + case PJSIP_SC_BUSY_HERE: + if (inv->role != PJSIP_ROLE_UAC) + break; + // close call + // The call terminates normally - BYE / CANCEL + case PJSIP_SC_OK: + case PJSIP_SC_REQUEST_TERMINATED: + call->onClosed(); + break; - case PJSIP_SC_DECLINE: //When the peer manually refuse the call - if (inv->role != PJSIP_ROLE_UAC) + // Error/unhandled conditions + default: + call->onFailure(inv->cause); break; + } + break; - case PJSIP_SC_OK: - case PJSIP_SC_REQUEST_TERMINATED: - call->onClosed(); - break; - - case PJSIP_SC_NOT_FOUND: - case PJSIP_SC_REQUEST_TIMEOUT: - case PJSIP_SC_NOT_ACCEPTABLE_HERE: /* no compatible codecs */ - case PJSIP_SC_NOT_ACCEPTABLE_ANYWHERE: - case PJSIP_SC_UNSUPPORTED_MEDIA_TYPE: - case PJSIP_SC_UNAUTHORIZED: - case PJSIP_SC_FORBIDDEN: - case PJSIP_SC_REQUEST_PENDING: - case PJSIP_SC_ADDRESS_INCOMPLETE: - default: - RING_WARN("PJSIP_INV_STATE_DISCONNECTED: %d %d", - inv->cause, ev ? ev->type : -1); - call->onFailure(inv->cause); - break; - } + default: + break; } } static void sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *offer) { - if (!inv) - return; - - auto call_ptr = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id]); - if (!call_ptr) - return; - auto call = std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this()); - call->onReceiveOffer(offer); + if (auto call = getCallFromInvite(inv)) + call->onReceiveOffer(offer); } static void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) { - if (!inv or !p_offer) + auto call = getCallFromInvite(inv); + if (not call) return; - auto call_ptr = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id]); - if (!call_ptr) - return; - auto call = std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this()); - const auto& account = call->getSIPAccount(); auto family = pj_AF_INET(); // FIXME : for now, use the same address family as the SIP transport @@ -960,38 +970,29 @@ get_active_local_sdp(pjsip_inv_session *inv) static void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) { - if (!inv) + auto call = getCallFromInvite(inv); + if (not call) return; - auto call_ptr = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id]); - if (!call_ptr) { - RING_DBG("Call declined by peer, SDP negotiation stopped"); - return; - } - auto call = std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this()); + RING_DBG("[call:%s] INVITE@%p media update: status %d", + call->getCallId().c_str(), inv, status); if (status != PJ_SUCCESS) { const int reason = inv->state != PJSIP_INV_STATE_NULL and inv->state != PJSIP_INV_STATE_CONFIRMED ? PJSIP_SC_UNSUPPORTED_MEDIA_TYPE : 0; - RING_WARN("Could not negotiate offer"); + RING_WARN("[call:%s] SDP offer failed, reason %d", call->getCallId().c_str(), reason); call->hangup(reason); return; } - if (!inv->neg) { - RING_WARN("No negotiator for this session"); - return; - } - + // Fetch SDP data from request const auto localSDP = get_active_local_sdp(inv); const auto remoteSDP = get_active_remote_sdp(inv); - // Update our sdp manager + // Update our SDP manager auto& sdp = call->getSDP(); - - // Set active SDP sessions sdp.setActiveLocalSdpSession(localSDP); sdp.setActiveRemoteSdpSession(remoteSDP); @@ -1152,39 +1153,34 @@ onRequestMessage(pjsip_inv_session* inv, pjsip_rx_data* rdata, pjsip_msg* msg, S static void transaction_state_changed_cb(pjsip_inv_session* inv, pjsip_transaction* tsx, pjsip_event* event) { - //RING_DBG("inv=%p, tsx=%p, ev=%p", inv, tsx, event); - // We process here only incoming request message + auto call = getCallFromInvite(inv); + if (not call) + return; - if (tsx->role != PJSIP_ROLE_UAS or tsx->state != PJSIP_TSX_STATE_TRYING + // We process here only incoming request message + if (tsx->role != PJSIP_ROLE_UAS + or tsx->state != PJSIP_TSX_STATE_TRYING or event->body.tsx_state.type != PJSIP_EVENT_RX_MSG) { - RING_DBG("tsx_role=%d, tsx_state=%d, ev_type=%d, tsx_state_type=%d", + RING_DBG("[INVITE:%p] tsx_role=%d, tsx_state=%d, ev_type=%d, tsx_state_type=%d", inv, tsx->role, tsx->state, event->type, event->body.tsx_state.type); return; } const auto rdata = event->body.tsx_state.src.rdata; if (!rdata) { - RING_ERR("SIP RX request without rx data"); + RING_ERR("[INVITE:%p] SIP RX request without rx data", inv); return; } const auto msg = rdata->msg_info.msg; if (msg->type != PJSIP_REQUEST_MSG) { - RING_ERR("SIP RX request without msg"); + RING_ERR("[INVITE:%p] SIP RX request without msg", inv); return; } - // Try to obtain associated SIPCall - auto call_ptr = static_cast<SIPCall*>(inv->mod_data[mod_ua_.id]); - if (!call_ptr) { - RING_ERR("SIP RX request without call"); - return; - } - auto call = std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this()); - // Using method name to dispatch const std::string methodName {msg->line.req.method.name.ptr, (unsigned)msg->line.req.method.name.slen}; - RING_DBG("RX SIP method %d (%#s)", msg->line.req.method.id, methodName.c_str()); + RING_DBG("[INVITE:%p] RX SIP method %d (%#s)", inv, msg->line.req.method.id, methodName.c_str()); #ifdef DEBUG_SIP_REQUEST_MSG char msgbuf[1000]; @@ -1208,7 +1204,10 @@ int SIPVoIPLink::getModId() } void SIPVoIPLink::createSDPOffer(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) -{ sdp_create_offer_cb(inv, p_offer); } +{ + assert(inv and p_offer); + sdp_create_offer_cb(inv, p_offer); +} // Thread-safe DNS resolver callback mapping class SafeResolveCallbackMap {