Commit 5e74c021 authored by Sébastien Blin's avatar Sébastien Blin

jamiaccount: use onInitDone callback for media transport

This avoid to wait on Ice initialization for 35 seconds if anything goes
wrong and block the main thread.

Change-Id: I6268802a341b0c366fddcf240f9abf6f1c7b36ad
parent 073d68f9
......@@ -759,43 +759,72 @@ JamiAccount::onConnectedOutgoingCall(SIPCall& call, const std::string& to_id, Ip
{
JAMI_DBG("[call:%s] outgoing call connected to %s", call.getCallId().c_str(), to_id.c_str());
call.initIceMediaTransport(true);
call.setIPToIP(true);
call.setPeerNumber(to_id);
const auto localAddress = ip_utils::getInterfaceAddr(getLocalInterface(), target.getFamily());
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;
}
/* fallback on local address */
if (not addrSdp)
addrSdp = localAddress;
auto opts = getIceOptions();
opts.onInitDone = [w = weak(), target = std::move(target), &call](bool ok) {
if (!ok) {
JAMI_ERR("ICE medias are not initialized");
return;
}
auto shared = w.lock();
if (!shared)
return;
// Initialize the session using ULAW as default codec in case of early media
// The session should be ready to receive media once the first INVITE is sent, before
// the session initialization is completed
if (!getSystemCodecContainer()->searchCodecByName("PCMA", jami::MEDIA_AUDIO))
throw VoipLinkException("Could not instantiate codec for early media");
const auto localAddress = ip_utils::getInterfaceAddr(shared->getLocalInterface(),
target.getFamily());
// Building the local SDP offer
auto& sdp = call.getSDP();
IpAddr addrSdp;
if (shared->getUPnPActive()) {
// use UPnP addr, or published addr if its set
addrSdp = shared->getPublishedSameasLocal() ? shared->getUPnPIpAddress()
: shared->getPublishedIpAddress();
} else {
addrSdp = shared->isStunEnabled() or (not shared->getPublishedSameasLocal())
? shared->getPublishedIpAddress()
: localAddress;
}
sdp.setPublishedIP(addrSdp);
const bool created = sdp.createOffer(getActiveAccountCodecInfoList(MEDIA_AUDIO),
getActiveAccountCodecInfoList(
videoEnabled_ and not call.isAudioOnly() ? MEDIA_VIDEO
: MEDIA_NONE),
getSrtpKeyExchange());
// fallback on local address
if (not addrSdp)
addrSdp = localAddress;
// Initialize the session using ULAW as default codec in case of early media
// The session should be ready to receive media once the first INVITE is sent, before
// the session initialization is completed
if (!getSystemCodecContainer()->searchCodecByName("PCMA", jami::MEDIA_AUDIO))
JAMI_WARN("Could not instantiate codec for early media");
// Building the local SDP offer
auto& sdp = call.getSDP();
sdp.setPublishedIP(addrSdp);
const bool created = sdp.createOffer(shared->getActiveAccountCodecInfoList(MEDIA_AUDIO),
shared->getActiveAccountCodecInfoList(
shared->videoEnabled_ and not call.isAudioOnly()
? MEDIA_VIDEO
: MEDIA_NONE),
shared->getSrtpKeyExchange());
if (not created) {
JAMI_ERR("Could not send outgoing INVITE request for new call");
return;
}
// Note: pj_ice_strans_create can call onComplete in the same thread
// This means that iceMutex_ in IceTransport can be locked when onInitDone is called
// So, we need to run the call creation in the main thread
// Also, we do not directly call SIPStartCall before receiving onInitDone, because
// there is an inside waitForInitialization that can block the thread.
runOnMainThread([w = std::move(w), target = std::move(target), &call] {
auto shared = w.lock();
if (!shared)
return;
if (not created or not SIPStartCall(call, target))
throw VoipLinkException("Could not send outgoing INVITE request for new call");
if (not shared->SIPStartCall(call, target)) {
JAMI_ERR("Could not send outgoing INVITE request for new call");
}
});
};
call.setIPToIP(true);
call.setPeerNumber(to_id);
call.initIceMediaTransport(true, std::move(opts));
}
std::shared_ptr<Call>
......
......@@ -342,11 +342,12 @@ SIPCall::sendSIPInfo(const char* const body, const char* const subtype)
void
SIPCall::updateRecState(bool state)
{
std::string BODY =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
"<media_control><vc_primitive><to_encoder>"
"<recording_state=" + std::to_string(state) + "/>"
"</to_encoder></vc_primitive></media_control>";
std::string BODY = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
"<media_control><vc_primitive><to_encoder>"
"<recording_state="
+ std::to_string(state)
+ "/>"
"</to_encoder></vc_primitive></media_control>";
// see https://tools.ietf.org/html/rfc5168 for XML Schema for Media Control details
JAMI_DBG("Sending recording state via SIP INFO");
......@@ -1212,10 +1213,8 @@ SIPCall::stopAllMedia()
videortp_->stop();
#endif
#ifdef ENABLE_PLUGIN
jami::Manager::instance()
.getJamiPluginManager()
.getCallServicesManager()
.clearAVSubject(getCallId());
jami::Manager::instance().getJamiPluginManager().getCallServicesManager().clearAVSubject(
getCallId());
#endif
}
......@@ -1536,15 +1535,18 @@ SIPCall::InvSessionDeleter::operator()(pjsip_inv_session* inv) const noexcept
}
bool
SIPCall::initIceMediaTransport(bool master, unsigned channel_num)
SIPCall::initIceMediaTransport(bool master,
std::optional<IceTransportOptions> options,
unsigned channel_num)
{
JAMI_DBG("[call:%s] create media ICE transport", getCallId().c_str());
auto iceOptions = options == std::nullopt ? getAccount().getIceOptions() : *options;
auto& iceTransportFactory = Manager::instance().getIceTransportFactory();
tmpMediaTransport_ = iceTransportFactory.createUTransport(getCallId().c_str(),
channel_num,
master,
getAccount().getIceOptions());
iceOptions);
return static_cast<bool>(tmpMediaTransport_);
}
......
......@@ -29,6 +29,7 @@
#endif
#include "call.h"
#include "ice_transport.h"
#include "media_codec.h" // for MediaType enum
#include "sip_utils.h"
......@@ -42,6 +43,7 @@
#include "noncopyable.h"
#include <memory>
#include <optional>
extern "C" {
#include <pjsip/sip_config.h>
......@@ -57,7 +59,6 @@ class Sdp;
class SIPAccountBase;
class SipTransport;
class AudioRtpSession;
class IceTransport;
class IceSocket;
using IceCandidate = pj_ice_sess_cand;
......@@ -225,7 +226,9 @@ public: // NOT SIP RELATED (good candidates to be moved elsewhere)
void setPeerUri(const std::string& peerUri) { peerUri_ = peerUri; }
bool initIceMediaTransport(bool master, unsigned channel_num = 4);
bool initIceMediaTransport(bool master,
std::optional<IceTransportOptions> options = std::nullopt,
unsigned channel_num = 4);
bool isIceRunning() const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment