blob: 380100d4df54dd37c22f83c2a417e93547206350 [file] [log] [blame]
// Copyright 2018 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.
#pragma once
#include <fuchsia/overnet/protocol/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/wait.h>
#include <lib/fidl/cpp/message.h>
#include <lib/zx/socket.h>
#include "src/connectivity/overnet/lib/endpoint/router_endpoint.h"
namespace overnetstack {
class OvernetApp;
// Creates a stream by combining a zx::socket with an overnet DatagramStream.
// Reads from the overnet stream become writes to the zx socket, and vice
// versa. Errors are propagated.
// TODO(ctiller): epitaph support.
// TODO(ctiller): rewrite messages to:
// - support some limited handle propagation across overnet.
// - ensure system messages are never propagated.
class BoundSocket {
public:
BoundSocket(OvernetApp* app, overnet::RouterEndpoint::NewStream ns,
zx::socket socket);
private:
void Close(const overnet::Status& status);
void StartNetRead();
void WriteToSocketAndStartNextRead(std::vector<uint8_t> message,
bool control);
void ShareToSocketAndStartNextRead(zx::socket socket);
void StartSocketRead();
struct BoundWait {
async_wait_t wait;
BoundSocket* stream;
};
static void SendReady(async_dispatcher_t* dispatcher, async_wait_t* wait,
zx_status_t status, const zx_packet_signal_t* signal);
void OnSendReady(zx_status_t status, const zx_packet_signal_t* signal);
static void CtlSendReady(async_dispatcher_t* dispatcher, async_wait_t* wait,
zx_status_t status,
const zx_packet_signal_t* signal);
void OnCtlSendReady(zx_status_t status, const zx_packet_signal_t* signal);
static void RecvReady(async_dispatcher_t* dispatcher, async_wait_t* wait,
zx_status_t status, const zx_packet_signal_t* signal);
void OnRecvReady(zx_status_t status, const zx_packet_signal_t* signal);
static void ShareReady(async_dispatcher_t* dispatcher, async_wait_t* wait,
zx_status_t status, const zx_packet_signal_t* signal);
void OnShareReady(zx_status_t status, const zx_packet_signal_t* signal);
class Proxy final : public fuchsia::overnet::protocol::ZirconSocket_Proxy {
public:
Proxy(BoundSocket* socket) : socket_(socket) {}
void Send_(fidl::Message message) override;
private:
BoundSocket* const socket_;
};
class Stub final : public fuchsia::overnet::protocol::ZirconSocket_Stub {
public:
Stub(BoundSocket* socket) : socket_(socket) {}
void Send_(fidl::Message message) override { abort(); }
void Message(std::vector<uint8_t> message) override;
void Control(std::vector<uint8_t> message) override;
void Share(fuchsia::overnet::protocol::SocketHandle socket) override;
private:
BoundSocket* const socket_;
};
OvernetApp* const app_;
Proxy proxy_{this};
Stub stub_{this};
async_dispatcher_t* const dispatcher_ = async_get_default_dispatcher();
bool closed_ = false;
overnet::RouterEndpoint::Stream overnet_stream_;
zx::socket zx_socket_;
overnet::Optional<overnet::RouterEndpoint::Stream::ReceiveOp> net_recv_;
std::vector<uint8_t> pending_write_;
zx::socket pending_share_;
bool sock_read_data_ = true;
bool sock_read_ctl_ = true;
bool sock_read_accept_ = true;
BoundWait wait_send_{{{ASYNC_STATE_INIT},
&BoundSocket::SendReady,
zx_socket_.get(),
ZX_SOCKET_WRITABLE},
this};
BoundWait wait_ctl_send_{{{ASYNC_STATE_INIT},
&BoundSocket::CtlSendReady,
zx_socket_.get(),
ZX_SOCKET_CONTROL_WRITABLE},
this};
BoundWait wait_share_{{{ASYNC_STATE_INIT},
&BoundSocket::ShareReady,
zx_socket_.get(),
ZX_SOCKET_SHARE},
this};
BoundWait wait_recv_{{{ASYNC_STATE_INIT},
&BoundSocket::RecvReady,
zx_socket_.get(),
ZX_SOCKET_READABLE | ZX_SOCKET_CONTROL_READABLE |
ZX_SOCKET_ACCEPT | ZX_SOCKET_PEER_CLOSED},
this};
};
} // namespace overnetstack