ed9fb8bf25a6fd3d0e0c8b1edf764d442d7bcb02
[WebKit-https.git] / Source / WebCore / platform / mediastream / libwebrtc / LibWebRTCProvider.cpp
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 "LibWebRTCProvider.h"
28
29 #if USE(LIBWEBRTC)
30 #include "LibWebRTCAudioModule.h"
31 #include "Logging.h"
32 #include "RTCRtpCapabilities.h"
33 #include <dlfcn.h>
34
35 ALLOW_UNUSED_PARAMETERS_BEGIN
36
37 #include <webrtc/api/asyncresolverfactory.h>
38 #include <webrtc/api/audio_codecs/builtin_audio_decoder_factory.h>
39 #include <webrtc/api/audio_codecs/builtin_audio_encoder_factory.h>
40 #include <webrtc/api/create_peerconnection_factory.h>
41 #include <webrtc/api/peerconnectionfactoryproxy.h>
42 #include <webrtc/modules/audio_processing/include/audio_processing.h>
43 #include <webrtc/p2p/base/basicpacketsocketfactory.h>
44 #include <webrtc/p2p/client/basicportallocator.h>
45 #include <webrtc/pc/peerconnectionfactory.h>
46 #include <webrtc/rtc_base/physicalsocketserver.h>
47
48 ALLOW_UNUSED_PARAMETERS_END
49
50 #include <wtf/Function.h>
51 #include <wtf/NeverDestroyed.h>
52 #endif
53
54 namespace WebCore {
55
56 #if !USE(LIBWEBRTC)
57 UniqueRef<LibWebRTCProvider> LibWebRTCProvider::create()
58 {
59     return makeUniqueRef<LibWebRTCProvider>();
60 }
61
62 bool LibWebRTCProvider::webRTCAvailable()
63 {
64     return false;
65 }
66 #endif
67
68 void LibWebRTCProvider::setActive(bool)
69 {
70 }
71
72 #if USE(LIBWEBRTC)
73 static inline rtc::SocketAddress prepareSocketAddress(const rtc::SocketAddress& address, bool disableNonLocalhostConnections)
74 {
75     auto result = address;
76     if (disableNonLocalhostConnections)
77         result.SetIP("127.0.0.1");
78     return result;
79 }
80
81 class BasicPacketSocketFactory : public rtc::BasicPacketSocketFactory {
82 public:
83     explicit BasicPacketSocketFactory(rtc::Thread& networkThread)
84         : m_socketFactory(makeUniqueRef<rtc::BasicPacketSocketFactory>(&networkThread))
85     {
86     }
87
88     void setDisableNonLocalhostConnections(bool disableNonLocalhostConnections) { m_disableNonLocalhostConnections = disableNonLocalhostConnections; }
89
90     rtc::AsyncPacketSocket* CreateUdpSocket(const rtc::SocketAddress& address, uint16_t minPort, uint16_t maxPort) final
91     {
92         return m_socketFactory->CreateUdpSocket(prepareSocketAddress(address, m_disableNonLocalhostConnections), minPort, maxPort);
93     }
94
95     rtc::AsyncPacketSocket* CreateServerTcpSocket(const rtc::SocketAddress& address, uint16_t minPort, uint16_t maxPort, int options) final
96     {
97         return m_socketFactory->CreateServerTcpSocket(prepareSocketAddress(address, m_disableNonLocalhostConnections), minPort, maxPort, options);
98     }
99
100     rtc::AsyncPacketSocket* CreateClientTcpSocket(const rtc::SocketAddress& localAddress, const rtc::SocketAddress& remoteAddress, const rtc::ProxyInfo& info, const std::string& name, int options)
101     {
102         return m_socketFactory->CreateClientTcpSocket(prepareSocketAddress(localAddress, m_disableNonLocalhostConnections), remoteAddress, info, name, options);
103     }
104
105 private:
106     bool m_disableNonLocalhostConnections { false };
107     UniqueRef<rtc::BasicPacketSocketFactory> m_socketFactory;
108 };
109
110 struct PeerConnectionFactoryAndThreads : public rtc::MessageHandler {
111     std::unique_ptr<rtc::Thread> networkThread;
112     std::unique_ptr<rtc::Thread> signalingThread;
113     bool networkThreadWithSocketServer { false };
114     std::unique_ptr<LibWebRTCAudioModule> audioDeviceModule;
115     std::unique_ptr<rtc::NetworkManager> networkManager;
116     std::unique_ptr<BasicPacketSocketFactory> packetSocketFactory;
117     std::unique_ptr<rtc::RTCCertificateGenerator> certificateGenerator;
118
119 private:
120     void OnMessage(rtc::Message*);
121 };
122
123 static void doReleaseLogging(rtc::LoggingSeverity severity, const char* message)
124 {
125     if (severity == rtc::LS_ERROR)
126         RELEASE_LOG_ERROR(WebRTC, "LibWebRTC error: %{public}s", message);
127     else
128         RELEASE_LOG(WebRTC, "LibWebRTC message: %{public}s", message);
129 }
130
131 static void setLogging(rtc::LoggingSeverity level)
132 {
133     rtc::LogMessage::SetLogOutput(level, (level == rtc::LS_NONE) ? nullptr : doReleaseLogging);
134 }
135
136 static rtc::LoggingSeverity computeLogLevel()
137 {
138 #if defined(NDEBUG)
139 #if !LOG_DISABLED || !RELEASE_LOG_DISABLED
140     if (LogWebRTC.state != WTFLogChannelOn)
141         return rtc::LS_ERROR;
142
143     switch (LogWebRTC.level) {
144     case WTFLogLevelAlways:
145     case WTFLogLevelError:
146         return rtc::LS_ERROR;
147     case WTFLogLevelWarning:
148         return rtc::LS_WARNING;
149     case WTFLogLevelInfo:
150         return rtc::LS_INFO;
151     case WTFLogLevelDebug:
152         return rtc::LS_VERBOSE;
153     }
154 #else
155     return rtc::LS_NONE;
156 #endif
157 #else
158     return (LogWebRTC.state != WTFLogChannelOn) ? rtc::LS_WARNING : rtc::LS_INFO;
159 #endif
160 }
161
162 static void initializePeerConnectionFactoryAndThreads(PeerConnectionFactoryAndThreads& factoryAndThreads)
163 {
164     ASSERT(!factoryAndThreads.networkThread);
165
166     factoryAndThreads.networkThread = factoryAndThreads.networkThreadWithSocketServer ? rtc::Thread::CreateWithSocketServer() : rtc::Thread::Create();
167     factoryAndThreads.networkThread->SetName("WebKitWebRTCNetwork", nullptr);
168     bool result = factoryAndThreads.networkThread->Start();
169     ASSERT_UNUSED(result, result);
170
171     factoryAndThreads.signalingThread = rtc::Thread::Create();
172     factoryAndThreads.signalingThread->SetName("WebKitWebRTCSignaling", nullptr);
173
174     result = factoryAndThreads.signalingThread->Start();
175     ASSERT(result);
176
177     factoryAndThreads.audioDeviceModule = std::make_unique<LibWebRTCAudioModule>();
178 }
179
180 static inline PeerConnectionFactoryAndThreads& staticFactoryAndThreads()
181 {
182     static NeverDestroyed<PeerConnectionFactoryAndThreads> factoryAndThreads;
183     return factoryAndThreads.get();
184 }
185
186 static inline PeerConnectionFactoryAndThreads& getStaticFactoryAndThreads(bool useNetworkThreadWithSocketServer)
187 {
188     auto& factoryAndThreads = staticFactoryAndThreads();
189
190     ASSERT(!factoryAndThreads.networkThread || factoryAndThreads.networkThreadWithSocketServer == useNetworkThreadWithSocketServer);
191
192     if (!factoryAndThreads.networkThread) {
193         factoryAndThreads.networkThreadWithSocketServer = useNetworkThreadWithSocketServer;
194         initializePeerConnectionFactoryAndThreads(factoryAndThreads);
195     }
196     return factoryAndThreads;
197 }
198
199 struct ThreadMessageData : public rtc::MessageData {
200     ThreadMessageData(Function<void()>&& callback)
201         : callback(WTFMove(callback))
202     { }
203     Function<void()> callback;
204 };
205
206 void PeerConnectionFactoryAndThreads::OnMessage(rtc::Message* message)
207 {
208     ASSERT(message->message_id == 1);
209     auto* data = static_cast<ThreadMessageData*>(message->pdata);
210     data->callback();
211     delete data;
212 }
213
214 void LibWebRTCProvider::callOnWebRTCNetworkThread(Function<void()>&& callback)
215 {
216     PeerConnectionFactoryAndThreads& threads = staticFactoryAndThreads();
217     threads.networkThread->Post(RTC_FROM_HERE, &threads, 1, new ThreadMessageData(WTFMove(callback)));
218 }
219
220 void LibWebRTCProvider::callOnWebRTCSignalingThread(Function<void()>&& callback)
221 {
222     PeerConnectionFactoryAndThreads& threads = staticFactoryAndThreads();
223     threads.signalingThread->Post(RTC_FROM_HERE, &threads, 1, new ThreadMessageData(WTFMove(callback)));
224 }
225
226 void LibWebRTCProvider::setEnableLogging(bool enableLogging)
227 {
228     if (!m_enableLogging)
229         return;
230     m_enableLogging = enableLogging;
231     setLogging(enableLogging ? computeLogLevel() : rtc::LS_NONE);
232 }
233
234 webrtc::PeerConnectionFactoryInterface* LibWebRTCProvider::factory()
235 {
236     if (m_factory)
237         return m_factory.get();
238
239     if (!webRTCAvailable())
240         return nullptr;
241
242     auto& factoryAndThreads = getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer);
243
244     m_factory = createPeerConnectionFactory(factoryAndThreads.networkThread.get(), factoryAndThreads.networkThread.get(), factoryAndThreads.audioDeviceModule.get());
245
246     return m_factory;
247 }
248
249 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> LibWebRTCProvider::createPeerConnectionFactory(rtc::Thread* networkThread, rtc::Thread* signalingThread, LibWebRTCAudioModule* audioModule)
250 {
251     return webrtc::CreatePeerConnectionFactory(networkThread, networkThread, signalingThread, audioModule, webrtc::CreateBuiltinAudioEncoderFactory(), webrtc::CreateBuiltinAudioDecoderFactory(), createEncoderFactory(), createDecoderFactory(), nullptr, nullptr);
252 }
253
254 std::unique_ptr<webrtc::VideoDecoderFactory> LibWebRTCProvider::createDecoderFactory()
255 {
256     return nullptr;
257 }
258
259 std::unique_ptr<webrtc::VideoEncoderFactory> LibWebRTCProvider::createEncoderFactory()
260 {
261     return nullptr;
262 }
263
264 void LibWebRTCProvider::setPeerConnectionFactory(rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>&& factory)
265 {
266     m_factory = webrtc::PeerConnectionFactoryProxy::Create(getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer).signalingThread.get(), WTFMove(factory));
267 }
268
269 void LibWebRTCProvider::disableEnumeratingAllNetworkInterfaces()
270 {
271     m_enableEnumeratingAllNetworkInterfaces = false;
272 }
273
274 void LibWebRTCProvider::enableEnumeratingAllNetworkInterfaces()
275 {
276     m_enableEnumeratingAllNetworkInterfaces = true;
277 }
278
279 rtc::scoped_refptr<webrtc::PeerConnectionInterface> LibWebRTCProvider::createPeerConnection(webrtc::PeerConnectionObserver& observer, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration)
280 {
281     // Default WK1 implementation.
282     ASSERT(m_useNetworkThreadWithSocketServer);
283     auto& factoryAndThreads = getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer);
284
285     if (!factoryAndThreads.networkManager)
286         factoryAndThreads.networkManager = std::make_unique<rtc::BasicNetworkManager>();
287
288     if (!factoryAndThreads.packetSocketFactory)
289         factoryAndThreads.packetSocketFactory = std::make_unique<BasicPacketSocketFactory>(*factoryAndThreads.networkThread);
290     factoryAndThreads.packetSocketFactory->setDisableNonLocalhostConnections(m_disableNonLocalhostConnections);
291
292     return createPeerConnection(observer, *factoryAndThreads.networkManager, *factoryAndThreads.packetSocketFactory, WTFMove(configuration), nullptr);
293 }
294
295 rtc::scoped_refptr<webrtc::PeerConnectionInterface> LibWebRTCProvider::createPeerConnection(webrtc::PeerConnectionObserver& observer, rtc::NetworkManager& networkManager, rtc::PacketSocketFactory& packetSocketFactory, webrtc::PeerConnectionInterface::RTCConfiguration&& configuration, std::unique_ptr<webrtc::AsyncResolverFactory>&& asyncResolveFactory)
296 {
297     auto& factoryAndThreads = getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer);
298
299     std::unique_ptr<cricket::BasicPortAllocator> portAllocator;
300     factoryAndThreads.signalingThread->Invoke<void>(RTC_FROM_HERE, [&]() {
301         auto basicPortAllocator = std::make_unique<cricket::BasicPortAllocator>(&networkManager, &packetSocketFactory);
302         if (!m_enableEnumeratingAllNetworkInterfaces)
303             basicPortAllocator->set_flags(basicPortAllocator->flags() | cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION);
304         portAllocator = WTFMove(basicPortAllocator);
305     });
306
307     auto* factory = this->factory();
308     if (!factory)
309         return nullptr;
310
311     webrtc::PeerConnectionDependencies dependencies { &observer };
312     dependencies.allocator = WTFMove(portAllocator);
313     dependencies.async_resolver_factory = WTFMove(asyncResolveFactory);
314
315     return m_factory->CreatePeerConnection(configuration, WTFMove(dependencies));
316 }
317
318 rtc::RTCCertificateGenerator& LibWebRTCProvider::certificateGenerator()
319 {
320     auto& factoryAndThreads = getStaticFactoryAndThreads(m_useNetworkThreadWithSocketServer);
321     if (!factoryAndThreads.certificateGenerator)
322         factoryAndThreads.certificateGenerator = std::make_unique<rtc::RTCCertificateGenerator>(factoryAndThreads.signalingThread.get(), factoryAndThreads.networkThread.get());
323
324     return *factoryAndThreads.certificateGenerator;
325 }
326
327 static inline Optional<cricket::MediaType> typeFromKind(const String& kind)
328 {
329     if (kind == "audio"_s)
330         return cricket::MediaType::MEDIA_TYPE_AUDIO;
331     if (kind == "video"_s)
332         return cricket::MediaType::MEDIA_TYPE_VIDEO;
333     return { };
334 }
335
336 static inline String fromStdString(const std::string& value)
337 {
338     return String::fromUTF8(value.data(), value.length());
339 }
340
341 static inline Optional<uint16_t> toChannels(absl::optional<int> numChannels)
342 {
343     if (!numChannels)
344         return { };
345     return static_cast<uint32_t>(*numChannels);
346 }
347
348 static inline RTCRtpCapabilities toRTCRtpCapabilities(const webrtc::RtpCapabilities& rtpCapabilities)
349 {
350     RTCRtpCapabilities capabilities;
351
352     capabilities.codecs.reserveInitialCapacity(rtpCapabilities.codecs.size());
353     for (auto& codec : rtpCapabilities.codecs)
354         capabilities.codecs.uncheckedAppend(RTCRtpCapabilities::CodecCapability { fromStdString(codec.mime_type()), static_cast<uint32_t>(codec.clock_rate ? *codec.clock_rate : 0), toChannels(codec.num_channels), { } });
355
356     capabilities.headerExtensions.reserveInitialCapacity(rtpCapabilities.header_extensions.size());
357     for (auto& header : rtpCapabilities.header_extensions)
358         capabilities.headerExtensions.uncheckedAppend(RTCRtpCapabilities::HeaderExtensionCapability { fromStdString(header.uri) });
359
360     return capabilities;
361 }
362
363 Optional<RTCRtpCapabilities> LibWebRTCProvider::receiverCapabilities(const String& kind)
364 {
365     auto mediaType = typeFromKind(kind);
366     if (!mediaType)
367         return { };
368
369     auto* factory = this->factory();
370     if (!factory)
371         return { };
372
373     return toRTCRtpCapabilities(factory->GetRtpReceiverCapabilities(*mediaType));
374 }
375
376 Optional<RTCRtpCapabilities> LibWebRTCProvider::senderCapabilities(const String& kind)
377 {
378     auto mediaType = typeFromKind(kind);
379     if (!mediaType)
380         return { };
381
382     auto* factory = this->factory();
383     if (!factory)
384         return { };
385
386     return toRTCRtpCapabilities(factory->GetRtpSenderCapabilities(*mediaType));
387 }
388
389 #endif // USE(LIBWEBRTC)
390
391 } // namespace WebCore