コード例 #1
0
void
SIPCall::hangup(int reason)
{
    // Stop all RTP streams
    stopAllMedia();

    if (not inv or not inv->dlg) {
        removeCall();
        throw VoipLinkException("No invite session for this call");
    }

    pjsip_route_hdr *route = inv->dlg->route_set.next;
    while (route and route != &inv->dlg->route_set) {
        char buf[1024];
        int printed = pjsip_hdr_print_on(route, buf, sizeof(buf));

        if (printed >= 0) {
            buf[printed] = '\0';
            RING_DBG("[call:%s] Route header %s", getCallId().c_str(), buf);
        }

        route = route->next;
    }

    const int status = reason ? reason :
                       inv->state <= PJSIP_INV_STATE_EARLY and inv->role != PJSIP_ROLE_UAC ?
                       PJSIP_SC_CALL_TSX_DOES_NOT_EXIST :
                       inv->state >= PJSIP_INV_STATE_DISCONNECTED ? PJSIP_SC_DECLINE : 0;

    // Notify the peer
    terminateSipSession(status);

    setState(Call::ConnectionState::DISCONNECTED, reason);
    removeCall();
}
コード例 #2
0
void
SIPCall::sendSIPInfo(const char *const body, const char *const subtype)
{
    if (not inv or not inv->dlg)
        throw VoipLinkException("Couldn't get invite dialog");

    pj_str_t methodName = CONST_PJ_STR("INFO");
    pjsip_method method;
    pjsip_method_init_np(&method, &methodName);

    /* Create request message. */
    pjsip_tx_data *tdata;

    if (pjsip_dlg_create_request(inv->dlg, &method, -1, &tdata) != PJ_SUCCESS) {
        RING_ERR("[call:%s] Could not create dialog", getCallId().c_str());
        return;
    }

    /* Create "application/<subtype>" message body. */
    pj_str_t content;
    pj_cstr(&content, body);
    const pj_str_t type = CONST_PJ_STR("application");
    pj_str_t pj_subtype;
    pj_cstr(&pj_subtype, subtype);
    tdata->msg->body = pjsip_msg_body_create(tdata->pool, &type, &pj_subtype, &content);

    if (tdata->msg->body == NULL)
        pjsip_tx_data_dec_ref(tdata);
    else
        pjsip_dlg_send_request(inv->dlg, tdata, getSIPVoIPLink()->getModId(), NULL);
}
コード例 #3
0
void
SIPCall::peerHungup()
{
    // Stop all RTP streams
    stopAllMedia();

    if (not inv)
        throw VoipLinkException("No invite session for this call");

    terminateSipSession(PJSIP_SC_NOT_FOUND);
    Call::peerHungup();
}
コード例 #4
0
void
SIPCall::sendTextMessage(const std::map<std::string, std::string>& messages,
                         const std::string& /* from */)
{
    if (not inv)
        throw VoipLinkException("No invite session for this call");

    //TODO: for now we ignore the "from" (the previous implementation for sending this info was
    //      buggy and verbose), another way to send the original message sender will be implemented
    //      in the future

    im::sendSipMessage(inv.get(), messages);
}
コード例 #5
0
ファイル: iaxvoiplink.cpp プロジェクト: dyfet/sflphone
void
IAXVoIPLink::peerHungup(const std::string& id)
{
    IAXCall* call = getIAXCall(id);

    if (call == NULL)
        throw VoipLinkException("Could not find call");

    Manager::instance().getMainBuffer()->unBindAll(call->getCallId());

    call->session = NULL;

    removeCall(id);
}
コード例 #6
0
ファイル: iaxvoiplink.cpp プロジェクト: dyfet/sflphone
void
IAXVoIPLink::sendRegister(Account *a)
{
    IAXAccount *account = dynamic_cast<IAXAccount*>(a);

    if (account->getHostname().empty())
        throw VoipLinkException("Account hostname is empty");

    if (account->getUsername().empty())
        throw VoipLinkException("Account username is empty");

    ost::MutexLock m(mutexIAX_);

    if (regSession_)
        iax_destroy(regSession_);

    regSession_ = iax_session_new();

    if (regSession_) {
        iax_register(regSession_, account->getHostname().data(), account->getUsername().data(), account->getPassword().data(), 120);
        nextRefreshStamp_ = time(NULL) + 10;
        account->setRegistrationState(Trying);
    }
}
コード例 #7
0
ファイル: iaxvoiplink.cpp プロジェクト: dyfet/sflphone
void
IAXVoIPLink::offhold(const std::string& id)
{
    IAXCall* call = getIAXCall(id);

    if (call == NULL)
        throw VoipLinkException("Call does not exist");

    Manager::instance().addStream(call->getCallId());

    mutexIAX_.enter();
    iax_unquelch(call->session);
    mutexIAX_.leave();
    Manager::instance().getAudioDriver()->startStream();
    call->setState(Call::ACTIVE);
}
コード例 #8
0
ファイル: iaxvoiplink.cpp プロジェクト: dyfet/sflphone
void
IAXVoIPLink::onhold(const std::string& id)
{
    IAXCall* call = getIAXCall(id);

    if (call == NULL)
        throw VoipLinkException("Call does not exist");

    Manager::instance().getMainBuffer()->unBindAll(call->getCallId());

    mutexIAX_.enter();
    iax_quelch_moh(call->session, true);
    mutexIAX_.leave();

    call->setState(Call::HOLD);
}
コード例 #9
0
void
SIPCall::transfer(const std::string& to)
{
    auto& account = getSIPAccount();

    stopRecording();

    std::string toUri;
    pj_str_t dst = { 0, 0 };

    toUri = account.getToUri(to);
    pj_cstr(&dst, toUri.c_str());
    RING_DBG("[call:%s] Transferring to %.*s", getCallId().c_str(), (int)dst.slen, dst.ptr);

    if (!transferCommon(&dst))
        throw VoipLinkException("Couldn't transfer");
}
コード例 #10
0
ファイル: iaxvoiplink.cpp プロジェクト: dyfet/sflphone
void
IAXVoIPLink::hangup(const std::string& id)
{
    IAXCall* call = getIAXCall(id);

    if (call == NULL)
        throw VoipLinkException("Could not find call");

    Manager::instance().getMainBuffer()->unBindAll(call->getCallId());

    mutexIAX_.enter();
    iax_hangup(call->session, (char*) "Dumped Call");
    mutexIAX_.leave();

    call->session = NULL;

    removeCall(id);
}
コード例 #11
0
bool
SIPCall::offhold()
{
    bool success = false;
    auto& account = getSIPAccount();

    try {
        if (account.isStunEnabled())
            success = internalOffHold([&] { updateSDPFromSTUN(); });
        else
            success = internalOffHold([] {});

    } catch (const SdpException &e) {
        RING_ERR("[call:%s] %s", getCallId().c_str(), e.what());
        throw VoipLinkException("SDP issue in offhold");
    }

    return success;
}
コード例 #12
0
void
SIPCall::answer()
{
    auto& account = getSIPAccount();

    if (not inv)
        throw VoipLinkException("No invite session for this call");

    if (!inv->neg) {
        RING_WARN("[call:%s] Negotiator is NULL, we've received an INVITE without an SDP",
                  getCallId().c_str());
        pjmedia_sdp_session *dummy = 0;
        getSIPVoIPLink()->createSDPOffer(inv.get(), &dummy);

        if (account.isStunEnabled())
            updateSDPFromSTUN();
    }

    pj_str_t contact(account.getContactHeader(transport_ ? transport_->get() : nullptr));
    setContactHeader(&contact);

    pjsip_tx_data *tdata;
    if (!inv->last_answer)
        throw std::runtime_error("Should only be called for initial answer");

    // answer with SDP if no SDP was given in initial invite (i.e. inv->neg is NULL)
    if (pjsip_inv_answer(inv.get(), PJSIP_SC_OK, NULL, !inv->neg ? sdp_->getLocalSdpSession() : NULL, &tdata) != PJ_SUCCESS)
        throw std::runtime_error("Could not init invite request answer (200 OK)");

    // contactStr must stay in scope as long as tdata
    if (contactHeader_.slen) {
        RING_DBG("[call:%s] Answering with contact header: %.*s",
                 getCallId().c_str(), (int)contactHeader_.slen, contactHeader_.ptr);
        sip_utils::addContactHeader(&contactHeader_, tdata);
    }

    if (pjsip_inv_send_msg(inv.get(), tdata) != PJ_SUCCESS) {
        inv.reset();
        throw std::runtime_error("Could not send invite request answer (200 OK)");
    }

    setState(CallState::ACTIVE, ConnectionState::CONNECTED);
}