• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "ClientHandler"
18 
19 #include "host/frontend/webrtc/lib/client_handler.h"
20 
21 #include <vector>
22 
23 #include <json/json.h>
24 #include <json/writer.h>
25 #include <netdb.h>
26 #include <openssl/rand.h>
27 
28 #include <android-base/logging.h>
29 
30 #include "host/frontend/webrtc/lib/keyboard.h"
31 #include "host/frontend/webrtc/lib/utils.h"
32 #include "host/libs/config/cuttlefish_config.h"
33 
34 namespace cuttlefish {
35 namespace webrtc_streaming {
36 
37 namespace {
38 
39 static constexpr auto kInputChannelLabel = "input-channel";
40 static constexpr auto kAdbChannelLabel = "adb-channel";
41 static constexpr auto kBluetoothChannelLabel = "bluetooth-channel";
42 static constexpr auto kCameraDataChannelLabel = "camera-data-channel";
43 static constexpr auto kCameraDataEof = "EOF";
44 
45 class CvdCreateSessionDescriptionObserver
46     : public webrtc::CreateSessionDescriptionObserver {
47  public:
CvdCreateSessionDescriptionObserver(std::weak_ptr<ClientHandler> client_handler)48   CvdCreateSessionDescriptionObserver(
49       std::weak_ptr<ClientHandler> client_handler)
50       : client_handler_(client_handler) {}
51 
OnSuccess(webrtc::SessionDescriptionInterface * desc)52   void OnSuccess(webrtc::SessionDescriptionInterface *desc) override {
53     auto client_handler = client_handler_.lock();
54     if (client_handler) {
55       client_handler->OnCreateSDPSuccess(desc);
56     }
57   }
OnFailure(webrtc::RTCError error)58   void OnFailure(webrtc::RTCError error) override {
59     auto client_handler = client_handler_.lock();
60     if (client_handler) {
61       client_handler->OnCreateSDPFailure(error);
62     }
63   }
64 
65  private:
66   std::weak_ptr<ClientHandler> client_handler_;
67 };
68 
69 class CvdSetSessionDescriptionObserver
70     : public webrtc::SetSessionDescriptionObserver {
71  public:
CvdSetSessionDescriptionObserver(std::weak_ptr<ClientHandler> client_handler)72   CvdSetSessionDescriptionObserver(std::weak_ptr<ClientHandler> client_handler)
73       : client_handler_(client_handler) {}
74 
OnSuccess()75   void OnSuccess() override {
76     // local description set, nothing else to do
77   }
OnFailure(webrtc::RTCError error)78   void OnFailure(webrtc::RTCError error) override {
79     auto client_handler = client_handler_.lock();
80     if (client_handler) {
81       client_handler->OnSetSDPFailure(error);
82     }
83   }
84 
85  private:
86   std::weak_ptr<ClientHandler> client_handler_;
87 };
88 
89 class CvdOnSetRemoteDescription
90     : public webrtc::SetRemoteDescriptionObserverInterface {
91  public:
CvdOnSetRemoteDescription(std::function<void (webrtc::RTCError error)> on_error)92   CvdOnSetRemoteDescription(
93       std::function<void(webrtc::RTCError error)> on_error)
94       : on_error_(on_error) {}
95 
OnSetRemoteDescriptionComplete(webrtc::RTCError error)96   void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override {
97     on_error_(error);
98   }
99 
100  private:
101   std::function<void(webrtc::RTCError error)> on_error_;
102 };
103 
104 }  // namespace
105 
106 // Video streams initiating in the client may be added and removed at unexpected
107 // times, causing the webrtc objects to be destroyed and created every time.
108 // This class hides away that complexity and allows to set up sinks only once.
109 class ClientVideoTrackImpl : public ClientVideoTrackInterface {
110  public:
AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame> * sink,const rtc::VideoSinkWants & wants)111   void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame> *sink,
112                        const rtc::VideoSinkWants &wants) override {
113     sink_ = sink;
114     wants_ = wants;
115     if (video_track_) {
116       video_track_->AddOrUpdateSink(sink, wants);
117     }
118   }
119 
SetVideoTrack(webrtc::VideoTrackInterface * track)120   void SetVideoTrack(webrtc::VideoTrackInterface *track) {
121     video_track_ = track;
122     if (sink_) {
123       video_track_->AddOrUpdateSink(sink_, wants_);
124     }
125   }
126 
UnsetVideoTrack(webrtc::VideoTrackInterface * track)127   void UnsetVideoTrack(webrtc::VideoTrackInterface *track) {
128     if (track == video_track_) {
129       video_track_ = nullptr;
130     }
131   }
132 
133  private:
134   webrtc::VideoTrackInterface* video_track_;
135   rtc::VideoSinkInterface<webrtc::VideoFrame> *sink_ = nullptr;
136   rtc::VideoSinkWants wants_ = {};
137 };
138 
139 class InputChannelHandler : public webrtc::DataChannelObserver {
140  public:
141   InputChannelHandler(
142       rtc::scoped_refptr<webrtc::DataChannelInterface> input_channel,
143       std::shared_ptr<ConnectionObserver> observer);
144   ~InputChannelHandler() override;
145 
146   void OnStateChange() override;
147   void OnMessage(const webrtc::DataBuffer &msg) override;
148 
149  private:
150   rtc::scoped_refptr<webrtc::DataChannelInterface> input_channel_;
151   std::shared_ptr<ConnectionObserver> observer_;
152 };
153 
154 class AdbChannelHandler : public webrtc::DataChannelObserver {
155  public:
156   AdbChannelHandler(
157       rtc::scoped_refptr<webrtc::DataChannelInterface> adb_channel,
158       std::shared_ptr<ConnectionObserver> observer);
159   ~AdbChannelHandler() override;
160 
161   void OnStateChange() override;
162   void OnMessage(const webrtc::DataBuffer &msg) override;
163 
164  private:
165   rtc::scoped_refptr<webrtc::DataChannelInterface> adb_channel_;
166   std::shared_ptr<ConnectionObserver> observer_;
167   bool channel_open_reported_ = false;
168 };
169 
170 class ControlChannelHandler : public webrtc::DataChannelObserver {
171  public:
172   ControlChannelHandler(
173       rtc::scoped_refptr<webrtc::DataChannelInterface> control_channel,
174       std::shared_ptr<ConnectionObserver> observer);
175   ~ControlChannelHandler() override;
176 
177   void OnStateChange() override;
178   void OnMessage(const webrtc::DataBuffer &msg) override;
179 
180   void Send(const Json::Value &message);
181   void Send(const uint8_t *msg, size_t size, bool binary);
182 
183  private:
184   rtc::scoped_refptr<webrtc::DataChannelInterface> control_channel_;
185   std::shared_ptr<ConnectionObserver> observer_;
186 };
187 
188 class BluetoothChannelHandler : public webrtc::DataChannelObserver {
189  public:
190   BluetoothChannelHandler(
191       rtc::scoped_refptr<webrtc::DataChannelInterface> bluetooth_channel,
192       std::shared_ptr<ConnectionObserver> observer);
193   ~BluetoothChannelHandler() override;
194 
195   void OnStateChange() override;
196   void OnMessage(const webrtc::DataBuffer &msg) override;
197 
198  private:
199   rtc::scoped_refptr<webrtc::DataChannelInterface> bluetooth_channel_;
200   std::shared_ptr<ConnectionObserver> observer_;
201   bool channel_open_reported_ = false;
202 };
203 
204 class CameraChannelHandler : public webrtc::DataChannelObserver {
205  public:
206   CameraChannelHandler(
207       rtc::scoped_refptr<webrtc::DataChannelInterface> bluetooth_channel,
208       std::shared_ptr<ConnectionObserver> observer);
209   ~CameraChannelHandler() override;
210 
211   void OnStateChange() override;
212   void OnMessage(const webrtc::DataBuffer &msg) override;
213 
214  private:
215   rtc::scoped_refptr<webrtc::DataChannelInterface> camera_channel_;
216   std::shared_ptr<ConnectionObserver> observer_;
217   std::vector<char> receive_buffer_;
218 };
219 
InputChannelHandler(rtc::scoped_refptr<webrtc::DataChannelInterface> input_channel,std::shared_ptr<ConnectionObserver> observer)220 InputChannelHandler::InputChannelHandler(
221     rtc::scoped_refptr<webrtc::DataChannelInterface> input_channel,
222     std::shared_ptr<ConnectionObserver> observer)
223     : input_channel_(input_channel), observer_(observer) {
224   input_channel->RegisterObserver(this);
225 }
226 
~InputChannelHandler()227 InputChannelHandler::~InputChannelHandler() {
228   input_channel_->UnregisterObserver();
229 }
230 
OnStateChange()231 void InputChannelHandler::OnStateChange() {
232   LOG(VERBOSE) << "Input channel state changed to "
233                << webrtc::DataChannelInterface::DataStateString(
234                       input_channel_->state());
235 }
236 
OnMessage(const webrtc::DataBuffer & msg)237 void InputChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
238   if (msg.binary) {
239     // TODO (jemoreira) consider binary protocol to avoid JSON parsing overhead
240     LOG(ERROR) << "Received invalid (binary) data on input channel";
241     return;
242   }
243   auto size = msg.size();
244 
245   Json::Value evt;
246   Json::CharReaderBuilder builder;
247   std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
248   std::string errorMessage;
249   auto str = msg.data.cdata<char>();
250   if (!json_reader->parse(str, str + size, &evt, &errorMessage) < 0) {
251     LOG(ERROR) << "Received invalid JSON object over input channel: "
252                << errorMessage;
253     return;
254   }
255   if (!evt.isMember("type") || !evt["type"].isString()) {
256     LOG(ERROR) << "Input event doesn't have a valid 'type' field: "
257                << evt.toStyledString();
258     return;
259   }
260   auto event_type = evt["type"].asString();
261   if (event_type == "mouse") {
262     auto result =
263         ValidationResult::ValidateJsonObject(evt, "mouse",
264                            {{"down", Json::ValueType::intValue},
265                             {"x", Json::ValueType::intValue},
266                             {"y", Json::ValueType::intValue},
267                             {"display_label", Json::ValueType::stringValue}});
268     if (!result.ok()) {
269       LOG(ERROR) << result.error();
270       return;
271     }
272     auto label = evt["display_label"].asString();
273     int32_t down = evt["down"].asInt();
274     int32_t x = evt["x"].asInt();
275     int32_t y = evt["y"].asInt();
276 
277     observer_->OnTouchEvent(label, x, y, down);
278   } else if (event_type == "multi-touch") {
279     auto result =
280         ValidationResult::ValidateJsonObject(evt, "multi-touch",
281                            {{"id", Json::ValueType::arrayValue},
282                             {"down", Json::ValueType::intValue},
283                             {"x", Json::ValueType::arrayValue},
284                             {"y", Json::ValueType::arrayValue},
285                             {"slot", Json::ValueType::arrayValue},
286                             {"display_label", Json::ValueType::stringValue}});
287     if (!result.ok()) {
288       LOG(ERROR) << result.error();
289       return;
290     }
291 
292     auto label = evt["display_label"].asString();
293     auto idArr = evt["id"];
294     int32_t down = evt["down"].asInt();
295     auto xArr = evt["x"];
296     auto yArr = evt["y"];
297     auto slotArr = evt["slot"];
298     int size = evt["id"].size();
299 
300     observer_->OnMultiTouchEvent(label, idArr, slotArr, xArr, yArr, down, size);
301   } else if (event_type == "keyboard") {
302     auto result =
303         ValidationResult::ValidateJsonObject(evt, "keyboard",
304                            {{"event_type", Json::ValueType::stringValue},
305                             {"keycode", Json::ValueType::stringValue}});
306     if (!result.ok()) {
307       LOG(ERROR) << result.error();
308       return;
309     }
310     auto down = evt["event_type"].asString() == std::string("keydown");
311     auto code = DomKeyCodeToLinux(evt["keycode"].asString());
312     observer_->OnKeyboardEvent(code, down);
313   } else {
314     LOG(ERROR) << "Unrecognized event type: " << event_type;
315     return;
316   }
317 }
318 
AdbChannelHandler(rtc::scoped_refptr<webrtc::DataChannelInterface> adb_channel,std::shared_ptr<ConnectionObserver> observer)319 AdbChannelHandler::AdbChannelHandler(
320     rtc::scoped_refptr<webrtc::DataChannelInterface> adb_channel,
321     std::shared_ptr<ConnectionObserver> observer)
322     : adb_channel_(adb_channel), observer_(observer) {
323   adb_channel->RegisterObserver(this);
324 }
325 
~AdbChannelHandler()326 AdbChannelHandler::~AdbChannelHandler() { adb_channel_->UnregisterObserver(); }
327 
OnStateChange()328 void AdbChannelHandler::OnStateChange() {
329   LOG(VERBOSE) << "Adb channel state changed to "
330                << webrtc::DataChannelInterface::DataStateString(
331                       adb_channel_->state());
332 }
333 
OnMessage(const webrtc::DataBuffer & msg)334 void AdbChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
335   // Report the adb channel as open on the first message received instead of at
336   // channel open, this avoids unnecessarily connecting to the adb daemon for
337   // clients that don't use ADB.
338   if (!channel_open_reported_) {
339     observer_->OnAdbChannelOpen([this](const uint8_t *msg, size_t size) {
340       webrtc::DataBuffer buffer(rtc::CopyOnWriteBuffer(msg, size),
341                                 true /*binary*/);
342       // TODO (b/185832105): When the SCTP channel is congested data channel
343       // messages are buffered up to 16MB, when the buffer is full the channel
344       // is abruptly closed. Keep track of the buffered data to avoid losing the
345       // adb data channel.
346       adb_channel_->Send(buffer);
347       return true;
348     });
349     channel_open_reported_ = true;
350   }
351   observer_->OnAdbMessage(msg.data.cdata(), msg.size());
352 }
353 
ControlChannelHandler(rtc::scoped_refptr<webrtc::DataChannelInterface> control_channel,std::shared_ptr<ConnectionObserver> observer)354 ControlChannelHandler::ControlChannelHandler(
355     rtc::scoped_refptr<webrtc::DataChannelInterface> control_channel,
356     std::shared_ptr<ConnectionObserver> observer)
357     : control_channel_(control_channel), observer_(observer) {
358   control_channel->RegisterObserver(this);
359   observer_->OnControlChannelOpen([this](const Json::Value& message) {
360     this->Send(message);
361     return true;
362   });
363 }
364 
~ControlChannelHandler()365 ControlChannelHandler::~ControlChannelHandler() {
366   control_channel_->UnregisterObserver();
367 }
368 
OnStateChange()369 void ControlChannelHandler::OnStateChange() {
370   LOG(VERBOSE) << "Control channel state changed to "
371                << webrtc::DataChannelInterface::DataStateString(
372                       control_channel_->state());
373 }
374 
OnMessage(const webrtc::DataBuffer & msg)375 void ControlChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
376   observer_->OnControlMessage(msg.data.cdata(), msg.size());
377 }
378 
Send(const Json::Value & message)379 void ControlChannelHandler::Send(const Json::Value& message) {
380   Json::StreamWriterBuilder factory;
381   std::string message_string = Json::writeString(factory, message);
382   Send(reinterpret_cast<const uint8_t*>(message_string.c_str()),
383        message_string.size(), /*binary=*/false);
384 }
385 
Send(const uint8_t * msg,size_t size,bool binary)386 void ControlChannelHandler::Send(const uint8_t *msg, size_t size, bool binary) {
387   webrtc::DataBuffer buffer(rtc::CopyOnWriteBuffer(msg, size), binary);
388   control_channel_->Send(buffer);
389 }
390 
BluetoothChannelHandler(rtc::scoped_refptr<webrtc::DataChannelInterface> bluetooth_channel,std::shared_ptr<ConnectionObserver> observer)391 BluetoothChannelHandler::BluetoothChannelHandler(
392     rtc::scoped_refptr<webrtc::DataChannelInterface> bluetooth_channel,
393     std::shared_ptr<ConnectionObserver> observer)
394     : bluetooth_channel_(bluetooth_channel), observer_(observer) {
395   bluetooth_channel_->RegisterObserver(this);
396 }
397 
~BluetoothChannelHandler()398 BluetoothChannelHandler::~BluetoothChannelHandler() {
399   bluetooth_channel_->UnregisterObserver();
400 }
401 
OnStateChange()402 void BluetoothChannelHandler::OnStateChange() {
403   LOG(VERBOSE) << "Bluetooth channel state changed to "
404                << webrtc::DataChannelInterface::DataStateString(
405                       bluetooth_channel_->state());
406 }
407 
OnMessage(const webrtc::DataBuffer & msg)408 void BluetoothChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
409   // Notify bluetooth channel opening when actually using the channel,
410   // it has the same reason with AdbChannelHandler::OnMessage,
411   // to avoid unnecessarily connection for Rootcanal.
412   if (channel_open_reported_ == false) {
413     channel_open_reported_ = true;
414     observer_->OnBluetoothChannelOpen([this](const uint8_t *msg, size_t size) {
415       webrtc::DataBuffer buffer(rtc::CopyOnWriteBuffer(msg, size),
416                                 true /*binary*/);
417       // TODO (b/185832105): When the SCTP channel is congested data channel
418       // messages are buffered up to 16MB, when the buffer is full the channel
419       // is abruptly closed. Keep track of the buffered data to avoid losing the
420       // adb data channel.
421       bluetooth_channel_->Send(buffer);
422       return true;
423     });
424   }
425 
426   observer_->OnBluetoothMessage(msg.data.cdata(), msg.size());
427 }
428 
CameraChannelHandler(rtc::scoped_refptr<webrtc::DataChannelInterface> camera_channel,std::shared_ptr<ConnectionObserver> observer)429 CameraChannelHandler::CameraChannelHandler(
430     rtc::scoped_refptr<webrtc::DataChannelInterface> camera_channel,
431     std::shared_ptr<ConnectionObserver> observer)
432     : camera_channel_(camera_channel), observer_(observer) {
433   camera_channel_->RegisterObserver(this);
434 }
435 
~CameraChannelHandler()436 CameraChannelHandler::~CameraChannelHandler() {
437   camera_channel_->UnregisterObserver();
438 }
439 
OnStateChange()440 void CameraChannelHandler::OnStateChange() {
441   LOG(VERBOSE) << "Camera channel state changed to "
442                << webrtc::DataChannelInterface::DataStateString(
443                       camera_channel_->state());
444 }
445 
OnMessage(const webrtc::DataBuffer & msg)446 void CameraChannelHandler::OnMessage(const webrtc::DataBuffer &msg) {
447   auto msg_data = msg.data.cdata<char>();
448   if (msg.size() == strlen(kCameraDataEof) &&
449       !strncmp(msg_data, kCameraDataEof, msg.size())) {
450     // Send complete buffer to observer on EOF marker
451     observer_->OnCameraData(receive_buffer_);
452     receive_buffer_.clear();
453     return;
454   }
455   // Otherwise buffer up data
456   receive_buffer_.insert(receive_buffer_.end(), msg_data,
457                          msg_data + msg.size());
458 }
459 
Create(int client_id,std::shared_ptr<ConnectionObserver> observer,std::function<void (const Json::Value &)> send_to_client_cb,std::function<void (bool)> on_connection_changed_cb)460 std::shared_ptr<ClientHandler> ClientHandler::Create(
461     int client_id, std::shared_ptr<ConnectionObserver> observer,
462     std::function<void(const Json::Value &)> send_to_client_cb,
463     std::function<void(bool)> on_connection_changed_cb) {
464   return std::shared_ptr<ClientHandler>(new ClientHandler(
465       client_id, observer, send_to_client_cb, on_connection_changed_cb));
466 }
467 
ClientHandler(int client_id,std::shared_ptr<ConnectionObserver> observer,std::function<void (const Json::Value &)> send_to_client_cb,std::function<void (bool)> on_connection_changed_cb)468 ClientHandler::ClientHandler(
469     int client_id, std::shared_ptr<ConnectionObserver> observer,
470     std::function<void(const Json::Value &)> send_to_client_cb,
471     std::function<void(bool)> on_connection_changed_cb)
472     : client_id_(client_id),
473       observer_(observer),
474       send_to_client_(send_to_client_cb),
475       on_connection_changed_cb_(on_connection_changed_cb),
476       camera_track_(new ClientVideoTrackImpl()) {}
477 
~ClientHandler()478 ClientHandler::~ClientHandler() {
479   for (auto &data_channel : data_channels_) {
480     data_channel->UnregisterObserver();
481   }
482 }
483 
SetPeerConnection(rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection)484 bool ClientHandler::SetPeerConnection(
485     rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection) {
486   peer_connection_ = peer_connection;
487 
488   // libwebrtc configures the video encoder with a start bitrate of just 300kbs
489   // which causes it to drop the first 4 frames it receives. Any value over 2Mbs
490   // will be capped at 2Mbs when passed to the encoder by the peer_connection
491   // object, so we pass the maximum possible value here.
492   webrtc::BitrateSettings bitrate_settings;
493   bitrate_settings.start_bitrate_bps = 2000000; // 2Mbs
494   peer_connection_->SetBitrate(bitrate_settings);
495   // At least one data channel needs to be created on the side that makes the
496   // SDP offer (the device) for data channels to be enabled at all.
497   // This channel is meant to carry control commands from the client.
498   auto control_channel = peer_connection_->CreateDataChannel(
499       "device-control", nullptr /* config */);
500   if (!control_channel) {
501     LOG(ERROR) << "Failed to create control data channel";
502     return false;
503   }
504   control_handler_.reset(new ControlChannelHandler(control_channel, observer_));
505   return true;
506 }
507 
AddDisplay(rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track,const std::string & label)508 bool ClientHandler::AddDisplay(
509     rtc::scoped_refptr<webrtc::VideoTrackInterface> video_track,
510     const std::string &label) {
511   // Send each track as part of a different stream with the label as id
512   auto err_or_sender =
513       peer_connection_->AddTrack(video_track, {label} /* stream_id */);
514   if (!err_or_sender.ok()) {
515     LOG(ERROR) << "Failed to add video track to the peer connection";
516     return false;
517   }
518   // TODO (b/154138394): use the returned sender (err_or_sender.value()) to
519   // remove the display from the connection.
520   return true;
521 }
522 
AddAudio(rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track,const std::string & label)523 bool ClientHandler::AddAudio(
524     rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track,
525     const std::string &label) {
526   // Send each track as part of a different stream with the label as id
527   auto err_or_sender =
528       peer_connection_->AddTrack(audio_track, {label} /* stream_id */);
529   if (!err_or_sender.ok()) {
530     LOG(ERROR) << "Failed to add video track to the peer connection";
531     return false;
532   }
533   return true;
534 }
535 
GetCameraStream()536 ClientVideoTrackInterface* ClientHandler::GetCameraStream() {
537   return camera_track_.get();
538 }
539 
LogAndReplyError(const std::string & error_msg) const540 void ClientHandler::LogAndReplyError(const std::string &error_msg) const {
541   LOG(ERROR) << error_msg;
542   Json::Value reply;
543   reply["type"] = "error";
544   reply["error"] = error_msg;
545   send_to_client_(reply);
546 }
547 
AddPendingIceCandidates()548 void ClientHandler::AddPendingIceCandidates() {
549   // Add any ice candidates that arrived before the remote description
550   for (auto& candidate: pending_ice_candidates_) {
551     peer_connection_->AddIceCandidate(std::move(candidate),
552                                       [this](webrtc::RTCError error) {
553                                         if (!error.ok()) {
554                                           LogAndReplyError(error.message());
555                                         }
556                                       });
557   }
558   pending_ice_candidates_.clear();
559 }
560 
OnCreateSDPSuccess(webrtc::SessionDescriptionInterface * desc)561 void ClientHandler::OnCreateSDPSuccess(
562     webrtc::SessionDescriptionInterface *desc) {
563   std::string offer_str;
564   desc->ToString(&offer_str);
565   std::string sdp_type = desc->type();
566   peer_connection_->SetLocalDescription(
567       // The peer connection wraps this raw pointer with a scoped_refptr, so
568       // it's guaranteed to be deleted at some point
569       new rtc::RefCountedObject<CvdSetSessionDescriptionObserver>(
570           weak_from_this()),
571       desc);
572   // The peer connection takes ownership of the description so it should not be
573   // used after this
574   desc = nullptr;
575 
576   Json::Value reply;
577   reply["type"] = sdp_type;
578   reply["sdp"] = offer_str;
579 
580   state_ = State::kAwaitingAnswer;
581   send_to_client_(reply);
582 }
583 
OnCreateSDPFailure(webrtc::RTCError error)584 void ClientHandler::OnCreateSDPFailure(webrtc::RTCError error) {
585   state_ = State::kFailed;
586   LogAndReplyError(error.message());
587   Close();
588 }
589 
OnSetSDPFailure(webrtc::RTCError error)590 void ClientHandler::OnSetSDPFailure(webrtc::RTCError error) {
591   state_ = State::kFailed;
592   LogAndReplyError(error.message());
593   LOG(ERROR) << "Error setting local description: Either there is a bug in "
594                 "libwebrtc or the local description was (incorrectly) modified "
595                 "after creating it";
596   Close();
597 }
598 
HandleMessage(const Json::Value & message)599 void ClientHandler::HandleMessage(const Json::Value &message) {
600   {
601     auto result = ValidationResult::ValidateJsonObject(message, "",
602                                      {{"type", Json::ValueType::stringValue}});
603     if (!result.ok()) {
604       LogAndReplyError(result.error());
605       return;
606     }
607   }
608   auto type = message["type"].asString();
609   if (type == "request-offer") {
610     // Can't check for state being different that kNew because renegotiation can
611     // start in any state after the answer is returned.
612     if (state_ == State::kCreatingOffer) {
613       // An offer has been requested already
614       LogAndReplyError("Multiple requests for offer received from single client");
615       return;
616     }
617     state_ = State::kCreatingOffer;
618     peer_connection_->CreateOffer(
619         // No memory leak here because this is a ref counted objects and the
620         // peer connection immediately wraps it with a scoped_refptr
621         new rtc::RefCountedObject<CvdCreateSessionDescriptionObserver>(
622             weak_from_this()),
623         webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
624     // The created offer wil be sent to the client on
625     // OnSuccess(webrtc::SessionDescriptionInterface* desc)
626   } else if (type == "offer") {
627     auto result = ValidationResult::ValidateJsonObject(
628         message, type, {{"sdp", Json::ValueType::stringValue}});
629     if (!result.ok()) {
630       LogAndReplyError(result.error());
631       return;
632     }
633     auto remote_desc_str = message["sdp"].asString();
634     auto remote_desc = webrtc::CreateSessionDescription(
635         webrtc::SdpType::kOffer, remote_desc_str, nullptr /*error*/);
636     if (!remote_desc) {
637       LogAndReplyError("Failed to parse answer.");
638       return;
639     }
640 
641     rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> observer(
642         new rtc::RefCountedObject<
643             CvdOnSetRemoteDescription>([this](webrtc::RTCError error) {
644           if (!error.ok()) {
645             LogAndReplyError(error.message());
646             // The remote description was rejected, this client can't be
647             // trusted anymore.
648             Close();
649             return;
650           }
651           remote_description_added_ = true;
652           AddPendingIceCandidates();
653           peer_connection_->CreateAnswer(
654               // No memory leak here because this is a ref counted objects and
655               // the peer connection immediately wraps it with a scoped_refptr
656               new rtc::RefCountedObject<CvdCreateSessionDescriptionObserver>(
657                   weak_from_this()),
658               webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
659         }));
660     peer_connection_->SetRemoteDescription(std::move(remote_desc), observer);
661     state_ = State::kConnecting;
662   } else if (type == "answer") {
663     if (state_ != State::kAwaitingAnswer) {
664       LogAndReplyError("Received unexpected SDP answer");
665       return;
666     }
667     auto result = ValidationResult::ValidateJsonObject(message, type,
668                                      {{"sdp", Json::ValueType::stringValue}});
669     if (!result.ok()) {
670       LogAndReplyError(result.error());
671       return;
672     }
673     auto remote_desc_str = message["sdp"].asString();
674     auto remote_desc = webrtc::CreateSessionDescription(
675         webrtc::SdpType::kAnswer, remote_desc_str, nullptr /*error*/);
676     if (!remote_desc) {
677       LogAndReplyError("Failed to parse answer.");
678       return;
679     }
680     rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> observer(
681         new rtc::RefCountedObject<CvdOnSetRemoteDescription>(
682             [this](webrtc::RTCError error) {
683               if (!error.ok()) {
684                 LogAndReplyError(error.message());
685                 // The remote description was rejected, this client can't be
686                 // trusted anymore.
687                 Close();
688               }
689             }));
690     peer_connection_->SetRemoteDescription(std::move(remote_desc), observer);
691     remote_description_added_ = true;
692     AddPendingIceCandidates();
693     state_ = State::kConnecting;
694 
695   } else if (type == "ice-candidate") {
696     {
697       auto result = ValidationResult::ValidateJsonObject(
698           message, type, {{"candidate", Json::ValueType::objectValue}});
699       if (!result.ok()) {
700         LogAndReplyError(result.error());
701         return;
702       }
703     }
704     auto candidate_json = message["candidate"];
705     {
706       auto result =
707           ValidationResult::ValidateJsonObject(candidate_json,
708                                                "ice-candidate/candidate",
709                              {
710                                  {"sdpMid", Json::ValueType::stringValue},
711                                  {"candidate", Json::ValueType::stringValue},
712                                  {"sdpMLineIndex", Json::ValueType::intValue},
713                              });
714       if (!result.ok()) {
715         LogAndReplyError(result.error());
716         return;
717       }
718     }
719     auto mid = candidate_json["sdpMid"].asString();
720     auto candidate_sdp = candidate_json["candidate"].asString();
721     auto line_index = candidate_json["sdpMLineIndex"].asInt();
722 
723     std::unique_ptr<webrtc::IceCandidateInterface> candidate(
724         webrtc::CreateIceCandidate(mid, line_index, candidate_sdp,
725                                    nullptr /*error*/));
726     if (!candidate) {
727       LogAndReplyError("Failed to parse ICE candidate");
728       return;
729     }
730     if (remote_description_added_) {
731       peer_connection_->AddIceCandidate(std::move(candidate),
732                                         [this](webrtc::RTCError error) {
733                                           if (!error.ok()) {
734                                             LogAndReplyError(error.message());
735                                           }
736                                         });
737     } else {
738       // Store the ice candidate to be added later if it arrives before the
739       // remote description. This could happen if the client uses polling
740       // instead of websockets because the candidates are generated immediately
741       // after the remote (offer) description is set and the events and the ajax
742       // calls are asynchronous.
743       pending_ice_candidates_.push_back(std::move(candidate));
744     }
745   } else {
746     LogAndReplyError("Unknown client message type: " + type);
747     return;
748   }
749 }
750 
Close()751 void ClientHandler::Close() {
752   // We can't simply call peer_connection_->Close() here because this method
753   // could be called from one of the PeerConnectionObserver callbacks and that
754   // would lead to a deadlock (Close eventually tries to destroy an object that
755   // will then wait for the callback to return -> deadlock). Destroying the
756   // peer_connection_ has the same effect. The only alternative is to postpone
757   // that operation until after the callback returns.
758   on_connection_changed_cb_(false);
759 }
760 
OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state)761 void ClientHandler::OnConnectionChange(
762     webrtc::PeerConnectionInterface::PeerConnectionState new_state) {
763   switch (new_state) {
764     case webrtc::PeerConnectionInterface::PeerConnectionState::kNew:
765       break;
766     case webrtc::PeerConnectionInterface::PeerConnectionState::kConnecting:
767       break;
768     case webrtc::PeerConnectionInterface::PeerConnectionState::kConnected:
769       LOG(VERBOSE) << "Client " << client_id_ << ": WebRTC connected";
770       state_ = State::kConnected;
771       observer_->OnConnected(
772           [this](const uint8_t *msg, size_t size, bool binary) {
773             control_handler_->Send(msg, size, binary);
774             return true;
775           });
776       on_connection_changed_cb_(true);
777       break;
778     case webrtc::PeerConnectionInterface::PeerConnectionState::kDisconnected:
779       LOG(VERBOSE) << "Client " << client_id_ << ": Connection disconnected";
780       Close();
781       break;
782     case webrtc::PeerConnectionInterface::PeerConnectionState::kFailed:
783       LOG(ERROR) << "Client " << client_id_ << ": Connection failed";
784       Close();
785       break;
786     case webrtc::PeerConnectionInterface::PeerConnectionState::kClosed:
787       LOG(VERBOSE) << "Client " << client_id_ << ": Connection closed";
788       Close();
789       break;
790   }
791 }
792 
OnIceCandidate(const webrtc::IceCandidateInterface * candidate)793 void ClientHandler::OnIceCandidate(
794     const webrtc::IceCandidateInterface *candidate) {
795   std::string candidate_sdp;
796   candidate->ToString(&candidate_sdp);
797   auto sdp_mid = candidate->sdp_mid();
798   auto line_index = candidate->sdp_mline_index();
799 
800   Json::Value reply;
801   reply["type"] = "ice-candidate";
802   reply["mid"] = sdp_mid;
803   reply["mLineIndex"] = static_cast<Json::UInt64>(line_index);
804   reply["candidate"] = candidate_sdp;
805 
806   send_to_client_(reply);
807 }
808 
OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel)809 void ClientHandler::OnDataChannel(
810     rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel) {
811   auto label = data_channel->label();
812   if (label == kInputChannelLabel) {
813     input_handler_.reset(new InputChannelHandler(data_channel, observer_));
814   } else if (label == kAdbChannelLabel) {
815     adb_handler_.reset(new AdbChannelHandler(data_channel, observer_));
816   } else if (label == kBluetoothChannelLabel) {
817     bluetooth_handler_.reset(
818         new BluetoothChannelHandler(data_channel, observer_));
819   } else if (label == kCameraDataChannelLabel) {
820     camera_data_handler_.reset(
821         new CameraChannelHandler(data_channel, observer_));
822   } else {
823     LOG(VERBOSE) << "Data channel connected: " << label;
824     data_channels_.push_back(data_channel);
825   }
826 }
827 
OnRenegotiationNeeded()828 void ClientHandler::OnRenegotiationNeeded() {
829   state_ = State::kNew;
830   LOG(VERBOSE) << "Client " << client_id_ << " needs renegotiation";
831 }
832 
OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state)833 void ClientHandler::OnIceGatheringChange(
834     webrtc::PeerConnectionInterface::IceGatheringState new_state) {
835   std::string state_str;
836   switch (new_state) {
837     case webrtc::PeerConnectionInterface::IceGatheringState::kIceGatheringNew:
838       state_str = "NEW";
839       break;
840     case webrtc::PeerConnectionInterface::IceGatheringState::
841         kIceGatheringGathering:
842       state_str = "GATHERING";
843       break;
844     case webrtc::PeerConnectionInterface::IceGatheringState::
845         kIceGatheringComplete:
846       state_str = "COMPLETE";
847       break;
848     default:
849       state_str = "UNKNOWN";
850   }
851   LOG(VERBOSE) << "Client " << client_id_
852                << ": ICE Gathering state set to: " << state_str;
853 }
854 
OnIceCandidateError(const std::string & host_candidate,const std::string & url,int error_code,const std::string & error_text)855 void ClientHandler::OnIceCandidateError(const std::string &host_candidate,
856                                         const std::string &url, int error_code,
857                                         const std::string &error_text) {
858   LOG(VERBOSE) << "Gathering of an ICE candidate (host candidate: "
859                << host_candidate << ", url: " << url
860                << ") failed: " << error_text;
861 }
862 
OnIceCandidateError(const std::string & address,int port,const std::string & url,int error_code,const std::string & error_text)863 void ClientHandler::OnIceCandidateError(const std::string &address, int port,
864                                         const std::string &url, int error_code,
865                                         const std::string &error_text) {
866   LOG(VERBOSE) << "Gathering of an ICE candidate (address: " << address
867                << ", port: " << port << ", url: " << url
868                << ") failed: " << error_text;
869 }
870 
OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state)871 void ClientHandler::OnSignalingChange(
872     webrtc::PeerConnectionInterface::SignalingState new_state) {
873   // ignore
874 }
OnStandardizedIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state)875 void ClientHandler::OnStandardizedIceConnectionChange(
876     webrtc::PeerConnectionInterface::IceConnectionState new_state) {
877   switch (new_state) {
878     case webrtc::PeerConnectionInterface::kIceConnectionNew:
879       LOG(DEBUG) << "ICE connection state: New";
880       break;
881     case webrtc::PeerConnectionInterface::kIceConnectionChecking:
882       LOG(DEBUG) << "ICE connection state: Checking";
883       break;
884     case webrtc::PeerConnectionInterface::kIceConnectionConnected:
885       LOG(DEBUG) << "ICE connection state: Connected";
886       break;
887     case webrtc::PeerConnectionInterface::kIceConnectionCompleted:
888       LOG(DEBUG) << "ICE connection state: Completed";
889       break;
890     case webrtc::PeerConnectionInterface::kIceConnectionFailed:
891       state_ = State::kFailed;
892       LOG(DEBUG) << "ICE connection state: Failed";
893       break;
894     case webrtc::PeerConnectionInterface::kIceConnectionDisconnected:
895       LOG(DEBUG) << "ICE connection state: Disconnected";
896       break;
897     case webrtc::PeerConnectionInterface::kIceConnectionClosed:
898       LOG(DEBUG) << "ICE connection state: Closed";
899       break;
900     case webrtc::PeerConnectionInterface::kIceConnectionMax:
901       LOG(DEBUG) << "ICE connection state: Max";
902       break;
903   }
904 }
OnIceCandidatesRemoved(const std::vector<cricket::Candidate> & candidates)905 void ClientHandler::OnIceCandidatesRemoved(
906     const std::vector<cricket::Candidate> &candidates) {
907   // ignore
908 }
OnTrack(rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver)909 void ClientHandler::OnTrack(
910     rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver) {
911   auto track = transceiver->receiver()->track();
912   if (track && track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) {
913     // It's ok to take the raw pointer here because we make sure to unset it
914     // when the track is removed
915     camera_track_->SetVideoTrack(
916         static_cast<webrtc::VideoTrackInterface *>(track.get()));
917   }
918 }
OnRemoveTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver)919 void ClientHandler::OnRemoveTrack(
920     rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) {
921   auto track = receiver->track();
922   if (track && track->kind() == webrtc::MediaStreamTrackInterface::kVideoKind) {
923     // this only unsets if the track matches the one already in store
924     camera_track_->UnsetVideoTrack(
925         reinterpret_cast<webrtc::VideoTrackInterface *>(track.get()));
926   }
927 }
928 
929 }  // namespace webrtc_streaming
930 }  // namespace cuttlefish
931