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 #include "host/frontend/webrtc_operator/client_handler.h"
17
18 #include <android-base/logging.h>
19
20 #include "host/frontend/webrtc_operator/constants/signaling_constants.h"
21 #include "host/frontend/webrtc_operator/device_handler.h"
22
23 namespace cuttlefish {
24
ClientHandler(struct lws * wsi,DeviceRegistry * registry,const ServerConfig & server_config)25 ClientHandler::ClientHandler(struct lws* wsi, DeviceRegistry* registry,
26 const ServerConfig& server_config)
27 : SignalHandler(wsi, registry, server_config),
28 device_handler_(),
29 client_id_(0) {}
30
OnClosed()31 void ClientHandler::OnClosed() {
32 auto device_handler = device_handler_.lock();
33 if (device_handler) {
34 device_handler->SendClientDisconnectMessage(client_id_);
35 }
36 }
37
SendDeviceMessage(const Json::Value & device_message)38 void ClientHandler::SendDeviceMessage(const Json::Value& device_message) {
39 Json::Value message;
40 message[webrtc_signaling::kTypeField] = webrtc_signaling::kDeviceMessageType;
41 message[webrtc_signaling::kPayloadField] = device_message;
42 Reply(message);
43 }
44
handleMessage(const std::string & type,const Json::Value & message)45 void ClientHandler::handleMessage(const std::string& type,
46 const Json::Value& message) {
47 if (type == webrtc_signaling::kConnectType) {
48 handleConnectionRequest(message);
49 } else if (type == webrtc_signaling::kForwardType) {
50 handleForward(message);
51 } else {
52 LogAndReplyError("Unknown message type: " + type);
53 }
54 }
55
handleConnectionRequest(const Json::Value & message)56 void ClientHandler::handleConnectionRequest(const Json::Value& message) {
57 if (client_id_ > 0) {
58 LogAndReplyError(
59 "Attempt to connect to multiple devices over same websocket");
60 Close();
61 return;
62 }
63 if (!message.isMember(webrtc_signaling::kDeviceIdField) ||
64 !message[webrtc_signaling::kDeviceIdField].isString()) {
65 LogAndReplyError("Invalid connection request: Missing device id");
66 Close();
67 return;
68 }
69 auto device_id = message[webrtc_signaling::kDeviceIdField].asString();
70 // Always send the server config back, even if the requested device is not
71 // registered. Applications may put clients on hold until the device is ready
72 // to connect.
73 SendServerConfig();
74
75 auto device_handler = registry_->GetDevice(device_id);
76 if (!device_handler) {
77 LogAndReplyError("Connection failed: Device not found: '" + device_id +
78 "'");
79 Close();
80 return;
81 }
82
83 client_id_ = device_handler->RegisterClient(shared_from_this());
84 device_handler_ = device_handler;
85 Json::Value device_info_reply;
86 device_info_reply[webrtc_signaling::kTypeField] =
87 webrtc_signaling::kDeviceInfoType;
88 device_info_reply[webrtc_signaling::kDeviceInfoField] =
89 device_handler->device_info();
90 Reply(device_info_reply);
91 }
92
handleForward(const Json::Value & message)93 void ClientHandler::handleForward(const Json::Value& message) {
94 if (client_id_ == 0) {
95 LogAndReplyError("Forward failed: No device asociated to client");
96 Close();
97 return;
98 }
99 if (!message.isMember(webrtc_signaling::kPayloadField)) {
100 LogAndReplyError("Forward failed: No payload present in message");
101 Close();
102 return;
103 }
104 auto device_handler = device_handler_.lock();
105 if (!device_handler) {
106 LogAndReplyError("Forward failed: Device disconnected");
107 // Disconnect this client since the device is gone
108 Close();
109 return;
110 }
111 device_handler->SendClientMessage(client_id_,
112 message[webrtc_signaling::kPayloadField]);
113 }
114
ClientHandlerFactory(DeviceRegistry * registry,const ServerConfig & server_config)115 ClientHandlerFactory::ClientHandlerFactory(DeviceRegistry* registry,
116 const ServerConfig& server_config)
117 : registry_(registry),
118 server_config_(server_config) {}
119
Build(struct lws * wsi)120 std::shared_ptr<WebSocketHandler> ClientHandlerFactory::Build(struct lws* wsi) {
121 return std::shared_ptr<WebSocketHandler>(
122 new ClientHandler(wsi, registry_, server_config_));
123 }
124
125 } // namespace cuttlefish
126