• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2021 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 "common/libs/confui/packet.h"
17 
18 #include <algorithm>
19 #include <iostream>
20 
21 #include <android-base/logging.h>
22 #include <android-base/strings.h>
23 
24 #include "common/libs/confui/protocol.h"
25 #include "common/libs/confui/utils.h"
26 #include "common/libs/fs/shared_buf.h"
27 
28 namespace cuttlefish {
29 namespace confui {
30 namespace packet {
PayloadToConfUiMessage(const std::string & str_to_parse)31 ConfUiMessage PayloadToConfUiMessage(const std::string& str_to_parse) {
32   auto tokens = android::base::Split(str_to_parse, ":");
33   ConfUiCheck(tokens.size() >= 3)
34       << "PayloadToConfUiMessage takes \"" + str_to_parse + "\""
35       << "and does not have 3 tokens";
36   std::string msg;
37   std::for_each(tokens.begin() + 2, tokens.end() - 1,
38                 [&msg](auto& token) { msg.append(token + ":"); });
39   msg.append(*tokens.rbegin());
40   return {tokens[0], tokens[1], msg};
41 }
42 
43 // Use only this function to make a packet to send over the confirmation
44 // ui packet layer
45 template <typename... Args>
ToPayload(const ConfUiCmd cmd,const std::string & session_id,Args &&...args)46 static Payload ToPayload(const ConfUiCmd cmd, const std::string& session_id,
47                          Args&&... args) {
48   std::string cmd_str = ToString(cmd);
49   std::string msg =
50       ArgsToString(session_id, ":", cmd_str, ":", std::forward<Args>(args)...);
51   PayloadHeader header;
52   header.payload_length_ = msg.size();
53   return {header, msg};
54 }
55 
56 template <typename... Args>
WritePayload(SharedFD d,const ConfUiCmd cmd,const std::string & session_id,Args &&...args)57 static bool WritePayload(SharedFD d, const ConfUiCmd cmd,
58                          const std::string& session_id, Args&&... args) {
59   if (!d->IsOpen()) {
60     LOG(ERROR) << "file, socket, etc, is not open to write";
61     return false;
62   }
63   auto [payload, msg] = ToPayload(cmd, session_id, std::forward<Args>(args)...);
64 
65   auto nwrite =
66       WriteAll(d, reinterpret_cast<const char*>(&payload), sizeof(payload));
67   if (nwrite != sizeof(payload)) {
68     return false;
69   }
70   nwrite = cuttlefish::WriteAll(d, msg.c_str(), msg.size());
71   if (nwrite != msg.size()) {
72     return false;
73   }
74   return true;
75 }
76 
ReadPayload(SharedFD s)77 static std::optional<ConfUiMessage> ReadPayload(SharedFD s) {
78   if (!s->IsOpen()) {
79     LOG(ERROR) << "file, socket, etc, is not open to read";
80     return std::nullopt;
81   }
82   PayloadHeader p;
83   auto nread = ReadExactBinary(s, &p);
84 
85   if (nread != sizeof(p)) {
86     return std::nullopt;
87   }
88 
89   if (p.payload_length_ == 0) {
90     return {{SESSION_ANY, ToString(ConfUiCmd::kUnknown), std::string{""}}};
91   }
92 
93   if (p.payload_length_ >= kMaxPayloadLength) {
94     LOG(ERROR) << "Payload length must be less than " << kMaxPayloadLength;
95     return std::nullopt;
96   }
97 
98   std::unique_ptr<char[]> buf{new char[p.payload_length_ + 1]};
99   nread = ReadExact(s, buf.get(), p.payload_length_);
100   buf[p.payload_length_] = 0;
101   if (nread != p.payload_length_) {
102     return std::nullopt;
103   }
104   std::string msg_to_parse{buf.get()};
105   auto [session_id, type, contents] = PayloadToConfUiMessage(msg_to_parse);
106   return {{session_id, type, contents}};
107 }
108 
RecvConfUiMsg(SharedFD fd)109 std::optional<ConfUiMessage> RecvConfUiMsg(SharedFD fd) {
110   return ReadPayload(fd);
111 }
112 
SendCmd(SharedFD fd,const std::string & session_id,ConfUiCmd cmd,const std::string & additional_info)113 bool SendCmd(SharedFD fd, const std::string& session_id, ConfUiCmd cmd,
114              const std::string& additional_info) {
115   return WritePayload(fd, cmd, session_id, additional_info);
116 }
117 
SendAck(SharedFD fd,const std::string & session_id,const bool is_success,const std::string & additional_info)118 bool SendAck(SharedFD fd, const std::string& session_id, const bool is_success,
119              const std::string& additional_info) {
120   return WritePayload(fd, ConfUiCmd::kCliAck, session_id,
121                       ToCliAckMessage(is_success, additional_info));
122 }
123 
SendResponse(SharedFD fd,const std::string & session_id,const std::string & additional_info)124 bool SendResponse(SharedFD fd, const std::string& session_id,
125                   const std::string& additional_info) {
126   return WritePayload(fd, ConfUiCmd::kCliRespond, session_id, additional_info);
127 }
128 
129 }  // end of namespace packet
130 }  // end of namespace confui
131 }  // end of namespace cuttlefish
132