// // Copyright (C) 2021 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "wmediumd_controller.h" #include #include #include #include #include #include #include "common/libs/fs/shared_buf.h" #include "host/libs/wmediumd_controller/wmediumd_api_protocol.h" namespace cuttlefish { std::unique_ptr WmediumdController::New( const std::string& serverSocketPath) { std::unique_ptr result(new WmediumdController); if (!result->Connect(serverSocketPath)) { return nullptr; } return result; } bool WmediumdController::Connect(const std::string& serverSocketPath) { wmediumd_socket_ = SharedFD::SocketLocalClient(serverSocketPath, false, SOCK_STREAM); if (!wmediumd_socket_->IsOpen()) { LOG(ERROR) << "Cannot connect wmediumd control socket " << serverSocketPath << ": " << wmediumd_socket_->StrError(); return false; } return SetControl(0); } bool WmediumdController::SetSnr(const std::string& node1, const std::string& node2, uint8_t snr) { return SendMessage(WmediumdMessageSetSnr(node1, node2, snr)); } bool WmediumdController::SetControl(const uint32_t flags) { return SendMessage(WmediumdMessageSetControl(flags)); } bool WmediumdController::ReloadCurrentConfig(void) { return SendMessage(WmediumdMessageReloadCurrentConfig()); } bool WmediumdController::ReloadConfig(const std::string& configPath) { return SendMessage(WmediumdMessageReloadConfig(configPath)); } bool WmediumdController::StartPcap(const std::string& pcapPath) { return SendMessage(WmediumdMessageStartPcap(pcapPath)); } bool WmediumdController::StopPcap(void) { return SendMessage(WmediumdMessageStopPcap()); } std::optional WmediumdController::GetStations( void) { auto reply = SendMessageWithReply(WmediumdMessageGetStations()); if (!reply) { return std::nullopt; } return WmediumdMessageStationsList::Parse(*reply); } bool WmediumdController::SendMessage(const WmediumdMessage& message) { auto reply = SendMessageWithReply(message); if (!reply) { return false; } if (reply->Type() != WmediumdMessageType::kAck) { return false; } return true; } std::optional WmediumdController::SendMessageWithReply( const WmediumdMessage& message) { auto sendResult = SendAll(wmediumd_socket_, message.Serialize()); if (!sendResult) { LOG(ERROR) << "sendmessage failed: " << wmediumd_socket_->StrError(); return std::nullopt; } std::string recvHeader = RecvAll(wmediumd_socket_, sizeof(uint32_t) * 2); if (recvHeader.size() != sizeof(uint32_t) * 2) { LOG(ERROR) << "error: RecvAll failed while receiving result header from server"; return std::nullopt; } uint32_t type = *reinterpret_cast(recvHeader.c_str()); uint32_t dataLen = *reinterpret_cast(recvHeader.c_str() + sizeof(uint32_t)); std::string recvData = RecvAll(wmediumd_socket_, dataLen); if (recvData.size() != dataLen) { LOG(ERROR) << "error: RecvAll failed while receiving result data from server"; return std::nullopt; } return WmediumdMessageReply(static_cast(type), recvData); } } // namespace cuttlefish