Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
frame.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
6
7#include <charconv>
8#include <cstring>
9#include <sstream>
10
12{
13
14auto grpc_message::parse(std::span<const uint8_t> input) -> Result<grpc_message>
15{
16 // Check minimum header size
17 if (input.size() < grpc_header_size)
18 {
21 "Input too small for gRPC message header",
22 "grpc::frame",
23 "Expected at least 5 bytes, got " + std::to_string(input.size()));
24 }
25
26 // Parse compressed flag (1 byte)
27 bool compressed = (input[0] != 0);
28
29 // Parse message length (4 bytes, big-endian)
30 uint32_t length = (static_cast<uint32_t>(input[1]) << 24) |
31 (static_cast<uint32_t>(input[2]) << 16) |
32 (static_cast<uint32_t>(input[3]) << 8) |
33 (static_cast<uint32_t>(input[4]));
34
35 // Validate message length
36 if (length > default_max_message_size)
37 {
40 "gRPC message exceeds maximum size",
41 "grpc::frame",
42 "Max: " + std::to_string(default_max_message_size) +
43 ", Got: " + std::to_string(length));
44 }
45
46 // Check if we have enough data
47 size_t total_size = grpc_header_size + length;
48 if (input.size() < total_size)
49 {
52 "Input too small for gRPC message payload",
53 "grpc::frame",
54 "Expected " + std::to_string(total_size) +
55 " bytes, got " + std::to_string(input.size()));
56 }
57
58 // Extract message data
59 grpc_message msg;
60 msg.compressed = compressed;
61 msg.data.assign(input.begin() + grpc_header_size,
62 input.begin() + grpc_header_size + length);
63
64 return ok(std::move(msg));
65}
66
67auto grpc_message::serialize() const -> std::vector<uint8_t>
68{
69 std::vector<uint8_t> result;
70 result.reserve(grpc_header_size + data.size());
71
72 // Compressed flag (1 byte)
73 result.push_back(compressed ? 1 : 0);
74
75 // Message length (4 bytes, big-endian)
76 uint32_t length = static_cast<uint32_t>(data.size());
77 result.push_back(static_cast<uint8_t>((length >> 24) & 0xFF));
78 result.push_back(static_cast<uint8_t>((length >> 16) & 0xFF));
79 result.push_back(static_cast<uint8_t>((length >> 8) & 0xFF));
80 result.push_back(static_cast<uint8_t>(length & 0xFF));
81
82 // Message data
83 result.insert(result.end(), data.begin(), data.end());
84
85 return result;
86}
87
88auto parse_timeout(std::string_view timeout_str) -> uint64_t
89{
90 if (timeout_str.empty())
91 {
92 return 0;
93 }
94
95 // Get the unit suffix
96 char unit = timeout_str.back();
97
98 // Parse the numeric value
99 std::string_view num_str = timeout_str.substr(0, timeout_str.size() - 1);
100 uint64_t value = 0;
101
102 auto result = std::from_chars(num_str.data(),
103 num_str.data() + num_str.size(),
104 value);
105
106 if (result.ec != std::errc{})
107 {
108 return 0;
109 }
110
111 // Convert to milliseconds based on unit
112 switch (unit)
113 {
114 case 'H': // Hours
115 return value * 3600000;
116 case 'M': // Minutes
117 return value * 60000;
118 case 'S': // Seconds
119 return value * 1000;
120 case 'm': // Milliseconds
121 return value;
122 case 'u': // Microseconds
123 return value / 1000;
124 case 'n': // Nanoseconds
125 return value / 1000000;
126 default:
127 return 0;
128 }
129}
130
131auto format_timeout(uint64_t timeout_ms) -> std::string
132{
133 std::ostringstream oss;
134
135 if (timeout_ms == 0)
136 {
137 return "0m";
138 }
139
140 // Use appropriate unit for best precision
141 if (timeout_ms >= 3600000 && timeout_ms % 3600000 == 0)
142 {
143 oss << (timeout_ms / 3600000) << "H";
144 }
145 else if (timeout_ms >= 60000 && timeout_ms % 60000 == 0)
146 {
147 oss << (timeout_ms / 60000) << "M";
148 }
149 else if (timeout_ms >= 1000 && timeout_ms % 1000 == 0)
150 {
151 oss << (timeout_ms / 1000) << "S";
152 }
153 else
154 {
155 oss << timeout_ms << "m";
156 }
157
158 return oss.str();
159}
160
161} // namespace kcenon::network::protocols::grpc
gRPC message framing and serialization.
gRPC protocol implementation
Definition client.h:34
constexpr size_t grpc_header_size
gRPC message header size (5 bytes)
Definition frame.h:35
constexpr size_t default_max_message_size
Maximum gRPC message size (default 4MB)
Definition frame.h:40
auto format_timeout(uint64_t timeout_ms) -> std::string
Format timeout as gRPC timeout string.
Definition frame.cpp:131
auto parse_timeout(std::string_view timeout_str) -> uint64_t
Parse timeout string (e.g., "10S", "100m", "1000u")
Definition frame.cpp:88
@ ok
Not an error; returned on success.
gRPC message with compression flag and payload
Definition frame.h:50
static auto parse(std::span< const uint8_t > input) -> Result< grpc_message >
Parse gRPC message from raw bytes.
Definition frame.cpp:14
auto serialize() const -> std::vector< uint8_t >
Serialize message to bytes with length prefix.
Definition frame.cpp:67
std::vector< uint8_t > data
Message payload.
Definition frame.h:52
bool compressed
Whether payload is compressed.
Definition frame.h:51