blob: 9754e29c6c13213ebffc2c7535e54f03ec4036b7 [file] [log] [blame]
Andreea Costinas41e06442020-03-09 09:41:51 +01001// Copyright 2020 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "system-proxy/server_proxy.h"
6
7#include <iostream>
8#include <string>
9#include <utility>
10#include <vector>
11
12#include <base/bind.h>
13#include <base/bind_helpers.h>
14#include <base/callback_helpers.h>
15#include <base/posix/eintr_wrapper.h>
16#include <base/files/file_util.h>
17#include <base/threading/thread.h>
Andreea Costinas41e06442020-03-09 09:41:51 +010018#include <base/threading/thread_task_runner_handle.h>
19
20#include "bindings/worker_common.pb.h"
21#include "system-proxy/protobuf_util.h"
22
23namespace system_proxy {
24
Andreea Costinas44cefa22020-03-09 09:07:39 +010025namespace {
26const int kMaxConn = 1000;
27} // namespace
28
Andreea Costinas41e06442020-03-09 09:41:51 +010029ServerProxy::ServerProxy(base::OnceClosure quit_closure)
30 : quit_closure_(std::move(quit_closure)) {}
31
32void ServerProxy::Init() {
33 // Start listening for input.
34 stdin_watcher_ = base::FileDescriptorWatcher::WatchReadable(
Andreea Costinas44cefa22020-03-09 09:07:39 +010035 GetStdinPipe(),
Andreea Costinas41e06442020-03-09 09:41:51 +010036 base::Bind(&ServerProxy::HandleStdinReadable, base::Unretained(this)));
37
38 // Handle termination signals.
39 signal_handler_.Init();
40 for (int signal : {SIGINT, SIGTERM, SIGHUP, SIGQUIT}) {
41 signal_handler_.RegisterHandler(
42 signal, base::BindRepeating(&ServerProxy::HandleSignal,
43 base::Unretained(this)));
44 }
45}
46
47ServerProxy::~ServerProxy() = default;
48
49void ServerProxy::HandleStdinReadable() {
50 WorkerConfigs config;
Andreea Costinas44cefa22020-03-09 09:07:39 +010051 if (!ReadProtobuf(GetStdinPipe(), &config)) {
52 LOG(ERROR) << "Error decoding protobuf configurations." << std::endl;
Andreea Costinas41e06442020-03-09 09:41:51 +010053 return;
54 }
Andreea Costinas44cefa22020-03-09 09:07:39 +010055
56 if (config.has_credentials()) {
57 username_ = config.credentials().username();
58 password_ = config.credentials().password();
59 }
60
61 if (config.has_listening_address()) {
62 if (listening_addr_ != 0) {
63 LOG(ERROR)
64 << "Failure to set configurations: listening port was already set."
65 << std::endl;
66 return;
67 }
68 listening_addr_ = config.listening_address().addr();
69 listening_port_ = config.listening_address().port();
70 CreateListeningSocket();
71 }
Andreea Costinas41e06442020-03-09 09:41:51 +010072}
73
74bool ServerProxy::HandleSignal(const struct signalfd_siginfo& siginfo) {
75 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
76 std::move(quit_closure_));
77 return true;
78}
79
Andreea Costinas44cefa22020-03-09 09:07:39 +010080int ServerProxy::GetStdinPipe() {
81 return STDIN_FILENO;
82}
83
84void ServerProxy::CreateListeningSocket() {
85 listening_fd_ = std::make_unique<arc_networkd::Socket>(
86 AF_INET, SOCK_STREAM | SOCK_NONBLOCK);
87
88 struct sockaddr_in addr = {0};
89 addr.sin_family = AF_INET;
90 addr.sin_port = htons(listening_port_);
91 addr.sin_addr.s_addr = listening_addr_;
92 if (!listening_fd_->Bind((const struct sockaddr*)&addr, sizeof(addr))) {
93 LOG(ERROR) << "Cannot bind source socket" << std::endl;
94 return;
95 }
96
97 if (!listening_fd_->Listen(kMaxConn)) {
98 LOG(ERROR) << "Cannot listen on source socket." << std::endl;
99 return;
100 }
101
102 fd_watcher_ = base::FileDescriptorWatcher::WatchReadable(
103 listening_fd_->fd(),
104 base::BindRepeating(&ServerProxy::OnConnectionRequest,
105 base::Unretained(this)));
106}
107
108void ServerProxy::OnConnectionRequest() {
109 struct sockaddr_storage client_src = {};
110 socklen_t sockaddr_len = sizeof(client_src);
111 if (auto client_conn =
112 listening_fd_->Accept((struct sockaddr*)&client_src, &sockaddr_len)) {
113 // TODO(acostinas,chromium:1042626): Do curl authentication.
114 }
115}
116
Andreea Costinas41e06442020-03-09 09:41:51 +0100117} // namespace system_proxy