13b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal/*
23b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal * Copyright (C) 2016 The Android Open Source Project
33b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal *
43b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal * Licensed under the Apache License, Version 2.0 (the "License");
53b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal * you may not use this file except in compliance with the License.
63b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal * You may obtain a copy of the License at
73b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal *
83b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal *      http://www.apache.org/licenses/LICENSE-2.0
93b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal *
103b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal * Unless required by applicable law or agreed to in writing, software
113b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal * distributed under the License is distributed on an "AS IS" BASIS,
123b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal * See the License for the specific language governing permissions and
143b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal * limitations under the License.
153b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal */
163b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
173b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal#include <array>
183b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal#include <cstdint>
193b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal#include <cstring>
203b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal#include <memory>
213b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal#include <utility>
223b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
233b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal#include "android-base/logging.h"
243b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
253b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal#include "wifilogd/main_loop.h"
263b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal#include "wifilogd/protocol.h"
273b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
283b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawalnamespace android {
293b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawalnamespace wifilogd {
303b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
313b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawalnamespace {
323b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawalconstexpr auto kMainBufferSizeBytes = 128 * 1024;
33fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal// TODO(b/32840641): Tune the sleep time.
34fd59221459953a821b9021e00276749ac46ea5eamukesh agrawalconstexpr auto kTransientErrorSleepTimeNsec = 100 * 1000;  // 100 usec
353b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal}
363b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
373b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawalMainLoop::MainLoop(const std::string& socket_name)
383b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal    : MainLoop(socket_name, std::make_unique<Os>(),
393b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal               std::make_unique<CommandProcessor>(kMainBufferSizeBytes)) {}
403b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
413b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawalMainLoop::MainLoop(const std::string& socket_name, std::unique_ptr<Os> os,
423b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal                   std::unique_ptr<CommandProcessor> command_processor)
433b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal    : os_(std::move(os)), command_processor_(std::move(command_processor)) {
443b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  Os::Errno err;
453b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  std::tie(sock_fd_, err) = os_->GetControlSocket(socket_name);
463b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  if (err) {
473b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal    LOG(FATAL) << "Failed to get control socket: " << std::strerror(errno);
483b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  }
493b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal}
503b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
513b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawalvoid MainLoop::RunOnce() {
523b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  std::array<uint8_t, protocol::kMaxMessageSize> input_buf;
533b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  size_t datagram_len;
543b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  Os::Errno err;
553b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  std::tie(datagram_len, err) =
563b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal      os_->ReceiveDatagram(sock_fd_, input_buf.data(), input_buf.size());
573b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  if (err) {
58fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal    ProcessError(err);
593b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal    return;
603b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  }
613b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
623b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  if (datagram_len > protocol::kMaxMessageSize) {
633b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal    // TODO(b/32098735): Increment stats counter.
643b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal    datagram_len = protocol::kMaxMessageSize;
653b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  }
663b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
673b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal  command_processor_->ProcessCommand(input_buf.data(), datagram_len,
683b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal                                     Os::kInvalidFd);
693b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal}
703b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal
71fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal// Private methods below.
72fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal
73fd59221459953a821b9021e00276749ac46ea5eamukesh agrawalvoid MainLoop::ProcessError(Os::Errno err) {
74fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal  if (err == EINTR || err == ENOMEM) {
75fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal    // TODO(b/32098735): Increment stats counter.
76fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal    os_->Nanosleep(kTransientErrorSleepTimeNsec);
77fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal    return;
78fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal  }
79fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal
80fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal  // Any other error is unexpected, and assumed to be non-recoverable.
81fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal  // (If, e.g., our socket is in a bad state, then we won't be able to receive
82fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal  // any new log messages.)
83fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal  LOG(FATAL) << "Unexpected error: " << std::strerror(err);
84fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal}
85fd59221459953a821b9021e00276749ac46ea5eamukesh agrawal
863b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal}  // namespace wifilogd
873b1d20a5720a5fe6b0a1eccd577b0d2447139efcmukesh agrawal}  // namespace android
88