blob: 8827a81c8d5b50dbc71e8fa71956e7b1af9686ef [file] [log] [blame]
// Copyright 2018 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.
#ifndef ARC_VM_VSOCK_PROXY_VSOCK_PROXY_H_
#define ARC_VM_VSOCK_PROXY_VSOCK_PROXY_H_
#include <stdint.h>
#include <map>
#include <memory>
#include <base/files/file_descriptor_watcher_posix.h>
#include <base/files/scoped_file.h>
#include <base/macros.h>
#include <base/memory/weak_ptr.h>
#include "arc/vm/vsock_proxy/message.pb.h"
#include "arc/vm/vsock_proxy/vsock_stream.h"
namespace arc {
class StreamBase;
// Proxies between local file descriptors and given VSOCK socket by Message
// protocol.
class VSockProxy {
public:
// Represents whether this proxy is server (host) side one, or client (guest)
// side one.
enum class Type {
SERVER = 1,
CLIENT = 2,
};
VSockProxy(Type type, base::ScopedFD vsock);
~VSockProxy();
// Registers the |fd| whose type is |fd_type| to watch.
// Internally, this creates Stream object to read/write Message protocol
// buffer.
// If |handle| is the value corresponding to the file descriptor on
// messages on VSOCK. If 0 is set, this internally generates the handle.
// Returns handle or 0 on error.
uint64_t RegisterFileDescriptor(base::ScopedFD fd,
arc_proxy::FileDescriptor::Type fd_type,
uint64_t handle);
// Unregisters the |fd|. Internally, this destroys the corresponding stream
// object.
void UnregisterFileDescriptor(int fd);
private:
// Callback called when VSOCK gets ready to read.
// Reads Message from VSOCK file descriptor, and dispatches it to the
// corresponding local file descriptor.
void OnVSockReadReady();
// Handlers for each command.
// TODO(crbug.com/842960): Use pass-by-value when protobuf is upreved enough
// to support rvalues. (At least, 3.5, or maybe 3.6).
void OnClose(arc_proxy::Message* message);
void OnData(arc_proxy::Message* message);
// Callback called when local file descriptor gets ready to read.
// Reads Message from |fd|, and forwards to VSOCK file descriptor.
void OnLocalFileDesciptorReadReady(int fd);
VSockStream vsock_;
std::unique_ptr<base::FileDescriptorWatcher::Controller> vsock_controller_;
// Map from a raw file descriptor to corresponding info.
// Note that the file descriptor should be owned by the stream instance.
// Erasing the entry from this map should close the file descriptor
// automatically.
struct FileDescriptorInfo {
// 64-bit handle representation in Message proto.
uint64_t handle;
// Stream instane to read/write Message.
std::unique_ptr<StreamBase> stream;
// Controller of FileDescriptorWatcher. Destroying this will
// stop watching.
std::unique_ptr<base::FileDescriptorWatcher::Controller> controller;
};
std::map<int, FileDescriptorInfo> fd_map_;
// Map from handle in the Message into a raw file descriptor.
std::map<uint64_t, int> handle_map_;
// File descriptor can be created in either side (guest or host), and it is
// necessary that the handler is unique across guest and host.
// In host side, the value is started from 2, since 1 is reserved for the
// /run/chrome/arc_bridge.sock connection.
// In guest side, the value is started from 1000000000000000001ULL, which
// is an arbitrally huge value, in order to avoid conflict.
// TODO(hidehiko,yusukes,keiichiw): Fix the protocol.
uint64_t next_handle_;
// WeakPtrFactory needs to be declared as the member of the class, so that
// on destruction, any pending Callbacks bound to WeakPtr are cancelled
// first.
base::WeakPtrFactory<VSockProxy> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(VSockProxy);
};
} // namespace arc
#endif // ARC_VM_VSOCK_PROXY_VSOCK_PROXY_H_