blob: 1a48ba2e4a5be39b64ca36c46f6a046e77b3f074 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 <fuchsia/device/llcpp/fidl.h>
#include <fuchsia/hardware/pty/llcpp/fidl.h>
#include <lib/zx/eventpair.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include "fifo.h"
#include "src/lib/storage/vfs/cpp/vfs.h"
// forward-decl
class PtyClient;
// Window size dimensions, in characters.
struct WindowSize {
uint32_t width = 0;
uint32_t height = 0;
class PtyServer : public fbl::RefCounted<PtyServer> {
// This ctor is only public for the use of fbl::MakeRefCounted. Use Create()
// instead.
PtyServer(zx::eventpair local, zx::eventpair remote, fs::Vfs* vfs);
// Create a new PtyServer. This method is preferred to the ctor.
static zx_status_t Create(fbl::RefPtr<PtyServer>* out, fs::Vfs* vfs);
zx_status_t Read(void* data, size_t len, size_t* out_actual);
zx_status_t Write(const void* data, size_t len, size_t* out_actual);
zx_status_t GetEvent(zx::eventpair* event) { return remote_.duplicate(ZX_RIGHTS_BASIC, event); }
// Create a new PtyClient
zx_status_t CreateClient(uint32_t id,
fidl::ServerEnd<fuchsia_hardware_pty::Device> client_request);
// Remove a PtyClient
void RemoveClient(PtyClient* client);
// Called when data is written by the active client
zx_status_t Recv(const void* data, size_t len, size_t* actual, bool* is_full);
// Called when data is being sent to the active client
zx_status_t Send(const void* data, size_t len, size_t* actual);
// Called when all connections to the PtyServerVnode are closed, to inform pty
// clients that the pty server is gone.
void Shutdown();
void AssertWritableSignal() {
local_.signal_peer(0, fuchsia_device::wire::kDeviceSignalWritable);
// Read all outstanding events, and reset the pending signal.
uint32_t DrainEvents();
// Called to make the given client active. Any existing active client is
// deactivated. Returns ZX_ERR_NOT_FOUND if the requested id does not exist.
zx_status_t MakeActive(uint32_t id);
WindowSize window_size() { return size_; }
void set_window_size(WindowSize size) { size_ = size; }
[[nodiscard]] bool is_active(const PtyClient* client) const { return active_.get() == client; }
[[nodiscard]] bool is_control(const PtyClient* client) const { return control_.get() == client; }
// Called to make the given client active. Any existing active client is
// deactivated.
void MakeActive(fbl::RefPtr<PtyClient> client);
// remote_ is signaled to indicate to server connections various status
// conditions.
zx::eventpair local_, remote_;
fs::Vfs* vfs_;
// Data waiting to be read by a connection to the server.
Fifo rx_fifo_;
// Pending out-of-band events
uint32_t events_ = 0;
// List of all clients
fbl::DoublyLinkedList<fbl::RefPtr<PtyClient>> clients_;
// Active client
fbl::RefPtr<PtyClient> active_;
// The control client is the client that receives events
fbl::RefPtr<PtyClient> control_;
// The dimensions (in characters) of the window
WindowSize size_ = {};