blob: 2e3da85a8c6f3d81a42fb57fa3bb2531e2759e6b [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 "src/connectivity/overnet/lib/protocol/reliable_framer.h"
#include "src/connectivity/overnet/lib/environment/trace.h"
namespace overnet {
ReliableFramer::ReliableFramer() : StreamFramer(Border::Prefix(2), 65536) {}
ReliableFramer::~ReliableFramer() = default;
void ReliableFramer::Push(Slice data) {
OVERNET_TRACE(DEBUG) << "ReliableFramer.Push: " << data;
buffered_input_.Append(std::move(data));
}
StatusOr<Optional<Slice>> ReliableFramer::Pop() {
OVERNET_TRACE(DEBUG) << "ReliableFramer.Pop: q=" << buffered_input_;
using Sts = StatusOr<Optional<Slice>>;
const uint8_t *begin = buffered_input_.begin();
const uint8_t *p = begin;
const uint8_t *end = buffered_input_.end();
OVERNET_TRACE(DEBUG) << "ReliableFramer.Pop: have " << (end - p) << " bytes";
if (end - p < 2) {
OVERNET_TRACE(DEBUG)
<< "ReliableFramer.Pop: insufficient bytes to see header";
return Nothing;
}
uint16_t hdr;
memcpy(&hdr, p, 2);
p += 2;
const ssize_t segment_length = ssize_t(hdr) + 1;
OVERNET_TRACE(DEBUG) << "ReliableFramer.Pop: hdr=" << hdr
<< " => segment_length " << segment_length;
if (end - p < segment_length) {
return Sts(Nothing);
}
buffered_input_.TrimBegin(p - begin);
return Sts(buffered_input_.TakeUntilOffset(segment_length));
}
bool ReliableFramer::InputEmpty() const {
return buffered_input_.length() == 0;
}
Optional<Slice> ReliableFramer::SkipNoise() { return Nothing; }
Slice ReliableFramer::Frame(Slice data) {
OVERNET_TRACE(DEBUG) << "ReliableFramer.Frame: " << data;
auto length = data.length();
if (length == 0) {
return data;
}
return data.WithPrefix(2, [length](uint8_t *p) {
uint16_t hdr = length - 1;
memcpy(p, &hdr, 2);
});
}
} // namespace overnet