• 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 
17 #include "wmediumd_api_protocol.h"
18 
19 #include <android-base/logging.h>
20 #include <android-base/strings.h>
21 
22 #include <cstdlib>
23 #include <iomanip>
24 #include <iostream>
25 #include <string>
26 #include <vector>
27 
28 #include "common/libs/fs/shared_buf.h"
29 
30 #define MAC_ADDR_LEN 6
31 #define STR_MAC_ADDR_LEN 17
32 
33 template <class T>
AppendBinaryRepresentation(std::string & buf,const T & data)34 static void AppendBinaryRepresentation(std::string& buf, const T& data) {
35   std::copy(reinterpret_cast<const char*>(&data),
36             reinterpret_cast<const char*>(&data) + sizeof(T),
37             std::back_inserter(buf));
38 }
39 
ParseMacAddress(const std::string & macAddr)40 static std::array<uint8_t, 6> ParseMacAddress(const std::string& macAddr) {
41   if (!cuttlefish::ValidMacAddr(macAddr)) {
42     LOG(FATAL) << "invalid mac address " << macAddr;
43   }
44 
45   auto split_mac = android::base::Split(macAddr, ":");
46   std::array<uint8_t, 6> mac;
47   for (int i = 0; i < 6; i++) {
48     char* end_ptr;
49     mac[i] = (uint8_t)strtol(split_mac[i].c_str(), &end_ptr, 16);
50   }
51 
52   return mac;
53 }
54 
55 namespace cuttlefish {
56 
ValidMacAddr(const std::string & macAddr)57 bool ValidMacAddr(const std::string& macAddr) {
58   if (macAddr.size() != STR_MAC_ADDR_LEN) {
59     return false;
60   }
61 
62   if (macAddr[2] != ':' || macAddr[5] != ':' || macAddr[8] != ':' ||
63       macAddr[11] != ':' || macAddr[14] != ':') {
64     return false;
65   }
66 
67   for (int i = 0; i < STR_MAC_ADDR_LEN; ++i) {
68     if ((i - 2) % 3 == 0) continue;
69     char c = macAddr[i];
70 
71     if (isupper(c)) {
72       c = tolower(c);
73     }
74 
75     if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) return false;
76   }
77 
78   return true;
79 }
80 
MacToString(const char * macAddr)81 std::string MacToString(const char* macAddr) {
82   std::stringstream result;
83 
84   for (int i = 0; i < MAC_ADDR_LEN; i++) {
85     result << std::setfill('0') << std::setw(2) << std::right << std::hex
86            << static_cast<int>(static_cast<uint8_t>(macAddr[i]));
87 
88     if (i != 5) {
89       result << ":";
90     }
91   }
92 
93   return result.str();
94 }
95 
Serialize(void) const96 std::string WmediumdMessage::Serialize(void) const {
97   std::string result;
98 
99   AppendBinaryRepresentation(result, this->Type());
100 
101   std::string body;
102   this->SerializeBody(body);
103 
104   AppendBinaryRepresentation(result, static_cast<uint32_t>(body.size()));
105 
106   std::copy(std::begin(body), std::end(body), std::back_inserter(result));
107 
108   return result;
109 }
110 
SerializeBody(std::string & buf) const111 void WmediumdMessageSetControl::SerializeBody(std::string& buf) const {
112   AppendBinaryRepresentation(buf, flags_);
113 }
114 
WmediumdMessageSetSnr(const std::string & node1,const std::string & node2,uint8_t snr)115 WmediumdMessageSetSnr::WmediumdMessageSetSnr(const std::string& node1,
116                                              const std::string& node2,
117                                              uint8_t snr) {
118   node1_mac_ = ParseMacAddress(node1);
119   node2_mac_ = ParseMacAddress(node2);
120   snr_ = snr;
121 }
122 
SerializeBody(std::string & buf) const123 void WmediumdMessageSetSnr::SerializeBody(std::string& buf) const {
124   std::copy(std::begin(node1_mac_), std::end(node1_mac_),
125             std::back_inserter(buf));
126   std::copy(std::begin(node2_mac_), std::end(node2_mac_),
127             std::back_inserter(buf));
128   buf.push_back(snr_);
129 }
130 
SerializeBody(std::string & buf) const131 void WmediumdMessageReloadConfig::SerializeBody(std::string& buf) const {
132   std::copy(std::begin(config_path_), std::end(config_path_),
133             std::back_inserter(buf));
134   buf.push_back('\0');
135 }
136 
SerializeBody(std::string & buf) const137 void WmediumdMessageStartPcap::SerializeBody(std::string& buf) const {
138   std::copy(std::begin(pcap_path_), std::end(pcap_path_),
139             std::back_inserter(buf));
140   buf.push_back('\0');
141 }
142 
WmediumdMessageSetPosition(const std::string & node,double x,double y)143 WmediumdMessageSetPosition::WmediumdMessageSetPosition(const std::string& node,
144                                                        double x, double y) {
145   mac_ = ParseMacAddress(node);
146   x_ = x;
147   y_ = y;
148 }
149 
SerializeBody(std::string & buf) const150 void WmediumdMessageSetPosition::SerializeBody(std::string& buf) const {
151   std::copy(std::begin(mac_), std::end(mac_), std::back_inserter(buf));
152   AppendBinaryRepresentation(buf, x_);
153   AppendBinaryRepresentation(buf, y_);
154 }
155 
WmediumdMessageSetLci(const std::string & node,const std::string & lci)156 WmediumdMessageSetLci::WmediumdMessageSetLci(const std::string& node,
157                                              const std::string& lci) {
158   mac_ = ParseMacAddress(node);
159   lci_ = lci;
160 }
161 
SerializeBody(std::string & buf) const162 void WmediumdMessageSetLci::SerializeBody(std::string& buf) const {
163   std::copy(std::begin(mac_), std::end(mac_), std::back_inserter(buf));
164   std::copy(std::begin(lci_), std::end(lci_), std::back_inserter(buf));
165   buf.push_back('\0');
166 }
167 
WmediumdMessageSetCivicloc(const std::string & node,const std::string & civicloc)168 WmediumdMessageSetCivicloc::WmediumdMessageSetCivicloc(
169     const std::string& node, const std::string& civicloc) {
170   mac_ = ParseMacAddress(node);
171   civicloc_ = civicloc;
172 }
173 
SerializeBody(std::string & buf) const174 void WmediumdMessageSetCivicloc::SerializeBody(std::string& buf) const {
175   std::copy(std::begin(mac_), std::end(mac_), std::back_inserter(buf));
176   std::copy(std::begin(civicloc_), std::end(civicloc_),
177             std::back_inserter(buf));
178   buf.push_back('\0');
179 }
180 
Parse(const WmediumdMessageReply & reply)181 std::optional<WmediumdMessageStationsList> WmediumdMessageStationsList::Parse(
182     const WmediumdMessageReply& reply) {
183   size_t pos = 0;
184   size_t dataSize = reply.Size();
185   auto data = reply.Data();
186 
187   if (reply.Type() != WmediumdMessageType::kStationsList) {
188     LOG(FATAL) << "expected reply type "
189                << static_cast<uint32_t>(WmediumdMessageType::kStationsList)
190                << ", got " << static_cast<uint32_t>(reply.Type()) << std::endl;
191   }
192 
193   WmediumdMessageStationsList result;
194 
195   if (pos + sizeof(uint32_t) > dataSize) {
196     LOG(ERROR) << "invalid response size";
197     return std::nullopt;
198   }
199 
200   uint32_t count = *reinterpret_cast<const uint32_t*>(data + pos);
201   pos += sizeof(uint32_t);
202 
203   for (uint32_t i = 0; i < count; ++i) {
204     if (pos + sizeof(wmediumd_station_info) > dataSize) {
205       LOG(ERROR) << "invalid response size";
206       return std::nullopt;
207     }
208 
209     const wmediumd_station_info* station =
210         reinterpret_cast<const wmediumd_station_info*>(data + pos);
211     std::string lci((char*)station + station->lci_offset);
212     std::string civicloc((char*)station + station->civicloc_offset);
213     result.station_list_.emplace_back(station->addr, station->hwaddr,
214                                       station->x, station->y, lci, civicloc,
215                                       station->tx_power);
216     pos += sizeof(wmediumd_station_info);
217   }
218 
219   return result;
220 }
221 
222 }  // namespace cuttlefish
223