Skip to content

Commit 29f4e1a

Browse files
committed
TCP input TLS - Optimize TlsDecoder.
This also brings new api for `DecodeBuffer` and simplification of IpfixDecoder.
1 parent 7cd0577 commit 29f4e1a

File tree

11 files changed

+179
-253
lines changed

11 files changed

+179
-253
lines changed

src/plugins/input/tcp/src/DecodeBuffer.cpp

Lines changed: 13 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -17,60 +17,38 @@
1717

1818
#include <ipfixcol2.h> // fds_ipfix_msg_hdr
1919

20+
#include "read_until_n.hpp"
21+
2022
namespace tcp_in {
2123

22-
void DecodeBuffer::read_from(const uint8_t *data, size_t size) {
23-
// read until there is something to read
24-
while (size) {
25-
// get the message size
26-
if (!read_header(&data, &size)) {
27-
// There is not enough data to read the whole header.
24+
void DecodeBuffer::read_from(Reader &reader, std::size_t consume) {
25+
consume += m_total_bytes_decoded;
26+
while (!enough_data() || consume < m_total_bytes_decoded) {
27+
if (!read_header(reader)) {
2828
break;
2929
}
3030

31-
// Read the body of the message.
32-
if (!read_body(&data, &size)) {
33-
// There is not enough data to read the whole body of the message.
31+
if (!read_body(reader)) {
3432
break;
3533
}
3634
}
3735
}
3836

39-
void DecodeBuffer::read_from(
40-
const uint8_t *data,
41-
size_t buffer_size,
42-
size_t data_size,
43-
size_t position
44-
) {
45-
// read until wrap
46-
auto block = data + position;
47-
auto block_size = std::min(data_size, buffer_size - position);
48-
read_from(block, block_size);
49-
50-
if (block_size == data_size) {
51-
// there was no need to wrap
52-
return;
53-
}
54-
55-
// read the second block (after wrap)
56-
read_from(data, data_size - block_size);
57-
}
58-
5937
void DecodeBuffer::signal_eof() {
6038
if (m_part_decoded.size() != 0) {
6139
throw std::runtime_error("Received incomplete message.");
6240
}
6341
m_eof_reached = true;
6442
}
6543

66-
bool DecodeBuffer::read_header(const uint8_t **data, size_t *size) {
44+
bool DecodeBuffer::read_header(Reader &reader) {
6745
if (m_decoded_size != 0) {
6846
// The header is already read, but the message body is incomplete.
6947
return true;
7048
}
7149

7250
// Read the header.
73-
if (!read_until_n(sizeof(fds_ipfix_msg_hdr), data, size)) {
51+
if (!read_until_n(sizeof(fds_ipfix_msg_hdr), reader)) {
7452
// There is not enough data to read the whole header.
7553
return false;
7654
}
@@ -86,9 +64,9 @@ bool DecodeBuffer::read_header(const uint8_t **data, size_t *size) {
8664
return true;
8765
}
8866

89-
bool DecodeBuffer::read_body(const uint8_t **data, size_t *size) {
67+
bool DecodeBuffer::read_body(Reader &reader) {
9068
// Read the body
91-
if (!read_until_n(m_decoded_size, data, size)) {
69+
if (!read_until_n(m_decoded_size, reader)) {
9270
// There is not enough data to read the whole body.
9371
return false;
9472
}
@@ -99,22 +77,10 @@ bool DecodeBuffer::read_body(const uint8_t **data, size_t *size) {
9977
return true;
10078
}
10179

102-
bool DecodeBuffer::read_until_n(size_t n, const uint8_t **data, size_t *data_len) {
103-
m_part_decoded.reserve(n);
104-
auto cnt = read_min(*data, n, *data_len);
105-
*data_len -= cnt;
106-
*data += cnt;
80+
bool DecodeBuffer::read_until_n(size_t n, Reader &reader) {
81+
m_total_bytes_decoded += ::read_until_n(n, reader, m_part_decoded, *this);
10782
return m_part_decoded.size() == n;
10883
}
10984

110-
size_t DecodeBuffer::read_min(const uint8_t *data, size_t size1, size_t size2) {
111-
auto size = std::min(size1, size2);
112-
auto filled = m_part_decoded.size();
113-
m_part_decoded.resize(filled + size);
114-
std::copy_n(data, size, m_part_decoded.data() + filled);
115-
m_total_bytes_decoded += size;
116-
return size;
117-
}
118-
11985
} // namespace tcp_in
12086

src/plugins/input/tcp/src/DecodeBuffer.hpp

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010

1111
#pragma once
1212

13-
#include <vector> // std::vector
1413
#include <cstdint> // uint8_t, UINT16_MAX
1514
#include <cstddef> // size_t
15+
#include <vector> // std::vector
1616

1717
#include "ByteVector.hpp" // ByteVector
18+
#include "Reader.hpp"
1819

1920
namespace tcp_in {
2021

@@ -50,28 +51,11 @@ class DecodeBuffer {
5051
}
5152

5253
/**
53-
* @brief Copies IPFIX data from buffer.
54-
*
55-
* The data may be any part of message (possibly incomplete or even multiple messages) but
56-
* multiple calls to this method must be with the message data in correct order so that it can
57-
* be reconstructed.
58-
* @param data data with the message
59-
* @param size size of the data in `data`
54+
* @brief Read data using generic reader function.
55+
* @param reader Generic reader function.
56+
* @param consume Minimum number of bytes that should be read from reader if possible.
6057
*/
61-
void read_from(const uint8_t *data, size_t size);
62-
63-
/**
64-
* @brief Copies IPFIX data from circular buffer.
65-
*
66-
* The data may be any part of message (possibly incomplete or even multiple messages) but
67-
* multiple calls to this metod must be with the message data in correct order so that it can be
68-
* reconstructed.
69-
* @param data data of the circullar buffer
70-
* @param buffer_size size of the circullar buffer (allocated space)
71-
* @param data_size size of data to copy from the buffer
72-
* @param position start position of the data in the buffer.
73-
*/
74-
void read_from(const uint8_t *data, size_t buffer_size, size_t data_size, size_t position);
58+
void read_from(Reader &reader, std::size_t consume = 0);
7559

7660
/**
7761
* @brief Checks whether enough data has been read since last time. When this returns true,
@@ -104,32 +88,23 @@ class DecodeBuffer {
10488
private:
10589
/**
10690
* @brief Reads the length from ipfix header to `m_decoded_size`.
107-
* @param[in,out] data Pointer to data. It is modified by the amount of read data.
108-
* @param[in,out] size Size of the data. It is modified by the amount of read data.
91+
* @param reader Reader from which to read.
10992
* @return `true` if the whole header could be read.
11093
*/
111-
bool read_header(const uint8_t **data, size_t *size);
94+
bool read_header(Reader &reader);
11295
/**
11396
* @brief Reads the body of ipfix message.
114-
* @param data Pointer to data. It is modified by the amount of read data.
115-
* @param size Size of the data. It is modified by the amount of read data.
97+
* @param reader Reader from which to read.
11698
* @return `true` if the whole header could be read.
11799
*/
118-
bool read_body(const uint8_t **data, size_t *size);
100+
bool read_body(Reader &reader);
119101
/**
120102
* @brief Reads to `m_part_decoded` until it reaches length of `n`.
121103
* @param n Target length for `m_part_decoded`.
122-
* @param[in,out] data Data to read from. It is modified by the read amount.
123-
* @param[in,out] data_len Length of data to read. It is modified by the read amount.
104+
* @param reader Generic reader from which to read.
124105
* @return `true` if `m_part_decoded` has reached length of `n`.
125106
*/
126-
bool read_until_n(size_t n, const uint8_t **data, size_t *data_len);
127-
/**
128-
* @brief Adds N elements from `src` to `m_part_decoded` where N is the smaller of the two
129-
* sizes.
130-
* @return The smaller of the two sizes.
131-
*/
132-
size_t read_min(const uint8_t *data, size_t size1, size_t size2);
107+
bool read_until_n(size_t n, Reader &reader);
133108

134109
/** number of bytes readed since last call to `get_decoded` */
135110
size_t m_total_bytes_decoded;

src/plugins/input/tcp/src/IpfixDecoder.cpp

Lines changed: 3 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,77 +10,16 @@
1010

1111
#include "IpfixDecoder.hpp"
1212

13-
#include <stdexcept> // runtime_error
14-
#include <string> // string
15-
#include <errno.h> // errno, EWOULDBLOCK, EAGAIN
16-
#include <stddef.h> // size_t
17-
18-
#include <unistd.h> // read
19-
20-
#include <ipfixcol2.h> // fds_ipfix_msg_hdr, ipx_strerror
21-
2213
#include "DecodeBuffer.hpp" // DecodeBuffer
23-
#include "read_until_n.hpp" // read_until_n
14+
#include "Reader.hpp"
2415

2516
namespace tcp_in {
2617

2718
DecodeBuffer &IpfixDecoder::decode() {
28-
while (!m_decoded.enough_data()) {
29-
// Read the header of the message.
30-
if (!read_header()) {
31-
// There is not enough data to read the whole header.
32-
break;
33-
}
34-
35-
// Read the body of the message.
36-
if (!read_body()) {
37-
// There is not enough data to read the whole body of the message.
38-
break;
39-
}
40-
}
41-
42-
if (m_decoded.is_eof_reached() && m_part_readed.size() != 0) {
43-
throw std::runtime_error("Received incomplete message.");
44-
}
45-
19+
auto reader = tcp_reader(m_fd);
20+
m_decoded.read_from(reader);
4621
return m_decoded;
4722
}
4823

49-
bool IpfixDecoder::read_header() {
50-
if (m_msg_size != 0) {
51-
// The header is already read, but the message body is incomplete.
52-
return true;
53-
}
54-
55-
// Read the header
56-
if (!read_until_n(sizeof(fds_ipfix_msg_hdr))) {
57-
// There is not enough data to read the whole header.
58-
return false;
59-
}
60-
61-
// The header has been read, load the size of the message.
62-
auto hdr = reinterpret_cast<fds_ipfix_msg_hdr *>(m_part_readed.data());
63-
m_msg_size = ntohs(hdr->length);
64-
return true;
65-
}
66-
67-
bool IpfixDecoder::read_body() {
68-
// Read the body.
69-
if (!read_until_n(m_msg_size)) {
70-
// There is not enough data to read the whole body
71-
return false;
72-
}
73-
74-
// Whole message has been read. Add it to the decode buffer.
75-
m_decoded.add(std::move(m_part_readed));
76-
m_part_readed = ByteVector();
77-
m_msg_size = 0;
78-
return true;
79-
}
80-
81-
bool IpfixDecoder::read_until_n(size_t n) {
82-
return ::read_until_n(n, m_fd, m_part_readed, m_decoded);
83-
}
84-
8524
} // namespace tcp_in
8625

src/plugins/input/tcp/src/IpfixDecoder.hpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
#include "Decoder.hpp" // Decoder
1717
#include "DecodeBuffer.hpp" // DecodeBuffer
18-
#include "ByteVector.hpp" // ByteVector
1918

2019
namespace tcp_in {
2120

@@ -29,7 +28,7 @@ class IpfixDecoder : public Decoder {
2928
* @brief Creates ipfix decoder.
3029
* @param fd TCP connection file descriptor.
3130
*/
32-
IpfixDecoder(int fd) : m_fd(fd), m_decoded(), m_part_readed(), m_msg_size(0) {}
31+
IpfixDecoder(int fd) : m_fd(fd), m_decoded() {}
3332

3433
virtual DecodeBuffer &decode() override;
3534

@@ -38,19 +37,8 @@ class IpfixDecoder : public Decoder {
3837
}
3938

4039
private:
41-
/** returns true if there was enough data to read the header or if the header is already read */
42-
bool read_header();
43-
/** returns true if there was enough data to read the body */
44-
bool read_body();
45-
/** returns true if there was enough data to read to the given amount */
46-
bool read_until_n(size_t n);
47-
4840
int m_fd;
4941
DecodeBuffer m_decoded;
50-
51-
ByteVector m_part_readed;
52-
/** Final size of the whole IPFIX message. When 0 IPIFX header is not fully read. */
53-
size_t m_msg_size;
5442
};
5543

5644
} // namespace tcp_in

0 commit comments

Comments
 (0)