--- a/dom/media/bridge/MediaModule.cpp
+++ b/dom/media/bridge/MediaModule.cpp
@@ -9,41 +9,45 @@
#include "PeerConnectionImpl.h"
#define PEERCONNECTION_CID \
{0xb93af7a1, 0x3411, 0x44a8, {0xbd, 0x0a, 0x8a, 0xf3, 0xdd, 0xe4, 0xd8, 0xd8}}
#define PEERCONNECTION_CONTRACTID "@mozilla.org/peerconnection;1"
-#include "stun_udp_socket_filter.h"
+#include "stun_socket_filter.h"
NS_DEFINE_NAMED_CID(NS_STUN_UDP_SOCKET_FILTER_HANDLER_CID)
+NS_DEFINE_NAMED_CID(NS_STUN_TCP_SOCKET_FILTER_HANDLER_CID)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStunUDPSocketFilterHandler)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsStunTCPSocketFilterHandler)
namespace mozilla
{
// Factory defined in mozilla::, defines mozilla::PeerConnectionImplConstructor
NS_GENERIC_FACTORY_CONSTRUCTOR(PeerConnectionImpl)
}
// Defines kPEERCONNECTION_CID
NS_DEFINE_NAMED_CID(PEERCONNECTION_CID);
static const mozilla::Module::CIDEntry kCIDs[] = {
{ &kPEERCONNECTION_CID, false, nullptr, mozilla::PeerConnectionImplConstructor },
{ &kNS_STUN_UDP_SOCKET_FILTER_HANDLER_CID, false, nullptr, nsStunUDPSocketFilterHandlerConstructor },
+ { &kNS_STUN_TCP_SOCKET_FILTER_HANDLER_CID, false, nullptr, nsStunTCPSocketFilterHandlerConstructor },
{ nullptr }
};
static const mozilla::Module::ContractIDEntry kContracts[] = {
{ PEERCONNECTION_CONTRACTID, &kPEERCONNECTION_CID },
{ NS_STUN_UDP_SOCKET_FILTER_HANDLER_CONTRACTID, &kNS_STUN_UDP_SOCKET_FILTER_HANDLER_CID },
+ { NS_STUN_TCP_SOCKET_FILTER_HANDLER_CONTRACTID, &kNS_STUN_TCP_SOCKET_FILTER_HANDLER_CID },
{ nullptr }
};
static const mozilla::Module kModule = {
mozilla::Module::kVersion,
kCIDs,
kContracts
};
--- a/dom/network/PTCPSocket.ipdl
+++ b/dom/network/PTCPSocket.ipdl
@@ -40,17 +40,17 @@ parent:
// is expanded to |useSSL| (from TCPOptions.useSecureTransport) and
// |binaryType| (from TCPOption.binaryType).
async Open(nsString host, uint16_t port, bool useSSL, bool useArrayBuffers);
// Ask parent to open a socket and bind the newly-opened socket to a local
// address specified in |localAddr| and |localPort|.
async OpenBind(nsCString host, uint16_t port,
nsCString localAddr, uint16_t localPort,
- bool useSSL, bool aUseArrayBuffers);
+ bool useSSL, bool aUseArrayBuffers, nsCString aFilter);
// When child's send() is called, this message requrests parent to send
// data and update it's trackingNumber.
async Data(SendableData data, uint32_t trackingNumber);
// Forward calling to child's upgradeToSecure() method to parent.
async StartTLS();
--- a/dom/network/TCPSocketChild.cpp
+++ b/dom/network/TCPSocketChild.cpp
@@ -97,33 +97,34 @@ TCPSocketChild::TCPSocketChild(const nsA
void
TCPSocketChild::SendOpen(nsITCPSocketCallback* aSocket, bool aUseSSL, bool aUseArrayBuffers)
{
mSocket = aSocket;
AddIPDLReference();
gNeckoChild->SendPTCPSocketConstructor(this, mHost, mPort);
+ MOZ_ASSERT(mFilterName.IsEmpty()); // Currently nobody should use this
PTCPSocketChild::SendOpen(mHost, mPort, aUseSSL, aUseArrayBuffers);
}
void
TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket,
const nsACString& aRemoteHost, uint16_t aRemotePort,
const nsACString& aLocalHost, uint16_t aLocalPort,
bool aUseSSL)
{
mSocket = aSocket;
AddIPDLReference();
gNeckoChild->SendPTCPSocketConstructor(this,
NS_ConvertUTF8toUTF16(aRemoteHost),
aRemotePort);
PTCPSocketChild::SendOpenBind(nsCString(aRemoteHost), aRemotePort,
nsCString(aLocalHost), aLocalPort,
- aUseSSL, true);
+ aUseSSL, true, mFilterName);
}
void
TCPSocketChildBase::ReleaseIPDLReference()
{
MOZ_ASSERT(mIPCOpen);
mIPCOpen = false;
this->Release();
@@ -225,16 +226,27 @@ TCPSocketChild::GetHost(nsAString& aHost
}
void
TCPSocketChild::GetPort(uint16_t* aPort)
{
*aPort = mPort;
}
+nsresult
+TCPSocketChild::SetFilterName(const nsACString& aFilterName)
+{
+ if (!mFilterName.IsEmpty()) {
+ // filter name can only be set once.
+ return NS_ERROR_FAILURE;
+ }
+ mFilterName = aFilterName;
+ return NS_OK;
+}
+
bool
TCPSocketChild::RecvRequestDelete()
{
mozilla::Unused << Send__delete__(this);
return true;
}
} // namespace dom
--- a/dom/network/TCPSocketChild.h
+++ b/dom/network/TCPSocketChild.h
@@ -71,17 +71,19 @@ public:
void GetPort(uint16_t* aPort);
virtual bool RecvCallback(const nsString& aType,
const CallbackData& aData,
const uint32_t& aReadyState) override;
virtual bool RecvRequestDelete() override;
virtual bool RecvUpdateBufferedAmount(const uint32_t& aBufferred,
const uint32_t& aTrackingNumber) override;
+ nsresult SetFilterName(const nsACString& aFilterName);
private:
nsString mHost;
uint16_t mPort;
+ nsCString mFilterName;
};
} // namespace dom
} // namespace mozilla
#endif
--- a/dom/network/TCPSocketParent.cpp
+++ b/dom/network/TCPSocketParent.cpp
@@ -16,16 +16,23 @@
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/HoldDropJSObjects.h"
#include "nsISocketTransportService.h"
#include "nsISocketTransport.h"
#include "nsIScriptSecurityManager.h"
#include "nsNetUtil.h"
+//
+// set NSPR_LOG_MODULES=TCPSocket:5
+//
+extern mozilla::LazyLogModule gTCPSocketLog;
+#define TCPSOCKET_LOG(args) MOZ_LOG(gTCPSocketLog, mozilla::LogLevel::Debug, args)
+#define TCPSOCKET_LOG_ENABLED() MOZ_LOG_TEST(gTCPSocketLog, mozilla::LogLevel::Debug)
+
namespace IPC {
//Defined in TCPSocketChild.cpp
extern bool
DeserializeArrayBuffer(JSContext* aCx,
const InfallibleTArray<uint8_t>& aBuffer,
JS::MutableHandle<JS::Value> aVal);
@@ -171,17 +178,18 @@ TCPSocketParent::RecvOpen(const nsString
}
bool
TCPSocketParent::RecvOpenBind(const nsCString& aRemoteHost,
const uint16_t& aRemotePort,
const nsCString& aLocalAddr,
const uint16_t& aLocalPort,
const bool& aUseSSL,
- const bool& aUseArrayBuffers)
+ const bool& aUseArrayBuffers,
+ const nsCString& aFilter)
{
if (net::UsingNeckoIPCSecurity() &&
!AssertAppProcessPermission(Manager()->Manager(), "tcp-socket")) {
FireInteralError(this, __LINE__);
return true;
}
nsresult rv;
@@ -214,16 +222,34 @@ TCPSocketParent::RecvOpenBind(const nsCS
mozilla::net::NetAddr addr;
PRNetAddrToNetAddr(&prAddr, &addr);
rv = socketTransport->Bind(&addr);
if (NS_FAILED(rv)) {
FireInteralError(this, __LINE__);
return true;
}
+ if (!aFilter.IsEmpty()) {
+ nsAutoCString contractId(NS_NETWORK_TCP_SOCKET_FILTER_HANDLER_PREFIX);
+ contractId.Append(aFilter);
+ nsCOMPtr<nsISocketFilterHandler> filterHandler =
+ do_GetService(contractId.get());
+ if (!filterHandler) {
+ NS_ERROR("Content doesn't have a valid filter");
+ FireInteralError(this, __LINE__);
+ return true;
+ }
+ rv = filterHandler->NewFilter(getter_AddRefs(mFilter));
+ if (NS_FAILED(rv)) {
+ NS_ERROR("Cannot create filter that content specified");
+ FireInteralError(this, __LINE__);
+ return true;
+ }
+ }
+
// Obtain App ID
uint32_t appId = nsIScriptSecurityManager::NO_APP_ID;
bool inIsolatedMozBrowser = false;
const PContentParent *content = Manager()->Manager();
if (PBrowserParent* browser = SingleManagedOrNull(content->ManagedPBrowserParent())) {
// appId's are for B2G only currently, where managees.Count() == 1
// This is not guaranteed currently in Desktop, so skip this there.
TabParent *tab = TabParent::GetFrom(browser);
@@ -267,16 +293,35 @@ TCPSocketParent::RecvResume()
return true;
}
bool
TCPSocketParent::RecvData(const SendableData& aData,
const uint32_t& aTrackingNumber)
{
ErrorResult rv;
+
+ if (mFilter) {
+ mozilla::net::NetAddr addr; // dummy value
+ bool allowed;
+ MOZ_ASSERT(aData.type() == SendableData::TArrayOfuint8_t,
+ "Unsupported data type for filtering");
+ const InfallibleTArray<uint8_t>& data(aData.get_ArrayOfuint8_t());
+ nsresult nsrv = mFilter->FilterPacket(&addr, data.Elements(),
+ data.Length(),
+ nsISocketFilter::SF_OUTGOING,
+ &allowed);
+
+ // Reject sending of unallowed data
+ if (NS_WARN_IF(NS_FAILED(nsrv)) || !allowed) {
+ TCPSOCKET_LOG(("%s: Dropping outgoing TCP packet", __FUNCTION__));
+ return false;
+ }
+ }
+
switch (aData.type()) {
case SendableData::TArrayOfuint8_t: {
AutoSafeJSContext autoCx;
JS::Rooted<JS::Value> val(autoCx);
const nsTArray<uint8_t>& buffer = aData.get_ArrayOfuint8_t();
bool ok = IPC::DeserializeArrayBuffer(autoCx, buffer, &val);
NS_ENSURE_TRUE(ok, true);
RootedTypedArray<ArrayBuffer> data(autoCx);
@@ -319,24 +364,42 @@ TCPSocketParent::FireEvent(const nsAStri
return SendEvent(aType, mozilla::void_t(), aReadyState);
}
void
TCPSocketParent::FireArrayBufferDataEvent(nsTArray<uint8_t>& aBuffer, TCPReadyState aReadyState)
{
InfallibleTArray<uint8_t> arr;
arr.SwapElements(aBuffer);
+
+ if (mFilter) {
+ bool allowed;
+ mozilla::net::NetAddr addr;
+ nsresult nsrv = mFilter->FilterPacket(&addr, arr.Elements(), arr.Length(),
+ nsISocketFilter::SF_INCOMING,
+ &allowed);
+ // receiving unallowed data, drop it.
+ if (NS_WARN_IF(NS_FAILED(nsrv)) || !allowed) {
+ TCPSOCKET_LOG(("%s: Dropping incoming TCP packet", __FUNCTION__));
+ return;
+ }
+ }
+
SendableData data(arr);
SendEvent(NS_LITERAL_STRING("data"), data, aReadyState);
}
void
TCPSocketParent::FireStringDataEvent(const nsACString& aData, TCPReadyState aReadyState)
{
- SendEvent(NS_LITERAL_STRING("data"), SendableData(nsCString(aData)), aReadyState);
+ SendableData data((nsCString(aData)));
+
+ MOZ_ASSERT(!mFilter, "Socket filtering doesn't support nsCString");
+
+ SendEvent(NS_LITERAL_STRING("data"), data, aReadyState);
}
void
TCPSocketParent::SendEvent(const nsAString& aType, CallbackData aData, TCPReadyState aReadyState)
{
mozilla::Unused << PTCPSocketParent::SendCallback(nsString(aType), aData,
static_cast<uint32_t>(aReadyState));
}
--- a/dom/network/TCPSocketParent.h
+++ b/dom/network/TCPSocketParent.h
@@ -6,16 +6,17 @@
#ifndef mozilla_dom_TCPSocketParent_h
#define mozilla_dom_TCPSocketParent_h
#include "mozilla/dom/TCPSocketBinding.h"
#include "mozilla/net/PTCPSocketParent.h"
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
+#include "nsISocketFilter.h"
#include "js/TypeDecls.h"
#include "mozilla/net/OfflineObserver.h"
#define TCPSOCKETPARENT_CID \
{ 0x4e7246c6, 0xa8b3, 0x426d, { 0x9c, 0x17, 0x76, 0xda, 0xb1, 0xe1, 0xe1, 0x4a } }
namespace mozilla {
namespace dom {
@@ -52,17 +53,18 @@ public:
virtual bool RecvOpen(const nsString& aHost, const uint16_t& aPort,
const bool& useSSL, const bool& aUseArrayBuffers) override;
virtual bool RecvOpenBind(const nsCString& aRemoteHost,
const uint16_t& aRemotePort,
const nsCString& aLocalAddr,
const uint16_t& aLocalPort,
const bool& aUseSSL,
- const bool& aUseArrayBuffers) override;
+ const bool& aUseArrayBuffers,
+ const nsCString& aFilter) override;
virtual bool RecvStartTLS() override;
virtual bool RecvSuspend() override;
virtual bool RecvResume() override;
virtual bool RecvClose() override;
virtual bool RecvData(const SendableData& aData,
const uint32_t& aTrackingNumber) override;
virtual bool RecvRequestDelete() override;
@@ -77,14 +79,17 @@ public:
void SetSocket(TCPSocket *socket);
nsresult GetHost(nsAString& aHost);
nsresult GetPort(uint16_t* aPort);
private:
virtual void ActorDestroy(ActorDestroyReason why) override;
void SendEvent(const nsAString& aType, CallbackData aData, TCPReadyState aReadyState);
+ nsresult SetFilter(const nsCString& aFilter);
+
+ nsCOMPtr<nsISocketFilter> mFilter;
};
} // namespace dom
} // namespace mozilla
#endif
--- a/dom/network/UDPSocketParent.cpp
+++ b/dom/network/UDPSocketParent.cpp
@@ -128,17 +128,17 @@ UDPSocketParent::Init(const IPC::Princip
if (permission != nsIPermissionManager::ALLOW_ACTION) {
return false;
}
}
if (!aFilter.IsEmpty()) {
nsAutoCString contractId(NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX);
contractId.Append(aFilter);
- nsCOMPtr<nsIUDPSocketFilterHandler> filterHandler =
+ nsCOMPtr<nsISocketFilterHandler> filterHandler =
do_GetService(contractId.get());
if (filterHandler) {
nsresult rv = filterHandler->NewFilter(getter_AddRefs(mFilter));
if (NS_FAILED(rv)) {
printf_stderr("Cannot create filter that content specified. "
"filter name: %s, error code: %u.", aFilter.BeginReading(), static_cast<uint32_t>(rv));
return false;
}
@@ -377,31 +377,29 @@ UDPSocketParent::ConnectInternal(const n
bool
UDPSocketParent::RecvOutgoingData(const UDPData& aData,
const UDPSocketAddr& aAddr)
{
MOZ_ASSERT(mSocket);
nsresult rv;
if (mFilter) {
- // TODO, Bug 933102, filter packets that are sent with hostname.
- // Until then we simply throw away packets that are sent to a hostname.
if (aAddr.type() != UDPSocketAddr::TNetAddr) {
return true;
}
// TODO, Packet filter doesn't support input stream yet.
if (aData.type() != UDPData::TArrayOfuint8_t) {
return true;
}
bool allowed;
const InfallibleTArray<uint8_t>& data(aData.get_ArrayOfuint8_t());
rv = mFilter->FilterPacket(&aAddr.get_NetAddr(), data.Elements(),
- data.Length(), nsIUDPSocketFilter::SF_OUTGOING,
+ data.Length(), nsISocketFilter::SF_OUTGOING,
&allowed);
// Sending unallowed data, kill content.
if (NS_WARN_IF(NS_FAILED(rv)) || !allowed) {
return false;
}
}
@@ -566,17 +564,17 @@ UDPSocketParent::OnPacketReceived(nsIUDP
UDPSOCKET_LOG(("%s: %s:%u, length %u", __FUNCTION__, ip.get(), port, len));
if (mFilter) {
bool allowed;
mozilla::net::NetAddr addr;
fromAddr->GetNetAddr(&addr);
nsresult rv = mFilter->FilterPacket(&addr,
(const uint8_t*)buffer, len,
- nsIUDPSocketFilter::SF_INCOMING,
+ nsISocketFilter::SF_INCOMING,
&allowed);
// Receiving unallowed data, drop.
if (NS_WARN_IF(NS_FAILED(rv)) || !allowed) {
if (!allowed) {
UDPSOCKET_LOG(("%s: not allowed", __FUNCTION__));
}
return NS_OK;
}
--- a/dom/network/UDPSocketParent.h
+++ b/dom/network/UDPSocketParent.h
@@ -5,17 +5,17 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_UDPSocketParent_h__
#define mozilla_dom_UDPSocketParent_h__
#include "mozilla/net/PUDPSocketParent.h"
#include "nsCOMPtr.h"
#include "nsIUDPSocket.h"
-#include "nsIUDPSocketFilter.h"
+#include "nsISocketFilter.h"
#include "mozilla/net/OfflineObserver.h"
#include "mozilla/dom/PermissionMessageUtils.h"
namespace mozilla {
namespace net {
class PNeckoParent;
} // namespace net
@@ -71,17 +71,17 @@ private:
uint32_t aLineNo);
// One of these will be null and the other non-null.
PBackgroundParent* mBackgroundManager;
PNeckoParent* mNeckoManager;
bool mIPCOpen;
nsCOMPtr<nsIUDPSocket> mSocket;
- nsCOMPtr<nsIUDPSocketFilter> mFilter;
+ nsCOMPtr<nsISocketFilter> mFilter;
RefPtr<mozilla::net::OfflineObserver> mObserver;
nsCOMPtr<nsIPrincipal> mPrincipal;
};
} // namespace dom
} // namespace mozilla
#endif // !defined(mozilla_dom_UDPSocketParent_h__)
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -413,19 +413,19 @@ BackgroundParentImpl::RecvPUDPSocketCons
return false;
}
// No principal - This must be from mtransport (WebRTC/ICE) - We'd want
// to DispatchToMainThread() here, but if we do we must block RecvBind()
// until Init() gets run. Since we don't have a principal, and we verify
// we have a filter, we can safely skip the Dispatch and just invoke Init()
// to install the filter.
- // For mtransport, this will always be "stun", which doesn't allow outbound packets if
- // they aren't STUN packets until a STUN response is seen.
- if (!aFilter.EqualsASCII("stun")) {
+ // For mtransport, this will always be "stun", which doesn't allow outbound
+ // packets if they aren't STUN packets until a STUN response is seen.
+ if (!aFilter.EqualsASCII(NS_NETWORK_SOCKET_FILTER_HANDLER_STUN_SUFFIX)) {
return false;
}
IPC::Principal principal;
if (!static_cast<UDPSocketParent*>(aActor)->Init(principal, aFilter)) {
MOZ_CRASH("UDPSocketCallback - failed init");
}
--- a/media/mtransport/build/moz.build
+++ b/media/mtransport/build/moz.build
@@ -11,17 +11,17 @@ EXPORTS.mtransport += [
'../m_cpp_utils.h',
'../nricectx.h',
'../nricemediastream.h',
'../nriceresolverfake.h',
'../rlogringbuffer.h',
'../runnable_utils.h',
'../sigslot.h',
'../simpletokenbucket.h',
- '../stun_udp_socket_filter.h',
+ '../stun_socket_filter.h',
'../transportflow.h',
'../transportlayer.h',
'../transportlayerdtls.h',
'../transportlayerice.h',
'../transportlayerlog.h',
'../transportlayerloopback.h',
'../transportlayerprsock.h',
]
--- a/media/mtransport/common.build
+++ b/media/mtransport/common.build
@@ -10,17 +10,17 @@ mtransport_lcppsrcs = [
'nr_timer.cpp',
'nricectx.cpp',
'nricemediastream.cpp',
'nriceresolver.cpp',
'nriceresolverfake.cpp',
'nrinterfaceprioritizer.cpp',
'rlogringbuffer.cpp',
'simpletokenbucket.cpp',
- 'stun_udp_socket_filter.cpp',
+ 'stun_socket_filter.cpp',
'test_nr_socket.cpp',
'transportflow.cpp',
'transportlayer.cpp',
'transportlayerdtls.cpp',
'transportlayerice.cpp',
'transportlayerlog.cpp',
'transportlayerloopback.cpp',
'transportlayerprsock.cpp',
--- a/media/mtransport/nr_socket_prsock.cpp
+++ b/media/mtransport/nr_socket_prsock.cpp
@@ -108,16 +108,17 @@ nrappkit copyright:
#include "nsXULAppAPI.h"
#include "runnable_utils.h"
#include "mozilla/SyncRunnable.h"
#include "nsTArray.h"
#include "mozilla/dom/TCPSocketBinding.h"
#include "nsITCPSocketCallback.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
+#include "nsISocketFilter.h"
#ifdef XP_WIN
#include "mozilla/WindowsVersion.h"
#endif
#if defined(MOZILLA_INTERNAL_API)
// csi_platform.h deep in nrappkit defines LOG_INFO and LOG_WARNING
#ifdef LOG_INFO
@@ -1491,17 +1492,17 @@ void NrUdpSocketIpc::create_i(const nsAC
}
// This can spin the event loop; don't do that with the monitor held
socketChild->SetBackgroundSpinsEvents();
ReentrantMonitorAutoEnter mon(monitor_);
if (!socket_child_) {
socket_child_ = socketChild;
- socket_child_->SetFilterName(nsCString("stun"));
+ socket_child_->SetFilterName(nsCString(NS_NETWORK_SOCKET_FILTER_HANDLER_STUN_SUFFIX));
} else {
socketChild = nullptr;
}
RefPtr<NrUdpSocketIpcProxy> proxy(new NrUdpSocketIpcProxy);
rv = proxy->Init(this);
if (NS_FAILED(rv)) {
err_ = true;
@@ -1922,16 +1923,18 @@ void NrTcpSocketIpc::connect_i(const nsA
const nsACString &local_addr,
uint16_t local_port) {
ASSERT_ON_THREAD(io_thread_);
mirror_state_ = NR_CONNECTING;
dom::TCPSocketChild* child = new dom::TCPSocketChild(NS_ConvertUTF8toUTF16(remote_addr), remote_port);
socket_child_ = child;
+ socket_child_->SetFilterName(nsCString(NS_NETWORK_SOCKET_FILTER_HANDLER_STUN_SUFFIX));
+
// XXX remove remote!
socket_child_->SendWindowlessOpenBind(this,
remote_addr, remote_port,
local_addr, local_port,
/* use ssl */ false);
}
void NrTcpSocketIpc::write_i(nsAutoPtr<InfallibleTArray<uint8_t>> arr,
rename from media/mtransport/stun_udp_socket_filter.cpp
rename to media/mtransport/stun_socket_filter.cpp
--- a/media/mtransport/stun_udp_socket_filter.cpp
+++ b/media/mtransport/stun_socket_filter.cpp
@@ -7,17 +7,17 @@
extern "C" {
#include "nr_api.h"
#include "transport_addr.h"
#include "stun.h"
}
#include "mozilla/Attributes.h"
#include "mozilla/net/DNS.h"
-#include "stun_udp_socket_filter.h"
+#include "stun_socket_filter.h"
#include "nr_socket_prsock.h"
namespace {
class NetAddrCompare {
public:
bool operator()(const mozilla::net::NetAddr& lhs,
const mozilla::net::NetAddr& rhs) const {
@@ -80,25 +80,25 @@ class PendingSTUNRequest {
}
private:
const UINT12 id_;
const mozilla::net::NetAddr net_addr_;
const bool is_id_set_;
};
-class STUNUDPSocketFilter : public nsIUDPSocketFilter {
+class STUNUDPSocketFilter : public nsISocketFilter {
public:
STUNUDPSocketFilter()
: white_list_(),
pending_requests_() {}
// Allocated/freed and used on the PBackground IPC thread
NS_DECL_ISUPPORTS
- NS_DECL_NSIUDPSOCKETFILTER
+ NS_DECL_NSISOCKETFILTER
private:
virtual ~STUNUDPSocketFilter() {}
bool filter_incoming_packet(const mozilla::net::NetAddr *remote_addr,
const uint8_t *data,
uint32_t len);
@@ -106,29 +106,29 @@ class STUNUDPSocketFilter : public nsIUD
const uint8_t *data,
uint32_t len);
std::set<mozilla::net::NetAddr, NetAddrCompare> white_list_;
std::set<PendingSTUNRequest> pending_requests_;
std::set<PendingSTUNRequest> response_allowed_;
};
-NS_IMPL_ISUPPORTS(STUNUDPSocketFilter, nsIUDPSocketFilter)
+NS_IMPL_ISUPPORTS(STUNUDPSocketFilter, nsISocketFilter)
NS_IMETHODIMP
STUNUDPSocketFilter::FilterPacket(const mozilla::net::NetAddr *remote_addr,
const uint8_t *data,
uint32_t len,
int32_t direction,
bool *result) {
switch (direction) {
- case nsIUDPSocketFilter::SF_INCOMING:
+ case nsISocketFilter::SF_INCOMING:
*result = filter_incoming_packet(remote_addr, data, len);
break;
- case nsIUDPSocketFilter::SF_OUTGOING:
+ case nsISocketFilter::SF_OUTGOING:
*result = filter_outgoing_packet(remote_addr, data, len);
break;
default:
MOZ_CRASH("Unknown packet direction");
}
return NS_OK;
}
@@ -192,21 +192,168 @@ bool STUNUDPSocketFilter::filter_outgoin
if (it != response_allowed_.end()) {
return true;
}
}
return false;
}
+class PendingSTUNId {
+ public:
+ explicit PendingSTUNId(const UINT12 &id)
+ : id_(id) {}
+
+ bool operator<(const PendingSTUNId& rhs) const {
+ return memcmp(id_.octet, rhs.id_.octet, sizeof(id_.octet)) < 0;
+ }
+ private:
+ const UINT12 id_;
+};
+
+class STUNTCPSocketFilter : public nsISocketFilter {
+ public:
+ STUNTCPSocketFilter()
+ : white_listed_(false),
+ pending_request_ids_(),
+ response_allowed_ids_() {}
+
+ // Allocated/freed and used on the PBackground IPC thread
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISOCKETFILTER
+
+ private:
+ virtual ~STUNTCPSocketFilter() {}
+
+ bool filter_incoming_packet(const uint8_t *data,
+ uint32_t len);
+
+ bool filter_outgoing_packet(const uint8_t *data,
+ uint32_t len);
+
+ bool white_listed_;
+ std::set<PendingSTUNId> pending_request_ids_;
+ std::set<PendingSTUNId> response_allowed_ids_;
+};
+
+NS_IMPL_ISUPPORTS(STUNTCPSocketFilter, nsISocketFilter)
+
+NS_IMETHODIMP
+STUNTCPSocketFilter::FilterPacket(const mozilla::net::NetAddr *remote_addr,
+ const uint8_t *data,
+ uint32_t len,
+ int32_t direction,
+ bool *result) {
+ switch (direction) {
+ case nsISocketFilter::SF_INCOMING:
+ *result = filter_incoming_packet(data, len);
+ break;
+ case nsISocketFilter::SF_OUTGOING:
+ *result = filter_outgoing_packet(data, len);
+ break;
+ default:
+ MOZ_CRASH("Unknown packet direction");
+ }
+ return NS_OK;
+}
+
+bool STUNTCPSocketFilter::filter_incoming_packet(const uint8_t *data, uint32_t len) {
+ // check if white listed already
+ if (white_listed_) {
+ return true;
+ }
+
+ UCHAR* stun = const_cast<uint8_t*>(data);
+ uint32_t length = len;
+ if (!nr_is_stun_message(stun, length)) {
+ stun += 2;
+ length -= 2;
+ if (!nr_is_stun_message(stun, length)) {
+ // Note: the UDP filter lets incoming packets pass, because order of
+ // packets is not guaranteed and the next packet is likely an important
+ // packet for DTLS (which is costly in terms of timing to wait for a
+ // retransmit). This does not apply to TCP with its guaranteed order. But
+ // we still let it pass, because otherwise we would have to buffer bytes
+ // here until the minimum STUN request size of bytes has been received.
+ return true;
+ }
+ }
+
+ const nr_stun_message_header *msg = reinterpret_cast<const nr_stun_message_header*>(stun);
+
+ // If it is a STUN response message and we can match its id with one of the
+ // pending requests, we can add this address into whitelist.
+ if (nr_is_stun_response_message(stun, length)) {
+ std::set<PendingSTUNId>::iterator it =
+ pending_request_ids_.find(PendingSTUNId(msg->id));
+ if (it != pending_request_ids_.end()) {
+ pending_request_ids_.erase(it);
+ white_listed_ = true;
+ }
+ } else {
+ // If it is a STUN message, but not a response message, we add it into
+ // response allowed list and allow outgoing filter to send a response back.
+ response_allowed_ids_.insert(PendingSTUNId(msg->id));
+ }
+
+ return true;
+}
+
+bool STUNTCPSocketFilter::filter_outgoing_packet(const uint8_t *data, uint32_t len) {
+ // check if white listed already
+ if (white_listed_) {
+ return true;
+ }
+
+ UCHAR* stun = const_cast<uint8_t*>(data);
+ uint32_t length = len;
+ if (!nr_is_stun_message(stun, length)) {
+ stun += 2;
+ length -= 2;
+ if (!nr_is_stun_message(stun, length)) {
+ return false;
+ }
+ }
+
+ const nr_stun_message_header *msg = reinterpret_cast<const nr_stun_message_header*>(stun);
+
+ // Check if it is a stun request. If yes, we put it into a pending list and wait for
+ // response packet.
+ if (nr_is_stun_request_message(stun, length)) {
+ pending_request_ids_.insert(PendingSTUNId(msg->id));
+ return true;
+ }
+
+ // If it is a stun response packet, and we had received the request before, we can
+ // allow it packet to pass filter.
+ if (nr_is_stun_response_message(stun, length)) {
+ std::set<PendingSTUNId>::iterator it =
+ response_allowed_ids_.find(PendingSTUNId(msg->id));
+ if (it != response_allowed_ids_.end()) {
+ response_allowed_ids_.erase(it);
+ white_listed_ = true;
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // anonymous namespace
-NS_IMPL_ISUPPORTS(nsStunUDPSocketFilterHandler, nsIUDPSocketFilterHandler)
+NS_IMPL_ISUPPORTS(nsStunUDPSocketFilterHandler, nsISocketFilterHandler)
-NS_IMETHODIMP nsStunUDPSocketFilterHandler::NewFilter(nsIUDPSocketFilter **result)
+NS_IMETHODIMP nsStunUDPSocketFilterHandler::NewFilter(nsISocketFilter **result)
{
- nsIUDPSocketFilter *ret = new STUNUDPSocketFilter();
- if (!ret) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
+ nsISocketFilter *ret = new STUNUDPSocketFilter();
NS_ADDREF(*result = ret);
return NS_OK;
}
+
+NS_IMPL_ISUPPORTS(nsStunTCPSocketFilterHandler, nsISocketFilterHandler)
+
+NS_IMETHODIMP nsStunTCPSocketFilterHandler::NewFilter(nsISocketFilter **result)
+{
+ nsISocketFilter *ret = new STUNTCPSocketFilter();
+ NS_ADDREF(*result = ret);
+ return NS_OK;
+}
+
rename from media/mtransport/stun_udp_socket_filter.h
rename to media/mtransport/stun_socket_filter.h
--- a/media/mtransport/stun_udp_socket_filter.h
+++ b/media/mtransport/stun_socket_filter.h
@@ -1,24 +1,36 @@
/* 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/. */
-#ifndef stun_udp_socket_filter_h__
-#define stun_udp_socket_filter_h__
+#ifndef stun_socket_filter_h__
+#define stun_socket_filter_h__
-#include "nsIUDPSocketFilter.h"
+#include "nsISocketFilter.h"
-#define NS_STUN_UDP_SOCKET_FILTER_HANDLER_CONTRACTID NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX "stun"
#define NS_STUN_UDP_SOCKET_FILTER_HANDLER_CID { 0x3e43ee93, 0x829e, 0x4ea6, \
{ 0xa3, 0x4e, 0x62, 0xd9, 0xe4, 0xc9, 0xf9, 0x93 } };
-class nsStunUDPSocketFilterHandler : public nsIUDPSocketFilterHandler {
+class nsStunUDPSocketFilterHandler : public nsISocketFilterHandler {
public:
// Threadsafe because we create off-main-thread, but destroy on MainThread
// via FreeFactoryEntries()
NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIUDPSOCKETFILTERHANDLER
+ NS_DECL_NSISOCKETFILTERHANDLER
private:
virtual ~nsStunUDPSocketFilterHandler() {}
};
+#define NS_STUN_TCP_SOCKET_FILTER_HANDLER_CID { 0x9fea635a, 0x2fc2, 0x4d08, \
+ { 0x97, 0x21, 0xd2, 0x38, 0xd3, 0xf5, 0x2f, 0x92 } };
-#endif // stun_udp_socket_filter_h__
+class nsStunTCPSocketFilterHandler : public nsISocketFilterHandler {
+public:
+ // Threadsafe because we create off-main-thread, but destroy on MainThread
+ // via FreeFactoryEntries()
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSISOCKETFILTERHANDLER
+private:
+ virtual ~nsStunTCPSocketFilterHandler() {}
+};
+
+
+#endif // stun_socket_filter_h__
--- a/media/mtransport/test/ice_unittest.cpp
+++ b/media/mtransport/test/ice_unittest.cpp
@@ -32,17 +32,17 @@
#include "nrinterfaceprioritizer.h"
#include "gtest_ringbuffer_dumper.h"
#include "rlogringbuffer.h"
#include "runnable_utils.h"
#include "stunserver.h"
#include "nr_socket_prsock.h"
#include "test_nr_socket.h"
#include "ice_ctx.h"
-#include "stun_udp_socket_filter.h"
+#include "stun_socket_filter.h"
#include "mozilla/net/DNS.h"
#include "ice_ctx.h"
#include "ice_peer_ctx.h"
#include "ice_media_stream.h"
extern "C" {
#include "async_timer.h"
@@ -1751,27 +1751,34 @@ class WebRtcIcePrioritizerTest : public
}
private:
nr_interface_prioritizer *prioritizer_;
};
class WebRtcIcePacketFilterTest : public StunTest {
public:
- WebRtcIcePacketFilterTest(): filter_(nullptr) {}
+ WebRtcIcePacketFilterTest(): udp_filter_(nullptr),
+ tcp_filter_(nullptr) {}
void SetUp() {
StunTest::SetUp();
// Set up enough of the ICE ctx to allow the packet filter to work
ice_ctx_ = NrIceCtx::Create("test", true);
- nsCOMPtr<nsIUDPSocketFilterHandler> handler =
+ nsCOMPtr<nsISocketFilterHandler> udp_handler =
do_GetService(NS_STUN_UDP_SOCKET_FILTER_HANDLER_CONTRACTID);
- handler->NewFilter(getter_AddRefs(filter_));
+ ASSERT_TRUE(udp_handler);
+ udp_handler->NewFilter(getter_AddRefs(udp_filter_));
+
+ nsCOMPtr<nsISocketFilterHandler> tcp_handler =
+ do_GetService(NS_STUN_TCP_SOCKET_FILTER_HANDLER_CONTRACTID);
+ ASSERT_TRUE(tcp_handler);
+ tcp_handler->NewFilter(getter_AddRefs(tcp_filter_));
}
void TearDown() {
test_utils_->sts_target()->Dispatch(WrapRunnable(this,
&WebRtcIcePacketFilterTest::TearDown_s),
NS_DISPATCH_SYNC);
StunTest::TearDown();
}
@@ -1781,45 +1788,98 @@ class WebRtcIcePacketFilterTest : public
}
void TestIncoming(const uint8_t* data, uint32_t len,
uint8_t from_addr, int from_port,
bool expected_result) {
mozilla::net::NetAddr addr;
MakeNetAddr(&addr, from_addr, from_port);
bool result;
- nsresult rv = filter_->FilterPacket(&addr, data, len,
- nsIUDPSocketFilter::SF_INCOMING,
- &result);
+ nsresult rv = udp_filter_->FilterPacket(&addr, data, len,
+ nsISocketFilter::SF_INCOMING,
+ &result);
+ ASSERT_EQ(NS_OK, rv);
+ ASSERT_EQ(expected_result, result);
+ }
+
+ void TestIncomingTcp(const uint8_t* data, uint32_t len,
+ bool expected_result) {
+ mozilla::net::NetAddr addr;
+ bool result;
+ nsresult rv = tcp_filter_->FilterPacket(&addr, data, len,
+ nsISocketFilter::SF_INCOMING,
+ &result);
ASSERT_EQ(NS_OK, rv);
ASSERT_EQ(expected_result, result);
}
+ void TestIncomingTcpFramed(const uint8_t* data, uint32_t len,
+ bool expected_result) {
+ mozilla::net::NetAddr addr;
+ bool result;
+ uint8_t* framed_data = new uint8_t[len+2];
+ framed_data[0] = htons(len);
+ memcpy(&framed_data[2], data, len);
+ nsresult rv = tcp_filter_->FilterPacket(&addr, framed_data, len+2,
+ nsISocketFilter::SF_INCOMING,
+ &result);
+ ASSERT_EQ(NS_OK, rv);
+ ASSERT_EQ(expected_result, result);
+ delete[] framed_data;
+ }
+
void TestOutgoing(const uint8_t* data, uint32_t len,
uint8_t to_addr, int to_port,
bool expected_result) {
mozilla::net::NetAddr addr;
MakeNetAddr(&addr, to_addr, to_port);
bool result;
- nsresult rv = filter_->FilterPacket(&addr, data, len,
- nsIUDPSocketFilter::SF_OUTGOING,
- &result);
+ nsresult rv = udp_filter_->FilterPacket(&addr, data, len,
+ nsISocketFilter::SF_OUTGOING,
+ &result);
+ ASSERT_EQ(NS_OK, rv);
+ ASSERT_EQ(expected_result, result);
+ }
+
+ void TestOutgoingTcp(const uint8_t* data, uint32_t len,
+ bool expected_result) {
+ mozilla::net::NetAddr addr;
+ bool result;
+ nsresult rv = tcp_filter_->FilterPacket(&addr, data, len,
+ nsISocketFilter::SF_OUTGOING,
+ &result);
ASSERT_EQ(NS_OK, rv);
ASSERT_EQ(expected_result, result);
}
+ void TestOutgoingTcpFramed(const uint8_t* data, uint32_t len,
+ bool expected_result) {
+ mozilla::net::NetAddr addr;
+ bool result;
+ uint8_t* framed_data = new uint8_t[len+2];
+ framed_data[0] = htons(len);
+ memcpy(&framed_data[2], data, len);
+ nsresult rv = tcp_filter_->FilterPacket(&addr, framed_data, len+2,
+ nsISocketFilter::SF_OUTGOING,
+ &result);
+ ASSERT_EQ(NS_OK, rv);
+ ASSERT_EQ(expected_result, result);
+ delete[] framed_data;
+ }
+
private:
void MakeNetAddr(mozilla::net::NetAddr* net_addr,
uint8_t last_digit, uint16_t port) {
net_addr->inet.family = AF_INET;
net_addr->inet.ip = 192 << 24 | 168 << 16 | 1 << 8 | last_digit;
net_addr->inet.port = port;
}
- nsCOMPtr<nsIUDPSocketFilter> filter_;
+ nsCOMPtr<nsISocketFilter> udp_filter_;
+ nsCOMPtr<nsISocketFilter> tcp_filter_;
RefPtr<NrIceCtx> ice_ctx_;
};
} // end namespace
TEST_F(WebRtcIceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
if (stun_server_hostname_.empty()) {
return;
}
@@ -3207,120 +3267,192 @@ TEST_F(WebRtcIcePrioritizerTest, TestPri
HasLowerPreference("7", "1");
HasLowerPreference("1", "5");
HasLowerPreference("5", "4");
}
TEST_F(WebRtcIcePacketFilterTest, TestSendNonStunPacket) {
const unsigned char data[] = "12345abcde";
TestOutgoing(data, sizeof(data), 123, 45, false);
+ TestOutgoingTcp(data, sizeof(data), false);
}
TEST_F(WebRtcIcePacketFilterTest, TestRecvNonStunPacket) {
const unsigned char data[] = "12345abcde";
TestIncoming(data, sizeof(data), 123, 45, false);
+ TestIncomingTcp(data, sizeof(data), true);
}
TEST_F(WebRtcIcePacketFilterTest, TestSendStunPacket) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestOutgoing(msg->buffer, msg->length, 123, 45, true);
+ TestOutgoingTcp(msg->buffer, msg->length, true);
+ TestOutgoingTcpFramed(msg->buffer, msg->length, true);
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithoutAPendingId) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
msg->header.id.octet[0] = 1;
msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestOutgoing(msg->buffer, msg->length, 123, 45, true);
+ TestOutgoingTcp(msg->buffer, msg->length, true);
msg->header.id.octet[0] = 0;
msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestIncoming(msg->buffer, msg->length, 123, 45, true);
+ TestIncomingTcp(msg->buffer, msg->length, true);
+
+ ASSERT_EQ(0, nr_stun_message_destroy(&msg));
+}
+
+TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithoutAPendingIdTcpFramed) {
+ nr_stun_message *msg;
+ ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
+
+ msg->header.id.octet[0] = 1;
+ msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
+ ASSERT_EQ(0, nr_stun_encode_message(msg));
+ TestOutgoingTcpFramed(msg->buffer, msg->length, true);
+
+ msg->header.id.octet[0] = 0;
+ msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
+ ASSERT_EQ(0, nr_stun_encode_message(msg));
+ TestIncomingTcpFramed(msg->buffer, msg->length, true);
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithoutAPendingAddress) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestOutgoing(msg->buffer, msg->length, 123, 45, true);
+ // nothing to test here for the TCP filter
msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestIncoming(msg->buffer, msg->length, 123, 46, false);
TestIncoming(msg->buffer, msg->length, 124, 45, false);
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithPendingIdAndAddress) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestOutgoing(msg->buffer, msg->length, 123, 45, true);
+ TestOutgoingTcp(msg->buffer, msg->length, true);
msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestIncoming(msg->buffer, msg->length, 123, 45, true);
+ TestIncomingTcp(msg->buffer, msg->length, true);
// Test whitelist by filtering non-stun packets.
const unsigned char data[] = "12345abcde";
// 123:45 is white-listed.
TestOutgoing(data, sizeof(data), 123, 45, true);
+ TestOutgoingTcp(data, sizeof(data), true);
TestIncoming(data, sizeof(data), 123, 45, true);
+ TestIncomingTcp(data, sizeof(data), true);
// Indications pass as well.
msg->header.type = NR_STUN_MSG_BINDING_INDICATION;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestOutgoing(msg->buffer, msg->length, 123, 45, true);
+ TestOutgoingTcp(msg->buffer, msg->length, true);
TestIncoming(msg->buffer, msg->length, 123, 45, true);
+ TestIncomingTcp(msg->buffer, msg->length, true);
// Packets from and to other address are still disallowed.
+ // Note: this doesn't apply for TCP connections
TestOutgoing(data, sizeof(data), 123, 46, false);
TestIncoming(data, sizeof(data), 123, 46, false);
TestOutgoing(data, sizeof(data), 124, 45, false);
TestIncoming(data, sizeof(data), 124, 45, false);
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
+TEST_F(WebRtcIcePacketFilterTest, TestRecvStunPacketWithPendingIdTcpFramed) {
+ nr_stun_message *msg;
+ ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
+
+ msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
+ ASSERT_EQ(0, nr_stun_encode_message(msg));
+ TestOutgoingTcpFramed(msg->buffer, msg->length, true);
+
+ msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
+ ASSERT_EQ(0, nr_stun_encode_message(msg));
+ TestIncomingTcpFramed(msg->buffer, msg->length, true);
+
+ // Test whitelist by filtering non-stun packets.
+ const unsigned char data[] = "12345abcde";
+
+ TestOutgoingTcpFramed(data, sizeof(data), true);
+ TestIncomingTcpFramed(data, sizeof(data), true);
+
+ ASSERT_EQ(0, nr_stun_message_destroy(&msg));
+}
+
TEST_F(WebRtcIcePacketFilterTest, TestSendNonRequestStunPacket) {
nr_stun_message *msg;
ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestOutgoing(msg->buffer, msg->length, 123, 45, false);
+ TestOutgoingTcp(msg->buffer, msg->length, false);
// Send a packet so we allow the incoming request.
msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestOutgoing(msg->buffer, msg->length, 123, 45, true);
+ TestOutgoingTcp(msg->buffer, msg->length, true);
// This packet makes us able to send a response.
msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestIncoming(msg->buffer, msg->length, 123, 45, true);
+ TestIncomingTcp(msg->buffer, msg->length, true);
msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
ASSERT_EQ(0, nr_stun_encode_message(msg));
TestOutgoing(msg->buffer, msg->length, 123, 45, true);
+ TestOutgoingTcp(msg->buffer, msg->length, true);
+
+ ASSERT_EQ(0, nr_stun_message_destroy(&msg));
+}
+
+TEST_F(WebRtcIcePacketFilterTest, TestRecvDataPacketWithAPendingAddress) {
+ nr_stun_message *msg;
+ ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
+
+ msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
+ ASSERT_EQ(0, nr_stun_encode_message(msg));
+ TestOutgoing(msg->buffer, msg->length, 123, 45, true);
+ TestOutgoingTcp(msg->buffer, msg->length, true);
+
+ const unsigned char data[] = "12345abcde";
+ TestIncoming(data, sizeof(data), 123, 45, true);
+ TestIncomingTcp(data, sizeof(data), true);
ASSERT_EQ(0, nr_stun_message_destroy(&msg));
}
TEST(WebRtcIceInternalsTest, TestAddBogusAttribute) {
nr_stun_message *req;
ASSERT_EQ(0, nr_stun_message_create(&req));
Data *data;
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -104,16 +104,17 @@ XPIDL_SOURCES += [
'nsISecretDecoderRing.idl',
'nsISecureBrowserUI.idl',
'nsISecurityEventSink.idl',
'nsISecurityInfoProvider.idl',
'nsISensitiveInfoHiddenURI.idl',
'nsISerializationHelper.idl',
'nsIServerSocket.idl',
'nsISimpleStreamListener.idl',
+ 'nsISocketFilter.idl',
'nsISocketTransport.idl',
'nsISocketTransportService.idl',
'nsISpeculativeConnect.idl',
'nsIStandardURL.idl',
'nsIStreamingProtocolController.idl',
'nsIStreamingProtocolService.idl',
'nsIStreamListener.idl',
'nsIStreamListenerTee.idl',
@@ -123,17 +124,16 @@ XPIDL_SOURCES += [
'nsISystemProxySettings.idl',
'nsIThreadRetargetableRequest.idl',
'nsIThreadRetargetableStreamListener.idl',
'nsITimedChannel.idl',
'nsITLSServerSocket.idl',
'nsITraceableChannel.idl',
'nsITransport.idl',
'nsIUDPSocket.idl',
- 'nsIUDPSocketFilter.idl',
'nsIUnicharStreamLoader.idl',
'nsIUploadChannel.idl',
'nsIUploadChannel2.idl',
'nsIURI.idl',
'nsIURIClassifier.idl',
'nsIURIWithPrincipal.idl',
'nsIURL.idl',
'nsIURLParser.idl',
rename from netwerk/base/nsIUDPSocketFilter.idl
rename to netwerk/base/nsISocketFilter.idl
--- a/netwerk/base/nsIUDPSocketFilter.idl
+++ b/netwerk/base/nsISocketFilter.idl
@@ -7,39 +7,47 @@
#include "nsISupports.idl"
#include "nsINetAddr.idl"
native NetAddr(mozilla::net::NetAddr);
[ptr] native NetAddrPtr(mozilla::net::NetAddr);
/**
- * Filters are created and run on the parent, and filter all UDP packets, both
+ * Filters are created and run on the parent, and filter all packets, both
* ingoing and outgoing. The child must specify the name of a recognized filter
- * in order to create a UDP socket.
+ * in order to create a socket.
*/
-[uuid(24f20de4-09e9-42ab-947a-0d6a3d103d59)]
-interface nsIUDPSocketFilter : nsISupports
+[uuid(afe2c40c-b9b9-4207-b898-e5cde18c6139)]
+interface nsISocketFilter : nsISupports
{
const long SF_INCOMING = 0;
const long SF_OUTGOING = 1;
bool filterPacket([const]in NetAddrPtr remote_addr,
[const, array, size_is(len)]in uint8_t data,
in unsigned long len,
in long direction);
};
/**
* Factory of a specified filter.
*/
[uuid(81ee76c6-4753-4125-9c8c-290ed9ba62fb)]
-interface nsIUDPSocketFilterHandler : nsISupports
+interface nsISocketFilterHandler : nsISupports
{
- nsIUDPSocketFilter newFilter();
+ nsISocketFilter newFilter();
};
%{C++
/**
* Filter handlers are registered with XPCOM under the following CONTRACTID prefix:
*/
#define NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX "@mozilla.org/network/udp-filter-handler;1?name="
+#define NS_NETWORK_TCP_SOCKET_FILTER_HANDLER_PREFIX "@mozilla.org/network/tcp-filter-handler;1?name="
+
+#define NS_NETWORK_SOCKET_FILTER_HANDLER_STUN_SUFFIX "stun"
+
+#define NS_STUN_UDP_SOCKET_FILTER_HANDLER_CONTRACTID NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX NS_NETWORK_SOCKET_FILTER_HANDLER_STUN_SUFFIX
+
+
+#define NS_STUN_TCP_SOCKET_FILTER_HANDLER_CONTRACTID NS_NETWORK_TCP_SOCKET_FILTER_HANDLER_PREFIX NS_NETWORK_SOCKET_FILTER_HANDLER_STUN_SUFFIX
%}
--- a/netwerk/base/nsSocketTransportService2.cpp
+++ b/netwerk/base/nsSocketTransportService2.cpp
@@ -27,16 +27,17 @@
#include "nsIFile.h"
#include "nsIWidget.h"
using namespace mozilla;
using namespace mozilla::net;
LazyLogModule gSocketTransportLog("nsSocketTransport");
LazyLogModule gUDPSocketLog("UDPSocket");
+LazyLogModule gTCPSocketLog("TCPSocket");
nsSocketTransportService *gSocketTransportService = nullptr;
Atomic<PRThread*, Relaxed> gSocketThread;
#define SEND_BUFFER_PREF "network.tcp.sendbuffer"
#define KEEPALIVE_ENABLED_PREF "network.tcp.keepalive.enabled"
#define KEEPALIVE_IDLE_TIME_PREF "network.tcp.keepalive.idle_time"
#define KEEPALIVE_RETRY_INTERVAL_PREF "network.tcp.keepalive.retry_interval"