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