blob: dc6c6298c40497e29640e6f9c8b324a2894e2e30 [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.
#pragma once
#include <fuchsia/net/ppp/llcpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fidl/llcpp/vector_view.h>
#include <lib/fit/function.h>
#include <lib/fit/result.h>
#include <lib/zx/channel.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include <array>
#include <cstddef>
#include <mutex>
#include <queue>
#include <thread>
#include <utility>
#include <ddktl/device.h>
#include <ddktl/protocol/empty-protocol.h>
#include <ddktl/protocol/serial.h>
#include <fbl/span.h>
#include "lib/common/ppp.h"
#include "lib/hdlc/frame.h"
namespace ppp {
class SerialPpp;
using DeviceType = ddk::Device<SerialPpp, ddk::Messageable>;
class SerialPpp final : public DeviceType, public ddk::EmptyProtocol<ZX_PROTOCOL_PPP> {
public:
SerialPpp();
explicit SerialPpp(zx_device_t* parent);
static zx_status_t Create(void* ctx, zx_device_t* parent);
zx_status_t Init();
// test-use only
void WaitCallbacks();
// ddk::Releasable
void DdkRelease();
// ddk::UnbindableNew
void DdkUnbindNew(ddk::UnbindTxn txn);
// ddk::Messageable
zx_status_t DdkMessage(fidl_msg_t* msg, fidl_txn_t* txn);
// fuchsia.connectivity.ppp.Device
// For ProtocolType::Control, the first two bytes of data encode (in network
// byte order) the PPP control protocol.
void Rx(llcpp::fuchsia::net::ppp::ProtocolType protocol,
fit::callback<void(fit::result<Frame, zx_status_t>)> callback);
// fuchsia.connectivity.ppp.Device
// For ProtocolType::Control, the first two bytes of data encode (in network
// byte order) the PPP control protocol.
zx_status_t Tx(llcpp::fuchsia::net::ppp::ProtocolType protocol, fbl::Span<const uint8_t> data);
// fuchsia.connectivity.ppp.Device
llcpp::fuchsia::net::ppp::Info GetInfo();
// fuchsia.connectivity.ppp.Device
bool GetStatus(llcpp::fuchsia::net::ppp::ProtocolType protocol);
// fuchsia.connectivity.ppp.Device
void SetStatus(llcpp::fuchsia::net::ppp::ProtocolType protocol, bool up);
// fuchsia.connectivity.ppp.Device
zx_status_t Enable(bool up);
// test-use only
zx_status_t Enable(bool up, zx::socket socket);
// fuchsia.connectivity.ppp.DeviceBootstrap
zx::channel GetInstance();
private:
class FrameDeviceServer final : public llcpp::fuchsia::net::ppp::Device::Interface {
public:
explicit FrameDeviceServer(SerialPpp* dev);
void Rx(llcpp::fuchsia::net::ppp::ProtocolType protocol, RxCompleter::Sync completer) override;
void Tx(llcpp::fuchsia::net::ppp::ProtocolType protocol, fidl::VectorView<uint8_t> data,
TxCompleter::Sync completer) override;
void GetInfo(GetInfoCompleter::Sync completer) override;
void GetStatus(llcpp::fuchsia::net::ppp::ProtocolType protocol,
GetStatusCompleter::Sync completer) override;
void SetStatus(llcpp::fuchsia::net::ppp::ProtocolType protocol, bool up,
SetStatusCompleter::Sync completer) override;
void Enable(bool up, EnableCompleter::Sync completer) override;
private:
SerialPpp* dev_ = nullptr;
};
class FrameDeviceBootstrapServer final
: public llcpp::fuchsia::net::ppp::DeviceBootstrap::Interface {
public:
explicit FrameDeviceBootstrapServer(SerialPpp* dev);
void GetInstance(GetInstanceCompleter::Sync completer) override;
private:
SerialPpp* dev_ = nullptr;
};
void RxLoop();
fit::result<Frame, zx_status_t> ReadFramed(std::vector<uint8_t>* raw_frame);
zx_status_t WriteFramed(FrameView frame);
ddk::SerialProtocolClient serial_protocol_;
zx::socket serial_;
FrameDeviceServer server_ = FrameDeviceServer(this);
FrameDeviceBootstrapServer bootstrap_server_ = FrameDeviceBootstrapServer(this);
std::atomic_bool enabled_ = false;
std::thread rx_thread_;
async::Loop loop_ = async::Loop(&kAsyncLoopConfigNoAttachToCurrentThread);
fit::callback<void(fit::result<Frame, zx_status_t>)> ipv4_callback_;
fit::callback<void(fit::result<Frame, zx_status_t>)> ipv6_callback_;
fit::callback<void(fit::result<Frame, zx_status_t>)> control_callback_;
std::mutex write_mutex_;
std::mutex ipv4_mutex_;
std::mutex ipv6_mutex_;
std::mutex control_mutex_;
std::queue<Frame> ipv4_frames_;
std::queue<Frame> ipv6_frames_;
std::queue<Frame> control_frames_;
std::atomic_bool ipv4_up_ = false;
std::atomic_bool ipv6_up_ = false;
};
} // namespace ppp