• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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