blob: 9ff11d27677b8943389dc403033bdba043151778 [file] [log] [blame]
// Copyright 2021 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 <iostream>
#include <memory>
#include <set>
#include <string>
#include <base/memory/weak_ptr.h>
#include <brillo/daemons/dbus_daemon.h>
#include <brillo/process/process_reaper.h>
#include <chromeos/patchpanel/dbus/client.h>
#include <shill/dbus/client/client.h>
#include "dns-proxy/metrics.h"
#include "dns-proxy/proxy.h"
namespace dns_proxy {
// The parent process for the service. Responsible for managing the proxy
// subprocesses.
class Controller : public brillo::DBusDaemon {
explicit Controller(const std::string& progname);
Controller(const Controller&) = delete;
Controller& operator=(const Controller&) = delete;
~Controller() = default;
int OnInit() override;
void OnShutdown(int*) override;
struct ProxyProc {
ProxyProc() : pid(0) {}
ProxyProc(Proxy::Type type, const std::string& ifname) : pid(0) {
opts.type = type;
opts.ifname = ifname;
friend std::ostream& operator<<(std::ostream& stream,
const Controller::ProxyProc& proc) {
stream << proc.opts;
if ( > 0) {
stream << "(pid: " << << ")";
return stream;
// |pid| is intentionally excluded as only the strings are used as a key.
bool operator<(const ProxyProc& that) const {
return (opts.type < that.opts.type || opts.ifname < that.opts.ifname);
pid_t pid;
Proxy::Options opts;
void Setup();
void SetupPatchpanel();
void OnPatchpanelReady(bool success);
void OnPatchpanelReset(bool reset);
void OnShillReady(bool success);
void OnShillReset(bool reset);
void RunProxy(Proxy::Type type, const std::string& ifname = "");
void KillProxy(Proxy::Type type, const std::string& ifname = "");
void Kill(const ProxyProc& proc);
void OnProxyExit(pid_t pid, const siginfo_t& siginfo);
void EvalProxyExit(const ProxyProc& proc);
// Callback used to run/kill default proxy based on its dependencies.
// |has_deps| will be true if either VPN or a single-networked guest OS is
// running.
void EvalDefaultProxyDeps(bool has_deps);
// Notified by shill whenever the default device changes.
void OnDefaultDeviceChanged(const shill::Client::Device* const device);
// Notified by patchpanel whenever a change occurs in one of its virtual
// network devices.
void OnVirtualDeviceChanged(
const patchpanel::NetworkDeviceChangedSignal& signal);
void VirtualDeviceAdded(const patchpanel::NetworkDevice& device);
void VirtualDeviceRemoved(const patchpanel::NetworkDevice& device);
const std::string progname_;
brillo::ProcessReaper process_reaper_;
std::set<ProxyProc> proxies_;
bool shill_ready_{false};
std::unique_ptr<shill::Client> shill_;
std::unique_ptr<patchpanel::Client> patchpanel_;
Metrics metrics_;
base::WeakPtrFactory<Controller> weak_factory_{this};
} // namespace dns_proxy