Bug 786236: Per-context configurable STUN servers. r=abr

This commit is contained in:
EKR 2013-01-05 11:40:34 -08:00
parent ae95b03e47
commit 63eedb4bb4
9 changed files with 185 additions and 25 deletions

View File

@ -239,7 +239,7 @@ static int nr_transport_addr_to_praddr(nr_transport_addr *addr,
return(_status);
}
static int nr_praddr_to_transport_addr(PRNetAddr *praddr,
int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
nr_transport_addr *addr, int keep)
{
int _status;

View File

@ -109,5 +109,8 @@ private:
nsCOMPtr<nsISocketTransportService> stservice_;
};
int nr_praddr_to_transport_addr(const PRNetAddr *praddr,
nr_transport_addr *addr, int keep);
} // close namespace
#endif

View File

@ -81,6 +81,7 @@ extern "C" {
#include "logging.h"
#include "nricectx.h"
#include "nricemediastream.h"
#include "nr_socket_prsock.h"
namespace mozilla {
@ -231,8 +232,8 @@ int NrIceCtx::msg_recvd(void *obj, nr_ice_peer_ctx *pctx,
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
bool offerer,
bool set_interface_priorities) {
bool offerer,
bool set_interface_priorities) {
RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer);
// Initialize the crypto callbacks
@ -275,8 +276,6 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232);
}
NR_reg_set_string((char *)"ice.stun.server.0.addr", (char *)"23.21.150.121");
NR_reg_set_uint2((char *)"ice.stun.server.0.port",3478);
NR_reg_set_uint4((char *)"stun.client.maximum_transmits",4);
}
@ -357,6 +356,33 @@ nsresult NrIceCtx::SetControlling(Controlling controlling) {
return NS_OK;
}
nsresult NrIceCtx::SetStunServers(const std::vector<NrIceStunServer>&
stun_servers) {
if (stun_servers.empty())
return NS_OK;
ScopedDeleteArray<nr_ice_stun_server> servers(
new nr_ice_stun_server[stun_servers.size()]);
int r;
for (size_t i=0; i < stun_servers.size(); ++i) {
r = nr_praddr_to_transport_addr(&stun_servers[i].addr(),
&servers[i].addr, 0);
if (r) {
MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set STUN server for '" << name_ << "'");
return NS_ERROR_FAILURE;
}
}
r = nr_ice_ctx_set_stun_servers(ctx_, servers, stun_servers.size());
if (r) {
MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set STUN server for '" << name_ << "'");
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult NrIceCtx::StartGathering() {
this->AddRef();
int r = nr_ice_initialize(ctx_, &NrIceCtx::initialized_cb,

View File

@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "sigslot.h"
#include "prnetdb.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Scoped.h"
#include "nsAutoPtr.h"
@ -74,6 +76,50 @@ typedef struct nr_ice_cand_pair_ nr_ice_cand_pair;
class NrIceMediaStream;
struct NrIceStunServer {
public:
NrIceStunServer(const PRNetAddr& addr) {
memcpy(&addr_, &addr, sizeof(addr));
}
// Convenience function to allow you to pass an IP addr as a string
static NrIceStunServer* Create(const std::string& addr, uint16_t port) {
ScopedDeletePtr<NrIceStunServer> server(
new NrIceStunServer());
nsresult rv = server->Init(addr, port);
if (NS_FAILED(rv))
return nullptr;
return server.forget();
}
const PRNetAddr& addr() const { return addr_; }
private:
NrIceStunServer() : addr_() {}
nsresult Init(const std::string& addr, uint16_t port) {
PRStatus status = PR_StringToNetAddr(addr.c_str(), &addr_);
if (status != PR_SUCCESS)
return NS_ERROR_INVALID_ARG;
addr_.inet.port = PR_htons(port);
return NS_OK;
}
PRNetAddr addr_;
};
struct NrIceTurnServer {
PRNetAddr addr;
std::string username;
std::string password;
};
class NrIceCtx {
public:
enum State { ICE_CTX_INIT,
@ -89,8 +135,8 @@ class NrIceCtx {
};
static RefPtr<NrIceCtx> Create(const std::string& name,
bool offerer,
bool set_interface_priorities = true);
bool offerer,
bool set_interface_priorities = true);
virtual ~NrIceCtx();
nr_ice_ctx *ctx() { return ctx_; }
@ -118,6 +164,10 @@ class NrIceCtx {
// Set whether we are controlling or not.
nsresult SetControlling(Controlling controlling);
// Set the STUN servers. Must be called before StartGathering
// (if at all).
nsresult SetStunServers(const std::vector<NrIceStunServer>& stun_servers);
// Start ICE gathering
nsresult StartGathering();
@ -139,15 +189,16 @@ class NrIceCtx {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceCtx)
private:
NrIceCtx(const std::string& name, bool offerer)
: state_(ICE_CTX_INIT),
name_(name),
offerer_(offerer),
streams_(),
ctx_(nullptr),
peer_(nullptr),
ice_handler_vtbl_(nullptr),
ice_handler_(nullptr) {}
NrIceCtx(const std::string& name,
bool offerer)
: state_(ICE_CTX_INIT),
name_(name),
offerer_(offerer),
streams_(),
ctx_(nullptr),
peer_(nullptr),
ice_handler_vtbl_(nullptr),
ice_handler_(nullptr) {}
DISALLOW_COPY_ASSIGN(NrIceCtx);

View File

@ -17,6 +17,7 @@
#include "nss.h"
#include "ssl.h"
#include "mozilla/Scoped.h"
#include "nsThreadUtils.h"
#include "nsXPCOM.h"
@ -75,6 +76,12 @@ class IceTestPeer : public sigslot::has_slots<> {
void Gather() {
nsresult res;
std::vector<NrIceStunServer> stun_servers;
ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create(
std::string((char *)"216.93.246.14"), 3478));
stun_servers.push_back(*server);
ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers)));
test_utils->sts_target()->Dispatch(
WrapRunnableRet(ice_ctx_, &NrIceCtx::StartGathering, &res),
NS_DISPATCH_SYNC);

View File

@ -112,6 +112,12 @@ class TransportTestPeer : public sigslot::has_slots<> {
peer_(nullptr),
gathering_complete_(false)
{
std::vector<NrIceStunServer> stun_servers;
ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create(
std::string((char *)"216.93.246.14"), 3478));
stun_servers.push_back(*server);
EXPECT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers)));
dtls_->SetIdentity(identity_);
dtls_->SetRole(name == "P2" ?
TransportLayerDtls::CLIENT :

View File

@ -112,6 +112,50 @@ int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
return(_status);
}
int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers,int ct)
{
int _status;
if(ctx->stun_servers){
RFREE(ctx->stun_servers);
ctx->stun_server_ct=0;
}
if (ct) {
if(!(ctx->stun_servers=RCALLOC(sizeof(nr_ice_stun_server)*ct)))
ABORT(R_NO_MEMORY);
memcpy(ctx->stun_servers,servers,sizeof(nr_ice_stun_server)*ct);
ctx->stun_server_ct = ct;
}
_status=0;
abort:
return(_status);
}
int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers,int ct)
{
int _status;
if(ctx->turn_servers){
RFREE(ctx->turn_servers);
ctx->turn_server_ct=0;
}
if(ct) {
if(!(ctx->turn_servers=RCALLOC(sizeof(nr_ice_turn_server)*ct)))
ABORT(R_NO_MEMORY);
memcpy(ctx->turn_servers,servers,sizeof(nr_ice_turn_server)*ct);
ctx->turn_server_ct = ct;
}
_status=0;
abort:
return(_status);
}
#ifdef USE_TURN
int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out)
{
@ -214,7 +258,7 @@ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
ABORT(r);
if(!(ctx->pwd=r_strdup(buf)))
ABORT(r);
/* Get the STUN servers */
if(r=NR_reg_get_child_count(NR_ICE_REG_STUN_SRV_PRFX,
(unsigned int *)&ctx->stun_server_ct)||ctx->stun_server_ct==0) {
@ -228,10 +272,12 @@ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
ctx->stun_server_ct=255;
}
if(r=nr_ice_fetch_stun_servers(ctx->stun_server_ct,&ctx->stun_servers)){
r_log(LOG_ICE,LOG_ERR,"Couldn't load STUN servers from registry");
ctx->turn_server_ct=0;
ABORT(r);
if(ctx->stun_server_ct>0){
if(r=nr_ice_fetch_stun_servers(ctx->stun_server_ct,&ctx->stun_servers)){
r_log(LOG_ICE,LOG_ERR,"Couldn't load STUN servers from registry");
ctx->stun_server_ct=0;
ABORT(r);
}
}
#ifdef USE_TURN
@ -252,10 +298,12 @@ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
}
#ifdef USE_TURN
if(r=nr_ice_fetch_turn_servers(ctx->turn_server_ct,&ctx->turn_servers)){
ctx->turn_server_ct=0;
r_log(LOG_ICE,LOG_ERR,"Couldn't load TURN servers from registry");
ABORT(r);
if(ctx->turn_server_ct>0){
if(r=nr_ice_fetch_turn_servers(ctx->turn_server_ct,&ctx->turn_servers)){
ctx->turn_server_ct=0;
r_log(LOG_ICE,LOG_ERR,"Couldn't load TURN servers from registry");
ABORT(r);
}
}
#endif /* USE_TURN */

View File

@ -147,6 +147,8 @@ int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transp
int nr_ice_ctx_is_known_id(nr_ice_ctx *ctx, UCHAR id[12]);
int nr_ice_ctx_remember_id(nr_ice_ctx *ctx, nr_stun_message *msg);
int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx);
int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers, int ct);
int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers, int ct);
extern int LOG_ICE;

View File

@ -78,6 +78,23 @@ nsresult PeerConnectionMedia::Init()
return NS_ERROR_FAILURE;
}
// Temporarily hardwire the ICE server.
// TODO(ekr@rtfm.com): Remove this when we have ICE configuration
// settings.
std::vector<NrIceStunServer> stun_servers;
ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create(
std::string((char *)"216.93.246.14"), 3478));
MOZ_ASSERT(server);
if (!server) {
CSFLogErrorS(logTag, __FUNCTION__ << ": Could not parse STUN server string");
return NS_ERROR_FAILURE;
}
stun_servers.push_back(*server);
nsresult rv = mIceCtx->SetStunServers(stun_servers);
if (NS_FAILED(rv))
return rv;
mIceCtx->SignalGatheringCompleted.connect(this,
&PeerConnectionMedia::IceGatheringCompleted);
mIceCtx->SignalCompleted.connect(this,