1/*
2 * Copyright (C) 2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "NetworkRTCProvider.h"
28
29#if USE(LIBWEBRTC)
30
31#include "Logging.h"
32#include "NetworkConnectionToWebProcess.h"
33#include "NetworkProcess.h"
34#include "NetworkRTCResolver.h"
35#include "NetworkRTCSocket.h"
36#include "WebRTCResolverMessages.h"
37#include "WebRTCSocketMessages.h"
38#include <WebCore/LibWebRTCMacros.h>
39#include <webrtc/rtc_base/asyncpacketsocket.h>
40#include <webrtc/rtc_base/logging.h>
41#include <wtf/MainThread.h>
42#include <wtf/text/WTFString.h>
43
44#if PLATFORM(COCOA)
45#include "NetworkRTCResolverCocoa.h"
46#endif
47
48namespace WebKit {
49
50static inline std::unique_ptr<rtc::Thread> createThread()
51{
52 auto thread = rtc::Thread::CreateWithSocketServer();
53 auto result = thread->Start();
54 ASSERT_UNUSED(result, result);
55 // FIXME: Set thread name.
56 return thread;
57}
58
59NetworkRTCProvider::NetworkRTCProvider(NetworkConnectionToWebProcess& connection)
60 : m_connection(&connection)
61 , m_rtcMonitor(*this)
62 , m_rtcNetworkThread(createThread())
63 , m_packetSocketFactory(makeUniqueRef<rtc::BasicPacketSocketFactory>(m_rtcNetworkThread.get()))
64{
65#if defined(NDEBUG)
66 rtc::LogMessage::LogToDebug(rtc::LS_NONE);
67#else
68 if (WebKit2LogWebRTC.state != WTFLogChannelState::On)
69 rtc::LogMessage::LogToDebug(rtc::LS_WARNING);
70#endif
71}
72
73NetworkRTCProvider::~NetworkRTCProvider()
74{
75 ASSERT(!m_connection);
76 ASSERT(!m_sockets.size());
77 ASSERT(!m_rtcMonitor.isStarted());
78}
79
80void NetworkRTCProvider::close()
81{
82 // Cancel all pending DNS resolutions.
83 while (!m_resolvers.isEmpty())
84 stopResolver(*m_resolvers.keys().begin());
85
86 m_connection = nullptr;
87 m_rtcMonitor.stopUpdating();
88
89 callOnRTCNetworkThread([this]() {
90 m_sockets.clear();
91 callOnMainThread([provider = makeRef(*this)]() {
92 if (provider->m_rtcNetworkThread)
93 provider->m_rtcNetworkThread->Stop();
94 });
95 });
96}
97
98void NetworkRTCProvider::createSocket(uint64_t identifier, std::unique_ptr<rtc::AsyncPacketSocket>&& socket, LibWebRTCSocketClient::Type type)
99{
100 if (!socket) {
101 sendFromMainThread([identifier](IPC::Connection& connection) {
102 connection.send(Messages::WebRTCSocket::SignalClose(1), identifier);
103 });
104 return;
105 }
106 addSocket(identifier, std::make_unique<LibWebRTCSocketClient>(identifier, *this, WTFMove(socket), type));
107}
108
109void NetworkRTCProvider::createUDPSocket(uint64_t identifier, const RTCNetwork::SocketAddress& address, uint16_t minPort, uint16_t maxPort)
110{
111 callOnRTCNetworkThread([this, identifier, address = RTCNetwork::isolatedCopy(address.value), minPort, maxPort]() {
112 std::unique_ptr<rtc::AsyncPacketSocket> socket(m_packetSocketFactory->CreateUdpSocket(address, minPort, maxPort));
113 createSocket(identifier, WTFMove(socket), LibWebRTCSocketClient::Type::UDP);
114 });
115}
116
117void NetworkRTCProvider::createServerTCPSocket(uint64_t identifier, const RTCNetwork::SocketAddress& address, uint16_t minPort, uint16_t maxPort, int options)
118{
119 if (!m_isListeningSocketAuthorized) {
120 if (m_connection)
121 m_connection->connection().send(Messages::WebRTCSocket::SignalClose(1), identifier);
122 return;
123 }
124
125 callOnRTCNetworkThread([this, identifier, address = RTCNetwork::isolatedCopy(address.value), minPort, maxPort, options]() {
126 std::unique_ptr<rtc::AsyncPacketSocket> socket(m_packetSocketFactory->CreateServerTcpSocket(address, minPort, maxPort, options));
127 createSocket(identifier, WTFMove(socket), LibWebRTCSocketClient::Type::ServerTCP);
128 });
129}
130
131void NetworkRTCProvider::createClientTCPSocket(uint64_t identifier, const RTCNetwork::SocketAddress& localAddress, const RTCNetwork::SocketAddress& remoteAddress, int options)
132{
133 callOnRTCNetworkThread([this, identifier, localAddress = RTCNetwork::isolatedCopy(localAddress.value), remoteAddress = RTCNetwork::isolatedCopy(remoteAddress.value), options]() {
134 std::unique_ptr<rtc::AsyncPacketSocket> socket(m_packetSocketFactory->CreateClientTcpSocket(localAddress, remoteAddress, { }, { }, options));
135 createSocket(identifier, WTFMove(socket), LibWebRTCSocketClient::Type::ClientTCP);
136 });
137}
138
139void NetworkRTCProvider::wrapNewTCPConnection(uint64_t identifier, uint64_t newConnectionSocketIdentifier)
140{
141 callOnRTCNetworkThread([this, identifier, newConnectionSocketIdentifier]() {
142 std::unique_ptr<rtc::AsyncPacketSocket> socket = m_pendingIncomingSockets.take(newConnectionSocketIdentifier);
143 addSocket(identifier, std::make_unique<LibWebRTCSocketClient>(identifier, *this, WTFMove(socket), LibWebRTCSocketClient::Type::ServerConnectionTCP));
144 });
145}
146
147void NetworkRTCProvider::addSocket(uint64_t identifier, std::unique_ptr<LibWebRTCSocketClient>&& socket)
148{
149 m_sockets.add(identifier, WTFMove(socket));
150}
151
152std::unique_ptr<LibWebRTCSocketClient> NetworkRTCProvider::takeSocket(uint64_t identifier)
153{
154 return m_sockets.take(identifier);
155}
156
157void NetworkRTCProvider::newConnection(LibWebRTCSocketClient& serverSocket, std::unique_ptr<rtc::AsyncPacketSocket>&& newSocket)
158{
159 sendFromMainThread([identifier = serverSocket.identifier(), incomingSocketIdentifier = ++m_incomingSocketIdentifier, remoteAddress = RTCNetwork::isolatedCopy(newSocket->GetRemoteAddress())](IPC::Connection& connection) {
160 connection.send(Messages::WebRTCSocket::SignalNewConnection(incomingSocketIdentifier, RTCNetwork::SocketAddress(remoteAddress)), identifier);
161 });
162 m_pendingIncomingSockets.add(m_incomingSocketIdentifier, WTFMove(newSocket));
163}
164
165void NetworkRTCProvider::didReceiveNetworkRTCSocketMessage(IPC::Connection& connection, IPC::Decoder& decoder)
166{
167 NetworkRTCSocket(decoder.destinationID(), *this).didReceiveMessage(connection, decoder);
168}
169
170#if PLATFORM(COCOA)
171
172void NetworkRTCProvider::createResolver(uint64_t identifier, const String& address)
173{
174 auto resolver = NetworkRTCResolver::create(identifier, [this, identifier](WebCore::DNSAddressesOrError&& result) mutable {
175 if (!result.has_value()) {
176 if (result.error() != WebCore::DNSError::Cancelled)
177 m_connection->connection().send(Messages::WebRTCResolver::ResolvedAddressError(1), identifier);
178 return;
179 }
180
181 auto addresses = WTF::map(result.value(), [] (auto& address) {
182 return RTCNetwork::IPAddress { rtc::IPAddress { address.getSinAddr() } };
183 });
184
185 m_connection->connection().send(Messages::WebRTCResolver::SetResolvedAddress(addresses), identifier);
186 });
187 resolver->start(address);
188 m_resolvers.add(identifier, WTFMove(resolver));
189}
190
191void NetworkRTCProvider::stopResolver(uint64_t identifier)
192{
193 if (auto resolver = m_resolvers.take(identifier))
194 resolver->stop();
195}
196
197#else
198
199void NetworkRTCProvider::createResolver(uint64_t identifier, const String& address)
200{
201 auto completionHandler = [this, identifier](WebCore::DNSAddressesOrError&& result) mutable {
202 if (!result.has_value()) {
203 if (result.error() != WebCore::DNSError::Cancelled)
204 m_connection->connection().send(Messages::WebRTCResolver::ResolvedAddressError(1), identifier);
205 return;
206 }
207
208 auto addresses = WTF::map(result.value(), [] (auto& address) {
209 return RTCNetwork::IPAddress { rtc::IPAddress { address.getSinAddr() } };
210 });
211
212 m_connection->connection().send(Messages::WebRTCResolver::SetResolvedAddress(addresses), identifier);
213 };
214
215 WebCore::resolveDNS(address, identifier, WTFMove(completionHandler));
216}
217
218void NetworkRTCProvider::stopResolver(uint64_t identifier)
219{
220 WebCore::stopResolveDNS(identifier);
221}
222
223#endif
224
225void NetworkRTCProvider::closeListeningSockets(Function<void()>&& completionHandler)
226{
227 if (!m_isListeningSocketAuthorized) {
228 completionHandler();
229 return;
230 }
231
232 m_isListeningSocketAuthorized = false;
233 callOnRTCNetworkThread([this, completionHandler = WTFMove(completionHandler)]() mutable {
234 Vector<uint64_t> listeningSocketIdentifiers;
235 for (auto& keyValue : m_sockets) {
236 if (keyValue.value->type() == LibWebRTCSocketClient::Type::ServerTCP)
237 listeningSocketIdentifiers.append(keyValue.key);
238 }
239 for (auto id : listeningSocketIdentifiers)
240 m_sockets.get(id)->close();
241
242 callOnMainThread([provider = makeRef(*this), listeningSocketIdentifiers = WTFMove(listeningSocketIdentifiers), completionHandler = WTFMove(completionHandler)] {
243 if (provider->m_connection) {
244 for (auto identifier : listeningSocketIdentifiers)
245 provider->m_connection->connection().send(Messages::WebRTCSocket::SignalClose(ECONNABORTED), identifier);
246 }
247 completionHandler();
248 });
249 });
250}
251
252struct NetworkMessageData : public rtc::MessageData {
253 NetworkMessageData(Ref<NetworkRTCProvider>&& rtcProvider, Function<void()>&& callback)
254 : rtcProvider(WTFMove(rtcProvider))
255 , callback(WTFMove(callback))
256 { }
257 Ref<NetworkRTCProvider> rtcProvider;
258 Function<void()> callback;
259};
260
261void NetworkRTCProvider::OnMessage(rtc::Message* message)
262{
263 ASSERT(message->message_id == 1);
264 auto* data = static_cast<NetworkMessageData*>(message->pdata);
265 data->callback();
266 delete data;
267}
268
269void NetworkRTCProvider::callOnRTCNetworkThread(Function<void()>&& callback)
270{
271 m_rtcNetworkThread->Post(RTC_FROM_HERE, this, 1, new NetworkMessageData(*this, WTFMove(callback)));
272}
273
274void NetworkRTCProvider::callSocket(uint64_t identifier, Function<void(LibWebRTCSocketClient&)>&& callback)
275{
276 callOnRTCNetworkThread([this, identifier, callback = WTFMove(callback)]() {
277 if (auto* socket = m_sockets.get(identifier))
278 callback(*socket);
279 });
280}
281
282void NetworkRTCProvider::sendFromMainThread(Function<void(IPC::Connection&)>&& callback)
283{
284 callOnMainThread([provider = makeRef(*this), callback = WTFMove(callback)]() {
285 if (provider->m_connection)
286 callback(provider->m_connection->connection());
287 });
288}
289
290} // namespace WebKit
291
292#endif // USE(LIBWEBRTC)
293