Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
message_validator.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
32#pragma once
33
34#include <cstdint>
35#include <cstddef>
36#include <cstring>
37#include <string>
38#include <string_view>
39#include <stdexcept>
40#include <algorithm>
41
42namespace kcenon::network {
43
52 static constexpr size_t MAX_MESSAGE_SIZE = 16 * 1024 * 1024;
53
55 static constexpr size_t MAX_HEADER_SIZE = 8192;
56
58 static constexpr size_t MAX_WEBSOCKET_FRAME = 1 * 1024 * 1024;
59
61 static constexpr size_t MAX_HTTP_LINE = 8192;
62
64 static constexpr size_t MAX_HEADER_COUNT = 100;
65
67 static constexpr size_t MAX_URL_LENGTH = 2048;
68
70 static constexpr size_t MAX_COOKIE_SIZE = 4096;
71};
72
84
88inline const char* to_string(validation_result result) {
89 switch (result) {
91 return "ok";
93 return "size_exceeded";
95 return "null_byte_detected";
97 return "invalid_format";
99 return "invalid_character";
101 return "header_count_exceeded";
102 default:
103 return "unknown";
104 }
105}
106
122public:
130 [[nodiscard]] static bool validate_size(
131 size_t size,
132 size_t max_size = message_limits::MAX_MESSAGE_SIZE) noexcept {
133 return size <= max_size;
134 }
135
144 size_t size,
145 size_t max_size = message_limits::MAX_MESSAGE_SIZE) {
146 if (size > max_size) {
147 throw std::length_error(
148 "Message size " + std::to_string(size) +
149 " exceeds limit " + std::to_string(max_size));
150 }
151 }
152
165 [[nodiscard]] static size_t safe_copy(
166 void* dest,
167 size_t dest_size,
168 const void* src,
169 size_t src_size) noexcept {
170 if (!dest || !src || dest_size == 0 || src_size == 0) {
171 return 0;
172 }
173
174 size_t copy_size = std::min(dest_size, src_size);
175 std::memcpy(dest, src, copy_size);
176 return copy_size;
177 }
178
187 [[nodiscard]] static size_t safe_strcpy(
188 char* dest,
189 size_t dest_size,
190 const char* src) noexcept {
191 if (!dest || dest_size == 0 || !src) {
192 return 0;
193 }
194
195 size_t src_len = std::strlen(src);
196 size_t copy_len = std::min(dest_size - 1, src_len);
197
198 std::memcpy(dest, src, copy_len);
199 dest[copy_len] = '\0';
200
201 return copy_len;
202 }
203
216 std::string_view header) noexcept {
217 // Check size
218 if (header.size() > message_limits::MAX_HEADER_SIZE) {
220 }
221
222 // Check for NULL bytes (NULL byte injection attack)
223 if (header.find('\0') != std::string_view::npos) {
225 }
226
227 // Check for invalid control characters (except \r\n\t)
228 for (char c : header) {
229 if (c < 0x20 && c != '\r' && c != '\n' && c != '\t') {
231 }
232 }
233
235 }
236
243 [[nodiscard]] static bool validate_header_count(size_t count) noexcept {
244 return count <= message_limits::MAX_HEADER_COUNT;
245 }
246
254 [[nodiscard]] static bool validate_websocket_frame(
255 size_t payload_length,
256 size_t max_size = message_limits::MAX_WEBSOCKET_FRAME) noexcept {
257 return payload_length <= max_size;
258 }
259
266 [[nodiscard]] static validation_result validate_url(
267 std::string_view url) noexcept {
268 if (url.size() > message_limits::MAX_URL_LENGTH) {
270 }
271
272 if (url.find('\0') != std::string_view::npos) {
274 }
275
277 }
278
288 [[nodiscard]] static bool contains_suspicious_pattern(
289 std::string_view data) noexcept {
290 // Check for NULL byte injection
291 if (data.find('\0') != std::string_view::npos) {
292 return true;
293 }
294
295 // Check for HTTP response splitting
296 if (data.find("\r\n\r\n") != std::string_view::npos) {
297 return true;
298 }
299
300 return false;
301 }
302
309 [[nodiscard]] static std::string sanitize_string(std::string_view input) {
310 std::string result;
311 result.reserve(input.size());
312
313 for (char c : input) {
314 // Keep printable ASCII and common whitespace
315 if (c >= 0x20 || c == '\t' || c == '\n' || c == '\r') {
316 result += c;
317 }
318 }
319
320 return result;
321 }
322
332 [[nodiscard]] static size_t safe_buffer_size(
333 size_t requested_size,
334 size_t max_size = message_limits::MAX_MESSAGE_SIZE) noexcept {
335 return std::min(requested_size, max_size);
336 }
337};
338
339} // namespace kcenon::network
Message validator for network input validation.
static validation_result validate_http_header(std::string_view header) noexcept
Validate HTTP header.
static size_t safe_strcpy(char *dest, size_t dest_size, const char *src) noexcept
Safe string copy with null termination.
static bool contains_suspicious_pattern(std::string_view data) noexcept
Check if data contains potential injection patterns.
static bool validate_header_count(size_t count) noexcept
Validate HTTP header count.
static size_t safe_copy(void *dest, size_t dest_size, const void *src, size_t src_size) noexcept
Safe buffer copy with size validation.
static void validate_size_or_throw(size_t size, size_t max_size=message_limits::MAX_MESSAGE_SIZE)
Validate and throw if size exceeds limit.
static std::string sanitize_string(std::string_view input)
Sanitize string by removing control characters.
static bool validate_websocket_frame(size_t payload_length, size_t max_size=message_limits::MAX_WEBSOCKET_FRAME) noexcept
Validate WebSocket frame payload size.
static bool validate_size(size_t size, size_t max_size=message_limits::MAX_MESSAGE_SIZE) noexcept
Validate message size against limit.
static validation_result validate_url(std::string_view url) noexcept
Validate URL length.
static size_t safe_buffer_size(size_t requested_size, size_t max_size=message_limits::MAX_MESSAGE_SIZE) noexcept
Calculate safe buffer size for operations.
Main namespace for all Network System components.
const char * to_string(validation_result result)
Convert validation result to string.
validation_result
Result type for validation operations.
@ size_exceeded
Size limit exceeded.
@ null_byte_detected
NULL byte found in string.
@ invalid_format
Invalid data format.
@ header_count_exceeded
Too many headers.
@ invalid_character
Invalid character detected.
VoidResult ok()
Configurable message size limits.
static constexpr size_t MAX_HEADER_SIZE
Maximum HTTP header size (default: 8KB - Apache default)
static constexpr size_t MAX_URL_LENGTH
Maximum URL length (default: 2KB)
static constexpr size_t MAX_HEADER_COUNT
Maximum number of HTTP headers (default: 100)
static constexpr size_t MAX_HTTP_LINE
Maximum HTTP request line length (default: 8KB)
static constexpr size_t MAX_WEBSOCKET_FRAME
Maximum WebSocket frame payload (default: 1MB)
static constexpr size_t MAX_MESSAGE_SIZE
Maximum allowed message size (default: 16MB)
static constexpr size_t MAX_COOKIE_SIZE
Maximum cookie size (default: 4KB)