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