• 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 "wmediumd_controller.h"
17 
18 #include <android-base/logging.h>
19 #include <sys/socket.h>
20 
21 #include <cstdint>
22 #include <memory>
23 #include <optional>
24 #include <string>
25 
26 #include "common/libs/fs/shared_buf.h"
27 
28 #include "host/libs/wmediumd_controller/wmediumd_api_protocol.h"
29 
30 namespace cuttlefish {
31 
New(const std::string & serverSocketPath)32 std::unique_ptr<WmediumdController> WmediumdController::New(
33     const std::string& serverSocketPath) {
34   std::unique_ptr<WmediumdController> result(new WmediumdController);
35 
36   if (!result->Connect(serverSocketPath)) {
37     return nullptr;
38   }
39 
40   return result;
41 }
42 
Connect(const std::string & serverSocketPath)43 bool WmediumdController::Connect(const std::string& serverSocketPath) {
44   wmediumd_socket_ =
45       SharedFD::SocketLocalClient(serverSocketPath, false, SOCK_STREAM);
46 
47   if (!wmediumd_socket_->IsOpen()) {
48     LOG(ERROR) << "Cannot connect wmediumd control socket " << serverSocketPath
49                << ": " << wmediumd_socket_->StrError();
50     return false;
51   }
52 
53   return SetControl(0);
54 }
55 
SetSnr(const std::string & node1,const std::string & node2,uint8_t snr)56 bool WmediumdController::SetSnr(const std::string& node1,
57                                 const std::string& node2, uint8_t snr) {
58   return SendMessage(WmediumdMessageSetSnr(node1, node2, snr));
59 }
60 
SetControl(const uint32_t flags)61 bool WmediumdController::SetControl(const uint32_t flags) {
62   return SendMessage(WmediumdMessageSetControl(flags));
63 }
64 
ReloadCurrentConfig(void)65 bool WmediumdController::ReloadCurrentConfig(void) {
66   return SendMessage(WmediumdMessageReloadCurrentConfig());
67 }
68 
ReloadConfig(const std::string & configPath)69 bool WmediumdController::ReloadConfig(const std::string& configPath) {
70   return SendMessage(WmediumdMessageReloadConfig(configPath));
71 }
72 
StartPcap(const std::string & pcapPath)73 bool WmediumdController::StartPcap(const std::string& pcapPath) {
74   return SendMessage(WmediumdMessageStartPcap(pcapPath));
75 }
76 
StopPcap(void)77 bool WmediumdController::StopPcap(void) {
78   return SendMessage(WmediumdMessageStopPcap());
79 }
80 
GetStations(void)81 std::optional<WmediumdMessageStationsList> WmediumdController::GetStations(
82     void) {
83   auto reply = SendMessageWithReply(WmediumdMessageGetStations());
84 
85   if (!reply) {
86     return std::nullopt;
87   }
88 
89   return WmediumdMessageStationsList::Parse(*reply);
90 }
91 
SetPosition(const std::string & node,double x,double y)92 bool WmediumdController::SetPosition(const std::string& node, double x,
93                                      double y) {
94   return SendMessage(WmediumdMessageSetPosition(node, x, y));
95 }
96 
SetLci(const std::string & node,const std::string & lci)97 bool WmediumdController::SetLci(const std::string& node,
98                                 const std::string& lci) {
99   return SendMessage(WmediumdMessageSetLci(node, lci));
100 }
101 
SetCivicloc(const std::string & node,const std::string & civicloc)102 bool WmediumdController::SetCivicloc(const std::string& node,
103                                      const std::string& civicloc) {
104   return SendMessage(WmediumdMessageSetCivicloc(node, civicloc));
105 }
106 
SendMessage(const WmediumdMessage & message)107 bool WmediumdController::SendMessage(const WmediumdMessage& message) {
108   auto reply = SendMessageWithReply(message);
109 
110   if (!reply) {
111     return false;
112   }
113 
114   if (reply->Type() != WmediumdMessageType::kAck) {
115     return false;
116   }
117 
118   return true;
119 }
120 
SendMessageWithReply(const WmediumdMessage & message)121 std::optional<WmediumdMessageReply> WmediumdController::SendMessageWithReply(
122     const WmediumdMessage& message) {
123   auto sendResult = SendAll(wmediumd_socket_, message.Serialize());
124 
125   if (!sendResult) {
126     LOG(ERROR) << "sendmessage failed: " << wmediumd_socket_->StrError();
127     return std::nullopt;
128   }
129 
130   std::string recvHeader = RecvAll(wmediumd_socket_, sizeof(uint32_t) * 2);
131 
132   if (recvHeader.size() != sizeof(uint32_t) * 2) {
133     LOG(ERROR)
134         << "error: RecvAll failed while receiving result header from server";
135     return std::nullopt;
136   }
137 
138   uint32_t type = *reinterpret_cast<const uint32_t*>(recvHeader.c_str());
139   uint32_t dataLen =
140       *reinterpret_cast<const uint32_t*>(recvHeader.c_str() + sizeof(uint32_t));
141 
142   std::string recvData = RecvAll(wmediumd_socket_, dataLen);
143 
144   if (recvData.size() != dataLen) {
145     LOG(ERROR)
146         << "error: RecvAll failed while receiving result data from server";
147     return std::nullopt;
148   }
149 
150   return WmediumdMessageReply(static_cast<WmediumdMessageType>(type), recvData);
151 }
152 
153 }  // namespace cuttlefish
154