blob: 7ad9251fb65f72a1439a00419644d1cdb720cb73 [file] [log] [blame]
Garrick Evans066dc2c2020-12-10 10:43:55 +09001// Copyright 2021 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#ifndef DNS_PROXY_CONTROLLER_H_
6#define DNS_PROXY_CONTROLLER_H_
7
8#include <iostream>
9#include <memory>
10#include <set>
11#include <string>
12
13#include <base/memory/weak_ptr.h>
14#include <brillo/daemons/dbus_daemon.h>
15#include <brillo/process/process_reaper.h>
16#include <chromeos/patchpanel/dbus/client.h>
17#include <shill/dbus/client/client.h>
18
19#include "dns-proxy/proxy.h"
20
21namespace dns_proxy {
22
23// The parent process for the service. Responsible for managing the proxy
24// subprocesses.
25class Controller : public brillo::DBusDaemon {
26 public:
27 explicit Controller(const std::string& progname);
28 Controller(const Controller&) = delete;
29 Controller& operator=(const Controller&) = delete;
30 ~Controller();
31
32 protected:
33 int OnInit() override;
34 void OnShutdown(int*) override;
35
36 private:
37 struct ProxyProc {
38 ProxyProc() : pid(0) {}
39 ProxyProc(Proxy::Type type, const std::string& ifname) : pid(0) {
40 opts.type = type;
41 opts.ifname = ifname;
42 }
43
44 friend std::ostream& operator<<(std::ostream& stream,
45 const Controller::ProxyProc& proc) {
46 stream << proc.opts;
47 if (proc.pid > 0) {
48 stream << "(pid: " << proc.pid << ")";
49 }
50 return stream;
51 }
52
53 // |pid| is intentionally excluded as only the strings are used as a key.
54 bool operator<(const ProxyProc& that) const {
55 return (opts.type < that.opts.type || opts.ifname < that.opts.ifname);
56 }
57
58 pid_t pid;
59 Proxy::Options opts;
60 };
61
62 // This helper class keeps track of the dependencies for which the default
63 // network proxy is required to run - namely whenever a VPN is connected or at
64 // least one single-networked guest is running.
65 class DefaultProxyDeps {
66 public:
67 explicit DefaultProxyDeps(base::RepeatingCallback<void(bool)> eval)
68 : vpn_(false), eval_(eval) {}
69
70 void vpn_on(bool b) {
71 vpn_ = b;
72 eval();
73 }
74 void guest_up(const std::string& s) {
75 guests_.insert(s);
76 eval();
77 }
78 void guest_down(const std::string& s) {
79 guests_.erase(s);
80 eval();
81 }
82
83 private:
84 void eval() { eval_.Run(vpn_ || !guests_.empty()); }
85
86 bool vpn_{false};
87 std::set<std::string> guests_;
88 base::RepeatingCallback<void(bool)> eval_;
89 };
90
91 void Setup();
92 void OnPatchpanelReady(bool success);
93
94 void RunProxy(Proxy::Type type, const std::string& ifname = "");
95 void KillProxy(Proxy::Type type, const std::string& ifname = "");
96 void Kill(const ProxyProc& proc);
97 void OnProxyExit(pid_t pid, const siginfo_t& siginfo);
98
99 // Callback used to run/kill default proxy based on its dependencies.
100 // |has_deps| will be true if either VPN or a single-networked guest OS is
101 // running.
102 void EvalDefaultProxyDeps(bool has_deps);
103
104 // Notified by shill whenever the device service changes.
105 void OnDefaultServiceChanged(const std::string& type);
106
107 // Notified by patchpanel whenever a change occurs in one of its virtual
108 // network devices.
109 void OnVirtualDeviceChanged(
110 const patchpanel::NetworkDeviceChangedSignal& signal);
111 void VirtualDeviceAdded(const patchpanel::NetworkDevice& device);
112 void VirtualDeviceRemoved(const patchpanel::NetworkDevice& device);
113
114 const std::string progname_;
115 brillo::ProcessReaper process_reaper_;
116 std::set<ProxyProc> proxies_;
117 std::unique_ptr<DefaultProxyDeps> default_proxy_deps_;
118
119 std::unique_ptr<shill::Client> shill_;
120 std::unique_ptr<patchpanel::Client> patchpanel_;
121
122 base::WeakPtrFactory<Controller> weak_factory_{this};
123};
124
125} // namespace dns_proxy
126
127#endif // DNS_PROXY_CONTROLLER_H_