diff --git a/daemon/src/call.h b/daemon/src/call.h index 1d6f231a8f64bb8b59691b5609fefb621bffcc7a..b93b051c6517d68695ab7829168a791b9f513160 100644 --- a/daemon/src/call.h +++ b/daemon/src/call.h @@ -184,8 +184,6 @@ class Call : public Recordable { isIPToIP_ = IPToIP; } - virtual void answer() = 0; - /** * Set my IP [not protected] * @param ip The local IP address @@ -239,6 +237,11 @@ class Call : public Recordable { virtual VoIPLink* getVoIPLink() const = 0; + /** + * Answer the call + */ + virtual void answer() = 0; + /** * Hang up the call * @param reason diff --git a/daemon/src/iax/iaxcall.cpp b/daemon/src/iax/iaxcall.cpp index 0dc26e6cd130a27c93d67fa61ce4dc5a45f2edab..a8cd5ab140a7930ff7f0a349c3177c924a89ef43 100644 --- a/daemon/src/iax/iaxcall.cpp +++ b/daemon/src/iax/iaxcall.cpp @@ -124,15 +124,26 @@ int IAXCall::getAudioCodec() const } } -void IAXCall::answer() -{ - iax_answer(session); -} - VoIPLink* IAXCall::getVoIPLink() const { return link_; } +void +IAXCall::answer() +{ + Manager::instance().addStream(getCallId()); + + { + std::lock_guard<std::mutex> lock(IAXVoIPLink::mutexIAX); + iax_answer(session); + } + + setState(Call::ACTIVE); + setConnectionState(Call::CONNECTED); + + Manager::instance().getMainBuffer().flushAllBuffers(); +} + void IAXCall::hangup(int reason UNUSED) { diff --git a/daemon/src/iax/iaxcall.h b/daemon/src/iax/iaxcall.h index f8969f1a7961ac787d807f4f7f7a518e5f6efa7a..21921475c9fbd6c0442b5fee46211c29148e44ad 100644 --- a/daemon/src/iax/iaxcall.h +++ b/daemon/src/iax/iaxcall.h @@ -80,11 +80,11 @@ class IAXCall : public Call { VoIPLink* getVoIPLink() const; + void answer(); + void hangup(int reason); private: - void answer(); - NON_COPYABLE(IAXCall); IAXVoIPLink* link_; diff --git a/daemon/src/iax/iaxvoiplink.cpp b/daemon/src/iax/iaxvoiplink.cpp index ec3d3184bea794b06240e51e89397d32170efc21..c7d6fedaa99579b5dc9a7388aa6cec71b1e894f5 100644 --- a/daemon/src/iax/iaxvoiplink.cpp +++ b/daemon/src/iax/iaxvoiplink.cpp @@ -313,24 +313,6 @@ IAXVoIPLink::newOutgoingCall(const std::string& id, const std::string& toUrl, co return call; } - -void -IAXVoIPLink::answer(Call *call) -{ - Manager::instance().addStream(call->getCallId()); - - { - std::lock_guard<std::mutex> lock(mutexIAX); - call->answer(); - } - - call->setState(Call::ACTIVE); - call->setConnectionState(Call::CONNECTED); - - Manager::instance().getMainBuffer().flushAllBuffers(); -} - - void IAXVoIPLink::peerHungup(const std::string& id) { @@ -348,8 +330,6 @@ IAXVoIPLink::peerHungup(const std::string& id) removeIaxCall(id); } - - void IAXVoIPLink::onhold(const std::string& id) { diff --git a/daemon/src/iax/iaxvoiplink.h b/daemon/src/iax/iaxvoiplink.h index 533c01d2b910d98d270bea774c0152c1e0bd51c5..b65be4d9ef99775047a465ab4d4efe685513dee9 100644 --- a/daemon/src/iax/iaxvoiplink.h +++ b/daemon/src/iax/iaxvoiplink.h @@ -121,12 +121,6 @@ class IAXVoIPLink : public VoIPLink { */ virtual std::shared_ptr<Call> newOutgoingCall(const std::string& id, const std::string& toUrl, const std::string &account_id); - /** - * Answer a call - * @param c The call - */ - virtual void answer(Call *c); - /** * Peer Hungup a call * @param id The ID of the call diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index ff0a253c470be0367ddb1e0af575a0e7d3d8caaf..b8cfcb18ad9bd094dab82c235e0e7739d71e1aa9 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -418,7 +418,7 @@ bool ManagerImpl::answerCall(const std::string& call_id) } try { - call->getVoIPLink()->answer(call.get()); + call->answer(); } catch (const std::runtime_error &e) { ERROR("%s", e.what()); result = false; diff --git a/daemon/src/sip/sipcall.cpp b/daemon/src/sip/sipcall.cpp index 1a4d4d564efbd49141d30a5d365f808685d770da..81c38fb275b6504a43fb01a555bb163c6c2e35a2 100644 --- a/daemon/src/sip/sipcall.cpp +++ b/daemon/src/sip/sipcall.cpp @@ -51,6 +51,26 @@ getSettings() static const int INITIAL_SIZE = 16384; static const int INCREMENT_SIZE = INITIAL_SIZE; +static void +updateSDPFromSTUN(SIPCall &call, SIPAccount &account, const SipTransport &transport) +{ + std::vector<long> socketDescriptors(call.getAudioRtp().getSocketDescriptors()); + + try { + std::vector<pj_sockaddr> stunPorts(transport.getSTUNAddresses(account, socketDescriptors)); + + // FIXME: get video sockets + //stunPorts.resize(4); + + account.setPublishedAddress(stunPorts[0]); + // published IP MUST be updated first, since RTCP depends on it + call.getLocalSDP()->setPublishedIP(account.getPublishedAddress()); + call.getLocalSDP()->updatePorts(stunPorts); + } catch (const std::runtime_error &e) { + ERROR("%s", e.what()); + } +} + SIPCall::SIPCall(const std::string& id, Call::CallType type, pj_caching_pool *caching_pool, const std::string &account_id) : Call(id, type, account_id) @@ -77,29 +97,6 @@ void SIPCall::setContactHeader(pj_str_t *contact) pj_strcpy(&contactHeader_, contact); } -void SIPCall::answer() -{ - 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, PJSIP_SC_OK, NULL, !inv->neg ? local_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) { - DEBUG("Answering with contact header: %.*s", contactHeader_.slen, contactHeader_.ptr); - sip_utils::addContactHeader(&contactHeader_, tdata); - } - - if (pjsip_inv_send_msg(inv, tdata) != PJ_SUCCESS) - throw std::runtime_error("Could not send invite request answer (200 OK)"); - - setConnectionState(CONNECTED); - setState(ACTIVE); -} - std::map<std::string, std::string> SIPCall::createHistoryEntry() const { @@ -226,6 +223,49 @@ VoIPLink* SIPCall::getVoIPLink() const { return &SIPVoIPLink::instance(); } +void SIPCall::answer() +{ + SIPAccount *account = Manager::instance().getSipAccount(getAccountId()); + if (!account) { + ERROR("Could not find account %s", getAccountId().c_str()); + return; + } + + if (!inv->neg) { + SIPVoIPLink& siplink = SIPVoIPLink::instance(); + + WARN("Negotiator is NULL, we've received an INVITE without an SDP"); + pjmedia_sdp_session *dummy = 0; + siplink.createSDPOffer(inv, &dummy); + + if (account->isStunEnabled()) + updateSDPFromSTUN(*this, *account, *siplink.sipTransport); + } + + pj_str_t contact(account->getContactHeader()); + 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, PJSIP_SC_OK, NULL, !inv->neg ? local_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) { + DEBUG("Answering with contact header: %.*s", contactHeader_.slen, contactHeader_.ptr); + sip_utils::addContactHeader(&contactHeader_, tdata); + } + + if (pjsip_inv_send_msg(inv, tdata) != PJ_SUCCESS) + throw std::runtime_error("Could not send invite request answer (200 OK)"); + + setConnectionState(CONNECTED); + setState(ACTIVE); +} + void SIPCall::hangup(int reason) { diff --git a/daemon/src/sip/sipcall.h b/daemon/src/sip/sipcall.h index 558aa39985c9dc3e6e69283030ea1448ed1438e9..974ac10deb0b6bdf06cafded515a3150bc97aa0f 100644 --- a/daemon/src/sip/sipcall.h +++ b/daemon/src/sip/sipcall.h @@ -103,8 +103,6 @@ class SIPCall : public Call { return pool_; } - void answer(); - /** * The invite session to be reused in case of transfer */ @@ -117,6 +115,8 @@ class SIPCall : public Call { VoIPLink* getVoIPLink() const; + void answer(); + void hangup(int reason); private: diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 09814478831fd7e1e5742c7423ccf5fbe9f662a7..b91cdb02ae085ef9eae27685503dd2094a39e6e3 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -1020,34 +1020,6 @@ std::shared_ptr<Call> SIPVoIPLink::newRegisteredAccountCall(const std::string& i return call; } -void -SIPVoIPLink::answer(Call *call) -{ - if (!call) - return; - - SIPCall *sipCall = static_cast<SIPCall*>(call); - SIPAccount *account = Manager::instance().getSipAccount(sipCall->getAccountId()); - - if (!account) { - ERROR("Could not find account %s", sipCall->getAccountId().c_str()); - return; - } - - if (!sipCall->inv->neg) { - WARN("Negotiator is NULL, we've received an INVITE without an SDP"); - pjmedia_sdp_session *dummy = 0; - sdp_create_offer_cb(sipCall->inv, &dummy); - - if (account->isStunEnabled()) - updateSDPFromSTUN(*sipCall, *account, *SIPVoIPLink::instance().sipTransport); - } - - pj_str_t contact(account->getContactHeader()); - sipCall->setContactHeader(&contact); - sipCall->answer(); -} - static void stopRtpIfCurrent(const std::string &id, SIPCall &call) { @@ -2359,3 +2331,6 @@ void SIPVoIPLink::loadIP2IPSettings() ERROR("%s", e.what()); } } + +void SIPVoIPLink::createSDPOffer(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) +{ sdp_create_offer_cb(inv, p_offer); } diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index 97364130900f53c0356cee812e5ef5994b3a6f1e..f727245aae9c89d4d10b6b5b5102fbf392c659ca 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -159,12 +159,6 @@ class SIPVoIPLink : public VoIPLink { const std::string& toUrl, const std::string &account_id); - /** - * Answer the call - * @param c The call - */ - virtual void answer(Call *c); - /** * Hang up the call * @param id The call identifier @@ -283,6 +277,9 @@ class SIPVoIPLink : public VoIPLink { public: void loadIP2IPSettings(); + static void createSDPOffer(pjsip_inv_session *inv, + pjmedia_sdp_session **p_offer); + /** * Instance that maintain and manage transport (UDP, TLS) */ diff --git a/daemon/src/voiplink.h b/daemon/src/voiplink.h index acdb080a8b0fe8f446b66cb261a0d5af70a65217..1cd5e17133da9b94adfa03230a85c7934a4e97f9 100644 --- a/daemon/src/voiplink.h +++ b/daemon/src/voiplink.h @@ -93,12 +93,6 @@ class VoIPLink { */ virtual std::vector<std::shared_ptr<Call> > getCalls(const std::string &account_id) const = 0; - /** - * Answer the call - * @param c The call - */ - virtual void answer(Call *c) = 0; - /** * Peer Hung up a call * @param id The call identifier