summaryrefslogtreecommitdiffstats
path: root/src/lib/tcp/tcp_stream_msg.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/tcp/tcp_stream_msg.cc')
-rw-r--r--src/lib/tcp/tcp_stream_msg.cc127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/lib/tcp/tcp_stream_msg.cc b/src/lib/tcp/tcp_stream_msg.cc
new file mode 100644
index 0000000..89fd5e8
--- /dev/null
+++ b/src/lib/tcp/tcp_stream_msg.cc
@@ -0,0 +1,127 @@
+// Copyright (C) 2022-2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <tcp/tcp_stream_msg.h>
+#include <util/strutil.h>
+
+#include <iomanip>
+#include <sstream>
+#include <functional>
+
+namespace isc {
+namespace tcp {
+
+bool
+TcpStreamRequest::needData() const {
+ return (!expected_size_ || (wire_data_.size() < expected_size_));
+}
+
+size_t
+TcpStreamRequest::postBuffer(const void* buf, const size_t nbytes) {
+ if (!nbytes) {
+ // Nothing to do.
+ return (0);
+ }
+
+ const char* bufptr = static_cast<const char*>(buf);
+ size_t bytes_left = nbytes;
+ size_t wire_size = wire_data_.size();
+ size_t bytes_used = 0;
+ while (bytes_left) {
+ if (expected_size_) {
+ // We have the length, copy as much of what we still need as we can.
+ size_t need_bytes = expected_size_ - wire_size;
+ size_t copy_bytes = (need_bytes <= bytes_left ? need_bytes : bytes_left);
+ wire_data_.insert(wire_data_.end(), bufptr, bufptr + copy_bytes);
+ // bytes_left -= copy_bytes; // Since we break, we don't need to do this anymore.
+ bytes_used += copy_bytes;
+ break;
+ }
+
+ // Otherwise we don't know the length yet.
+ while (wire_size < 2 && bytes_left) {
+ wire_data_.push_back(*bufptr);
+ ++bufptr;
+ --bytes_left;
+ ++bytes_used;
+ ++wire_size;
+ }
+
+ // If we have enough to do it, calculate the expected length.
+ if (wire_size == 2 ) {
+ const uint8_t* cp = static_cast<const uint8_t*>(wire_data_.data());
+ uint16_t len = static_cast<unsigned int>(cp[0]) << 8;
+ len |= static_cast<unsigned int>(cp[1]);
+ expected_size_ = len + sizeof(len);
+ }
+ }
+
+ // Return how much we used.
+ return (bytes_used);
+}
+
+std::string
+TcpStreamRequest::logFormatRequest(const size_t limit) const {
+ std::stringstream output;
+ try {
+ size_t max = (limit && (limit < wire_data_.size()) ? limit : wire_data_.size());
+ output << "expected_size_: " << expected_size_ << ", current size: " << wire_data_.size()
+ << ", data: "
+ << isc::util::str::dumpAsHex(wire_data_.data(), max);
+ } catch (const std::exception& ex) {
+ std::stringstream output;
+ output << "logFormatRequest error: " << ex.what();
+ }
+
+ return (output.str());
+}
+
+void TcpStreamRequest::unpack() {
+ if (needData()) {
+ isc_throw(InvalidOperation, "Cannot unpack an incomplete request");
+ }
+
+ if (wire_data_.size() < sizeof(uint16_t)) {
+ isc_throw(Unexpected, "Request is malformed, too short");
+ }
+
+ request_ = std::vector<uint8_t>(wire_data_.begin() + sizeof(uint16_t), wire_data_.end());
+}
+
+void
+TcpStreamResponse::setResponseData(const uint8_t* data, size_t length) {
+ response_.assign(data, data + length);
+}
+
+void
+TcpStreamResponse::appendResponseData(const uint8_t* data, size_t length) {
+ response_.insert(response_.end(), data, data + length);
+}
+
+void
+TcpStreamResponse::setResponseData(const std::string& str) {
+ response_.assign(str.begin(), str.end());
+}
+
+void
+TcpStreamResponse::appendResponseData(const std::string& str) {
+ response_.insert(response_.end(), str.begin(), str.end());
+}
+
+void
+TcpStreamResponse::pack() {
+ wire_data_.clear();
+ // Prepend the length of the request.
+ uint16_t size = static_cast<uint16_t>(response_.size());
+ wire_data_.push_back(static_cast<uint8_t>((size & 0xff00U) >> 8));
+ wire_data_.push_back(static_cast<uint8_t>(size & 0x00ffU));
+ wire_data_.insert(wire_data_.end(), response_.begin(), response_.end());
+}
+
+} // end of namespace isc::tcp
+} // end of namespace isc