/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=2 ts=8 et tw=80 ft=cpp : */ /* 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/. */ #include "WebrtcTCPSocketWrapper.h" #include "mozilla/net/WebrtcTCPSocketChild.h" #include "nsNetCID.h" #include "nsProxyRelease.h" #include "nsServiceManagerUtils.h" #include "nr_socket_proxy_config.h" namespace mozilla::net { using std::shared_ptr; WebrtcTCPSocketWrapper::WebrtcTCPSocketWrapper( WebrtcTCPSocketCallback* aCallbacks) : mProxyCallbacks(aCallbacks), mWebrtcTCPSocket(nullptr), mMainThread(nullptr), mSocketThread(nullptr) { mMainThread = GetMainThreadSerialEventTarget(); mSocketThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID); MOZ_RELEASE_ASSERT(mMainThread, "no main thread"); MOZ_RELEASE_ASSERT(mSocketThread, "no socket thread"); } WebrtcTCPSocketWrapper::~WebrtcTCPSocketWrapper() { MOZ_ASSERT(!mWebrtcTCPSocket, "webrtc TCP socket non-null"); // If we're never opened then we never get an OnClose from our parent process. // We need to release our callbacks here safely. NS_ProxyRelease("WebrtcTCPSocketWrapper::CleanUpCallbacks", mSocketThread, mProxyCallbacks.forget()); } void WebrtcTCPSocketWrapper::AsyncOpen( const nsCString& aHost, const int& aPort, const nsCString& aLocalAddress, const int& aLocalPort, bool aUseTls, const shared_ptr& aConfig) { if (!NS_IsMainThread()) { MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch( NewRunnableMethod>( "WebrtcTCPSocketWrapper::AsyncOpen", this, &WebrtcTCPSocketWrapper::AsyncOpen, aHost, aPort, aLocalAddress, aLocalPort, aUseTls, aConfig))); return; } MOZ_ASSERT(!mWebrtcTCPSocket, "wrapper already open"); mWebrtcTCPSocket = new WebrtcTCPSocketChild(this); mWebrtcTCPSocket->AsyncOpen(aHost, aPort, aLocalAddress, aLocalPort, aUseTls, aConfig); } void WebrtcTCPSocketWrapper::SendWrite(nsTArray&& aReadData) { if (!NS_IsMainThread()) { MOZ_ALWAYS_SUCCEEDS( mMainThread->Dispatch(NewRunnableMethod&&>( "WebrtcTCPSocketWrapper::SendWrite", this, &WebrtcTCPSocketWrapper::SendWrite, std::move(aReadData)))); return; } MOZ_ASSERT(mWebrtcTCPSocket, "webrtc TCP socket should be non-null"); mWebrtcTCPSocket->SendWrite(aReadData); } void WebrtcTCPSocketWrapper::Close() { if (!NS_IsMainThread()) { MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch( NewRunnableMethod("WebrtcTCPSocketWrapper::Close", this, &WebrtcTCPSocketWrapper::Close))); return; } // We're only open if we have a channel. Also Close() should be idempotent. if (mWebrtcTCPSocket) { RefPtr child = mWebrtcTCPSocket; mWebrtcTCPSocket = nullptr; child->SendClose(); } } void WebrtcTCPSocketWrapper::OnClose(nsresult aReason) { MOZ_ASSERT(NS_IsMainThread(), "not on main thread"); MOZ_ASSERT(mProxyCallbacks, "webrtc TCP callbacks should be non-null"); MOZ_ALWAYS_SUCCEEDS(mSocketThread->Dispatch(NewRunnableMethod( "WebrtcTCPSocketWrapper::OnClose", mProxyCallbacks, &WebrtcTCPSocketCallback::OnClose, aReason))); NS_ProxyRelease("WebrtcTCPSocketWrapper::CleanUpCallbacks", mSocketThread, mProxyCallbacks.forget()); } void WebrtcTCPSocketWrapper::OnRead(nsTArray&& aReadData) { MOZ_ASSERT(NS_IsMainThread(), "not on main thread"); MOZ_ASSERT(mProxyCallbacks, "webrtc TCP callbacks should be non-null"); MOZ_ALWAYS_SUCCEEDS( mSocketThread->Dispatch(NewRunnableMethod&&>( "WebrtcTCPSocketWrapper::OnRead", mProxyCallbacks, &WebrtcTCPSocketCallback::OnRead, std::move(aReadData)))); } void WebrtcTCPSocketWrapper::OnConnected(const nsACString& aProxyType) { MOZ_ASSERT(NS_IsMainThread(), "not on main thread"); MOZ_ASSERT(mProxyCallbacks, "webrtc TCP callbacks should be non-null"); MOZ_ALWAYS_SUCCEEDS(mSocketThread->Dispatch(NewRunnableMethod( "WebrtcTCPSocketWrapper::OnConnected", mProxyCallbacks, &WebrtcTCPSocketCallback::OnConnected, aProxyType))); } } // namespace mozilla::net