| /* |
| * Copyright 2017 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include <fcntl.h> |
| #include <signal.h> |
| #include <sys/resource.h> |
| #include <sys/socket.h> |
| #include <sys/types.h> |
| |
| #include <utility> |
| #include <vector> |
| |
| #include <base/at_exit.h> |
| #include <base/files/file_path.h> |
| #include <base/files/file_util.h> |
| #include <base/files/scoped_file.h> |
| #include <base/logging.h> |
| #include <brillo/flag_helper.h> |
| #include <brillo/syslog_logging.h> |
| #include <mojo/public/cpp/platform/socket_utils_posix.h> |
| |
| #include "common/camera_algorithm_adapter.h" |
| #include "cros-camera/common.h" |
| #include "cros-camera/constants.h" |
| #include "cros-camera/ipc_util.h" |
| |
| int main(int argc, char** argv) { |
| static base::AtExitManager exit_manager; |
| int kCameraProcessPriority = 0; |
| DEFINE_string(type, "vendor", "Algorithm type, e.g. vendor or gpu"); |
| brillo::FlagHelper::Init(argc, argv, "Camera algorithm service."); |
| if (FLAGS_type != "vendor" && FLAGS_type != "gpu") { |
| LOGF(ERROR) << "Invalid type"; |
| return EXIT_FAILURE; |
| } |
| |
| // Set up logging so we can enable VLOGs with -v / --vmodule. |
| logging::LoggingSettings settings; |
| settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; |
| LOG_ASSERT(logging::InitLogging(settings)); |
| |
| brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderrIfTty); |
| |
| int ret = setpriority(PRIO_PROCESS, 0, kCameraProcessPriority); |
| if (ret) { |
| LOGF(WARNING) << "Failed to set process priority"; |
| } |
| |
| base::FilePath socket_file_path( |
| (FLAGS_type == "vendor") |
| ? cros::constants::kCrosCameraAlgoSocketPathString |
| : cros::constants::kCrosCameraGPUAlgoSocketPathString); |
| // Create unix socket to receive the adapter token and connection handle |
| int fd = -1; |
| if (!cros::CreateServerUnixDomainSocket(socket_file_path, &fd)) { |
| LOGF(ERROR) << "CreateSreverUnixDomainSocket failed"; |
| return EXIT_FAILURE; |
| } |
| base::ScopedFD socket_fd(fd); |
| int flags = HANDLE_EINTR(fcntl(socket_fd.get(), F_GETFL)); |
| if (flags == -1) { |
| PLOGF(ERROR) << "fcntl(F_GETFL)"; |
| return EXIT_FAILURE; |
| } |
| if (HANDLE_EINTR(fcntl(socket_fd.get(), F_SETFL, flags & ~O_NONBLOCK)) == |
| -1) { |
| PLOGF(ERROR) << "fcntl(F_SETFL) failed to disable O_NONBLOCK"; |
| return EXIT_FAILURE; |
| } |
| |
| pid_t pid = 0; |
| while (1) { |
| VLOGF(1) << "Waiting for incoming connection for " |
| << socket_file_path.value(); |
| base::ScopedFD connection_fd(accept(socket_fd.get(), NULL, 0)); |
| if (!connection_fd.is_valid()) { |
| LOGF(ERROR) << "Failed to accept client connect request"; |
| return EXIT_FAILURE; |
| } |
| constexpr size_t kMaxMessageLength = 33; |
| char recv_buf[kMaxMessageLength] = {0}; |
| std::vector<base::ScopedFD> platform_handles; |
| if (mojo::SocketRecvmsg(connection_fd.get(), recv_buf, sizeof(recv_buf) - 1, |
| &platform_handles, true) == 0) { |
| LOGF(ERROR) << "Failed to receive message"; |
| return EXIT_FAILURE; |
| } |
| if (platform_handles.size() != 1 || !platform_handles.front().is_valid()) { |
| LOGF(ERROR) << "Received connection handle is invalid"; |
| return EXIT_FAILURE; |
| } |
| |
| VLOGF(1) << "Message from client: " << recv_buf; |
| if (pid > 0) { |
| kill(pid, SIGTERM); |
| } |
| pid = fork(); |
| if (pid == 0) { |
| cros::CameraAlgorithmAdapter adapter; |
| adapter.Run(std::string(recv_buf), std::move(platform_handles[0])); |
| exit(0); |
| } else if (pid < 0) { |
| LOGF(ERROR) << "Fork failed"; |
| } |
| } |
| } |