diff --git a/bin/dbus/cx.ring.Ring.CallManager.xml b/bin/dbus/cx.ring.Ring.CallManager.xml index 426320592364a77ed10f4c9727ff2045706d19ec..a2e8b328df94c2a64463570604a2762ad8311652 100644 --- a/bin/dbus/cx.ring.Ring.CallManager.xml +++ b/bin/dbus/cx.ring.Ring.CallManager.xml @@ -25,30 +25,6 @@ <arg type="s" name="callId" direction="out"/> </method> - <method name="placeCallWithDetails" tp:name-for-bindings="placeCallWithDetails"> - <tp:added version="4.1.0"/> - <tp:docstring> - <p>This is a method in order to place a new call. This version allows to pass some call details. The call is registered with the daemon using this method.</p> - </tp:docstring> - <arg type="s" name="accountId" direction="in"> - <tp:docstring> - The ID of the account with which you want to make a call. If the call is to be placed without any account by means of a SIP URI (i.e. sip:num@server), the "IP2IP_PROFILE" is passed as the accountId. For more details on accounts see the configuration manager interface. - </tp:docstring> - </arg> - <arg type="s" name="to" direction="in"> - <tp:docstring> - If bound to a VoIP account, then the argument is the phone number. In case of calls involving "IP2IP_PROFILE", a complete SIP URI must be specified. - </tp:docstring> - </arg> - <annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="MapStringString"/> - <arg type="a{ss}" name="VolatileCallDetails" direction="in"> - <tp:docstring> - TBD. - </tp:docstring> - </arg> - <arg type="s" name="callId" direction="out"/> - </method> - <method name="placeCallWithMedia" tp:name-for-bindings="placeCallWithMedia"> <tp:added version="9.10.0"/> <tp:docstring> diff --git a/bin/dbus/dbuscallmanager.cpp b/bin/dbus/dbuscallmanager.cpp index 1c12c3b889af6ec1cf0f3edd5dfa1674042d72ae..9cff6a97c4324cf658b778cc437d42009a6c8f01 100644 --- a/bin/dbus/dbuscallmanager.cpp +++ b/bin/dbus/dbuscallmanager.cpp @@ -31,16 +31,6 @@ DBusCallManager::placeCall(const std::string& accountId, const std::string& to) { return DRing::placeCall(accountId, to); } - -auto -DBusCallManager::placeCallWithDetails(const std::string& accountId, - const std::string& to, - const std::map<std::string, std::string>& VolatileCallDetails) - -> decltype(DRing::placeCall(accountId, to, VolatileCallDetails)) -{ - return DRing::placeCall(accountId, to, VolatileCallDetails); -} - auto DBusCallManager::placeCallWithMedia(const std::string& accountId, const std::string& to, diff --git a/bin/dbus/dbuscallmanager.h b/bin/dbus/dbuscallmanager.h index dc976ad38ad482da58ae8789966a0b0deec64adf..e7d5203b35323a21970464607c10e22c41dde5d7 100644 --- a/bin/dbus/dbuscallmanager.h +++ b/bin/dbus/dbuscallmanager.h @@ -55,10 +55,6 @@ public: // Methods std::string placeCall(const std::string& accountId, const std::string& to); - std::string placeCallWithDetails(const std::string& accountId, - const std::string& to, - const std::map<std::string, std::string>& VolatileCallDetails); - std::string placeCallWithMedia(const std::string& accountId, const std::string& to, const std::vector<std::map<std::string, std::string>>& mediaList); diff --git a/bin/jni/callmanager.i b/bin/jni/callmanager.i index fdc6ea7b4c719b3e066ab5d138a91f86734d48ae..2c13cc7a657d29ab71f872000719e106fcf6aaba 100644 --- a/bin/jni/callmanager.i +++ b/bin/jni/callmanager.i @@ -66,7 +66,6 @@ public: namespace DRing { /* Call related methods */ -std::string placeCall(const std::string& accountId, const std::string& to, const std::map<std::string, std::string>& volatileCallDetails); std::string placeCallWithMedia(const std::string& accountId, const std::string& to, const std::vector<std::map<std::string, std::string>>& mediaList); diff --git a/src/account.h b/src/account.h index 5c923a96d53835500cfbf3d7fa6728886cced34c..93d07e9cbf215ecc3686418733d491f93ded095c 100644 --- a/src/account.h +++ b/src/account.h @@ -146,16 +146,6 @@ public: RegistrationState getRegistrationState() const { return registrationState_; } - /** - * Create a new outgoing call. - * - * @param toUrl The address to call - * @return std::shared_ptr<Call> A pointer on the created call - */ - virtual std::shared_ptr<Call> newOutgoingCall( - std::string_view toUrl, const std::map<std::string, std::string>& volatileCallDetails = {}) - = 0; - /** * Create a new outgoing call. * @@ -357,13 +347,6 @@ public: bool isEmptyOffersEnabled() const { return emptyOffersEnabled_; } void enableEmptyOffers(bool enable) { emptyOffersEnabled_ = enable; } - // Enable/disable multi-stream feature. - // Multi-stream feature changes the callflow of the re-invite process. All - // clients must support this feature before it can be enabled by default. - // These two internal APIs allow controlling the callflow accordingly. They - // should be removed once the multi-stream feature is fully supported. - bool isMultiStreamEnabled() const { return multiStreamEnabled_; } - void enableMultiStream(bool enable) { multiStreamEnabled_ = enable; } // Check if a Daemon version (typically peer's version) satisfies the // minimum required version. This check is typically used to disable a // feature if it's not backward compatible with the peer's version. diff --git a/src/call_factory.cpp b/src/call_factory.cpp index cc625c8b96bad8c577ec572a1d41390f17bb89fc..e55979a37accdecef4a9031f048ef4b001a8d008 100644 --- a/src/call_factory.cpp +++ b/src/call_factory.cpp @@ -39,24 +39,6 @@ CallFactory::getNewCallID() const return random_id; } -std::shared_ptr<SIPCall> -CallFactory::newSipCall(const std::shared_ptr<SIPAccountBase>& account, - Call::CallType type, - const std::map<std::string, std::string>& details) -{ - if (not allowNewCall_) { - JAMI_WARN("Creation of new calls is not allowed"); - return nullptr; - } - - std::lock_guard<std::recursive_mutex> lk(callMapsMutex_); - auto id = getNewCallID(); - auto call = std::make_shared<SIPCall>(account, id, type, details); - callMaps_[call->getLinkType()].emplace(id, call); - account->attach(call); - return call; -} - std::shared_ptr<SIPCall> CallFactory::newSipCall(const std::shared_ptr<SIPAccountBase>& account, Call::CallType type, diff --git a/src/call_factory.h b/src/call_factory.h index 4acfb15c3ed45d43fccf211043d8c20822539121..c6b48fb93bd12f077618fe0cf75450eb23ec4872 100644 --- a/src/call_factory.h +++ b/src/call_factory.h @@ -42,17 +42,6 @@ public: : rand_(rand) {} - /** - * Create and register a new SIPCall instance. - * @param account Account used to create this call - * @param type The call type (incoming/outgoing) - * @param details Call details - * @return A shared pointer to the created call - */ - std::shared_ptr<SIPCall> newSipCall(const std::shared_ptr<SIPAccountBase>& account, - Call::CallType type, - const std::map<std::string, std::string>& details = {}); - std::string getNewCallID() const; /** diff --git a/src/client/callmanager.cpp b/src/client/callmanager.cpp index ebc0d029c5ec39a23d5d7d830f27707d83d0d8b6..ecd6d9f7426e99c284f7457be53d3dae07bd1323 100644 --- a/src/client/callmanager.cpp +++ b/src/client/callmanager.cpp @@ -47,27 +47,9 @@ registerCallHandlers(const std::map<std::string, std::shared_ptr<CallbackWrapper std::string placeCall(const std::string& accountId, const std::string& to) { - // Check if a destination number is available - if (to.empty()) { - JAMI_DBG("No number entered - Call stopped"); - return {}; - } else { - return jami::Manager::instance().outgoingCall(accountId, to); - } -} - -std::string -placeCall(const std::string& accountId, - const std::string& to, - const std::map<std::string, std::string>& volatileCallDetails) -{ - // Check if a destination number is available - if (to.empty()) { - JAMI_DBG("No number entered - Call stopped"); - return {}; - } else { - return jami::Manager::instance().outgoingCall(accountId, to, {}, volatileCallDetails); - } + // TODO. Remove ASAP. + JAMI_WARN("This API is deprecated, use placeCallWithMedia() instead"); + return placeCallWithMedia(accountId, to, {}); } std::string diff --git a/src/jami/callmanager_interface.h b/src/jami/callmanager_interface.h index ff8738a192acf850175b83186b075ada1fa2fce2..f2a7ff3c38abc3a002270b1775233300c80bd8ac 100644 --- a/src/jami/callmanager_interface.h +++ b/src/jami/callmanager_interface.h @@ -40,9 +40,7 @@ namespace DRing { /* Call related methods */ DRING_PUBLIC std::string placeCall(const std::string& accountId, const std::string& to); -DRING_PUBLIC std::string placeCall(const std::string& accountId, - const std::string& to, - const std::map<std::string, std::string>& VolatileCallDetails); + DRING_PUBLIC std::string placeCallWithMedia( const std::string& accountId, const std::string& to, @@ -67,12 +65,6 @@ DRING_PUBLIC std::map<std::string, std::string> getCallDetails(const std::string DRING_PUBLIC std::vector<std::string> getCallList(const std::string& accountId); /* APIs that supports an arbitrary number of media */ -DRING_PUBLIC std::string placeCall(const std::string& accountId, - const std::string& to, - const std::vector<DRing::MediaMap>& mediaList); -DRING_PUBLIC bool accept(const std::string& accountId, - const std::string& callId, - const std::vector<DRing::MediaMap>& mediaList); DRING_PUBLIC bool acceptWithMedia(const std::string& accountId, const std::string& callId, const std::vector<DRing::MediaMap>& mediaList); diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index 8e9fe1da92966a9859049a821b183029865ae138..7f90c98c68d0b9d75f7ad1686296af1554d1d56a 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -414,29 +414,6 @@ JamiAccount::newIncomingCall(const std::string& from, return nullptr; } -std::shared_ptr<Call> -JamiAccount::newOutgoingCall(std::string_view toUrl, - const std::map<std::string, std::string>& volatileCallDetails) -{ - auto& manager = Manager::instance(); - auto call = manager.callFactory.newSipCall(shared(), - Call::CallType::OUTGOING, - volatileCallDetails); - if (not call) - return {}; - - if (call->isIceEnabled()) { - call->createIceMediaTransport(); - getIceOptions([=](auto&& opts) { - call->initIceMediaTransport(true, std::forward<IceTransportOptions>(opts)); - }); - } - - newOutgoingCallHelper(call, toUrl); - - return call; -} - std::shared_ptr<Call> JamiAccount::newOutgoingCall(std::string_view toUrl, const std::vector<DRing::MediaMap>& mediaList) { @@ -444,8 +421,18 @@ JamiAccount::newOutgoingCall(std::string_view toUrl, const std::vector<DRing::Me JAMI_DBG() << *this << "Calling peer " << suffix; auto& manager = Manager::instance(); + std::shared_ptr<SIPCall> call; - auto call = manager.callFactory.newSipCall(shared(), Call::CallType::OUTGOING, mediaList); + // SIP allows sending empty invites, this use case is not used with Jami accounts. + if (not mediaList.empty()) { + call = manager.callFactory.newSipCall(shared(), Call::CallType::OUTGOING, mediaList); + } else { + JAMI_WARN("Media list is empty, setting a default list"); + call = manager.callFactory.newSipCall(shared(), + Call::CallType::OUTGOING, + MediaAttribute::mediaAttributesToMediaMaps( + createDefaultMediaList(isVideoEnabled()))); + } if (not call) return {}; @@ -506,15 +493,7 @@ std::shared_ptr<SIPCall> JamiAccount::createSubCall(const std::shared_ptr<SIPCall>& mainCall) { auto mediaList = MediaAttribute::mediaAttributesToMediaMaps(mainCall->getMediaAttributeList()); - if (not mediaList.empty()) { - return Manager::instance().callFactory.newSipCall(shared(), - Call::CallType::OUTGOING, - mediaList); - } else { - return Manager::instance().callFactory.newSipCall(shared(), - Call::CallType::OUTGOING, - mainCall->getDetails()); - } + return Manager::instance().callFactory.newSipCall(shared(), Call::CallType::OUTGOING, mediaList); } void diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h index 02bf3972772552e1c5e117ed9aca6d9a6726e6c4..9396e94ff12a1338e4927220cd84036990118086 100644 --- a/src/jamidht/jamiaccount.h +++ b/src/jamidht/jamiaccount.h @@ -258,17 +258,6 @@ public: /* Returns true if the username and/or hostname match this account */ MatchRank matches(std::string_view username, std::string_view hostname) const override; - /** - * Create outgoing SIPCall. - * @param[in] toUrl The address to call - * @return std::shared_ptr<T> A shared pointer on the created call. - * The type of this instance is given in template argument. - * This type can be any base class of SIPCall class (included). - */ - std::shared_ptr<Call> newOutgoingCall( - std::string_view toUrl, - const std::map<std::string, std::string>& volatileCallDetails = {}) override; - /** * Create outgoing SIPCall. * @param[in] toUrl The address to call diff --git a/src/manager.cpp b/src/manager.cpp index 870336ca653a45dbe99ce7ff1d5fdbffc8a9cfc4..86138ba947666c57eda634e1b72b9fc57cd4aaaf 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -1000,29 +1000,6 @@ Manager::unregisterAccounts() /////////////////////////////////////////////////////////////////////////////// /* Main Thread */ -std::string -Manager::outgoingCall(const std::string& account_id, - const std::string& to, - std::shared_ptr<Conference>, - const std::map<std::string, std::string>& volatileCallDetails) -{ - JAMI_DBG() << "try outgoing call to '" << to << "'" - << " with account '" << account_id << "'"; - - try { - if (auto call = newOutgoingCall(trim(to), account_id, volatileCallDetails)) { - stopTone(); - - pimpl_->switchCall(call->getCallId()); - - return call->getCallId(); - } - } catch (const std::exception& e) { - JAMI_ERR("%s", e.what()); - } - return {}; -} - std::string Manager::outgoingCall(const std::string& account_id, const std::string& to, @@ -1499,7 +1476,7 @@ Manager::createConfFromParticipantList(const std::string& accountId, pimpl_->unsetCurrentCall(); // Create call - auto callId = outgoingCall(account, tostr, conf); + auto callId = outgoingCall(account, tostr, {}, conf); if (callId.empty()) continue; @@ -1846,32 +1823,23 @@ Manager::incomingCall(const std::string& accountId, Call& call) return; } - if (account->isMultiStreamEnabled()) { - // Report incoming call using "CallSignal::IncomingCallWithMedia" signal. - auto const& mediaList = MediaAttribute::mediaAttributesToMediaMaps( - call.getMediaAttributeList()); - - if (mediaList.empty()) { - JAMI_WARN("Incoming call %s has an empty media list", call.getCallId().c_str()); - } + // Report incoming call using "CallSignal::IncomingCallWithMedia" signal. + auto const& mediaList = MediaAttribute::mediaAttributesToMediaMaps(call.getMediaAttributeList()); - JAMI_INFO("Incoming call %s on account %s with %lu media", - call.getCallId().c_str(), - accountId.c_str(), - mediaList.size()); + if (mediaList.empty()) { + JAMI_WARN("Incoming call %s has an empty media list", call.getCallId().c_str()); + } - // Report the call using new API. - emitSignal<DRing::CallSignal::IncomingCallWithMedia>(accountId, - call.getCallId(), - call.getPeerDisplayName() + " " + from, - mediaList); - } else { - JAMI_INFO("Incoming call %s on account %s", call.getCallId().c_str(), accountId.c_str()); + JAMI_INFO("Incoming call %s on account %s with %lu media", + call.getCallId().c_str(), + accountId.c_str(), + mediaList.size()); - emitSignal<DRing::CallSignal::IncomingCall>(accountId, - call.getCallId(), - call.getPeerDisplayName() + " " + from); - } + // Report the call using new API. + emitSignal<DRing::CallSignal::IncomingCallWithMedia>(accountId, + call.getCallId(), + call.getPeerDisplayName() + " " + from, + mediaList); // Process the call. pimpl_->processIncomingCall(accountId, call); @@ -3023,20 +2991,6 @@ Manager::getAudioDriver() return pimpl_->audiodriver_; } -std::shared_ptr<Call> -Manager::newOutgoingCall(std::string_view toUrl, - const std::string& accountId, - const std::map<std::string, std::string>& volatileCallDetails) -{ - auto account = getAccount(accountId); - if (!account or !account->isUsable()) { - JAMI_WARN("Account is not usable for calling"); - return nullptr; - } - - return account->newOutgoingCall(toUrl, volatileCallDetails); -} - std::shared_ptr<Call> Manager::newOutgoingCall(std::string_view toUrl, const std::string& accountId, diff --git a/src/manager.h b/src/manager.h index b3cd17df1cab4954caf6825881af78ada4b9062b..2e7920d15b6f7847ebf5b7bc9d81493a50a70f21 100644 --- a/src/manager.h +++ b/src/manager.h @@ -142,19 +142,6 @@ public: return std::make_unique<AudioDeviceGuard>(*this, stream); } - /** - * Functions which occur with a user's action - * Place a new call - * @param accountId The account to make the call with - * @param to The recipient of the call - * @param conf_id The conference identifier if any - * @return id The call ID on success, empty string otherwise - */ - std::string outgoingCall(const std::string& accountId, - const std::string& to, - std::shared_ptr<Conference> conference = {}, - const std::map<std::string, std::string>& volatileCallDetails = {}); - /** * Place a new call * @param accountId the user's account ID @@ -166,7 +153,7 @@ public: */ std::string outgoingCall(const std::string& accountId, const std::string& callee, - const std::vector<DRing::MediaMap>& mediaList, + const std::vector<DRing::MediaMap>& mediaList = {}, std::shared_ptr<Conference> conference = {}); /** @@ -783,18 +770,6 @@ public: * Call periodically to poll for VoIP events */ void pollEvents(); - /** - * Create a new outgoing call - * @param toUrl The address to call - * @param accountId account to use - * @return Call* A shared pointer on a valid call. - * @note This function raises VoipLinkException() on errors. - */ - std::shared_ptr<Call> newOutgoingCall( - std::string_view toUrl, - const std::string& accountId, - const std::map<std::string, std::string>& volatileCallDetails = {}); - /** * Create a new outgoing call * @param toUrl Destination address diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp index 0c3193014890edda93da48e8b488ad9c9cb91d60..4a401efb022d8f5b855481a3168b7a6f4eec9378 100644 --- a/src/sip/sipaccount.cpp +++ b/src/sip/sipaccount.cpp @@ -177,10 +177,8 @@ SIPAccount::newIncomingCall(const std::string& from UNUSED, return call; } -template<> -std::shared_ptr<SIPCall> -SIPAccount::newOutgoingCall(std::string_view toUrl, - const std::map<std::string, std::string>& volatileCallDetails) +std::shared_ptr<Call> +SIPAccount::newOutgoingCall(std::string_view toUrl, const std::vector<DRing::MediaMap>& mediaList) { std::string to; int family; @@ -188,97 +186,19 @@ SIPAccount::newOutgoingCall(std::string_view toUrl, JAMI_DBG() << *this << "Calling SIP peer " << toUrl; auto& manager = Manager::instance(); - auto call = manager.callFactory.newSipCall(shared(), - Call::CallType::OUTGOING, - volatileCallDetails); - if (isIP2IP()) { - bool ipv6 = IpAddr::isIpv6(toUrl); - to = ipv6 ? IpAddr(toUrl).toString(false, true) : toUrl; - family = ipv6 ? pj_AF_INET6() : pj_AF_INET(); - - // TODO: resolve remote host using SIPVoIPLink::resolveSrvName - std::shared_ptr<SipTransport> t - = isTlsEnabled() - ? link_.sipTransportBroker->getTlsTransport(tlsListener_, - IpAddr(sip_utils::getHostFromUri(to))) - : transport_; - setTransport(t); - call->setSipTransport(t, getContactHeader()); - - JAMI_DBG("New %s IP to IP call to %s", ipv6 ? "IPv6" : "IPv4", to.c_str()); - } else { - to = toUrl; - auto contactHdr = getContactHeader(); - call->setSipTransport(transport_, contactHdr); - // FIXME : for now, use the same address family as the SIP transport - family = pjsip_transport_type_get_af(getTransportType()); - - JAMI_DBG("UserAgent: New registered account call to %.*s", (int) toUrl.size(), toUrl.data()); - } - - auto toUri = getToUri(to); - if (call->isIceEnabled()) { - call->createIceMediaTransport(); - call->initIceMediaTransport(true); - } - call->setPeerNumber(toUri); - call->setPeerUri(toUri); - - const auto localAddress = ip_utils::getInterfaceAddr(getLocalInterface(), family); - - IpAddr addrSdp; - if (getUPnPActive()) { - /* use UPnP addr, or published addr if its set */ - addrSdp = getPublishedSameasLocal() ? getUPnPIpAddress() : getPublishedIpAddress(); - } else { - addrSdp = isStunEnabled() or (not getPublishedSameasLocal()) ? getPublishedIpAddress() - : localAddress; - } + std::shared_ptr<SIPCall> call; - /* fallback on local address */ - if (not addrSdp) - addrSdp = localAddress; - - // Building the local SDP offer - auto& sdp = call->getSDP(); - - if (getPublishedSameasLocal()) - sdp.setPublishedIP(addrSdp); - else - sdp.setPublishedIP(getPublishedAddress()); - - auto mediaList = createDefaultMediaList(videoEnabled_ and not call->isAudioOnly()); - const bool created = sdp.createOffer(mediaList); - - if (created) { - std::weak_ptr<SIPCall> weak_call = call; - manager.scheduler().run([this, weak_call] { - if (auto call = weak_call.lock()) { - if (not SIPStartCall(call)) { - JAMI_ERR("Could not send outgoing INVITE request for new call"); - call->onFailure(); - } - } - return false; - }); + // SIP allows sending empty invites. + if (not mediaList.empty() or isEmptyOffersEnabled()) { + call = manager.callFactory.newSipCall(shared(), Call::CallType::OUTGOING, mediaList); } else { - throw VoipLinkException("Could not send outgoing INVITE request for new call"); + JAMI_WARN("Media list is empty, setting a default list"); + call = manager.callFactory.newSipCall(shared(), + Call::CallType::OUTGOING, + MediaAttribute::mediaAttributesToMediaMaps( + createDefaultMediaList(isVideoEnabled()))); } - return call; -} - -std::shared_ptr<Call> -SIPAccount::newOutgoingCall(std::string_view toUrl, const std::vector<DRing::MediaMap>& mediaList) -{ - std::string to; - int family; - - JAMI_DBG() << *this << "Calling SIP peer " << toUrl; - - auto& manager = Manager::instance(); - - auto call = manager.callFactory.newSipCall(shared(), Call::CallType::OUTGOING, mediaList); if (not call) throw std::runtime_error("Failed to create the call"); @@ -308,7 +228,7 @@ SIPAccount::newOutgoingCall(std::string_view toUrl, const std::vector<DRing::Med auto toUri = getToUri(to); - // Do not init ICE yet if the the media list is empty. This may occur + // Do not init ICE yet if the media list is empty. This may occur // if we are sending an invite with no SDP offer. if (call->isIceEnabled() and not mediaList.empty()) { call->createIceMediaTransport(); @@ -433,13 +353,6 @@ SIPAccount::getTransportSelector() return SIPVoIPLink::getTransportSelector(transport_->get()); } -std::shared_ptr<Call> -SIPAccount::newOutgoingCall(std::string_view toUrl, - const std::map<std::string, std::string>& volatileCallDetails) -{ - return newOutgoingCall<SIPCall>(toUrl, volatileCallDetails); -} - bool SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call) { @@ -1527,7 +1440,7 @@ SIPAccount::getToUri(const std::string& username) const scheme = "sip:"; // Check if scheme is already specified - if (username.find("sip") == 0) + if (username.find("sip") != std::string::npos) scheme = ""; // Check if hostname is already specified @@ -1537,7 +1450,11 @@ SIPAccount::getToUri(const std::string& username) const if (not hostname.empty() and IpAddr::isIpv6(hostname)) hostname = IpAddr(hostname).toString(false, true); - return "<" + scheme + username + (hostname.empty() ? "" : "@") + hostname + transport + ">"; + auto ltSymbol = username.find('<') == std::string::npos ? "<" : ""; + auto gtSymbol = username.find('>') == std::string::npos ? ">" : ""; + + return ltSymbol + scheme + username + (hostname.empty() ? "" : "@") + hostname + transport + + gtSymbol; } std::string diff --git a/src/sip/sipaccount.h b/src/sip/sipaccount.h index dcb93f0c98e93000b7c50e9630d42a98bb3434cb..05f76ac3c46dbd3c93d7975311aadc33399cdec5 100644 --- a/src/sip/sipaccount.h +++ b/src/sip/sipaccount.h @@ -419,31 +419,6 @@ public: */ void supportPresence(int function, bool enable); - /** - * Implementation of Account::newOutgoingCall() - * Note: keep declaration before newOutgoingCall template. - */ - std::shared_ptr<Call> newOutgoingCall( - std::string_view toUrl, - const std::map<std::string, std::string>& volatileCallDetails = {}) override; - - /** - * Create outgoing SIPCall. - * @param[in] toUrl The address to call - * @return std::shared_ptr<T> A shared pointer on the created call. - * The type of this instance is given in template argument. - * This type can be any base class of SIPCall class (included). - */ -#ifndef _MSC_VER - template<class T = SIPCall> - std::shared_ptr<enable_if_base_of<T, SIPCall>> newOutgoingCall( - std::string_view toUrl, const std::map<std::string, std::string>& volatileCallDetails = {}); -#else - template<class T> - std::shared_ptr<T> newOutgoingCall( - std::string_view toUrl, const std::map<std::string, std::string>& volatileCallDetails = {}); -#endif - /** * Create outgoing SIPCall. * @param[in] toUrl the address to call diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp index 498561e7e50d3f1176215f6153b6b2c2a39c65c5..a322c3bfbbff51911d288ab525230ff750dc9670 100644 --- a/src/sip/sipaccountbase.cpp +++ b/src/sip/sipaccountbase.cpp @@ -80,15 +80,15 @@ SIPAccountBase::CreateClientDialogAndInvite(const pj_str_t* from, pjsip_inv_session** inv) { JAMI_DBG("Creating SIP dialog: \n" - "from: %s\n" - "contact: %s\n" - "to: %s\n", + "From: %s\n" + "Contact: %s\n" + "To: %s\n", from->ptr, contact->ptr, to->ptr); if (target) { - JAMI_DBG("target: %s", target->ptr); + JAMI_DBG("Target: %s", target->ptr); } else { JAMI_DBG("No target provided, using 'to' as target"); } diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp index 9179e3da9817ede92c791088a1ee26701b0b7bb2..cd670fe2ffd8edcf3c447fe056355aefecf75a42 100644 --- a/src/sip/sipcall.cpp +++ b/src/sip/sipcall.cpp @@ -90,40 +90,6 @@ static const std::vector<unsigned> MULTISTREAM_REQUIRED_VERSION constexpr auto DUMMY_VIDEO_STR = "dummy video session"; -SIPCall::SIPCall(const std::shared_ptr<SIPAccountBase>& account, - const std::string& callId, - Call::CallType type, - const std::map<std::string, std::string>& details) - : Call(account, callId, type, details) - , sdp_(new Sdp(callId)) - , enableIce_(account->isIceForMediaEnabled()) - , srtpEnabled_(account->isSrtpEnabled()) -{ - if (account->getUPnPActive()) - upnp_.reset(new upnp::Controller()); - - setCallMediaLocal(); - - // Set the media caps. - sdp_->setLocalMediaCapabilities(MediaType::MEDIA_AUDIO, - account->getActiveAccountCodecInfoList(MEDIA_AUDIO)); -#ifdef ENABLE_VIDEO - sdp_->setLocalMediaCapabilities(MediaType::MEDIA_VIDEO, - account->getActiveAccountCodecInfoList(MEDIA_VIDEO)); -#endif - auto mediaAttrList = getSIPAccount()->createDefaultMediaList(getSIPAccount()->isVideoEnabled() - and not isAudioOnly(), - getState() == CallState::HOLD); - JAMI_DBG("[call:%s] Create a new [%s] SIP call with %lu media", - getCallId().c_str(), - type == Call::CallType::INCOMING - ? "INCOMING" - : (type == Call::CallType::OUTGOING ? "OUTGOING" : "MISSED"), - mediaAttrList.size()); - - initMediaStreams(mediaAttrList); -} - SIPCall::SIPCall(const std::shared_ptr<SIPAccountBase>& account, const std::string& callId, Call::CallType type, @@ -2548,11 +2514,11 @@ SIPCall::handleMediaChangeRequest(const std::vector<DRing::MediaMap>& remoteMedi return; } - // If multi-stream is supported and the offered media differ from - // the current media, the request is reported to the client to be - // processed. Otherwise, we answer with the current local media. + // If the offered media differ from the current local media, the + // request is reported to the client to be processed. Otherwise, + // it will be processed using the current local media. - if (account->isMultiStreamEnabled() and checkMediaChangeRequest(remoteMediaList)) { + if (checkMediaChangeRequest(remoteMediaList)) { // Report the media change request. emitSignal<DRing::CallSignal::MediaChangeRequested>(getAccountId(), getCallId(), @@ -2611,76 +2577,9 @@ SIPCall::onReceiveReinvite(const pjmedia_sdp_session* offer, pjsip_rx_data* rdat } else { handleMediaChangeRequest(remoteMediaList); } - return res; } -int -SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer, const pjsip_rx_data* rdata) -{ - if (!sdp_) - return !PJ_SUCCESS; - sdp_->clearIce(); - auto acc = getSIPAccount(); - if (!acc) { - JAMI_ERR("No account detected"); - return !PJ_SUCCESS; - } - - JAMI_DBG("[call:%s] Received a new offer (re-invite)", getCallId().c_str()); - - sdp_->setReceivedOffer(offer); - - // Use current media list. - sdp_->processIncomingOffer(getMediaAttributeList()); - - if (isIceEnabled() and offer != nullptr) { - setupIceResponse(); - } - - sdp_->startNegotiation(); - - pjsip_tx_data* tdata = nullptr; - - if (pjsip_inv_initial_answer(inviteSession_.get(), - const_cast<pjsip_rx_data*>(rdata), - PJSIP_SC_OK, - NULL, - NULL, - &tdata) - != PJ_SUCCESS) { - JAMI_ERR("[call:%s] Could not create initial answer OK", getCallId().c_str()); - return !PJ_SUCCESS; - } - - // Add user-agent header - sip_utils::addUserAgentHeader(getSIPAccount()->getUserAgentName(), tdata); - - if (pjsip_inv_answer(inviteSession_.get(), PJSIP_SC_OK, NULL, sdp_->getLocalSdpSession(), &tdata) - != PJ_SUCCESS) { - JAMI_ERR("Could not create answer OK"); - return !PJ_SUCCESS; - } - - if (contactHeader_.empty()) { - JAMI_ERR("[call:%s] Contact header is empty!", getCallId().c_str()); - return !PJ_SUCCESS; - } - - sip_utils::addContactHeader(contactHeader_, tdata); - - if (pjsip_inv_send_msg(inviteSession_.get(), tdata) != PJ_SUCCESS) { - JAMI_ERR("[call:%s] Could not send msg OK", getCallId().c_str()); - return !PJ_SUCCESS; - } - - if (upnp_) { - openPortsUPnP(); - } - - return PJ_SUCCESS; -} - void SIPCall::onReceiveOfferIn200OK(const pjmedia_sdp_session* offer) { diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h index d89f4e03b278c6005872d54511b79acc857cea67..11243c0f77309cf24ef39cc0bae926e7c7bcdf82 100644 --- a/src/sip/sipcall.h +++ b/src/sip/sipcall.h @@ -95,17 +95,6 @@ public: */ ~SIPCall(); - /** - * Constructor - * @param id The call identifier - * @param type The type of the call. Could be Incoming or Outgoing - * @param details Extra infos - */ - SIPCall(const std::shared_ptr<SIPAccountBase>& account, - const std::string& id, - Call::CallType type, - const std::map<std::string, std::string>& details = {}); - /** * Constructor * @param id The call identifier @@ -215,12 +204,6 @@ public: * Peer closed the connection */ void onClosed(); - /** - * Report a new offer from peer on a existing invite session - * (aka re-invite) - */ - [[deprecated("Replaced by onReceiveReinvite")]] int onReceiveOffer( - const pjmedia_sdp_session* offer, const pjsip_rx_data* rdata); pj_status_t onReceiveReinvite(const pjmedia_sdp_session* offer, pjsip_rx_data* rdata); void onReceiveOfferIn200OK(const pjmedia_sdp_session* offer); diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp index 98c226b2ad5380d408990794f955c8780a4351ee..eea0c2468ae0f33bc154063c5768961337e0dc62 100644 --- a/src/sip/sipvoiplink.cpp +++ b/src/sip/sipvoiplink.cpp @@ -1001,11 +1001,7 @@ reinvite_received_cb(pjsip_inv_session* inv, const pjmedia_sdp_session* offer, p return !PJ_SUCCESS; if (auto call = getCallFromInvite(inv)) { if (auto const& account = call->getAccount().lock()) { - if (account->isMultiStreamEnabled()) { - return call->onReceiveReinvite(offer, rdata); - } else { - return call->onReceiveOffer(offer, rdata); - } + return call->onReceiveReinvite(offer, rdata); } } @@ -1248,7 +1244,10 @@ transferCall(SIPCall& call, const std::string& refer_to) const auto& callId = call.getCallId(); JAMI_WARN("[call:%s] Trying to transfer to %s", callId.c_str(), refer_to.c_str()); try { - Manager::instance().newOutgoingCall(refer_to, call.getAccountId()); + Manager::instance().newOutgoingCall(refer_to, + call.getAccountId(), + MediaAttribute::mediaAttributesToMediaMaps( + call.getMediaAttributeList())); Manager::instance().hangupCall(call.getAccountId(), callId); } catch (const std::exception& e) { JAMI_ERR("[call:%s] SIP transfer failed: %s", callId.c_str(), e.what()); diff --git a/test/agent/src/bindings/call.h b/test/agent/src/bindings/call.h index d62f4c921b8debb3ec358ece45478ea8ce34dee2..df318c033d10c2867635fdf467c4e4add6b2ab46 100644 --- a/test/agent/src/bindings/call.h +++ b/test/agent/src/bindings/call.h @@ -28,22 +28,9 @@ #include "utils.h" static SCM -place_call_binding(SCM accountID_str, SCM contact_str, SCM call_details_alist_optional) -{ - LOG_BINDING(); - - if (SCM_UNBNDP(call_details_alist_optional)) { - return to_guile(DRing::placeCall(from_guile(accountID_str), - from_guile(contact_str))); - } - - return to_guile(DRing::placeCall(from_guile(accountID_str), - from_guile(contact_str), - static_cast<std::map<std::string, std::string>>(from_guile(call_details_alist_optional)))); -} - -static SCM -place_call_with_media_binding(SCM accountID_str, SCM contact_str, SCM call_media_vector_alist_optional) +place_call_with_media_binding(SCM accountID_str, + SCM contact_str, + SCM call_media_vector_alist_optional) { LOG_BINDING(); @@ -61,8 +48,7 @@ hang_up_binding(SCM accountID_str, SCM callID_str) { LOG_BINDING(); - return to_guile(DRing::hangUp(from_guile(accountID_str), - from_guile(callID_str))); + return to_guile(DRing::hangUp(from_guile(accountID_str), from_guile(callID_str))); } static SCM @@ -71,8 +57,7 @@ accept_binding(SCM accountID_str, SCM callID_str, SCM call_media_vector_alist_op LOG_BINDING(); if (SCM_UNBNDP(call_media_vector_alist_optional)) { - return to_guile(DRing::accept(from_guile(accountID_str), - from_guile(callID_str))); + return to_guile(DRing::accept(from_guile(accountID_str), from_guile(callID_str))); } return to_guile(DRing::acceptWithMedia(from_guile(accountID_str), @@ -85,8 +70,7 @@ refuse_binding(SCM accountID_str, SCM callID_str) { LOG_BINDING(); - return to_guile(DRing::refuse(from_guile(accountID_str), - from_guile(callID_str))); + return to_guile(DRing::refuse(from_guile(accountID_str), from_guile(callID_str))); } static SCM @@ -94,8 +78,7 @@ hold_binding(SCM accountID_str, SCM callID_str) { LOG_BINDING(); - return to_guile(DRing::hold(from_guile(accountID_str), - from_guile(callID_str))); + return to_guile(DRing::hold(from_guile(accountID_str), from_guile(callID_str))); } static SCM @@ -103,14 +86,12 @@ unhold_binding(SCM accountID_str, SCM callID_str) { LOG_BINDING(); - return to_guile(DRing::unhold(from_guile(accountID_str), - from_guile(callID_str))); + return to_guile(DRing::unhold(from_guile(accountID_str), from_guile(callID_str))); } static void -install_call_primitives(void *) +install_call_primitives(void*) { - define_primitive("place-call", 2, 1, 0, (void*) place_call_binding); define_primitive("place-call/media", 2, 1, 0, (void*) place_call_with_media_binding); define_primitive("hang-up", 2, 0, 0, (void*) hang_up_binding); define_primitive("accept", 2, 1, 0, (void*) accept_binding); diff --git a/test/sip/test_SIP.cpp b/test/sip/test_SIP.cpp index 66203a1da72e4960074090c070d52609ff86d8a9..23fe3f58affddde06fac4ab46a4f53618f79431a 100644 --- a/test/sip/test_SIP.cpp +++ b/test/sip/test_SIP.cpp @@ -144,7 +144,7 @@ test_SIP::testSimpleOutgoingIpCall() CPPUNIT_ASSERT(!Manager::instance().hasCurrentCall()); // start a new call sending INVITE message to sipp instance - testcallid = Manager::instance().outgoingCall(testaccount, testcallnumber); + testcallid = DRing::placeCallWithMedia(testaccount, testcallnumber, {}); // wait for receiving 180 and 200 message from peer std::this_thread::sleep_for(std::chrono::seconds(1)); // should be enough @@ -256,7 +256,7 @@ test_SIP::testMultipleOutgoingIpCall() // start a user agent server waiting for a call sippThread("sipp -sn uas -i 127.0.0.1 -p 5061 -m " + std::to_string(numberOfCall) + " -bg"); - callID[i] = Manager::instance().outgoingCall(testaccount, callNumber); + callID[i] = DRing::placeCallWithMedia(testaccount, callNumber, {}); auto newCall = Manager::instance().getCallFromCallID(callID[i]); CPPUNIT_ASSERT(newCall); @@ -302,7 +302,7 @@ test_SIP::testHoldIpCall() auto callThread = sippThread("sipp -sf sippxml/test_3.xml -i 127.0.0.1 -p 5062 -m 1 -bg"); - auto testCallId = Manager::instance().outgoingCall(testAccount, testCallNumber); + auto testCallId = DRing::placeCallWithMedia(testAccount, testCallNumber, {}); auto call = Manager::instance().getCallFromCallID(testCallId); std::this_thread::sleep_for(std::chrono::seconds(2)); diff --git a/test/unitTest/call/call.cpp b/test/unitTest/call/call.cpp index b8311412e537174bb5f73d51bce95fc91bc41e43..79240fdc8e446d0ea88388cb8d8763fc80f16ea7 100644 --- a/test/unitTest/call/call.cpp +++ b/test/unitTest/call/call.cpp @@ -128,13 +128,13 @@ CallTest::testCall() DRing::registerSignalHandlers(confHandlers); JAMI_INFO("Start call between alice and Bob"); - auto call = aliceAccount->newOutgoingCall(bobUri); + auto call = DRing::placeCallWithMedia(aliceId, bobUri, {}); CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return callReceived.load(); })); JAMI_INFO("Stop call between alice and Bob"); callStopped = 0; - Manager::instance().hangupCall(aliceId, call->getCallId()); + Manager::instance().hangupCall(aliceId, call); CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return callStopped == 2; })); } @@ -186,12 +186,12 @@ CallTest::testCachedCall() cv.wait_for(lk, std::chrono::seconds(30), [&] { return successfullyConnected.load(); })); JAMI_INFO("Start call between alice and Bob"); - auto call = aliceAccount->newOutgoingCall(bobUri); + auto call = DRing::placeCallWithMedia(aliceId, bobUri, {}); CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return callReceived.load(); })); callStopped = 0; JAMI_INFO("Stop call between alice and Bob"); - Manager::instance().hangupCall(aliceId, call->getCallId()); + Manager::instance().hangupCall(aliceId, call); CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return callStopped == 2; })); } @@ -221,7 +221,7 @@ CallTest::testStopSearching() DRing::registerSignalHandlers(confHandlers); JAMI_INFO("Start call between alice and Bob"); - auto call = aliceAccount->newOutgoingCall(bobUri); + auto call = DRing::placeCallWithMedia(aliceId, bobUri, {}); // Bob not there, so we should get a SEARCHING STATUS JAMI_INFO("Wait OVER state"); @@ -282,7 +282,7 @@ CallTest::testDeclineMultiDevice() DRing::registerSignalHandlers(confHandlers); JAMI_INFO("Start call between alice and Bob"); - auto call = aliceAccount->newOutgoingCall(bobUri); + auto call = DRing::placeCallWithMedia(aliceId, bobUri, {}); CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return callReceived == 2 && !callIdBob.empty(); diff --git a/test/unitTest/call/conference.cpp b/test/unitTest/call/conference.cpp index b2ffe302fff62e9ecf9598cbf66fa21e56fc0cd6..c3e904641c65ec0d8cabe48101a60aaff705a3c6 100644 --- a/test/unitTest/call/conference.cpp +++ b/test/unitTest/call/conference.cpp @@ -165,8 +165,11 @@ ConferenceTest::registerSignalHandlers() } cv.notify_one(); })); - confHandlers.insert(DRing::exportable_callback<DRing::CallSignal::StateChange>( - [=](const std::string& accountId, const std::string& callId, const std::string& state, signed) { + confHandlers.insert( + DRing::exportable_callback<DRing::CallSignal::StateChange>([=](const std::string& accountId, + const std::string& callId, + const std::string& state, + signed) { if (accountId == aliceId) { auto details = DRing::getCallDetails(aliceId, callId); if (details["PEER_NUMBER"].find(bobUri) != std::string::npos) @@ -231,7 +234,7 @@ ConferenceTest::startConference() auto carlaUri = carlaAccount->getUsername(); JAMI_INFO("Start call between Alice and Bob"); - auto call1 = aliceAccount->newOutgoingCall(bobUri); + auto call1 = DRing::placeCallWithMedia(aliceId, bobUri, {}); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return !bobCall.callId.empty(); })); Manager::instance().answerCall(bobId, bobCall.callId); @@ -239,18 +242,20 @@ ConferenceTest::startConference() cv.wait_for(lk, std::chrono::seconds(20), [&] { return bobCall.hostState == "CURRENT"; })); JAMI_INFO("Start call between Alice and Carla"); - auto call2 = aliceAccount->newOutgoingCall(carlaUri); + auto call2 = DRing::placeCallWithMedia(aliceId, carlaUri, {}); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return !carlaCall.callId.empty(); })); Manager::instance().answerCall(carlaId, carlaCall.callId); - CPPUNIT_ASSERT( - cv.wait_for(lk, std::chrono::seconds(20), [&] { return carlaCall.hostState == "CURRENT"; })); + CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(20), [&] { + return carlaCall.hostState == "CURRENT"; + })); JAMI_INFO("Start conference"); confChanged = false; - Manager::instance().joinParticipant(aliceId, call1->getCallId(), aliceId, call2->getCallId()); + Manager::instance().joinParticipant(aliceId, call1, aliceId, call2); // ConfChanged is the signal emitted when the 2 calls will be added to the conference - CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(20), [&] { return !confId.empty() && confChanged; })); + CPPUNIT_ASSERT( + cv.wait_for(lk, std::chrono::seconds(20), [&] { return !confId.empty() && confChanged; })); } void @@ -318,29 +323,31 @@ ConferenceTest::testAudioVideoMutedStates() auto carlaUri = carlaAccount->getUsername(); JAMI_INFO("Start call between Alice and Bob"); - auto call1 = aliceAccount->newOutgoingCall(bobUri); + auto call1Id = DRing::placeCallWithMedia(aliceId, bobUri, {}); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return !bobCall.callId.empty(); })); Manager::instance().answerCall(bobId, bobCall.callId); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return bobCall.hostState == "CURRENT"; })); - + auto call1 = aliceAccount->getCall(call1Id); call1->muteMedia(DRing::Media::MediaAttributeValue::AUDIO, true); call1->muteMedia(DRing::Media::MediaAttributeValue::VIDEO, true); JAMI_INFO("Start call between Alice and Carla"); - auto call2 = aliceAccount->newOutgoingCall(carlaUri); + auto call2Id = DRing::placeCallWithMedia(aliceId, carlaUri, {}); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return !carlaCall.callId.empty(); })); Manager::instance().answerCall(carlaId, carlaCall.callId); - CPPUNIT_ASSERT( - cv.wait_for(lk, std::chrono::seconds(20), [&] { return carlaCall.hostState == "CURRENT"; })); + CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(20), [&] { + return carlaCall.hostState == "CURRENT"; + })); + auto call2 = aliceAccount->getCall(call2Id); call2->muteMedia(DRing::Media::MediaAttributeValue::AUDIO, true); call2->muteMedia(DRing::Media::MediaAttributeValue::VIDEO, true); JAMI_INFO("Start conference"); - Manager::instance().joinParticipant(aliceId, call1->getCallId(), aliceId, call2->getCallId()); + Manager::instance().joinParticipant(aliceId, call1Id, aliceId, call2Id); CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(20), [&] { return !confId.empty(); })); auto conf = aliceAccount->getConference(confId); @@ -401,13 +408,13 @@ ConferenceTest::testMuteStatusAfterRemove() startConference(); JAMI_INFO("Start call between Alice and Davi"); - auto call1 = aliceAccount->newOutgoingCall(daviUri); + auto call1 = DRing::placeCallWithMedia(aliceId, daviUri, {}); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); })); Manager::instance().answerCall(daviId, daviCall.callId); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.hostState == "CURRENT"; })); - Manager::instance().addParticipant(aliceId, call1->getCallId(), aliceId, confId); + Manager::instance().addParticipant(aliceId, call1, aliceId, confId); DRing::muteParticipant(aliceId, confId, daviUri, true); CPPUNIT_ASSERT( @@ -418,13 +425,13 @@ ConferenceTest::testMuteStatusAfterRemove() cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.state == "OVER"; })); daviCall.reset(); - auto call2 = aliceAccount->newOutgoingCall(daviUri); + auto call2 = DRing::placeCallWithMedia(aliceId, daviUri, {}); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); })); Manager::instance().answerCall(daviId, daviCall.callId); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.hostState == "CURRENT"; })); - Manager::instance().addParticipant(aliceId, call2->getCallId(), aliceId, confId); + Manager::instance().addParticipant(aliceId, call2, aliceId, confId); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(5), [&] { return !daviCall.moderatorMuted.load(); })); @@ -460,13 +467,13 @@ ConferenceTest::testHandsUp() cv.wait_for(lk, std::chrono::seconds(5), [&] { return !bobCall.raisedHand.load(); })); JAMI_INFO("Start call between Alice and Davi"); - auto call1 = aliceAccount->newOutgoingCall(daviUri); + auto call1 = DRing::placeCallWithMedia(aliceId, daviUri, {}); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); })); Manager::instance().answerCall(daviId, daviCall.callId); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.hostState == "CURRENT"; })); - Manager::instance().addParticipant(aliceId, call1->getCallId(), aliceId, confId); + Manager::instance().addParticipant(aliceId, call1, aliceId, confId); DRing::raiseParticipantHand(aliceId, confId, daviUri, true); CPPUNIT_ASSERT( @@ -477,13 +484,13 @@ ConferenceTest::testHandsUp() cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.state == "OVER"; })); daviCall.reset(); - auto call2 = aliceAccount->newOutgoingCall(daviUri); + auto call2 = DRing::placeCallWithMedia(aliceId, daviUri, {}); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); })); Manager::instance().answerCall(daviId, daviCall.callId); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return daviCall.hostState == "CURRENT"; })); - Manager::instance().addParticipant(aliceId, call2->getCallId(), aliceId, confId); + Manager::instance().addParticipant(aliceId, call2, aliceId, confId); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(5), [&] { return !daviCall.raisedHand.load(); })); @@ -537,7 +544,7 @@ ConferenceTest::testJoinCallFromOtherAccount() cv.wait_for(lk, std::chrono::seconds(5), [&] { return !bobCall.raisedHand.load(); })); JAMI_INFO("Start call between Alice and Davi"); - auto call1 = aliceAccount->newOutgoingCall(daviUri); + auto call1 = DRing::placeCallWithMedia(aliceId, daviUri, {}); CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(20), [&] { return !daviCall.callId.empty(); })); Manager::instance().answerCall(daviId, daviCall.callId); diff --git a/test/unitTest/ice/ice_media_cand_exchange.cpp b/test/unitTest/ice/ice_media_cand_exchange.cpp index 0307b9ce769962f10d36c3eb39342edfab7f5ec3..705c166e4258be07314f2c7ecb4be8415920fdc1 100644 --- a/test/unitTest/ice/ice_media_cand_exchange.cpp +++ b/test/unitTest/ice/ice_media_cand_exchange.cpp @@ -328,8 +328,6 @@ IceMediaCandExchangeTest::setupJamiAccount(CallData& user) details[ConfProperties::UPNP_ENABLED] = user.upnpEnabled_ ? "true" : "false"; details[ConfProperties::TURN::ENABLED] = user.turnEnabled_ ? "true" : "false"; DRing::setAccountDetails(user.accountId_, details); - - account->enableMultiStream(true); } void @@ -359,7 +357,6 @@ IceMediaCandExchangeTest::setupSipAccount(CallData& user) user.alias_ = details[ConfProperties::ALIAS]; account->enableIceForMedia(true); - account->enableMultiStream(true); user.dest_ = ip_utils::getLocalAddr(AF_INET); user.dest_.setPort(user.listeningPort_); diff --git a/test/unitTest/ice/ice_sdp_parser.cpp b/test/unitTest/ice/ice_sdp_parser.cpp index 55fad046054535a2960d18a875b771f0fbaf109b..bcf74d346a19495243abc9d5315b63900ece194b 100644 --- a/test/unitTest/ice/ice_sdp_parser.cpp +++ b/test/unitTest/ice/ice_sdp_parser.cpp @@ -206,9 +206,7 @@ IceSdpParsingTest::setUp() JAMI_INFO("Initialize accounts ..."); auto aliceAccount = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_); - aliceAccount->enableMultiStream(true); auto bobAccount = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_); - bobAccount->enableMultiStream(true); } void diff --git a/test/unitTest/media_negotiation/hold_resume.cpp b/test/unitTest/media_negotiation/hold_resume.cpp index d2644adeb484e0c50b9128460e03ff22d694112d..0c57663f5ce306669d3fdf1c06d6e4fe94b7742d 100644 --- a/test/unitTest/media_negotiation/hold_resume.cpp +++ b/test/unitTest/media_negotiation/hold_resume.cpp @@ -81,7 +81,6 @@ struct CallData std::string userName_ {}; std::string alias_ {}; std::string callId_ {}; - bool enableMultiStream_ {true}; std::vector<Signal> signals_; std::condition_variable cv_ {}; std::mutex mtx_; @@ -163,9 +162,7 @@ HoldResumeTest::setUp() JAMI_INFO("Initialize account..."); auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceData_.accountId_); - aliceAccount->enableMultiStream(true); auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobData_.accountId_); - bobAccount->enableMultiStream(true); wait_for_announcement_of({aliceAccount->getAccountID(), bobAccount->getAccountID()}); } @@ -402,7 +399,6 @@ HoldResumeTest::configureScenario(CallData& aliceData, CallData& bobData) auto const& account = Manager::instance().getAccount<JamiAccount>(aliceData.accountId_); aliceData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME]; aliceData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS]; - account->enableMultiStream(aliceData.enableMultiStream_); } { @@ -410,7 +406,6 @@ HoldResumeTest::configureScenario(CallData& aliceData, CallData& bobData) auto const& account = Manager::instance().getAccount<JamiAccount>(bobData.accountId_); bobData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME]; bobData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS]; - account->enableMultiStream(bobData.enableMultiStream_); } std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> signalHandlers; @@ -493,11 +488,7 @@ HoldResumeTest::testWithScenario(CallData& aliceData, bobData.accountId_.c_str()); // Wait for incoming call signal. - if (bobData.enableMultiStream_) { - CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCallWithMedia::name)); - } else { - CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCall::name)); - } + CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCallWithMedia::name)); // Answer the call. { diff --git a/test/unitTest/media_negotiation/media_negotiation.cpp b/test/unitTest/media_negotiation/media_negotiation.cpp index be5bb40464ae68d81ede383dbbf9a93ec3309430..cef99d187decb6e339368775f55c82a80a71ed33 100644 --- a/test/unitTest/media_negotiation/media_negotiation.cpp +++ b/test/unitTest/media_negotiation/media_negotiation.cpp @@ -83,7 +83,6 @@ struct CallData std::string userName_ {}; std::string alias_ {}; std::string callId_ {}; - bool enableMultiStream_ {true}; std::vector<Signal> signals_; std::condition_variable cv_ {}; std::mutex mtx_; @@ -114,14 +113,12 @@ private: void audio_only_then_add_video(); void audio_and_video_then_mute_audio(); void audio_and_video_then_change_video_source(); - void audio_only_then_add_video_but_peer_disabled_multistream(); CPPUNIT_TEST_SUITE(MediaNegotiationTest); CPPUNIT_TEST(audio_and_video_then_mute_video); CPPUNIT_TEST(audio_only_then_add_video); CPPUNIT_TEST(audio_and_video_then_mute_audio); CPPUNIT_TEST(audio_and_video_then_change_video_source); - CPPUNIT_TEST(audio_only_then_add_video_but_peer_disabled_multistream); CPPUNIT_TEST_SUITE_END(); // Event/Signal handlers @@ -178,9 +175,7 @@ MediaNegotiationTest::setUp() JAMI_INFO("Initialize account..."); auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceData_.accountId_); - aliceAccount->enableMultiStream(true); auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobData_.accountId_); - bobAccount->enableMultiStream(true); wait_for_announcement_of({aliceAccount->getAccountID(), bobAccount->getAccountID()}); } @@ -490,7 +485,6 @@ MediaNegotiationTest::configureScenario(CallData& aliceData, CallData& bobData) auto const& account = Manager::instance().getAccount<JamiAccount>(aliceData.accountId_); aliceData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME]; aliceData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS]; - account->enableMultiStream(aliceData.enableMultiStream_); } { @@ -498,7 +492,6 @@ MediaNegotiationTest::configureScenario(CallData& aliceData, CallData& bobData) auto const& account = Manager::instance().getAccount<JamiAccount>(bobData.accountId_); bobData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME]; bobData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS]; - account->enableMultiStream(bobData.enableMultiStream_); } std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> signalHandlers; @@ -594,11 +587,7 @@ MediaNegotiationTest::testWithScenario(CallData& aliceData, bobData.accountId_.c_str()); // Wait for incoming call signal. - if (bobData.enableMultiStream_) { - CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCallWithMedia::name)); - } else { - CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCall::name)); - } + CPPUNIT_ASSERT(waitForSignal(bobData, DRing::CallSignal::IncomingCallWithMedia::name)); // Answer the call. { @@ -899,49 +888,6 @@ MediaNegotiationTest::audio_and_video_then_change_video_source() JAMI_INFO("=== End test %s ===", __FUNCTION__); } -void -MediaNegotiationTest::audio_only_then_add_video_but_peer_disabled_multistream() -{ - JAMI_INFO("=== Begin test %s ===", __FUNCTION__); - - // Disable multi-stream on Bob's side - bobData_.enableMultiStream_ = false; - - configureScenario(aliceData_, bobData_); - - MediaAttribute defaultAudio(MediaType::MEDIA_AUDIO); - defaultAudio.label_ = "audio_0"; - defaultAudio.enabled_ = true; - - MediaAttribute defaultVideo(MediaType::MEDIA_VIDEO); - defaultVideo.label_ = "video_0"; - defaultVideo.enabled_ = true; - - { - MediaAttribute audio(defaultAudio); - MediaAttribute video(defaultVideo); - - TestScenario scenario; - // First offer/answer - scenario.offer_.emplace_back(audio); - scenario.answer_.emplace_back(audio); - - // Updated offer/answer - scenario.offerUpdate_.emplace_back(audio); - scenario.offerUpdate_.emplace_back(video); - scenario.answerUpdate_.emplace_back(audio); - scenario.answerUpdate_.emplace_back(video); - scenario.expectMediaRenegotiation_ = false; - scenario.expectMediaChangeRequest_ = false; - - testWithScenario(aliceData_, bobData_, scenario); - } - - DRing::unregisterSignalHandlers(); - - JAMI_INFO("=== End test %s ===", __FUNCTION__); -} - } // namespace test } // namespace jami diff --git a/test/unitTest/sip_account/sip_basic_calls.cpp b/test/unitTest/sip_account/sip_basic_calls.cpp index 784fb41da74e0991d456e7cbc95be13105707d22..fcd27d7d5a810e17a16a83dd918bcacd647c2439 100644 --- a/test/unitTest/sip_account/sip_basic_calls.cpp +++ b/test/unitTest/sip_account/sip_basic_calls.cpp @@ -88,6 +88,7 @@ private: void audio_video_test(); void peer_answer_with_all_media_disabled(); void hold_resume_test(); + void blind_transfer_test(); CPPUNIT_TEST_SUITE(SipBasicCallTest); CPPUNIT_TEST(audio_only_test); @@ -95,6 +96,7 @@ private: // Test when the peer answers with all the media disabled (RTP port = 0) CPPUNIT_TEST(peer_answer_with_all_media_disabled); CPPUNIT_TEST(hold_resume_test); + CPPUNIT_TEST(blind_transfer_test); CPPUNIT_TEST_SUITE_END(); // Event/Signal handlers @@ -115,7 +117,7 @@ private: std::vector<MediaAttribute> answer, bool expectedToSucceed = true, bool validateMedia = true); - static void configureTest(CallData& bob, CallData& alice); + static void configureTest(CallData& bob, CallData& alice, CallData& carla); static std::string getUserAlias(const std::string& callId); // Wait for a signal from the callbacks. Some signals also report the event that // triggered the signal a like the StateChange signal. @@ -126,6 +128,7 @@ private: private: CallData aliceData_; CallData bobData_; + CallData carlaData_; }; CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(SipBasicCallTest, SipBasicCallTest::name()); @@ -136,6 +139,7 @@ SipBasicCallTest::setUp() aliceData_.listeningPort_ = 5080; std::map<std::string, std::string> details = DRing::getAccountTemplate("SIP"); details[ConfProperties::TYPE] = "SIP"; + details[ConfProperties::USERNAME] = "ALICE"; details[ConfProperties::DISPLAYNAME] = "ALICE"; details[ConfProperties::ALIAS] = "ALICE"; details[ConfProperties::LOCAL_PORT] = std::to_string(aliceData_.listeningPort_); @@ -145,17 +149,27 @@ SipBasicCallTest::setUp() bobData_.listeningPort_ = 5082; details = DRing::getAccountTemplate("SIP"); details[ConfProperties::TYPE] = "SIP"; + details[ConfProperties::USERNAME] = "BOB"; details[ConfProperties::DISPLAYNAME] = "BOB"; details[ConfProperties::ALIAS] = "BOB"; details[ConfProperties::LOCAL_PORT] = std::to_string(bobData_.listeningPort_); details[ConfProperties::UPNP_ENABLED] = "false"; bobData_.accountId_ = Manager::instance().addAccount(details); + carlaData_.listeningPort_ = 5084; + details = DRing::getAccountTemplate("SIP"); + details[ConfProperties::TYPE] = "SIP"; + details[ConfProperties::USERNAME] = "CARLA"; + details[ConfProperties::DISPLAYNAME] = "CARLA"; + details[ConfProperties::ALIAS] = "CARLA"; + details[ConfProperties::LOCAL_PORT] = std::to_string(carlaData_.listeningPort_); + details[ConfProperties::UPNP_ENABLED] = "false"; + carlaData_.accountId_ = Manager::instance().addAccount(details); + JAMI_INFO("Initialize accounts ..."); auto aliceAccount = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_); - aliceAccount->enableMultiStream(true); auto bobAccount = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_); - bobAccount->enableMultiStream(true); + auto carlaAccount = Manager::instance().getAccount<SIPAccount>(carlaData_.accountId_); } void @@ -180,7 +194,8 @@ SipBasicCallTest::tearDown() Manager::instance().removeAccount(aliceData_.accountId_, true); Manager::instance().removeAccount(bobData_.accountId_, true); - // Because cppunit is not linked with dbus, just poll if removed + Manager::instance().removeAccount(carlaData_.accountId_, true); + CPPUNIT_ASSERT( cv.wait_for(lk, std::chrono::seconds(30), [&] { return accountsRemoved.load(); })); @@ -356,7 +371,7 @@ SipBasicCallTest::waitForSignal(CallData& callData, } void -SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData) +SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData, CallData& carlaData) { { CPPUNIT_ASSERT(not aliceData.accountId_.empty()); @@ -374,6 +389,15 @@ SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData) bobData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS]; account->setLocalPort(bobData.listeningPort_); } +#if 1 + { + CPPUNIT_ASSERT(not carlaData.accountId_.empty()); + auto const& account = Manager::instance().getAccount<SIPAccount>(carlaData.accountId_); + carlaData.userName_ = account->getAccountDetails()[ConfProperties::USERNAME]; + carlaData.alias_ = account->getAccountDetails()[ConfProperties::ALIAS]; + account->setLocalPort(carlaData.listeningPort_); + } +#endif std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> signalHandlers; @@ -388,7 +412,9 @@ SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData) onIncomingCallWithMedia(accountId, callId, mediaList, - user == aliceData.alias_ ? aliceData : bobData); + user == aliceData.alias_ + ? aliceData + : (user == bobData.alias_ ? bobData : carlaData)); })); signalHandlers.insert( @@ -401,7 +427,9 @@ SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData) onCallStateChange(accountId, callId, state, - user == aliceData.alias_ ? aliceData : bobData); + user == aliceData.alias_ + ? aliceData + : (user == bobData.alias_ ? bobData : carlaData)); })); signalHandlers.insert(DRing::exportable_callback<DRing::CallSignal::MediaNegotiationStatus>( @@ -412,7 +440,9 @@ SipBasicCallTest::configureTest(CallData& aliceData, CallData& bobData) if (not user.empty()) onMediaNegotiationStatus(callId, event, - user == aliceData.alias_ ? aliceData : bobData); + user == aliceData.alias_ + ? aliceData + : (user == bobData.alias_ ? bobData : carlaData)); })); DRing::registerSignalHandlers(signalHandlers); @@ -424,11 +454,12 @@ SipBasicCallTest::audio_video_call(std::vector<MediaAttribute> offer, bool expectedToSucceed, bool validateMedia) { - configureTest(aliceData_, bobData_); + configureTest(aliceData_, bobData_, carlaData_); JAMI_INFO("=== Start a call and validate ==="); - std::string bobUri = "127.0.0.1:" + std::to_string(bobData_.listeningPort_); + std::string bobUri = bobData_.userName_ + + "@127.0.0.1:" + std::to_string(bobData_.listeningPort_); aliceData_.callId_ = DRing::placeCallWithMedia(aliceData_.accountId_, bobUri, @@ -660,11 +691,12 @@ SipBasicCallTest::hold_resume_test() answer.emplace_back(audio); { - configureTest(aliceData_, bobData_); + configureTest(aliceData_, bobData_, carlaData_); JAMI_INFO("=== Start a call and validate ==="); - std::string bobUri = "127.0.0.1:" + std::to_string(bobData_.listeningPort_); + std::string bobUri = bobData_.userName_ + + "@127.0.0.1:" + std::to_string(bobData_.listeningPort_); aliceData_.callId_ = DRing::placeCallWithMedia(aliceData_.accountId_, bobUri, @@ -821,6 +853,195 @@ SipBasicCallTest::hold_resume_test() } } +void +SipBasicCallTest::blind_transfer_test() +{ + // Test a "blind" (a.k.a. unattended) transfer as described in + // https://datatracker.ietf.org/doc/html/rfc5589 + + /** Call transfer scenario: + * + * Alice and Bob are in an active call + * Alice performs a call transfer (SIP REFER method) to Carla + * Bob automatically accepts the transfer request + * Alice ends the call with Bob + * Bob send a new call invite to Carla + * Carla accepts the call + * Carl ends the call + * + * Here is a simplified version of a call flow from + * rfc5589 + * + * + Alice Bob Carla + | REFER | | + |----------------------->| | + | 202 Accepted | | + |<-----------------------| | + | BYE | | + |<-----------------------| | + | 200 OK | | + |----------------------->| | + | | INVITE | + | |----------------------->| + | | 200 OK | + | |<-----------------------| + */ + + JAMI_INFO("=== Begin test %s ===", __FUNCTION__); + + auto const aliceAcc = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_); + auto const bobAcc = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_); + auto const carlaAcc = Manager::instance().getAccount<SIPAccount>(carlaData_.accountId_); + + aliceAcc->enableIceForMedia(false); + bobAcc->enableIceForMedia(false); + carlaAcc->enableIceForMedia(false); + + std::vector<MediaAttribute> offer; + std::vector<MediaAttribute> answer; + + MediaAttribute audio(MediaType::MEDIA_AUDIO); + MediaAttribute video(MediaType::MEDIA_VIDEO); + + audio.enabled_ = true; + audio.label_ = "audio_0"; + + // Alice's media + offer.emplace_back(audio); + + // Bob's media + answer.emplace_back(audio); + + configureTest(aliceData_, bobData_, carlaData_); + + JAMI_INFO("=== Start a call and validate ==="); + + std::string bobUri = bobData_.userName_ + + "@127.0.0.1:" + std::to_string(bobData_.listeningPort_); + + aliceData_.callId_ = DRing::placeCallWithMedia(aliceData_.accountId_, + bobUri, + MediaAttribute::mediaAttributesToMediaMaps( + offer)); + + CPPUNIT_ASSERT(not aliceData_.callId_.empty()); + + JAMI_INFO("ALICE [%s] started a call with BOB [%s] and wait for answer", + aliceData_.accountId_.c_str(), + bobData_.accountId_.c_str()); + + // Give it some time to ring + std::this_thread::sleep_for(std::chrono::seconds(2)); + + // Wait for call to be processed. + CPPUNIT_ASSERT( + waitForSignal(aliceData_, DRing::CallSignal::StateChange::name, StateEvent::RINGING)); + + // Wait for incoming call signal. + CPPUNIT_ASSERT(waitForSignal(bobData_, DRing::CallSignal::IncomingCallWithMedia::name)); + + // Answer the call. + DRing::acceptWithMedia(bobData_.accountId_, + bobData_.callId_, + MediaAttribute::mediaAttributesToMediaMaps(answer)); + + // Wait for media negotiation complete signal. + CPPUNIT_ASSERT(waitForSignal(bobData_, + DRing::CallSignal::MediaNegotiationStatus::name, + DRing::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS)); + + // Wait for the StateChange signal. + CPPUNIT_ASSERT( + waitForSignal(bobData_, DRing::CallSignal::StateChange::name, StateEvent::CURRENT)); + + JAMI_INFO("BOB answered the call [%s]", bobData_.callId_.c_str()); + + // Wait for media negotiation complete signal. + CPPUNIT_ASSERT(waitForSignal(aliceData_, + DRing::CallSignal::MediaNegotiationStatus::name, + DRing::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS)); + + // Give some time to media to start and flow + std::this_thread::sleep_for(std::chrono::seconds(2)); + + // Transfer the call to Carla + std::string carlaUri = carlaAcc->getUsername() + + "@127.0.0.1:" + std::to_string(carlaData_.listeningPort_); + + DRing::transfer(aliceData_.accountId_, aliceData_.callId_, carlaUri); // TODO. Check trim + + // Expect Alice's call to end. + CPPUNIT_ASSERT( + waitForSignal(aliceData_, DRing::CallSignal::StateChange::name, StateEvent::HUNGUP)); + + // Wait for the new call to be processed. + CPPUNIT_ASSERT( + waitForSignal(bobData_, DRing::CallSignal::StateChange::name, StateEvent::RINGING)); + + // Wait for incoming call signal. + CPPUNIT_ASSERT(waitForSignal(carlaData_, DRing::CallSignal::IncomingCallWithMedia::name)); + + // Let it ring + std::this_thread::sleep_for(std::chrono::seconds(2)); + + // Carla answers the call. + DRing::acceptWithMedia(carlaData_.accountId_, + carlaData_.callId_, + MediaAttribute::mediaAttributesToMediaMaps(answer)); + + // Wait for media negotiation complete signal. + CPPUNIT_ASSERT(waitForSignal(carlaData_, + DRing::CallSignal::MediaNegotiationStatus::name, + DRing::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS)); + + // Wait for the StateChange signal. + CPPUNIT_ASSERT( + waitForSignal(carlaData_, DRing::CallSignal::StateChange::name, StateEvent::CURRENT)); + + JAMI_INFO("CARLA answered the call [%s]", bobData_.callId_.c_str()); + + // Wait for media negotiation complete signal. + CPPUNIT_ASSERT(waitForSignal(bobData_, + DRing::CallSignal::MediaNegotiationStatus::name, + DRing::Media::MediaNegotiationStatusEvents::NEGOTIATION_SUCCESS)); + // Wait for the StateChange signal. + CPPUNIT_ASSERT( + waitForSignal(bobData_, DRing::CallSignal::StateChange::name, StateEvent::CURRENT)); + + // Validate Carla's side of media direction + { + auto call = std::static_pointer_cast<SIPCall>( + Manager::instance().getCallFromCallID(carlaData_.callId_)); + auto& sdp = call->getSDP(); + auto mediaStreams = sdp.getMediaSlots(); + for (auto const& media : mediaStreams) { + CPPUNIT_ASSERT_EQUAL(media.first.direction_, MediaDirection::SENDRECV); + CPPUNIT_ASSERT_EQUAL(media.second.direction_, MediaDirection::SENDRECV); + } + } + + // NOTE: + // For now, we dont validate Bob's media because currently + // test does not update BOB's call ID (bobData_.callId_ + // still point to the first call). + // It seems there is no easy way to get the ID of the new call + // made by Bob to Carla. + + // Give some time to media to start and flow + std::this_thread::sleep_for(std::chrono::seconds(2)); + + // Bob hang-up. + JAMI_INFO("Hang up CARLA's call and wait for CARLA to hang up"); + DRing::hangUp(carlaData_.accountId_, carlaData_.callId_); + + // Expect end call on Carla's side. + CPPUNIT_ASSERT( + waitForSignal(carlaData_, DRing::CallSignal::StateChange::name, StateEvent::HUNGUP)); + + JAMI_INFO("Calls normally ended on both sides"); +} + } // namespace test } // namespace jami diff --git a/test/unitTest/sip_account/sip_empty_offer.cpp b/test/unitTest/sip_account/sip_empty_offer.cpp index 907b57338a09e162a06a00cb8672d0d5bde4831c..0851f7d7f9d98ff767a3d77bccee863dc33f39c0 100644 --- a/test/unitTest/sip_account/sip_empty_offer.cpp +++ b/test/unitTest/sip_account/sip_empty_offer.cpp @@ -142,9 +142,7 @@ SipEmptyOfferTest::setUp() JAMI_INFO("Initialize accounts ..."); auto aliceAccount = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_); - aliceAccount->enableMultiStream(true); auto bobAccount = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_); - bobAccount->enableMultiStream(true); } void diff --git a/test/unitTest/sip_account/sip_srtp.cpp b/test/unitTest/sip_account/sip_srtp.cpp index 191ad8dcbf0c2831a290b8d2a33fd1046c0da497..0a174b72630ac5751bc18af63a9192aaea7c84e9 100644 --- a/test/unitTest/sip_account/sip_srtp.cpp +++ b/test/unitTest/sip_account/sip_srtp.cpp @@ -147,9 +147,7 @@ SipSrtpTest::setUp() JAMI_INFO("Initialize accounts ..."); auto aliceAccount = Manager::instance().getAccount<SIPAccount>(aliceData_.accountId_); - aliceAccount->enableMultiStream(true); auto bobAccount = Manager::instance().getAccount<SIPAccount>(bobData_.accountId_); - bobAccount->enableMultiStream(true); } void