JSON-RPC 2.0
JSON-RPC 2.0 Modern C++ Library
Loading...
Searching...
No Matches
message_framer.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <sstream>
4#include <string>
5
6namespace jsonrpc::transport {
7
9 public:
11 bool complete{false};
12 std::string message;
13 std::size_t consumed_bytes{0};
14 std::string error;
15 };
16
17 static auto Frame(
18 const std::string& message,
19 const std::string& content_type =
20 "application/vscode-jsonrpc; charset=utf-8") -> std::string {
21 std::ostringstream out;
22 out << "Content-Length: " << message.size() << "\r\n"
23 << "Content-Type: " << content_type << "\r\n"
24 << "\r\n"
25 << message;
26 return out.str();
27 }
28
29 auto TryDeframe(const std::string& buffer) -> DeframeResult {
30 if (!header_complete_) {
31 auto header_end = buffer.find("\r\n\r\n");
32 if (header_end == std::string::npos) {
33 return {
34 .complete = false,
35 .message = "",
36 .consumed_bytes = 0,
37 .error = ""}; // Need more data
38 }
39
40 // Parse headers
41 std::istringstream header_stream(buffer.substr(0, header_end));
42 std::string header_line;
43 bool found_length = false;
44 while (std::getline(header_stream, header_line) && !header_line.empty()) {
45 if (header_line.starts_with("Content-Length:")) {
46 try {
47 expected_length_ = std::stoi(header_line.substr(15));
48 found_length = true;
49 } catch (const std::exception&) {
50 return {
51 .complete = false,
52 .message = "",
53 .consumed_bytes = 0,
54 .error = "Invalid Content-Length header"};
55 }
56 }
57 }
58
59 if (!found_length) {
60 return {
61 .complete = false,
62 .message = "",
63 .consumed_bytes = 0,
64 .error = "Missing Content-Length header"};
65 }
66
67 header_complete_ = true;
68 header_size_ = header_end + 4; // Include \r\n\r\n
69 }
70
71 // Check if we have enough data for the content
72 if (buffer.size() < header_size_ + expected_length_) {
73 return {
74 .complete = false,
75 .message = "",
76 .consumed_bytes = 0,
77 .error = ""}; // Need more data
78 }
79
80 // Extract message
81 std::string message = buffer.substr(header_size_, expected_length_);
82 std::size_t total_consumed = header_size_ + expected_length_;
83
84 // Reset state for next message
85 header_complete_ = false;
86 expected_length_ = 0;
87 header_size_ = 0;
88
89 return {
90 .complete = true,
91 .message = message,
92 .consumed_bytes = total_consumed,
93 .error = ""};
94 }
95
96 private:
97 bool header_complete_{false};
98 std::size_t expected_length_{0};
99 std::size_t header_size_{0};
100};
101
102} // namespace jsonrpc::transport
static auto Frame(const std::string &message, const std::string &content_type="application/vscode-jsonrpc; charset=utf-8") -> std::string
auto TryDeframe(const std::string &buffer) -> DeframeResult