Commit a0d2e366 authored by Guillaume Roguez's avatar Guillaume Roguez

ice: implement TURN/STUN servers options

This patch modifies the internal IceTransport API.
We now use a IceTransportOptions to select ICE options.
STUN/TURN servers are modified using this options struture.

Refs #72663

Change-Id: I35106000d803c1374f97ce89e7b895faf1e97b77
parent 63b7de4e
......@@ -52,6 +52,7 @@
#include "string_utils.h"
#include "config/yamlparser.h"
#include "system_codec_container.h"
#include "ice_transport.h"
#include <yaml-cpp/yaml.h>
......@@ -539,4 +540,12 @@ Account::getActiveAccountCodecInfoList(MediaType mediaType) const
return accountCodecList;
}
const IceTransportOptions
Account::getIceOptions() const noexcept
{
IceTransportOptions opts;
opts.upnpEnable = getUPnPActive();
return opts;
}
} // namespace ring
......@@ -68,6 +68,7 @@ namespace ring {
class Call;
class SystemCodecContainer;
class IceTransportOptions;
class VoipLinkException : public std::runtime_error
{
......@@ -271,6 +272,8 @@ class Account : public Serializable, public std::enable_shared_from_this<Account
*/
IpAddr getUPnPIpAddress() const;
virtual const IceTransportOptions getIceOptions() const noexcept;
private:
NON_COPYABLE(Account);
......
......@@ -271,8 +271,9 @@ bool
Call::initIceTransport(bool master, unsigned channel_num)
{
auto& iceTransportFactory = Manager::instance().getIceTransportFactory();
iceTransport_ = iceTransportFactory.createTransport(getCallId().c_str(), channel_num,
master, account_.getUPnPActive());
iceTransport_ = iceTransportFactory.createTransport(getCallId().c_str(),
channel_num, master,
account_.getIceOptions());
return static_cast<bool>(iceTransport_);
}
......
......@@ -96,21 +96,21 @@ IceTransport::cb_on_ice_complete(pj_ice_strans* ice_st,
RING_WARN("null IceTransport");
}
IceTransport::IceTransport(const char* name, int component_count,
bool master, bool upnp_enabled,
IceTransportCompleteCb on_initdone_cb,
IceTransportCompleteCb on_negodone_cb)
IceTransport::IceTransport(const char* name, int component_count, bool master,
const IceTransportOptions& options)
: pool_(nullptr, pj_pool_release)
, on_initdone_cb_(on_initdone_cb)
, on_negodone_cb_(on_negodone_cb)
, on_initdone_cb_(options.onInitDone)
, on_negodone_cb_(options.onNegoDone)
, component_count_(component_count)
, compIO_(component_count)
, initiator_session_(master)
{
if (upnp_enabled)
if (options.upnpEnable)
upnp_.reset(new upnp::Controller());
auto& iceTransportFactory = Manager::instance().getIceTransportFactory();
config_ = iceTransportFactory.getIceCfg();
pool_.reset(pj_pool_create(iceTransportFactory.getPoolFactory(),
"IceTransport.pool", 512, 512, NULL));
......@@ -122,11 +122,46 @@ IceTransport::IceTransport(const char* name, int component_count,
icecb.on_rx_data = cb_on_rx_data;
icecb.on_ice_complete = cb_on_ice_complete;
/* STUN */
if (not options.stunServer.empty()) {
const auto n = options.stunServer.rfind(':');
if (n != std::string::npos) {
const auto p = options.stunServer.c_str();
pj_strset(&config_.stun.server, (char*)p, n);
config_.stun.port = (pj_uint16_t)std::atoi(p+n+1);
} else {
pj_cstr(&config_.stun.server, options.stunServer.c_str());
config_.stun.port = PJ_STUN_PORT;
}
RING_WARN("ICE: STUN='%s', PORT=%d", options.stunServer.c_str(),
config_.stun.port);
}
/* TURN */
if (not options.turnServer.empty()) {
const auto n = options.turnServer.rfind(':');
if (n != std::string::npos) {
const auto p = options.turnServer.c_str();
pj_strset(&config_.turn.server, (char*)p, n);
config_.turn.port = (pj_uint16_t)std::atoi(p+n+1);
} else {
pj_cstr(&config_.turn.server, options.turnServer.c_str());
config_.turn.port = PJ_STUN_PORT;
}
// No authorization yet
//config_.turn.auth_cred.type = PJ_STUN_AUTH_STATIC;
// Only UDP yet
config_.turn.conn_type = PJ_TURN_TP_UDP;
RING_WARN("ICE: TURN='%s', PORT=%d", options.turnServer.c_str(),
config_.turn.port);
}
pj_ice_strans* icest = nullptr;
pj_status_t status = pj_ice_strans_create(name,
iceTransportFactory.getIceCfg(),
component_count, this, &icecb,
&icest);
pj_status_t status = pj_ice_strans_create(name, &config_, component_count,
this, &icecb, &icest);
if (status != PJ_SUCCESS || icest == nullptr)
throw std::runtime_error("pj_ice_strans_create() failed");
}
......@@ -762,10 +797,6 @@ IceTransportFactory::IceTransportFactory()
ice_cfg_.turn.cfg.max_pkt_size = 8192;
//ice_cfg_.stun.max_host_cands = icedemo.opt.max_host;
ice_cfg_.opt.aggressive = PJ_FALSE;
// TODO: STUN server candidate
// TODO: TURN server candidate
}
IceTransportFactory::~IceTransportFactory()
......@@ -841,17 +872,13 @@ IceTransportFactory::processThread()
}
std::shared_ptr<IceTransport>
IceTransportFactory::createTransport(const char* name,
int component_count,
IceTransportFactory::createTransport(const char* name, int component_count,
bool master,
bool upnp_enabled,
IceTransportCompleteCb&& on_initdone_cb,
IceTransportCompleteCb&& on_negodone_cb)
const IceTransportOptions& options)
{
try {
return std::make_shared<IceTransport>(name, component_count, master, upnp_enabled,
std::forward<IceTransportCompleteCb>(on_initdone_cb),
std::forward<IceTransportCompleteCb>(on_negodone_cb));
return std::make_shared<IceTransport>(name, component_count, master,
options);
} catch(const std::exception& e) {
RING_ERR("%s",e.what());
return nullptr;
......
......@@ -59,6 +59,14 @@ using IceTransportCompleteCb = std::function<void(IceTransport&, bool)>;
using IceRecvCb = std::function<ssize_t(unsigned char* buf, size_t len)>;
using IceCandidate = pj_ice_sess_cand;
struct IceTransportOptions {
bool upnpEnable {false};
IceTransportCompleteCb onInitDone {};
IceTransportCompleteCb onNegoDone {};
std::string stunServer {};
std::string turnServer {};
};
class IceTransport {
public:
using Attribute = struct {
......@@ -69,11 +77,8 @@ class IceTransport {
/**
* Constructor
*/
IceTransport(const char* name, int component_count,
bool master,
bool upnp_enabled = false,
IceTransportCompleteCb on_initdone_cb={},
IceTransportCompleteCb on_negodone_cb={});
IceTransport(const char* name, int component_count, bool master,
const IceTransportOptions& options = {});
/**
* Destructor
......@@ -215,6 +220,7 @@ class IceTransport {
pj_sockaddr remoteAddr_;
std::condition_variable iceCV_ {};
mutable std::mutex iceMutex_ {};
pj_ice_strans_cfg config_;
struct Packet {
Packet(void *pkt, pj_size_t size);
......@@ -258,16 +264,14 @@ class IceTransportFactory {
std::shared_ptr<IceTransport> createTransport(const char* name,
int component_count,
bool master,
bool upnp_enabled = false,
IceTransportCompleteCb&& on_initdone_cb={},
IceTransportCompleteCb&& on_negodone_cb={});
const IceTransportOptions& options = {});
int processThread();
/**
* PJSIP specifics
*/
const pj_ice_strans_cfg* getIceCfg() const { return &ice_cfg_; }
pj_ice_strans_cfg getIceCfg() const { return ice_cfg_; }
pj_pool_factory* getPoolFactory() { return &cp_.factory; }
private:
......
......@@ -163,7 +163,7 @@ RingAccount::newOutgoingCall(const std::string& toUrl)
// Create an ICE transport for SIP channel
auto& tfactory = manager.getIceTransportFactory();
auto ice = tfactory.createTransport(("sip:" + call->getCallId()).c_str(),
ICE_COMPONENTS, true, getUPnPActive());
ICE_COMPONENTS, true, getIceOptions());
if (not ice) {
call->removeCall();
return nullptr;
......@@ -840,11 +840,7 @@ void RingAccount::incomingCall(dht::IceCandidates&& msg)
RING_WARN("Received incoming DHT call request from %s", from.c_str());
auto call = Manager::instance().callFactory.newCall<SIPCall, RingAccount>(*this, Manager::instance().getNewCallID(), Call::INCOMING);
auto ice = Manager::instance().getIceTransportFactory().createTransport(
("sip:"+call->getCallId()).c_str(),
ICE_COMPONENTS,
false,
getUPnPActive()
);
("sip:"+call->getCallId()).c_str(), ICE_COMPONENTS, false, getIceOptions());
if (ice->waitForInitialization(ICE_INIT_TIMEOUT) <= 0)
throw std::runtime_error("Can't initialize ICE..");
......
......@@ -39,6 +39,7 @@
#include "account_schema.h"
#include "manager.h"
#include "ice_transport.h"
#include "config/yamlparser.h"
#include <yaml-cpp/yaml.h>
......@@ -324,4 +325,15 @@ SIPAccountBase::generateVideoPort() const
}
#endif
const IceTransportOptions
SIPAccountBase::getIceOptions() const noexcept
{
auto opts = Account::getIceOptions();
if (stunEnabled_)
opts.stunServer = stunServer_;
if (turnEnabled_)
opts.turnServer = turnServer_;
return opts;
}
} // namespace ring
......@@ -242,6 +242,8 @@ public:
stunServer_ = srv;
}
const IceTransportOptions getIceOptions() const noexcept override;
protected:
virtual void serialize(YAML::Emitter &out);
virtual void serializeTls(YAML::Emitter &out);
......
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