1 /*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "rtc_tools/data_channel_benchmark/peer_connection_client.h"
11
12 #include <memory>
13 #include <string>
14 #include <utility>
15
16 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
17 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
18 #include "api/create_peerconnection_factory.h"
19 #include "api/jsep.h"
20 #include "api/peer_connection_interface.h"
21 #include "api/rtc_error.h"
22 #include "api/scoped_refptr.h"
23 #include "api/set_remote_description_observer_interface.h"
24 #include "api/video_codecs/builtin_video_decoder_factory.h"
25 #include "api/video_codecs/builtin_video_encoder_factory.h"
26 #include "rtc_base/logging.h"
27 #include "rtc_base/thread.h"
28
29 namespace {
30
31 constexpr char kStunServer[] = "stun:stun.l.google.com:19302";
32
33 class SetLocalDescriptionObserverAdapter
34 : public webrtc::SetLocalDescriptionObserverInterface {
35 public:
36 using Callback = std::function<void(webrtc::RTCError)>;
Create(Callback callback)37 static rtc::scoped_refptr<SetLocalDescriptionObserverAdapter> Create(
38 Callback callback) {
39 return rtc::scoped_refptr<SetLocalDescriptionObserverAdapter>(
40 new rtc::RefCountedObject<SetLocalDescriptionObserverAdapter>(
41 std::move(callback)));
42 }
43
SetLocalDescriptionObserverAdapter(Callback callback)44 explicit SetLocalDescriptionObserverAdapter(Callback callback)
45 : callback_(std::move(callback)) {}
46 ~SetLocalDescriptionObserverAdapter() override = default;
47
48 private:
OnSetLocalDescriptionComplete(webrtc::RTCError error)49 void OnSetLocalDescriptionComplete(webrtc::RTCError error) override {
50 callback_(std::move(error));
51 }
52
53 Callback callback_;
54 };
55
56 class SetRemoteDescriptionObserverAdapter
57 : public webrtc::SetRemoteDescriptionObserverInterface {
58 public:
59 using Callback = std::function<void(webrtc::RTCError)>;
Create(Callback callback)60 static rtc::scoped_refptr<SetRemoteDescriptionObserverAdapter> Create(
61 Callback callback) {
62 return rtc::scoped_refptr<SetRemoteDescriptionObserverAdapter>(
63 new rtc::RefCountedObject<SetRemoteDescriptionObserverAdapter>(
64 std::move(callback)));
65 }
66
SetRemoteDescriptionObserverAdapter(Callback callback)67 explicit SetRemoteDescriptionObserverAdapter(Callback callback)
68 : callback_(std::move(callback)) {}
69 ~SetRemoteDescriptionObserverAdapter() override = default;
70
71 private:
OnSetRemoteDescriptionComplete(webrtc::RTCError error)72 void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override {
73 callback_(std::move(error));
74 }
75
76 Callback callback_;
77 };
78
79 class CreateSessionDescriptionObserverAdapter
80 : public webrtc::CreateSessionDescriptionObserver {
81 public:
82 using Success = std::function<void(webrtc::SessionDescriptionInterface*)>;
83 using Failure = std::function<void(webrtc::RTCError)>;
84
Create(Success success,Failure failure)85 static rtc::scoped_refptr<CreateSessionDescriptionObserverAdapter> Create(
86 Success success,
87 Failure failure) {
88 return rtc::scoped_refptr<CreateSessionDescriptionObserverAdapter>(
89 new rtc::RefCountedObject<CreateSessionDescriptionObserverAdapter>(
90 std::move(success), std::move(failure)));
91 }
92
CreateSessionDescriptionObserverAdapter(Success success,Failure failure)93 CreateSessionDescriptionObserverAdapter(Success success, Failure failure)
94 : success_(std::move(success)), failure_(std::move(failure)) {}
95 ~CreateSessionDescriptionObserverAdapter() override = default;
96
97 private:
OnSuccess(webrtc::SessionDescriptionInterface * desc)98 void OnSuccess(webrtc::SessionDescriptionInterface* desc) override {
99 success_(desc);
100 }
101
OnFailure(webrtc::RTCError error)102 void OnFailure(webrtc::RTCError error) override {
103 failure_(std::move(error));
104 }
105
106 Success success_;
107 Failure failure_;
108 };
109
110 } // namespace
111
112 namespace webrtc {
113
PeerConnectionClient(webrtc::PeerConnectionFactoryInterface * factory,webrtc::SignalingInterface * signaling)114 PeerConnectionClient::PeerConnectionClient(
115 webrtc::PeerConnectionFactoryInterface* factory,
116 webrtc::SignalingInterface* signaling)
117 : signaling_(signaling) {
118 signaling_->OnIceCandidate(
119 [&](std::unique_ptr<webrtc::IceCandidateInterface> candidate) {
120 AddIceCandidate(std::move(candidate));
121 });
122 signaling_->OnRemoteDescription(
123 [&](std::unique_ptr<webrtc::SessionDescriptionInterface> sdp) {
124 SetRemoteDescription(std::move(sdp));
125 });
126 InitializePeerConnection(factory);
127 }
128
~PeerConnectionClient()129 PeerConnectionClient::~PeerConnectionClient() {
130 Disconnect();
131 }
132
133 rtc::scoped_refptr<PeerConnectionFactoryInterface>
CreateDefaultFactory(rtc::Thread * signaling_thread)134 PeerConnectionClient::CreateDefaultFactory(rtc::Thread* signaling_thread) {
135 auto factory = webrtc::CreatePeerConnectionFactory(
136 /*network_thread=*/nullptr, /*worker_thread=*/nullptr,
137 /*signaling_thread*/ signaling_thread,
138 /*default_adm=*/nullptr, webrtc::CreateBuiltinAudioEncoderFactory(),
139 webrtc::CreateBuiltinAudioDecoderFactory(),
140 webrtc::CreateBuiltinVideoEncoderFactory(),
141 webrtc::CreateBuiltinVideoDecoderFactory(),
142 /*audio_mixer=*/nullptr, /*audio_processing=*/nullptr);
143
144 if (!factory) {
145 RTC_LOG(LS_ERROR) << "Failed to initialize PeerConnectionFactory";
146 return nullptr;
147 }
148
149 return factory;
150 }
151
InitializePeerConnection(webrtc::PeerConnectionFactoryInterface * factory)152 bool PeerConnectionClient::InitializePeerConnection(
153 webrtc::PeerConnectionFactoryInterface* factory) {
154 RTC_CHECK(factory)
155 << "Must call InitializeFactory before InitializePeerConnection";
156
157 webrtc::PeerConnectionInterface::RTCConfiguration config;
158 webrtc::PeerConnectionInterface::IceServer server;
159 server.urls.push_back(kStunServer);
160 config.servers.push_back(server);
161 config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan;
162
163 webrtc::PeerConnectionDependencies dependencies(this);
164 auto result =
165 factory->CreatePeerConnectionOrError(config, std::move(dependencies));
166
167 if (!result.ok()) {
168 RTC_LOG(LS_ERROR) << "Failed to create PeerConnection: "
169 << result.error().message();
170 DeletePeerConnection();
171 return false;
172 }
173 peer_connection_ = result.MoveValue();
174 RTC_LOG(LS_INFO) << "PeerConnection created successfully";
175 return true;
176 }
177
StartPeerConnection()178 bool PeerConnectionClient::StartPeerConnection() {
179 RTC_LOG(LS_INFO) << "Creating offer";
180
181 peer_connection_->SetLocalDescription(
182 SetLocalDescriptionObserverAdapter::Create([this](
183 webrtc::RTCError error) {
184 if (error.ok())
185 signaling_->SendDescription(peer_connection_->local_description());
186 }));
187
188 return true;
189 }
190
IsConnected()191 bool PeerConnectionClient::IsConnected() {
192 return peer_connection_->peer_connection_state() ==
193 webrtc::PeerConnectionInterface::PeerConnectionState::kConnected;
194 }
195
196 // Disconnect from the call.
Disconnect()197 void PeerConnectionClient::Disconnect() {
198 for (auto& data_channel : data_channels_) {
199 data_channel->Close();
200 data_channel.release();
201 }
202 data_channels_.clear();
203 DeletePeerConnection();
204 }
205
206 // Delete the WebRTC PeerConnection.
DeletePeerConnection()207 void PeerConnectionClient::DeletePeerConnection() {
208 RTC_LOG(LS_INFO);
209
210 if (peer_connection_) {
211 peer_connection_->Close();
212 }
213 peer_connection_.release();
214 }
215
OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state)216 void PeerConnectionClient::OnIceConnectionChange(
217 webrtc::PeerConnectionInterface::IceConnectionState new_state) {
218 if (new_state == webrtc::PeerConnectionInterface::IceConnectionState::
219 kIceConnectionCompleted) {
220 RTC_LOG(LS_INFO) << "State is updating to connected";
221 } else if (new_state == webrtc::PeerConnectionInterface::IceConnectionState::
222 kIceConnectionDisconnected) {
223 RTC_LOG(LS_INFO) << "Disconnecting from peer";
224 Disconnect();
225 }
226 }
227
OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state)228 void PeerConnectionClient::OnIceGatheringChange(
229 webrtc::PeerConnectionInterface::IceGatheringState new_state) {
230 if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) {
231 RTC_LOG(LS_INFO) << "Client is ready to receive remote SDP";
232 }
233 }
234
OnIceCandidate(const webrtc::IceCandidateInterface * candidate)235 void PeerConnectionClient::OnIceCandidate(
236 const webrtc::IceCandidateInterface* candidate) {
237 signaling_->SendIceCandidate(candidate);
238 }
239
OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> channel)240 void PeerConnectionClient::OnDataChannel(
241 rtc::scoped_refptr<webrtc::DataChannelInterface> channel) {
242 RTC_LOG(LS_INFO) << __FUNCTION__ << " remote datachannel created";
243 if (on_data_channel_callback_)
244 on_data_channel_callback_(channel);
245 data_channels_.push_back(channel);
246 }
247
SetOnDataChannel(std::function<void (rtc::scoped_refptr<webrtc::DataChannelInterface>)> callback)248 void PeerConnectionClient::SetOnDataChannel(
249 std::function<void(rtc::scoped_refptr<webrtc::DataChannelInterface>)>
250 callback) {
251 on_data_channel_callback_ = callback;
252 }
253
OnNegotiationNeededEvent(uint32_t event_id)254 void PeerConnectionClient::OnNegotiationNeededEvent(uint32_t event_id) {
255 RTC_LOG(LS_INFO) << "OnNegotiationNeededEvent";
256
257 peer_connection_->SetLocalDescription(
258 SetLocalDescriptionObserverAdapter::Create([this](
259 webrtc::RTCError error) {
260 if (error.ok())
261 signaling_->SendDescription(peer_connection_->local_description());
262 }));
263 }
264
SetRemoteDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> desc)265 bool PeerConnectionClient::SetRemoteDescription(
266 std::unique_ptr<webrtc::SessionDescriptionInterface> desc) {
267 RTC_LOG(LS_INFO) << "SetRemoteDescription";
268 auto type = desc->GetType();
269
270 peer_connection_->SetRemoteDescription(
271 std::move(desc),
272 SetRemoteDescriptionObserverAdapter::Create([&](webrtc::RTCError) {
273 RTC_LOG(LS_INFO) << "SetRemoteDescription done";
274
275 if (type == webrtc::SdpType::kOffer) {
276 // Got an offer from the remote, need to set an answer and send it.
277 peer_connection_->SetLocalDescription(
278 SetLocalDescriptionObserverAdapter::Create(
279 [this](webrtc::RTCError error) {
280 if (error.ok())
281 signaling_->SendDescription(
282 peer_connection_->local_description());
283 }));
284 }
285 }));
286
287 return true;
288 }
289
AddIceCandidate(std::unique_ptr<webrtc::IceCandidateInterface> candidate)290 void PeerConnectionClient::AddIceCandidate(
291 std::unique_ptr<webrtc::IceCandidateInterface> candidate) {
292 RTC_LOG(LS_INFO) << "AddIceCandidate";
293
294 peer_connection_->AddIceCandidate(
295 std::move(candidate), [](const webrtc::RTCError& error) {
296 RTC_LOG(LS_INFO) << "Failed to add candidate: " << error.message();
297 });
298 }
299
300 } // namespace webrtc
301