1/*
2 * Copyright (C) 2017 Apple Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted, provided that the following conditions
6 * are required to be met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Inc. nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. AND ITS CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30#include "LibWebRTCUtils.h"
31
32#if USE(LIBWEBRTC)
33
34#include <webrtc/api/peerconnectionfactory.h>
35#include <webrtc/base/physicalsocketserver.h>
36#include <webrtc/p2p/client/basicportallocator.h>
37#include <webrtc/sdk/objc/Framework/Classes/videotoolboxvideocodecfactory.h>
38#include <wtf/Function.h>
39#include <wtf/NeverDestroyed.h>
40
41namespace WebCore {
42
43struct PeerConnectionFactoryAndThreads : public rtc::MessageHandler {
44 std::unique_ptr<rtc::Thread> networkThread;
45 std::unique_ptr<rtc::Thread> signalingThread;
46 rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory;
47 bool networkThreadWithSocketServer { false };
48private:
49 void OnMessage(rtc::Message*);
50};
51
52static inline PeerConnectionFactoryAndThreads& staticFactoryAndThreads()
53{
54 static NeverDestroyed<PeerConnectionFactoryAndThreads> factoryAndThreads;
55 return factoryAndThreads.get();
56}
57
58struct ThreadMessageData : public rtc::MessageData {
59 ThreadMessageData(Function<void()>&& function) : function(WTFMove(function)) { }
60 Function<void()> function;
61};
62
63void PeerConnectionFactoryAndThreads::OnMessage(rtc::Message* message)
64{
65 ASSERT(message->message_id == 1);
66 static_cast<ThreadMessageData*>(message->pdata)->function();
67}
68
69void callOnWebRTCNetworkThread(Function<void()>&& callback)
70{
71 PeerConnectionFactoryAndThreads& threads = staticFactoryAndThreads();
72 threads.networkThread->Post(RTC_FROM_HERE, &threads, 1, new ThreadMessageData(WTFMove(callback)));
73}
74
75static void initializePeerConnectionFactoryAndThreads()
76{
77 auto& factoryAndThreads = staticFactoryAndThreads();
78
79 ASSERT(!factoryAndThreads.factory);
80
81 auto thread = rtc::Thread::Create();
82 factoryAndThreads.networkThread = factoryAndThreads.networkThreadWithSocketServer ? rtc::Thread::CreateWithSocketServer() : rtc::Thread::Create();
83 bool result = factoryAndThreads.networkThread->Start();
84 ASSERT_UNUSED(result, result);
85
86 factoryAndThreads.signalingThread = rtc::Thread::Create();
87 result = factoryAndThreads.signalingThread->Start();
88 ASSERT(result);
89
90 factoryAndThreads.factory = webrtc::CreatePeerConnectionFactory(factoryAndThreads.networkThread.get(), factoryAndThreads.networkThread.get(), factoryAndThreads.signalingThread.get(), nullptr, new webrtc::VideoToolboxVideoEncoderFactory() , new webrtc::VideoToolboxVideoDecoderFactory());
91
92 ASSERT(factoryAndThreads.factory);
93}
94
95void initializeLibWebRTCInternalsWithSocketServer()
96{
97 staticFactoryAndThreads().networkThreadWithSocketServer = true;
98}
99
100webrtc::PeerConnectionFactoryInterface& peerConnectionFactory()
101{
102 if (!staticFactoryAndThreads().factory)
103 initializePeerConnectionFactoryAndThreads();
104 return *staticFactoryAndThreads().factory;
105}
106
107static rtc::scoped_refptr<webrtc::PeerConnectionInterface> createPeerConnection(webrtc::PeerConnectionObserver& observer, std::unique_ptr<cricket::BasicPortAllocator>&& portAllocator)
108{
109 ASSERT(staticFactoryAndThreads().factory);
110
111 webrtc::PeerConnectionInterface::RTCConfiguration config;
112 // FIXME: Add a default configuration.
113 return staticFactoryAndThreads().factory->CreatePeerConnection(config, WTFMove(portAllocator), nullptr, &observer);
114}
115
116rtc::scoped_refptr<webrtc::PeerConnectionInterface> createPeerConnection(webrtc::PeerConnectionObserver& observer)
117{
118 ASSERT(staticFactoryAndThreads().networkThreadWithSocketServer);
119
120 auto& factoryAndThreads = staticFactoryAndThreads();
121 if (!factoryAndThreads.factory)
122 initializePeerConnectionFactoryAndThreads();
123
124 return createPeerConnection(observer, nullptr);
125}
126
127rtc::scoped_refptr<webrtc::PeerConnectionInterface> createPeerConnection(webrtc::PeerConnectionObserver& observer, rtc::NetworkManager& networkManager, rtc::PacketSocketFactory& packetSocketFactory)
128{
129 ASSERT(!staticFactoryAndThreads().networkThreadWithSocketServer);
130
131 auto& factoryAndThreads = staticFactoryAndThreads();
132 if (!factoryAndThreads.factory)
133 initializePeerConnectionFactoryAndThreads();
134
135 std::unique_ptr<cricket::BasicPortAllocator> portAllocator;
136 staticFactoryAndThreads().signalingThread->Invoke<void>(RTC_FROM_HERE, [&]() {
137 portAllocator.reset(new cricket::BasicPortAllocator(&networkManager, &packetSocketFactory));
138 });
139
140 return createPeerConnection(observer, WTFMove(portAllocator));
141}
142
143} // namespace WebCore
144
145#endif // USE(LIBWEBRTC)