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/signal_handler.h"
17 
18 #include <android-base/logging.h>
19 #include <json/json.h>
20 
21 #include "host/frontend/webrtc_operator/constants/signaling_constants.h"
22 
23 namespace cuttlefish {
24 
SignalHandler(struct lws * wsi,DeviceRegistry * registry,const ServerConfig & server_config)25 SignalHandler::SignalHandler(struct lws* wsi, DeviceRegistry* registry,
26                              const ServerConfig& server_config)
27     : WebSocketHandler(wsi),
28       registry_(registry),
29       server_config_(server_config) {}
30 
OnConnected()31 void SignalHandler::OnConnected() {}
32 
OnReceive(const uint8_t * msg,size_t len,bool binary)33 void SignalHandler::OnReceive(const uint8_t* msg, size_t len, bool binary) {
34   if (binary) {
35     LogAndReplyError("Received a binary message");
36     Close();
37     return;
38   }
39   Json::Value json_message;
40   Json::CharReaderBuilder builder;
41   std::unique_ptr<Json::CharReader> json_reader(builder.newCharReader());
42   std::string errorMessage;
43   auto str = reinterpret_cast<const char*>(msg);
44   if (!json_reader->parse(str, str + len, &json_message, &errorMessage)) {
45     LogAndReplyError("Received Invalid JSON");
46     // Rate limiting would be a good idea here
47     Close();
48     return;
49   }
50   if (!json_message.isMember(webrtc_signaling::kTypeField) ||
51       !json_message[webrtc_signaling::kTypeField].isString()) {
52     LogAndReplyError("Invalid message format: '" + std::string(msg, msg + len) +
53                      "'");
54     // Rate limiting would be a good idea here
55     Close();
56     return;
57   }
58 
59   auto type = json_message[webrtc_signaling::kTypeField].asString();
60   handleMessage(type, json_message);
61 }
62 
OnReceive(const uint8_t * msg,size_t len,bool binary,bool is_final)63 void SignalHandler::OnReceive(const uint8_t* msg, size_t len, bool binary,
64                               bool is_final) {
65   if (is_final) {
66     if (receive_buffer_.empty()) {
67       // no previous data - receive as-is
68       OnReceive(msg, len, binary);
69     } else {
70       // concatenate to previous data and receive
71       receive_buffer_.insert(receive_buffer_.end(), msg, msg + len);
72       OnReceive(receive_buffer_.data(), receive_buffer_.size(), binary);
73       receive_buffer_.clear();
74     }
75   } else {
76     // buffer up incomplete messages
77     receive_buffer_.insert(receive_buffer_.end(), msg, msg + len);
78   }
79 }
80 
SendServerConfig()81 void SignalHandler::SendServerConfig() {
82   // Call every time to allow config changes?
83   auto reply = server_config_.ToJson();
84   reply[webrtc_signaling::kTypeField] = webrtc_signaling::kConfigType;
85   Reply(reply);
86 }
87 
LogAndReplyError(const std::string & error_message)88 void SignalHandler::LogAndReplyError(const std::string& error_message) {
89   LOG(ERROR) << error_message;
90   auto reply_str = "{\"error\":\"" + error_message + "\"}";
91   EnqueueMessage(reply_str.c_str(), reply_str.size());
92 }
93 
Reply(const Json::Value & json)94 void SignalHandler::Reply(const Json::Value& json) {
95   Json::StreamWriterBuilder factory;
96   auto replyAsString = Json::writeString(factory, json);
97   EnqueueMessage(replyAsString.c_str(), replyAsString.size());
98 }
99 
100 }  // namespace cuttlefish
101