diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js index d2f098b1fa..77b7a58980 100644 --- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -588,7 +588,7 @@ RTCPeerConnection.prototype = { throw new this._win.DOMException(msg + " - improper scheme: " + url.scheme, "SyntaxError"); } - if (url.scheme in { stuns:1, turns:1 }) { + if (url.scheme in { stuns:1 }) { this.logWarning(url.scheme.toUpperCase() + " is not yet supported."); } }); diff --git a/dom/media/tests/mochitest/addTurnsSelfsignedCert.js b/dom/media/tests/mochitest/addTurnsSelfsignedCert.js new file mode 100644 index 0000000000..cad3d04465 --- /dev/null +++ b/dom/media/tests/mochitest/addTurnsSelfsignedCert.js @@ -0,0 +1,26 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +var { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +// This is only usable from the parent process, even for doing simple stuff like +// serializing a cert. +var gCertMaker = Cc["@mozilla.org/security/x509certdb;1"]. + getService(Ci.nsIX509CertDB); + +var gCertOverrides = Cc["@mozilla.org/security/certoverride;1"]. + getService(Ci.nsICertOverrideService); + + +addMessageListener('add-turns-certs', certs => { + var port = 5349; + certs.forEach(certDescription => { + var cert = gCertMaker.constructX509FromBase64(certDescription.cert); + gCertOverrides.rememberValidityOverride(certDescription.hostname, port, + cert, Ci.nsICertOverrideService.ERROR_UNTRUSTED, false); + }); + sendAsyncMessage('certs-added'); +}); diff --git a/dom/media/tests/mochitest/mochitest.ini b/dom/media/tests/mochitest/mochitest.ini index a492979db5..fc749de973 100644 --- a/dom/media/tests/mochitest/mochitest.ini +++ b/dom/media/tests/mochitest/mochitest.ini @@ -13,6 +13,7 @@ support-files = blacksilence.js turnConfig.js sdpUtils.js + addTurnsSelfsignedCert.js !/dom/canvas/test/captureStream_common.js !/dom/canvas/test/webgl-mochitest/webgl-util.js !/dom/media/test/manifest.js @@ -97,6 +98,8 @@ skip-if = toolkit == 'android' # websockets don't work on android (bug 1266217) skip-if = toolkit == 'android' # websockets don't work on android (bug 1266217) [test_peerConnection_basicAudioNATRelayTCP.html] skip-if = toolkit == 'android' # websockets don't work on android (bug 1266217) +[test_peerConnection_basicAudioNATRelayTLS.html] +skip-if = true # need pyopenssl on builders, see bug 1323439 [test_peerConnection_basicAudioRequireEOC.html] skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator) [test_peerConnection_basicAudioPcmaPcmuOnly.html] diff --git a/dom/media/tests/mochitest/pc.js b/dom/media/tests/mochitest/pc.js index 84714b9626..6de16d271e 100644 --- a/dom/media/tests/mochitest/pc.js +++ b/dom/media/tests/mochitest/pc.js @@ -1869,6 +1869,33 @@ function createHTML(options) { var iceServerWebsocket; var iceServersArray = []; +var addTurnsSelfsignedCerts = () => { + var gUrl = SimpleTest.getTestFileURL('addTurnsSelfsignedCert.js'); + var gScript = SpecialPowers.loadChromeScript(gUrl); + var certs = []; + // If the ICE server is running TURNS, and includes a "cert" attribute in + // its JSON, we set up an override that will forgive things like + // self-signed for it. + iceServersArray.forEach(iceServer => { + if (iceServer.hasOwnProperty("cert")) { + iceServer.urls.forEach(url => { + if (url.startsWith("turns:")) { + // Assumes no port or params! + certs.push({"cert": iceServer.cert, "hostname": url.substr(6)}); + } + }); + } + }); + + return new Promise((resolve, reject) => { + gScript.addMessageListener('certs-added', () => { + resolve(); + }); + + gScript.sendAsyncMessage('add-turns-certs', certs); + }); +}; + var setupIceServerConfig = useIceServer => { // We disable ICE support for HTTP proxy when using a TURN server, because // mochitest uses a fake HTTP proxy to serve content, which will eat our STUN @@ -1910,7 +1937,8 @@ var setupIceServerConfig = useIceServer => { return enableHttpProxy(false) .then(spawnIceServer) - .then(iceServersStr => { iceServersArray = JSON.parse(iceServersStr); }); + .then(iceServersStr => { iceServersArray = JSON.parse(iceServersStr); }) + .then(addTurnsSelfsignedCerts); }; function runNetworkTest(testFunction, fixtureOptions) { diff --git a/dom/media/tests/mochitest/test_peerConnection_basicAudioNATRelayTLS.html b/dom/media/tests/mochitest/test_peerConnection_basicAudioNATRelayTLS.html new file mode 100644 index 0000000000..c295955d81 --- /dev/null +++ b/dom/media/tests/mochitest/test_peerConnection_basicAudioNATRelayTLS.html @@ -0,0 +1,38 @@ + + + + + + +
+
+
+ + diff --git a/dom/media/webaudio/blink/DynamicsCompressor.h b/dom/media/webaudio/blink/DynamicsCompressor.h index f460836b49..24f4fc7f71 100644 --- a/dom/media/webaudio/blink/DynamicsCompressor.h +++ b/dom/media/webaudio/blink/DynamicsCompressor.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2011 Google Inc. + * Copyright (C) 2022 Moonchild Productions. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -104,7 +105,7 @@ protected: float m_lastAnchor; float m_lastFilterStageGain; - typedef struct { + typedef struct ZeroPoleFilterPack4 { ZeroPole filters[4]; size_t sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { diff --git a/dom/network/PTCPSocket.ipdl b/dom/network/PTCPSocket.ipdl index aa7c51e45f..ea00856029 100644 --- a/dom/network/PTCPSocket.ipdl +++ b/dom/network/PTCPSocket.ipdl @@ -44,7 +44,8 @@ parent: // address specified in |localAddr| and |localPort|. async OpenBind(nsCString host, uint16_t port, nsCString localAddr, uint16_t localPort, - bool useSSL, bool aUseArrayBuffers, nsCString aFilter); + bool useSSL, bool reuseAddrPort, + bool aUseArrayBuffers, nsCString aFilter); // When child's send() is called, this message requrests parent to send // data and update it's trackingNumber. diff --git a/dom/network/TCPSocketChild.cpp b/dom/network/TCPSocketChild.cpp index 9e1dce2769..b2b8db78a3 100644 --- a/dom/network/TCPSocketChild.cpp +++ b/dom/network/TCPSocketChild.cpp @@ -108,7 +108,7 @@ void TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket, const nsACString& aRemoteHost, uint16_t aRemotePort, const nsACString& aLocalHost, uint16_t aLocalPort, - bool aUseSSL) + bool aUseSSL, bool aReuseAddrPort) { mSocket = aSocket; AddIPDLReference(); @@ -117,7 +117,8 @@ TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket, aRemotePort); PTCPSocketChild::SendOpenBind(nsCString(aRemoteHost), aRemotePort, nsCString(aLocalHost), aLocalPort, - aUseSSL, true, mFilterName); + aUseSSL, aReuseAddrPort, + true, mFilterName); } void diff --git a/dom/network/TCPSocketChild.h b/dom/network/TCPSocketChild.h index 7e9b59e8b5..46e9b0a90f 100644 --- a/dom/network/TCPSocketChild.h +++ b/dom/network/TCPSocketChild.h @@ -55,7 +55,7 @@ public: void SendWindowlessOpenBind(nsITCPSocketCallback* aSocket, const nsACString& aRemoteHost, uint16_t aRemotePort, const nsACString& aLocalHost, uint16_t aLocalPort, - bool aUseSSL); + bool aUseSSL, bool aUseRealtimeOptions); NS_IMETHOD SendSendArray(nsTArray& aArray, uint32_t aTrackingNumber); void SendSend(const nsACString& aData, uint32_t aTrackingNumber); diff --git a/dom/network/TCPSocketParent.cpp b/dom/network/TCPSocketParent.cpp index 313d13f759..96eab44510 100644 --- a/dom/network/TCPSocketParent.cpp +++ b/dom/network/TCPSocketParent.cpp @@ -149,6 +149,7 @@ TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost, const nsCString& aLocalAddr, const uint16_t& aLocalPort, const bool& aUseSSL, + const bool& aReuseAddrPort, const bool& aUseArrayBuffers, const nsCString& aFilter) { @@ -167,14 +168,27 @@ TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost, } nsCOMPtr socketTransport; - rv = sts->CreateTransport(nullptr, 0, - aRemoteHost, aRemotePort, - nullptr, getter_AddRefs(socketTransport)); + if (aUseSSL) { + const char* socketTypes[1]; + socketTypes[0] = "ssl"; + rv = sts->CreateTransport(socketTypes, 1, + aRemoteHost, aRemotePort, + nullptr, getter_AddRefs(socketTransport)); + } else { + rv = sts->CreateTransport(nullptr, 0, + aRemoteHost, aRemotePort, + nullptr, getter_AddRefs(socketTransport)); + } + if (NS_FAILED(rv)) { FireInteralError(this, __LINE__); return true; } + // in most cases aReuseAddrPort is false, but ICE TCP needs + // sockets options set that allow addr/port reuse + socketTransport->SetReuseAddrPort(aReuseAddrPort); + PRNetAddr prAddr; if (PR_SUCCESS != PR_InitializeNetAddr(PR_IpAddrAny, aLocalPort, &prAddr)) { FireInteralError(this, __LINE__); diff --git a/dom/network/TCPSocketParent.h b/dom/network/TCPSocketParent.h index 07112f1e2d..e0f987b17f 100644 --- a/dom/network/TCPSocketParent.h +++ b/dom/network/TCPSocketParent.h @@ -54,6 +54,7 @@ public: const nsCString& aLocalAddr, const uint16_t& aLocalPort, const bool& aUseSSL, + const bool& aReuseAddrPort, const bool& aUseArrayBuffers, const nsCString& aFilter) override; diff --git a/gfx/gl/GLContextGLX.h b/gfx/gl/GLContextGLX.h index f7dd90c2b5..d431116756 100644 --- a/gfx/gl/GLContextGLX.h +++ b/gfx/gl/GLContextGLX.h @@ -25,8 +25,7 @@ public: Display* display, GLXDrawable drawable, GLXFBConfig cfg, - bool deleteDrawable, - gfxXlibSurface* pixmap = nullptr, + Drawable ownedPixmap = X11None, ContextProfile profile = ContextProfile::OpenGLCompatibility); // Finds a GLXFBConfig compatible with the provided window. @@ -77,25 +76,26 @@ private: Display* aDisplay, GLXDrawable aDrawable, GLXContext aContext, - bool aDeleteDrawable, bool aDoubleBuffered, - gfxXlibSurface* aPixmap, - ContextProfile profile); + ContextProfile profile, + Drawable aOwnedPixmap = X11None); GLXContext mContext; Display* mDisplay; GLXDrawable mDrawable; Maybe mOverrideDrawable; - bool mDeleteDrawable; + // The X pixmap associated with the GLX pixmap. If this is provided, then + // this class assumes responsibility for freeing both. Otherwise, the + // user of this class is responsibile for freeing the drawables. + const Drawable mOwnedPixmap; bool mDoubleBuffered; GLXLibrary* mGLX; - RefPtr mPixmap; bool mOwnsContext; }; -} -} +} // namespace gl +} // namespace mozilla #endif // GLCONTEXTGLX_H_ diff --git a/gfx/gl/GLContextProviderGLX.cpp b/gfx/gl/GLContextProviderGLX.cpp index c44b1a9f06..27d07e391d 100644 --- a/gfx/gl/GLContextProviderGLX.cpp +++ b/gfx/gl/GLContextProviderGLX.cpp @@ -327,7 +327,7 @@ GLXLibrary::CreatePixmap(gfxASurface* aSurface) X11None }; int numConfigs = 0; - Display* display = xs->XDisplay(); + Display *display = xs->XDisplay(); int xscreen = DefaultScreen(display); ScopedXFree cfgs(xChooseFBConfig(display, @@ -800,7 +800,7 @@ already_AddRefed GLContextGLX::CreateGLContext(CreateContextFlags flags, const SurfaceCaps& caps, GLContextGLX* shareContext, bool isOffscreen, Display* display, GLXDrawable drawable, GLXFBConfig cfg, - bool deleteDrawable, gfxXlibSurface* pixmap, + Drawable ownedPixmap, ContextProfile profile) { GLXLibrary& glx = sGLXLibrary; @@ -860,8 +860,7 @@ GLContextGLX::CreateGLContext(CreateContextFlags flags, const SurfaceCaps& caps, if (context) { glContext = new GLContextGLX(flags, caps, shareContext, isOffscreen, display, - drawable, context, deleteDrawable, db, pixmap, - profile); + drawable, context, db, profile, ownedPixmap); if (!glContext->Init()) error = true; } else { @@ -896,8 +895,9 @@ GLContextGLX::~GLContextGLX() mGLX->xDestroyContext(mDisplay, mContext); - if (mDeleteDrawable) { + if (mOwnedPixmap) { mGLX->xDestroyPixmap(mDisplay, mDrawable); + XFreePixmap(mDisplay, mOwnedPixmap); } MOZ_ASSERT(!mOverrideDrawable); } @@ -1035,18 +1035,16 @@ GLContextGLX::GLContextGLX( Display* aDisplay, GLXDrawable aDrawable, GLXContext aContext, - bool aDeleteDrawable, bool aDoubleBuffered, - gfxXlibSurface* aPixmap, - ContextProfile profile) + ContextProfile profile, + Drawable aOwnedPixmap) : GLContext(flags, caps, shareContext, isOffscreen), mContext(aContext), mDisplay(aDisplay), mDrawable(aDrawable), - mDeleteDrawable(aDeleteDrawable), + mOwnedPixmap(aOwnedPixmap), mDoubleBuffered(aDoubleBuffered), mGLX(&sGLXLibrary), - mPixmap(aPixmap), mOwnsContext(true) { MOZ_ASSERT(mGLX); @@ -1098,10 +1096,9 @@ GLContextProviderGLX::CreateWrappingExisting(void* aContext, void* aSurface) false, // Offscreen (Display*)DefaultXDisplay(), // Display (GLXDrawable)aSurface, (GLXContext)aContext, - false, // aDeleteDrawable, true, - (gfxXlibSurface*)nullptr, - ContextProfile::OpenGLCompatibility); + ContextProfile::OpenGLCompatibility, + (Drawable)nullptr); glContext->mOwnsContext = false; gGlobalContext = glContext; @@ -1146,8 +1143,7 @@ CreateForWidget(Display* aXDisplay, Window aXWindow, bool aForceAccelerated) GLContextGLX* shareContext = GetGlobalContextGLX(); RefPtr gl = GLContextGLX::CreateGLContext(CreateContextFlags::NONE, caps, shareContext, false, - aXDisplay, aXWindow, config, - false); + aXDisplay, aXWindow, config); return gl.forget(); } @@ -1326,24 +1322,20 @@ CreateOffscreenPixmapContext(CreateContextFlags flags, const IntSize& size, FindVisualAndDepth(display, visid, &visual, &depth); OffMainThreadScopedXErrorHandler xErrorHandler; - bool error = false; - Drawable drawable; GLXPixmap pixmap = 0; gfx::IntSize dummySize(16, 16); - RefPtr surface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display), - visual, - dummySize); - if (surface->CairoStatus() != 0) { - mozilla::Unused << xErrorHandler.SyncAndGetError(display); - return nullptr; + const auto drawable = + XCreatePixmap(display, DefaultRootWindow(display), + dummySize.width, dummySize.height, depth); + if (!drawable) { + mozilla::Unused << xErrorHandler.SyncAndGetError(display); + return nullptr; } - // Handle slightly different signature between glXCreatePixmap and // its pre-GLX-1.3 extension equivalent (though given the ABI, we // might not need to). - drawable = surface->XDrawable(); if (glx->GLXVersionCheck(1, 3)) { pixmap = glx->xCreatePixmap(display, config, drawable, nullptr); } else { @@ -1351,16 +1343,17 @@ CreateOffscreenPixmapContext(CreateContextFlags flags, const IntSize& size, } if (pixmap == 0) { - error = true; + XFreePixmap(display, drawable); + return nullptr; } bool serverError = xErrorHandler.SyncAndGetError(display); - if (error || serverError) + if (serverError) return nullptr; GLContextGLX* shareContext = GetGlobalContextGLX(); return GLContextGLX::CreateGLContext(flags, minCaps, shareContext, true, display, - pixmap, config, true, surface, profile); + pixmap, config, drawable, profile); } /*static*/ already_AddRefed diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index 6b55935248..73d1741922 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -731,8 +731,7 @@ public: false, mXDisplay, root, - config, - false); + config); if (!mGLContext) { lock.NotifyAll(); diff --git a/js/src/builtin/Array.js b/js/src/builtin/Array.js index 05fc41bc14..1e7776e228 100644 --- a/js/src/builtin/Array.js +++ b/js/src/builtin/Array.js @@ -833,7 +833,7 @@ function ArrayFrom(items, mapfn=undefined, thisArg=undefined) { } // Step 7. - assert(usingIterator === undefined, "`items` can't be an Iterable after step 6.g.iv"); + assert(usingIterator === undefined, "`items` cannot be an Iterable after step 6.g.iv"); // Steps 8-9. var arrayLike = ToObject(items); @@ -1181,6 +1181,35 @@ function FlattenIntoArray(target, source, sourceLen, start, depth, mapperFunctio return targetIndex; } +// ES2022 at() method on the built-in indexables +// Array.prototype.at(index) +function ArrayAt(index) { + // Step 1. + var O = ToObject(this); + + // Step 2. + var len = ToLength(O.length); + + // Step 3. + var relativeIndex = ToInteger(index); + + // Steps 4-5. + var k; + if (relativeIndex >= 0) { + k = relativeIndex; + } else { + k = len + relativeIndex; + } + + // Step 6. + if (k < 0 || k >= len) { + return undefined; + } + + // Step 7. + return O[k]; +} + function ArrayStaticConcat(arr, arg1) { if (arguments.length < 1) ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.concat'); diff --git a/js/src/builtin/String.js b/js/src/builtin/String.js index 233a7323b2..b0928fe88c 100644 --- a/js/src/builtin/String.js +++ b/js/src/builtin/String.js @@ -784,6 +784,39 @@ function String_static_raw(callSite, ...substitutions) { } } +// ES2022 at() method on the built-in indexables +// String.prototype.at(index) +function String_at(index) { + // Step 1. + if (this === undefined || this === null) + ThrowIncompatibleMethod("at", this); + + // Step 2. + var string = ToString(this); + + // Step 3. + var len = string.length; + + // Step 4. + var relativeIndex = ToInteger(index); + + // Steps 5-6. + var k; + if (relativeIndex >= 0) { + k = relativeIndex; + } else { + k = len + relativeIndex; + } + + // Step 7. + if (k < 0 || k >= len) { + return undefined; + } + + // Step 8. + return string[k]; +} + /** * Compare String str1 against String str2, using the locale and collation * options provided. diff --git a/js/src/builtin/TypedArray.js b/js/src/builtin/TypedArray.js index a1934051da..5b7a1dfc22 100644 --- a/js/src/builtin/TypedArray.js +++ b/js/src/builtin/TypedArray.js @@ -1308,6 +1308,45 @@ function TypedArraySubarray(begin, end) { return TypedArraySpeciesCreateWithBuffer(obj, buffer, beginByteOffset, newLength); } +// ES2022 at() method on the built-in indexables +// %TypedArray%.prototype.at(index) +function TypedArrayAt(index) { + // Step 1. + var obj = this; + + // Step 2. + // This function is not generic. + if (!IsObject(obj) || !IsTypedArray(obj)) { + return callFunction(CallTypedArrayMethodIfWrapped, obj, index, + "TypedArrayAt"); + } + GetAttachedArrayBuffer(obj); + + // If we got here, `this` is either a typed array or a wrapper for one. + + // Step 3. + var len = TypedArrayLength(obj); + + // Step 4. + var relativeIndex = ToInteger(index); + + // Steps 5-6. + var k; + if (relativeIndex >= 0) { + k = relativeIndex; + } else { + k = len + relativeIndex; + } + + // Step 7. + if (k < 0 || k >= len) { + return undefined; + } + + // Step 8. + return obj[k]; +} + // ES6 draft rev30 (2014/12/24) 22.2.3.30 %TypedArray%.prototype.values() function TypedArrayValues() { // Step 1. diff --git a/js/src/gc/StoreBuffer.h b/js/src/gc/StoreBuffer.h index ade111739d..f9158ef9c2 100644 --- a/js/src/gc/StoreBuffer.h +++ b/js/src/gc/StoreBuffer.h @@ -332,7 +332,7 @@ class StoreBuffer explicit operator bool() const { return objectAndKind_ != 0; } - typedef struct { + typedef struct Hasher { typedef SlotsEdge Lookup; static HashNumber hash(const Lookup& l) { return l.objectAndKind_ ^ l.start_ ^ l.count_; } static bool match(const SlotsEdge& k, const Lookup& l) { return k == l; } diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index a1b9f74b4f..912f393942 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -3189,6 +3189,9 @@ static const JSFunctionSpec array_methods[] = { JS_SELF_HOSTED_FN("flat", "ArrayFlat", 0,0), JS_SELF_HOSTED_FN("flatMap", "ArrayFlatMap", 1,0), + /* ES2022 additions */ + JS_SELF_HOSTED_FN("at", "ArrayAt", 1,0), + JS_FS_END }; diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 6eb11b1cc1..4167d78741 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -2847,6 +2847,9 @@ static const JSFunctionSpec string_methods[] = { /* Python-esque sequence methods. */ JS_FN("concat", str_concat, 1,0), JS_SELF_HOSTED_FN("slice", "String_slice", 2,0), + + /* ES2022 additions */ + JS_SELF_HOSTED_FN("at", "String_at", 1,0), /* HTML string methods. */ JS_SELF_HOSTED_FN("bold", "String_bold", 0,0), diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 84d73411bf..1b8a1089ae 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -1538,6 +1538,10 @@ TypedArrayObject::protoFunctions[] = { JS_SELF_HOSTED_FN("includes", "TypedArrayIncludes", 2, 0), JS_SELF_HOSTED_FN("toString", "ArrayToString", 0, 0), JS_SELF_HOSTED_FN("toLocaleString", "TypedArrayToLocaleString", 2, 0), + + /* ES2022 additions */ + JS_SELF_HOSTED_FN("at", "TypedArrayAt", 1, 0), + JS_FS_END }; diff --git a/media/mtransport/nr_socket_prsock.cpp b/media/mtransport/nr_socket_prsock.cpp index 80e5ef51e4..3fd223349c 100644 --- a/media/mtransport/nr_socket_prsock.cpp +++ b/media/mtransport/nr_socket_prsock.cpp @@ -858,6 +858,10 @@ int NrSocket::connect(nr_transport_addr *addr) { PRNetAddr naddr; int32_t connect_status, getsockname_status; + // TODO: Add TLS layer with nsISocketProviderService? + if (addr->tls_host[0] != '\0') + ABORT(R_INTERNAL); + if ((r=nr_transport_addr_to_praddr(addr, &naddr))) ABORT(r); @@ -1840,7 +1844,7 @@ void NrTcpSocketIpc::close() { } int NrTcpSocketIpc::connect(nr_transport_addr *addr) { - nsCString remote_addr, local_addr; + nsCString remote_addr, local_addr, tls_host; int32_t remote_port, local_port; int r, _status; if ((r=nr_transport_addr_get_addrstring_and_port(addr, @@ -1856,6 +1860,8 @@ int NrTcpSocketIpc::connect(nr_transport_addr *addr) { ABORT(r); } + tls_host = addr->tls_host; + state_ = mirror_state_ = NR_CONNECTING; RUN_ON_THREAD(io_thread_, mozilla::WrapRunnable(RefPtr(this), @@ -1863,7 +1869,8 @@ int NrTcpSocketIpc::connect(nr_transport_addr *addr) { remote_addr, static_cast(remote_port), local_addr, - static_cast(local_port)), + static_cast(local_port), + tls_host), NS_DISPATCH_NORMAL); // Make caller wait for ready to write. @@ -1939,7 +1946,8 @@ int NrTcpSocketIpc::accept(nr_transport_addr *addrp, nr_socket **sockp) { void NrTcpSocketIpc::connect_i(const nsACString &remote_addr, uint16_t remote_port, const nsACString &local_addr, - uint16_t local_port) { + uint16_t local_port, + const nsACString &tls_host) { ASSERT_ON_THREAD(io_thread_); mirror_state_ = NR_CONNECTING; @@ -1948,11 +1956,21 @@ void NrTcpSocketIpc::connect_i(const nsACString &remote_addr, // Bug 1285330: put filtering back in here - // XXX remove remote! - socket_child_->SendWindowlessOpenBind(this, - remote_addr, remote_port, - local_addr, local_port, - /* use ssl */ false); + if (tls_host.IsEmpty()) { + // XXX remove remote! + socket_child_->SendWindowlessOpenBind(this, + remote_addr, remote_port, + local_addr, local_port, + /* use ssl */ false, + /* reuse addr port */ true); + } else { + // XXX remove remote! + socket_child_->SendWindowlessOpenBind(this, + tls_host, remote_port, + local_addr, local_port, + /* use ssl */ true, + /* reuse addr port */ true); + } } void NrTcpSocketIpc::write_i(nsAutoPtr> arr, diff --git a/media/mtransport/nr_socket_prsock.h b/media/mtransport/nr_socket_prsock.h index 5ed9a6a219..7d372ccb16 100644 --- a/media/mtransport/nr_socket_prsock.h +++ b/media/mtransport/nr_socket_prsock.h @@ -369,7 +369,8 @@ private: void connect_i(const nsACString &remote_addr, uint16_t remote_port, const nsACString &local_addr, - uint16_t local_port); + uint16_t local_port, + const nsACString &tls_host); void write_i(nsAutoPtr> buf, uint32_t tracking_number); void close_i(); diff --git a/media/mtransport/nricectx.cpp b/media/mtransport/nricectx.cpp index be50f50169..75d3d2519d 100644 --- a/media/mtransport/nricectx.cpp +++ b/media/mtransport/nricectx.cpp @@ -108,6 +108,7 @@ MOZ_MTLOG_MODULE("mtransport") const char kNrIceTransportUdp[] = "udp"; const char kNrIceTransportTcp[] = "tcp"; +const char kNrIceTransportTls[] = "tls"; static bool initialized = false; @@ -210,6 +211,9 @@ nsresult NrIceStunServer::ToNicerStunStruct(nr_ice_stun_server *server) const { server->transport = IPPROTO_UDP; } else if (transport_ == kNrIceTransportTcp) { server->transport = IPPROTO_TCP; + } else if (transport_ == kNrIceTransportTls) { + server->transport = IPPROTO_TCP; + server->tls = 1; } else { MOZ_MTLOG(ML_ERROR, "Unsupported STUN server transport: " << transport_); return NS_ERROR_FAILURE; @@ -586,6 +590,7 @@ NrIceCtx::Initialize(const std::string& ufrag, nsCString mapping_type; nsCString filtering_type; bool block_udp = false; + bool block_tcp = false; nsresult rv; nsCOMPtr pref_service = @@ -604,6 +609,9 @@ NrIceCtx::Initialize(const std::string& ufrag, rv = pref_branch->GetBoolPref( "media.peerconnection.nat_simulator.block_udp", &block_udp); + rv = pref_branch->GetBoolPref( + "media.peerconnection.nat_simulator.block_tcp", + &block_tcp); } } @@ -614,6 +622,7 @@ NrIceCtx::Initialize(const std::string& ufrag, test_nat->filtering_type_ = TestNat::ToNatBehavior(filtering_type.get()); test_nat->mapping_type_ = TestNat::ToNatBehavior(mapping_type.get()); test_nat->block_udp_ = block_udp; + test_nat->block_tcp_ = block_tcp; test_nat->enabled_ = true; SetNat(test_nat); } diff --git a/media/mtransport/nricectx.h b/media/mtransport/nricectx.h index ce104ac317..87122121e5 100644 --- a/media/mtransport/nricectx.h +++ b/media/mtransport/nricectx.h @@ -90,6 +90,7 @@ class NrIceMediaStream; extern const char kNrIceTransportUdp[]; extern const char kNrIceTransportTcp[]; +extern const char kNrIceTransportTls[]; class NrIceStunServer { public: diff --git a/media/mtransport/test_nr_socket.cpp b/media/mtransport/test_nr_socket.cpp index e7dad79cd1..fb2de3096e 100644 --- a/media/mtransport/test_nr_socket.cpp +++ b/media/mtransport/test_nr_socket.cpp @@ -200,6 +200,7 @@ int TestNat::create_socket_factory(nr_socket_factory **factorypp) { TestNrSocket::TestNrSocket(TestNat *nat) : nat_(nat), + tls_(false), timer_handle_(nullptr) { nat_->insert_socket(this); } @@ -473,6 +474,10 @@ int TestNrSocket::connect(nr_transport_addr *addr) { return R_INTERNAL; } + if (addr->tls_host[0] != '\0') { + tls_ = true; + } + if (!nat_->enabled_ || addr->protocol==IPPROTO_UDP // Horrible hack to allow default address // discovery to work. Only works because @@ -508,6 +513,24 @@ int TestNrSocket::connect(nr_transport_addr *addr) { } int TestNrSocket::write(const void *msg, size_t len, size_t *written) { + UCHAR *buf = static_cast(const_cast(msg)); + if (nat_->block_stun_ && nr_is_stun_message(buf, len)) { + // Should cause this socket to be abandoned + r_log(LOG_GENERIC, LOG_DEBUG, + "TestNrSocket %s dropping outgoing TCP " + "because it is configured to drop STUN", + my_addr().as_string); + return R_INTERNAL; + } + + if (nat_->block_tcp_ && !tls_) { + // Should cause this socket to be abandoned + r_log(LOG_GENERIC, LOG_DEBUG, + "TestNrSocket %s dropping outgoing TCP " + "because it is configured to drop TCP", + my_addr().as_string); + return R_INTERNAL; + } if (port_mappings_.empty()) { // The no-nat case, just pass call through. @@ -518,7 +541,11 @@ int TestNrSocket::write(const void *msg, size_t len, size_t *written) { } else { destroy_stale_port_mappings(); if (port_mappings_.empty()) { - return -1; + r_log(LOG_GENERIC, LOG_DEBUG, + "TestNrSocket %s dropping outgoing TCP " + "because the port mapping was stale", + my_addr().as_string); + return R_INTERNAL; } // This is TCP only MOZ_ASSERT(port_mappings_.size() == 1); @@ -533,18 +560,34 @@ int TestNrSocket::write(const void *msg, size_t len, size_t *written) { } int TestNrSocket::read(void *buf, size_t maxlen, size_t *len) { + int r; if (port_mappings_.empty()) { - return internal_socket_->read(buf, maxlen, len); + r = internal_socket_->read(buf, maxlen, len); } else { MOZ_ASSERT(port_mappings_.size() == 1); - int bytesRead = - port_mappings_.front()->external_socket_->read(buf, maxlen, len); - if (bytesRead > 0 && nat_->refresh_on_ingress_) { + r = port_mappings_.front()->external_socket_->read(buf, maxlen, len); + if (!r && nat_->refresh_on_ingress_) { port_mappings_.front()->last_used_ = PR_IntervalNow(); } - return bytesRead; } + + if (r) { + return r; + } + + if (nat_->block_tcp_ && !tls_) { + // Should cause this socket to be abandoned + return R_INTERNAL; + } + + UCHAR *cbuf = static_cast(const_cast(buf)); + if (nat_->block_stun_ && nr_is_stun_message(cbuf, *len)) { + // Should cause this socket to be abandoned + return R_INTERNAL; + } + + return r; } int TestNrSocket::async_wait(int how, NR_async_cb cb, void *cb_arg, diff --git a/media/mtransport/test_nr_socket.h b/media/mtransport/test_nr_socket.h index 91c9030f17..a47a88beb9 100644 --- a/media/mtransport/test_nr_socket.h +++ b/media/mtransport/test_nr_socket.h @@ -137,6 +137,7 @@ class TestNat { refresh_on_ingress_(false), block_udp_(false), block_stun_(false), + block_tcp_(false), delay_stun_resp_ms_(0), sockets_() {} @@ -168,6 +169,7 @@ class TestNat { bool refresh_on_ingress_; bool block_udp_; bool block_stun_; + bool block_tcp_; /* Note: this can only delay a single response so far (bug 1253657) */ uint32_t delay_stun_resp_ms_; @@ -319,6 +321,7 @@ class TestNrSocket : public NrSocketBase { // same nat. RefPtr internal_socket_; RefPtr nat_; + bool tls_; // Since our comparison logic is different depending on what kind of NAT // we simulate, and the STL does not make it very easy to switch out the // comparison function at runtime, and these lists are going to be very diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c index e48b7b5e1a..879b77933e 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c @@ -666,6 +666,14 @@ static int nr_ice_candidate_resolved_cb(void *cb_arg, nr_transport_addr *addr) if(r=nr_transport_addr_copy(&cand->stun_server_addr,addr)) ABORT(r); + if (cand->stun_server->tls) { + /* Copy over the DNS name; needed for TLS. There is already a null at the + * end of the buffer, leave it there. */ + strncpy(cand->stun_server_addr.tls_host, + cand->stun_server->u.dnsname.host, + sizeof(cand->stun_server_addr.tls_host) - 1); + } + if (cand->tcp_type == TCP_TYPE_PASSIVE || cand->tcp_type == TCP_TYPE_SO){ if (r=nr_socket_multi_tcp_stun_server_connect(cand->osock, addr)) ABORT(r); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h index cc79304f08..1e815ac2ac 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h @@ -63,6 +63,7 @@ typedef struct nr_ice_stun_server_ { } u; int id; int transport; + int tls; /* Whether to use TLS or not */ } nr_ice_stun_server; typedef struct nr_ice_turn_server_ { diff --git a/media/mtransport/third_party/nICEr/src/net/transport_addr.h b/media/mtransport/third_party/nICEr/src/net/transport_addr.h index dfec633291..06c8b8c9c5 100644 --- a/media/mtransport/third_party/nICEr/src/net/transport_addr.h +++ b/media/mtransport/third_party/nICEr/src/net/transport_addr.h @@ -66,6 +66,7 @@ typedef struct nr_transport_addr_ { /* A string version. 56 = 5 ("IP6:[") + 39 (ipv6 address) + 2 ("]:") + 5 (port) + 4 (/UDP) + 1 (null) */ char as_string[56]; + char tls_host[256]; } nr_transport_addr; typedef struct nr_transport_addr_mask_ { diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp index 27146ce362..1d0614b6b0 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -335,6 +335,7 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal) , mSTSThread(nullptr) , mAllowIceLoopback(false) , mAllowIceLinkLocal(false) + , mForceIceTcp(false) , mMedia(nullptr) , mUuidGen(MakeUnique()) , mNumAudioStreams(0) @@ -365,6 +366,8 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal) "media.peerconnection.ice.loopback", false); mAllowIceLinkLocal = Preferences::GetBool( "media.peerconnection.ice.link_local", false); + mForceIceTcp = Preferences::GetBool( + "media.peerconnection.ice.force_ice_tcp", false); #endif memset(mMaxReceiving, 0, sizeof(mMaxReceiving)); memset(mMaxSending, 0, sizeof(mMaxSending)); @@ -527,8 +530,8 @@ PeerConnectionConfiguration::AddIceServer(const RTCIceServer &aServer) if (!(isStun || isStuns || isTurn || isTurns)) { return NS_ERROR_FAILURE; } - if (isTurns || isStuns) { - continue; // TODO: Support TURNS and STUNS (Bug 1056934) + if (isStuns) { + continue; // TODO: Support STUNS (Bug 1056934) } nsAutoCString spec; rv = url->GetSpec(spec); @@ -577,6 +580,11 @@ PeerConnectionConfiguration::AddIceServer(const RTCIceServer &aServer) if (port == -1) port = (isStuns || isTurns)? 5349 : 3478; + if (isStuns || isTurns) { + // Should we barf if transport is set to udp or something? + transport = "tls"; + } + // First check the known good ports for webrtc bool knownGoodPort = false; for (int i = 0; !knownGoodPort && gGoodWebrtcPortList[i]; i++) { @@ -2256,6 +2264,11 @@ NS_IMETHODIMP PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, unsigned short aLevel) { PC_AUTO_ENTER_API_CALL(true); + if (mForceIceTcp && std::string::npos != std::string(aCandidate).find(" UDP ")) { + CSFLogError(logTag, "Blocking remote UDP candidate: %s", aCandidate); + return NS_OK; + } + JSErrorResult rv; RefPtr pco = do_QueryObjectReferent(mPCObserver); if (!pco) { @@ -3111,7 +3124,7 @@ PeerConnectionImpl::SetSignalingState_m(PCImplSignalingState aSignalingState, mNegotiationNeeded = false; // If we're rolling back a local offer, we might need to remove some // transports, but nothing further needs to be done. - mMedia->ActivateOrRemoveTransports(*mJsepSession); + mMedia->ActivateOrRemoveTransports(*mJsepSession, mForceIceTcp); if (!rollback) { if (NS_FAILED(mMedia->UpdateMediaPipelines(*mJsepSession))) { CSFLogError(logTag, "Error Updating MediaPipelines"); @@ -3277,6 +3290,11 @@ PeerConnectionImpl::CandidateReady(const std::string& candidate, uint16_t level) { PC_AUTO_ENTER_API_CALL_VOID_RETURN(false); + if (mForceIceTcp && std::string::npos != candidate.find(" UDP ")) { + CSFLogError(logTag, "Blocking local UDP candidate: %s", candidate.c_str()); + return; + } + std::string mid; bool skipped = false; nsresult res = mJsepSession->AddLocalIceCandidate(candidate, diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h index 7b53ea1160..098b34249a 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h @@ -803,6 +803,7 @@ private: bool mAllowIceLoopback; bool mAllowIceLinkLocal; + bool mForceIceTcp; RefPtr mMedia; // The JSEP negotiation session. diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index 30bcadd2b9..b26515c9c0 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -468,7 +468,8 @@ PeerConnectionMedia::EnsureTransport_s(size_t aLevel, size_t aComponentCount) } void -PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession) +PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession, + const bool forceIceTcp) { auto transports = aSession.GetTransports(); for (size_t i = 0; i < transports.size(); ++i) { @@ -491,6 +492,14 @@ PeerConnectionMedia::ActivateOrRemoveTransports(const JsepSession& aSession) RemoveTransportFlow(i, true); } + if (forceIceTcp) { + candidates.erase(std::remove_if(candidates.begin(), + candidates.end(), + [](const std::string & s) { + return s.find(" UDP "); }), + candidates.end()); + } + RUN_ON_THREAD( GetSTSThread(), WrapRunnable(RefPtr(this), diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index 3ecddf8ca3..d0834dbf82 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -270,7 +270,8 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // Activate or remove ICE transports at the conclusion of offer/answer, // or when rollback occurs. - void ActivateOrRemoveTransports(const JsepSession& aSession); + void ActivateOrRemoveTransports(const JsepSession& aSession, + const bool forceIceTcp); // Start ICE checks. void StartIceChecks(const JsepSession& session); diff --git a/netwerk/base/nsISocketTransport.idl b/netwerk/base/nsISocketTransport.idl index 9b5bc23fb7..3525aad5d9 100644 --- a/netwerk/base/nsISocketTransport.idl +++ b/netwerk/base/nsISocketTransport.idl @@ -129,6 +129,11 @@ interface nsISocketTransport : nsITransport unsigned long getTimeout(in unsigned long aType); void setTimeout(in unsigned long aType, in unsigned long aValue); + /** + * True to set addr and port reuse socket options. + */ + void setReuseAddrPort(in bool reuseAddrPort); + /** * Values for the aType parameter passed to get/setTimeout. */ diff --git a/netwerk/base/nsSocketTransport2.cpp b/netwerk/base/nsSocketTransport2.cpp index d6b713fe6e..157cb2add1 100644 --- a/netwerk/base/nsSocketTransport2.cpp +++ b/netwerk/base/nsSocketTransport2.cpp @@ -738,6 +738,7 @@ nsSocketTransport::nsSocketTransport() , mProxyTransparentResolvesHost(false) , mHttpsProxy(false) , mConnectionFlags(0) + , mReuseAddrPort(false) , mState(STATE_CLOSED) , mAttached(false) , mInputClosed(true) @@ -1355,6 +1356,32 @@ nsSocketTransport::InitiateSocket() status = PR_SetSocketOption(fd, &opt); NS_ASSERTION(status == PR_SUCCESS, "unable to make socket non-blocking"); + if (mReuseAddrPort) { + SOCKET_LOG((" Setting port/addr reuse socket options\n")); + + // Set ReuseAddr for TCP sockets to enable having several + // sockets bound to same local IP and port + PRSocketOptionData opt_reuseaddr; + opt_reuseaddr.option = PR_SockOpt_Reuseaddr; + opt_reuseaddr.value.reuse_addr = PR_TRUE; + status = PR_SetSocketOption(fd, &opt_reuseaddr); + if (status != PR_SUCCESS) { + SOCKET_LOG((" Couldn't set reuse addr socket option: %d\n", + status)); + } + + // And also set ReusePort for platforms supporting this socket option + PRSocketOptionData opt_reuseport; + opt_reuseport.option = PR_SockOpt_Reuseport; + opt_reuseport.value.reuse_port = PR_TRUE; + status = PR_SetSocketOption(fd, &opt_reuseport); + if (status != PR_SUCCESS + && PR_GetError() != PR_OPERATION_NOT_SUPPORTED_ERROR) { + SOCKET_LOG((" Couldn't set reuse port socket option: %d\n", + status)); + } + } + // disable the nagle algorithm - if we rely on it to coalesce writes into // full packets the final packet of a multi segment POST/PUT or pipeline // sequence is delayed a full rtt @@ -2484,6 +2511,13 @@ nsSocketTransport::SetTimeout(uint32_t type, uint32_t value) return NS_OK; } +NS_IMETHODIMP +nsSocketTransport::SetReuseAddrPort(bool reuseAddrPort) +{ + mReuseAddrPort = reuseAddrPort; + return NS_OK; +} + NS_IMETHODIMP nsSocketTransport::SetQoSBits(uint8_t aQoSBits) { diff --git a/netwerk/base/nsSocketTransport2.h b/netwerk/base/nsSocketTransport2.h index 89b75efa57..a61e432b48 100644 --- a/netwerk/base/nsSocketTransport2.h +++ b/netwerk/base/nsSocketTransport2.h @@ -295,6 +295,7 @@ private: bool mProxyTransparentResolvesHost; bool mHttpsProxy; uint32_t mConnectionFlags; + bool mReuseAddrPort; // The origin attributes are used to create sockets. The first party domain // will eventually be used to isolate OCSP cache and is only non-empty when diff --git a/netwerk/protocol/http/TunnelUtils.cpp b/netwerk/protocol/http/TunnelUtils.cpp index eeaf57f55c..01075d2c0c 100644 --- a/netwerk/protocol/http/TunnelUtils.cpp +++ b/netwerk/protocol/http/TunnelUtils.cpp @@ -1685,6 +1685,12 @@ SocketTransportShim::SetTimeout(uint32_t aType, uint32_t aValue) return mWrapped->SetTimeout(aType, aValue); } +NS_IMETHODIMP +SocketTransportShim::SetReuseAddrPort(bool aReuseAddrPort) +{ + return mWrapped->SetReuseAddrPort(aReuseAddrPort); +} + NS_IMETHODIMP SocketTransportShim::GetQoSBits(uint8_t *aQoSBits) { diff --git a/python/virtualenv/virtualenv.py b/python/virtualenv/virtualenv.py index d22207e257..60a42e4dcb 100644 --- a/python/virtualenv/virtualenv.py +++ b/python/virtualenv/virtualenv.py @@ -1346,7 +1346,7 @@ def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, sy raise # Resign the executable, since install_name_tool invalidates the signature - call_subprocess(["codesign", "-s", "-", py_executable]) + call_subprocess(["codesign", "-fs", "-", py_executable]) if not is_win: # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist diff --git a/testing/tools/iceserver/iceserver.py b/testing/tools/iceserver/iceserver.py index 2089301af8..85d0f3ee54 100644 --- a/testing/tools/iceserver/iceserver.py +++ b/testing/tools/iceserver/iceserver.py @@ -10,7 +10,9 @@ import passlib.utils # for saslprep import copy import random import operator +import os import platform +import string import time from string import Template from twisted.internet import reactor, protocol @@ -715,6 +717,38 @@ def prune_allocations(): del allocations[key] allocation.close() +CERT_FILE = "selfsigned.crt" +KEY_FILE = "private.key" + +def create_self_signed_cert(name): + from OpenSSL import crypto + if os.path.isfile(CERT_FILE) and os.path.isfile(KEY_FILE): + return + + # create a key pair + k = crypto.PKey() + k.generate_key(crypto.TYPE_RSA, 1024) + + # create a self-signed cert + cert = crypto.X509() + cert.get_subject().C = "US" + cert.get_subject().ST = "TX" + cert.get_subject().L = "Dallas" + cert.get_subject().O = "Mozilla test iceserver" + cert.get_subject().OU = "Mozilla test iceserver" + cert.get_subject().CN = name + cert.set_serial_number(1000) + cert.gmtime_adj_notBefore(0) + cert.gmtime_adj_notAfter(10*365*24*60*60) + cert.set_issuer(cert.get_subject()) + cert.set_pubkey(k) + cert.sign(k, 'sha1') + + open(CERT_FILE, "wt").write( + crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) + open(KEY_FILE, "wt").write( + crypto.dump_privatekey(crypto.FILETYPE_PEM, k)) + if __name__ == "__main__": random.seed() @@ -739,20 +773,48 @@ if __name__ == "__main__": except: pass + try: + from twisted.internet import ssl + from OpenSSL import SSL + create_self_signed_cert(hostname) + tls_context_factory = ssl.DefaultOpenSSLContextFactory(KEY_FILE, CERT_FILE, SSL.TLSv1_2_METHOD) + reactor.listenSSL(5349, TcpStunHandlerFactory(), tls_context_factory, interface=interface_4) + + try: + reactor.listenSSL(5349, TcpStunHandlerFactory(), tls_context_factory, interface=interface_6) + except: + pass + + f = open(CERT_FILE, 'r'); + lines = f.readlines(); + lines.pop(0); # Remove BEGIN CERTIFICATE + lines.pop(); # Remove END CERTIFICATE + lines = map(string.strip, lines); + certbase64 = string.join(lines, ''); + + turns_url = ', "turns:' + hostname + '"' + cert_prop = ', "cert":"' + certbase64 + '"' + except: + turns_url = '' + cert_prop = '' + pass + allocation_pruner = LoopingCall(prune_allocations) allocation_pruner.start(1) template = Template( '[\ -{"url":"stun:$hostname"}, \ -{"url":"stun:$hostname?transport=tcp"}, \ -{"username":"$user","credential":"$pwd","url":"turn:$hostname"}, \ -{"username":"$user","credential":"$pwd","url":"turn:$hostname?transport=tcp"}]' +{"urls":["stun:$hostname", "stun:$hostname?transport=tcp"]}, \ +{"username":"$user","credential":"$pwd","urls": \ +["turn:$hostname", "turn:$hostname?transport=tcp" $turns_url] \ +$cert_prop}]' # Hack to make it easier to override cert checks ) print(template.substitute(user=turn_user, pwd=turn_pass, - hostname=hostname)) + hostname=hostname, + turns_url=turns_url, + cert_prop=cert_prop)) reactor.run()