drachtio / drachtio-server

A SIP call processing server that can be controlled via nodejs applications
https://drachtio.org
MIT License
246 stars 93 forks source link

Second INVITE for authentication not sent #386

Closed AndreHeber closed 1 hour ago

AndreHeber commented 3 hours ago

We authenticate during the INVITE process, which usually looks like that: INVITE -> 407 Proxy Authentication Required (with nonce) -> ACK INVITE (with nonce response) -> 200 OK -> ACK

But we experience that for a small amount of calls, the second INVITE is simply not sent and the process is stuck. I've added the logs: sbc-sip-1-drachtio-no-auth.log

The SipDialogController::processResponseOutsideDialog - retransmitted ACK for callid log line is unusual, that isn't logged for successful calls. So I searched for other occurences of that line and every time that line is logged, something is odd with the call.

The responsible code:

if (sip->sip_cseq->cs_method == sip_method_invite && m_timerDHandler.resendIfNeeded(orq)) {
    DR_LOG(log_info) << "SipDialogController::processResponseOutsideDialog - retransmitted ACK for callid: " << sip->sip_call_id->i_id  <<
        " for invite with orq: " << std::hex << (void *) orq;
    msg_destroy( msg ) ; 
    return 0;
}

And the resendIfNeeded function:

// call this when we received a response to check it if is a retransmitted response
bool TimerDHandler::resendIfNeeded(nta_outgoing_t* invite) {
    mapInvite2Ack::const_iterator it = m_mapInvite2Ack.find(invite);
    if (it != m_mapInvite2Ack.end()) {
        outgoing_retransmit(it->second) ;
        return true;
    }
    else if (m_mapCallIdAndCSeq2Invite.size() > 0) {
        string callIdAndCSeq = combineCallIdAndCSeq(invite);
        if (m_mapCallIdAndCSeq2Invite.find(callIdAndCSeq) != m_mapCallIdAndCSeq2Invite.end()) {
            DR_LOG(log_error) << "TimerDHandler::resendIfNeeded - cannot retransmit ACK because app has not yet provided it " << nta_outgoing_call_id(invite);
            return true;
        }
    }
    return false;
}

And

typedef std::unordered_map<nta_outgoing_t*, nta_outgoing_t*> mapInvite2Ack;
mapInvite2Ack                   m_mapInvite2Ack;

I suspect that there are cases, where the orq/invite is not erased from the m_mapInvite2Ack and the same memory address is used by a request for another call and then things go wrong.

AndreHeber commented 2 hours ago

image Maybe erasing the orq from the m_mapInvite2Ack in the SipDialogController::clearRIP function?

davehorton commented 1 hour ago

handling the 401/407 challenge is the responsibility of the client app, not the server