Kea  2.5.2
tcp_stream_msg.cc
Go to the documentation of this file.
1 // Copyright (C) 2022-2023 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <tcp/tcp_stream_msg.h>
10 #include <util/strutil.h>
11 
12 #include <iomanip>
13 #include <sstream>
14 #include <functional>
15 
16 namespace isc {
17 namespace tcp {
18 
19 bool
21  return (!expected_size_ || (wire_data_.size() < expected_size_));
22 }
23 
24 size_t
25 TcpStreamRequest::postBuffer(const void* buf, const size_t nbytes) {
26  if (!nbytes) {
27  // Nothing to do.
28  return (0);
29  }
30 
31  const char* bufptr = static_cast<const char*>(buf);
32  size_t bytes_left = nbytes;
33  size_t wire_size = wire_data_.size();
34  size_t bytes_used = 0;
35  while (bytes_left) {
36  if (expected_size_) {
37  // We have the length, copy as much of what we still need as we can.
38  size_t need_bytes = expected_size_ - wire_size;
39  size_t copy_bytes = (need_bytes <= bytes_left ? need_bytes : bytes_left);
40  wire_data_.insert(wire_data_.end(), bufptr, bufptr + copy_bytes);
41  // bytes_left -= copy_bytes; // Since we break, we don't need to do this anymore.
42  bytes_used += copy_bytes;
43  break;
44  }
45 
46  // Otherwise we don't know the length yet.
47  while (wire_size < 2 && bytes_left) {
48  wire_data_.push_back(*bufptr);
49  ++bufptr;
50  --bytes_left;
51  ++bytes_used;
52  ++wire_size;
53  }
54 
55  // If we have enough to do it, calculate the expected length.
56  if (wire_size == 2 ) {
57  const uint8_t* cp = static_cast<const uint8_t*>(wire_data_.data());
58  uint16_t len = static_cast<unsigned int>(cp[0]) << 8;
59  len |= static_cast<unsigned int>(cp[1]);
60  expected_size_ = len + sizeof(len);
61  }
62  }
63 
64  // Return how much we used.
65  return (bytes_used);
66 }
67 
68 std::string
69 TcpStreamRequest::logFormatRequest(const size_t limit) const {
70  std::stringstream output;
71  try {
72  size_t max = (limit && (limit < wire_data_.size()) ? limit : wire_data_.size());
73  output << "expected_size_: " << expected_size_ << ", current size: " << wire_data_.size()
74  << ", data: "
75  << isc::util::str::dumpAsHex(wire_data_.data(), max);
76  } catch (const std::exception& ex) {
77  std::stringstream output;
78  output << "logFormatRequest error: " << ex.what();
79  }
80 
81  return (output.str());
82 }
83 
85  if (needData()) {
86  isc_throw(InvalidOperation, "Cannot unpack an incomplete request");
87  }
88 
89  if (wire_data_.size() < sizeof(uint16_t)) {
90  isc_throw(Unexpected, "Request is malformed, too short");
91  }
92 
93  request_ = std::vector<uint8_t>(wire_data_.begin() + sizeof(uint16_t), wire_data_.end());
94 }
95 
96 void
97 TcpStreamResponse::setResponseData(const uint8_t* data, size_t length) {
98  response_.assign(data, data + length);
99 }
100 
101 void
102 TcpStreamResponse::appendResponseData(const uint8_t* data, size_t length) {
103  response_.insert(response_.end(), data, data + length);
104 }
105 
106 void
107 TcpStreamResponse::setResponseData(const std::string& str) {
108  response_.assign(str.begin(), str.end());
109 }
110 
111 void
112 TcpStreamResponse::appendResponseData(const std::string& str) {
113  response_.insert(response_.end(), str.begin(), str.end());
114 }
115 
116 void
118  wire_data_.clear();
119  // Prepend the length of the request.
120  uint16_t size = static_cast<uint16_t>(response_.size());
121  wire_data_.push_back(static_cast<uint8_t>((size & 0xff00U) >> 8));
122  wire_data_.push_back(static_cast<uint8_t>(size & 0x00ffU));
123  wire_data_.insert(wire_data_.end(), response_.begin(), response_.end());
124 }
125 
126 } // end of namespace isc::tcp
127 } // end of namespace isc
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when an unexpected error condition occurs.
WireData wire_data_
Buffer used for data in wire format data.
virtual std::string logFormatRequest(const size_t limit=0) const
Returns request contents formatted for log output.
virtual void unpack()
Unpacks the wire data into a string request.
virtual size_t postBuffer(const void *buf, const size_t nbytes)
Adds data to an incomplete request.
virtual bool needData() const
Returns true if the request is incomplete.
std::vector< uint8_t > request_
Unpacked request content.
virtual void appendResponseData(const uint8_t *data, size_t length)
Appends a data to the response content.
virtual void setResponseData(const uint8_t *data, size_t length)
Replaces the response content .
virtual void pack()
Packs the response content into wire data buffer.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::string dumpAsHex(const uint8_t *data, size_t length)
Dumps a buffer of bytes as a string of hexadecimal digits.
Definition: strutil.cc:451
Defines the logger used by the top-level component of kea-lfc.