blob: b17cfee07b9eaba180c9935b9e10da91b5b98dc0 [file] [log] [blame]
Garrick Evans96e03042019-05-28 14:30:52 +09001// Copyright 2016 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
Garrick Evans3388a032020-03-24 11:25:55 +09005#include "patchpanel/message_dispatcher.h"
Garrick Evans96e03042019-05-28 14:30:52 +09006
7#include <utility>
8#include <vector>
9
10#include <base/bind.h>
11#include <base/files/scoped_file.h>
12#include <base/logging.h>
Hidehiko Abede129222019-08-16 00:55:04 +090013#include <base/posix/unix_domain_socket.h>
Garrick Evans96e03042019-05-28 14:30:52 +090014
Garrick Evans3388a032020-03-24 11:25:55 +090015namespace patchpanel {
Garrick Evans96e03042019-05-28 14:30:52 +090016
Taoyu Liaf944c92019-10-01 12:22:31 +090017MessageDispatcher::MessageDispatcher(base::ScopedFD fd, bool start)
18 : fd_(std::move(fd)) {
19 if (start)
20 Start();
21}
22
23void MessageDispatcher::Start() {
24 watcher_ = base::FileDescriptorWatcher::WatchReadable(
25 fd_.get(),
26 base::BindRepeating(&MessageDispatcher::OnFileCanReadWithoutBlocking,
27 base::Unretained(this)));
28}
Garrick Evans96e03042019-05-28 14:30:52 +090029
30void MessageDispatcher::RegisterFailureHandler(
31 const base::Callback<void()>& handler) {
32 failure_handler_ = handler;
33}
34
Taoyu Lia0727dc2020-09-24 19:54:59 +090035void MessageDispatcher::RegisterNDProxyMessageHandler(
36 const base::Callback<void(const NDProxyMessage&)>& handler) {
37 ndproxy_handler_ = handler;
38}
39
Garrick Evans96e03042019-05-28 14:30:52 +090040void MessageDispatcher::RegisterGuestMessageHandler(
41 const base::Callback<void(const GuestMessage&)>& handler) {
42 guest_handler_ = handler;
43}
44
45void MessageDispatcher::RegisterDeviceMessageHandler(
46 const base::Callback<void(const DeviceMessage&)>& handler) {
47 device_handler_ = handler;
48}
49
Hidehiko Abede129222019-08-16 00:55:04 +090050void MessageDispatcher::OnFileCanReadWithoutBlocking() {
Garrick Evans96e03042019-05-28 14:30:52 +090051 char buffer[1024];
52 std::vector<base::ScopedFD> fds{};
53 ssize_t len =
Hidehiko Abede129222019-08-16 00:55:04 +090054 base::UnixDomainSocket::RecvMsg(fd_.get(), buffer, sizeof(buffer), &fds);
Garrick Evans96e03042019-05-28 14:30:52 +090055
56 if (len <= 0) {
57 PLOG(ERROR) << "Read failed: exiting";
Hidehiko Abede129222019-08-16 00:55:04 +090058 watcher_.reset();
Garrick Evans96e03042019-05-28 14:30:52 +090059 if (!failure_handler_.is_null())
60 failure_handler_.Run();
61 return;
62 }
63
64 msg_.Clear();
65 if (!msg_.ParseFromArray(buffer, len)) {
66 LOG(ERROR) << "Error parsing protobuf";
67 return;
68 }
69
Taoyu Lia0727dc2020-09-24 19:54:59 +090070 if (msg_.has_ndproxy_message() && !ndproxy_handler_.is_null()) {
71 ndproxy_handler_.Run(msg_.ndproxy_message());
72 }
73
Garrick Evans96e03042019-05-28 14:30:52 +090074 if (msg_.has_guest_message() && !guest_handler_.is_null()) {
75 guest_handler_.Run(msg_.guest_message());
76 }
77
78 if (msg_.has_device_message() && !device_handler_.is_null()) {
79 device_handler_.Run(msg_.device_message());
80 }
81}
Taoyu Liaf944c92019-10-01 12:22:31 +090082void MessageDispatcher::SendMessage(
83 const google::protobuf::MessageLite& proto) const {
84 std::string str;
85 if (!proto.SerializeToString(&str)) {
86 LOG(ERROR) << "error serializing protobuf";
87 }
88 if (write(fd_.get(), str.data(), str.size()) !=
89 static_cast<ssize_t>(str.size())) {
90 LOG(ERROR) << "short write on protobuf";
91 }
92}
Garrick Evans96e03042019-05-28 14:30:52 +090093
Garrick Evans3388a032020-03-24 11:25:55 +090094} // namespace patchpanel