1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "WebrtcTCPSocketWrapper.h"
8 
9 #include "mozilla/net/WebrtcTCPSocketChild.h"
10 #include "ipc/WebrtcTCPSocket.h"
11 #include "mozilla/LoadInfo.h"
12 
13 #include "nsNetCID.h"
14 #include "nsProxyRelease.h"
15 
16 #include "nr_socket_proxy_config.h"
17 
18 namespace mozilla::net {
19 
20 using std::shared_ptr;
21 
WebrtcTCPSocketWrapper(WebrtcTCPSocketCallback * aCallbacks)22 WebrtcTCPSocketWrapper::WebrtcTCPSocketWrapper(
23     WebrtcTCPSocketCallback* aCallbacks)
24     : mProxyCallbacks(aCallbacks),
25       mWebrtcTCPSocket(nullptr),
26       mMainThread(nullptr),
27       mSocketThread(nullptr) {
28   mMainThread = GetMainThreadEventTarget();
29   mSocketThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
30   MOZ_RELEASE_ASSERT(mMainThread, "no main thread");
31   MOZ_RELEASE_ASSERT(mSocketThread, "no socket thread");
32 }
33 
~WebrtcTCPSocketWrapper()34 WebrtcTCPSocketWrapper::~WebrtcTCPSocketWrapper() {
35   MOZ_ASSERT(!mWebrtcTCPSocket, "webrtc TCP socket non-null");
36 
37   // If we're never opened then we never get an OnClose from our parent process.
38   // We need to release our callbacks here safely.
39   NS_ProxyRelease("WebrtcTCPSocketWrapper::CleanUpCallbacks", mSocketThread,
40                   mProxyCallbacks.forget());
41 }
42 
AsyncOpen(const nsCString & aHost,const int & aPort,const nsCString & aLocalAddress,const int & aLocalPort,bool aUseTls,const shared_ptr<NrSocketProxyConfig> & aConfig)43 void WebrtcTCPSocketWrapper::AsyncOpen(
44     const nsCString& aHost, const int& aPort, const nsCString& aLocalAddress,
45     const int& aLocalPort, bool aUseTls,
46     const shared_ptr<NrSocketProxyConfig>& aConfig) {
47   if (!NS_IsMainThread()) {
48     MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch(
49         NewRunnableMethod<const nsCString, const int, const nsCString,
50                           const int, bool,
51                           const shared_ptr<NrSocketProxyConfig>>(
52             "WebrtcTCPSocketWrapper::AsyncOpen", this,
53             &WebrtcTCPSocketWrapper::AsyncOpen, aHost, aPort, aLocalAddress,
54             aLocalPort, aUseTls, aConfig)));
55     return;
56   }
57 
58   MOZ_ASSERT(!mWebrtcTCPSocket, "wrapper already open");
59   mWebrtcTCPSocket = new WebrtcTCPSocketChild(this);
60   mWebrtcTCPSocket->AsyncOpen(aHost, aPort, aLocalAddress, aLocalPort, aUseTls,
61                               aConfig);
62 }
63 
SendWrite(nsTArray<uint8_t> && aReadData)64 void WebrtcTCPSocketWrapper::SendWrite(nsTArray<uint8_t>&& aReadData) {
65   if (!NS_IsMainThread()) {
66     MOZ_ALWAYS_SUCCEEDS(
67         mMainThread->Dispatch(NewRunnableMethod<nsTArray<uint8_t>&&>(
68             "WebrtcTCPSocketWrapper::SendWrite", this,
69             &WebrtcTCPSocketWrapper::SendWrite, std::move(aReadData))));
70     return;
71   }
72 
73   MOZ_ASSERT(mWebrtcTCPSocket, "webrtc TCP socket should be non-null");
74   mWebrtcTCPSocket->SendWrite(aReadData);
75 }
76 
Close()77 void WebrtcTCPSocketWrapper::Close() {
78   if (!NS_IsMainThread()) {
79     MOZ_ALWAYS_SUCCEEDS(mMainThread->Dispatch(
80         NewRunnableMethod("WebrtcTCPSocketWrapper::Close", this,
81                           &WebrtcTCPSocketWrapper::Close)));
82     return;
83   }
84 
85   // We're only open if we have a channel. Also Close() should be idempotent.
86   if (mWebrtcTCPSocket) {
87     RefPtr<WebrtcTCPSocketChild> child = mWebrtcTCPSocket;
88     mWebrtcTCPSocket = nullptr;
89     child->SendClose();
90   }
91 }
92 
OnClose(nsresult aReason)93 void WebrtcTCPSocketWrapper::OnClose(nsresult aReason) {
94   MOZ_ASSERT(NS_IsMainThread(), "not on main thread");
95   MOZ_ASSERT(mProxyCallbacks, "webrtc TCP callbacks should be non-null");
96 
97   MOZ_ALWAYS_SUCCEEDS(mSocketThread->Dispatch(NewRunnableMethod<nsresult>(
98       "WebrtcTCPSocketWrapper::OnClose", mProxyCallbacks,
99       &WebrtcTCPSocketCallback::OnClose, aReason)));
100 
101   NS_ProxyRelease("WebrtcTCPSocketWrapper::CleanUpCallbacks", mSocketThread,
102                   mProxyCallbacks.forget());
103 }
104 
OnRead(nsTArray<uint8_t> && aReadData)105 void WebrtcTCPSocketWrapper::OnRead(nsTArray<uint8_t>&& aReadData) {
106   MOZ_ASSERT(NS_IsMainThread(), "not on main thread");
107   MOZ_ASSERT(mProxyCallbacks, "webrtc TCP callbacks should be non-null");
108 
109   MOZ_ALWAYS_SUCCEEDS(
110       mSocketThread->Dispatch(NewRunnableMethod<nsTArray<uint8_t>&&>(
111           "WebrtcTCPSocketWrapper::OnRead", mProxyCallbacks,
112           &WebrtcTCPSocketCallback::OnRead, std::move(aReadData))));
113 }
114 
OnConnected(const nsCString & aProxyType)115 void WebrtcTCPSocketWrapper::OnConnected(const nsCString& aProxyType) {
116   MOZ_ASSERT(NS_IsMainThread(), "not on main thread");
117   MOZ_ASSERT(mProxyCallbacks, "webrtc TCP callbacks should be non-null");
118 
119   MOZ_ALWAYS_SUCCEEDS(mSocketThread->Dispatch(NewRunnableMethod<nsCString>(
120       "WebrtcTCPSocketWrapper::OnConnected", mProxyCallbacks,
121       &WebrtcTCPSocketCallback::OnConnected, aProxyType)));
122 }
123 
124 }  // namespace mozilla::net
125