/* * Copyright (C) 2016 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 <array> #include <cstdint> #include <cstring> #include <memory> #include <utility> #include "android-base/logging.h" #include "wifilogd/main_loop.h" #include "wifilogd/protocol.h" namespace android { namespace wifilogd { namespace { constexpr auto kMainBufferSizeBytes = 128 * 1024; // TODO(b/32840641): Tune the sleep time. constexpr auto kTransientErrorSleepTimeNsec = 100 * 1000; // 100 usec } MainLoop::MainLoop(const std::string& socket_name) : MainLoop(socket_name, std::make_unique<Os>(), std::make_unique<CommandProcessor>(kMainBufferSizeBytes)) {} MainLoop::MainLoop(const std::string& socket_name, std::unique_ptr<Os> os, std::unique_ptr<CommandProcessor> command_processor) : os_(std::move(os)), command_processor_(std::move(command_processor)) { Os::Errno err; std::tie(sock_fd_, err) = os_->GetControlSocket(socket_name); if (err) { LOG(FATAL) << "Failed to get control socket: " << std::strerror(errno); } } void MainLoop::RunOnce() { std::array<uint8_t, protocol::kMaxMessageSize> input_buf; size_t datagram_len; Os::Errno err; std::tie(datagram_len, err) = os_->ReceiveDatagram(sock_fd_, input_buf.data(), input_buf.size()); if (err) { ProcessError(err); return; } if (datagram_len > protocol::kMaxMessageSize) { // TODO(b/32098735): Increment stats counter. datagram_len = protocol::kMaxMessageSize; } command_processor_->ProcessCommand(input_buf.data(), datagram_len, Os::kInvalidFd); } // Private methods below. void MainLoop::ProcessError(Os::Errno err) { if (err == EINTR || err == ENOMEM) { // TODO(b/32098735): Increment stats counter. os_->Nanosleep(kTransientErrorSleepTimeNsec); return; } // Any other error is unexpected, and assumed to be non-recoverable. // (If, e.g., our socket is in a bad state, then we won't be able to receive // any new log messages.) LOG(FATAL) << "Unexpected error: " << std::strerror(err); } } // namespace wifilogd } // namespace android