blob: deba22d18cbc1d0a3194cf69ae4dabf7317ae4ad [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
35void MessageDispatcher::RegisterGuestMessageHandler(
36 const base::Callback<void(const GuestMessage&)>& handler) {
37 guest_handler_ = handler;
38}
39
40void MessageDispatcher::RegisterDeviceMessageHandler(
41 const base::Callback<void(const DeviceMessage&)>& handler) {
42 device_handler_ = handler;
43}
44
Hidehiko Abede129222019-08-16 00:55:04 +090045void MessageDispatcher::OnFileCanReadWithoutBlocking() {
Garrick Evans96e03042019-05-28 14:30:52 +090046 char buffer[1024];
47 std::vector<base::ScopedFD> fds{};
48 ssize_t len =
Hidehiko Abede129222019-08-16 00:55:04 +090049 base::UnixDomainSocket::RecvMsg(fd_.get(), buffer, sizeof(buffer), &fds);
Garrick Evans96e03042019-05-28 14:30:52 +090050
51 if (len <= 0) {
52 PLOG(ERROR) << "Read failed: exiting";
Hidehiko Abede129222019-08-16 00:55:04 +090053 watcher_.reset();
Garrick Evans96e03042019-05-28 14:30:52 +090054 if (!failure_handler_.is_null())
55 failure_handler_.Run();
56 return;
57 }
58
59 msg_.Clear();
60 if (!msg_.ParseFromArray(buffer, len)) {
61 LOG(ERROR) << "Error parsing protobuf";
62 return;
63 }
64
65 if (msg_.has_guest_message() && !guest_handler_.is_null()) {
66 guest_handler_.Run(msg_.guest_message());
67 }
68
69 if (msg_.has_device_message() && !device_handler_.is_null()) {
70 device_handler_.Run(msg_.device_message());
71 }
72}
Taoyu Liaf944c92019-10-01 12:22:31 +090073void MessageDispatcher::SendMessage(
74 const google::protobuf::MessageLite& proto) const {
75 std::string str;
76 if (!proto.SerializeToString(&str)) {
77 LOG(ERROR) << "error serializing protobuf";
78 }
79 if (write(fd_.get(), str.data(), str.size()) !=
80 static_cast<ssize_t>(str.size())) {
81 LOG(ERROR) << "short write on protobuf";
82 }
83}
Garrick Evans96e03042019-05-28 14:30:52 +090084
Garrick Evans3388a032020-03-24 11:25:55 +090085} // namespace patchpanel