blob: f3084e202d0b27517bfe377ab87126be8ec85b55 [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.
#include "fake_endpoint.h"
namespace netemul {
FakeEndpoint::FakeEndpoint(data::BusConsumer::Ptr sink,
fidl::InterfaceRequest<FakeEndpoint::FFakeEndpoint> request,
async_dispatcher_t* dispatcher)
: sink_(std::move(sink)),
binding_(this, std::move(request), dispatcher),
weak_ptr_factory_(this),
dropped_(0) {
binding_.set_error_handler([this](zx_status_t err) {
if (on_disconnected_) {
on_disconnected_(this);
}
});
}
void FakeEndpoint::SetOnDisconnected(OnDisconnectedCallback cl) {
on_disconnected_ = std::move(cl);
}
fxl::WeakPtr<data::Consumer> FakeEndpoint::GetPointer() { return weak_ptr_factory_.GetWeakPtr(); }
void FakeEndpoint::Consume(const void* data, size_t len) {
// copy data to fidl vec:
std::vector<uint8_t> vec(len);
memcpy(vec.data(), data, len);
pending_frames_.push(std::move(vec));
if (pending_frames_.size() > kMaxPendingFrames) {
pending_frames_.pop();
dropped_++;
}
PopReadQueue();
}
void FakeEndpoint::Write(::std::vector<uint8_t> data, WriteCallback callback) {
if (!sink_) {
// sink has disappeared from under us!
// close the binding
binding_.Close(ZX_ERR_PEER_CLOSED);
return;
}
sink_->Consume(data.data(), data.size(), GetPointer());
callback();
}
void FakeEndpoint::Read(ReadCallback callback) {
if (pending_callback_.has_value()) {
// Not allowed to enqueue two calls.
binding_.Close(ZX_ERR_BAD_STATE);
return;
}
pending_callback_ = std::move(callback);
PopReadQueue();
}
void FakeEndpoint::PopReadQueue() {
if (pending_callback_.has_value() && !pending_frames_.empty()) {
(*pending_callback_)(std::move(pending_frames_.front()), dropped_);
dropped_ = 0;
pending_frames_.pop();
pending_callback_.reset();
}
}
} // namespace netemul