CIRCT 24.0.0git
Loading...
Searching...
No Matches
RpcWire.h
Go to the documentation of this file.
1//===- RpcWire.h - Shared cosim wire-format helpers -------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Small inline helpers for encoding/decoding the cosim binary data-frame
10// layout (`[u64 LE channel_id][payload]`). Used by both RpcServer.cpp and
11// RpcClient.cpp so the two ends can't drift apart on wire format. Header is
12// private to the CosimRpc library; not installed.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef ESI_BACKENDS_RPC_WIRE_H
17#define ESI_BACKENDS_RPC_WIRE_H
18
19#include <cstddef>
20#include <cstdint>
21#include <exception>
22#include <mutex>
23#include <string>
24
25namespace esi {
26namespace cosim {
27
28/// Wire protocol version. Both ends must agree exactly; see `hello` in
29/// cosim-protocol.md.
30inline constexpr uint64_t kProtocolVersion = 4;
31
32/// Pack a cosim binary data frame: `[u64 LE channel_id][payload]`.
33inline std::string buildDataFrame(uint64_t channelId, const uint8_t *bytes,
34 size_t size) {
35 std::string frame;
36 frame.reserve(8 + size);
37 uint8_t hdr[8];
38 for (int i = 0; i < 8; ++i)
39 hdr[i] = static_cast<uint8_t>((channelId >> (8 * i)) & 0xFF);
40 frame.append(reinterpret_cast<const char *>(hdr), 8);
41 frame.append(reinterpret_cast<const char *>(bytes), size);
42 return frame;
43}
44
45/// Size of the binary data-frame header (LE channel_id).
46inline constexpr size_t kDataFrameHeaderSize = 8;
47
48/// Parse a cosim binary data frame. On success returns true and sets
49/// `channelId` to the decoded id; `payload` / `payloadSize` point into
50/// `data` past the header. Returns false if `data` is too short to contain
51/// the header.
52inline bool parseDataFrame(const std::string &data, uint64_t &channelId,
53 const uint8_t *&payload, size_t &payloadSize) {
54 if (data.size() < kDataFrameHeaderSize)
55 return false;
56 uint64_t id = 0;
57 for (int i = 0; i < 8; ++i)
58 id |= static_cast<uint64_t>(static_cast<uint8_t>(data[i])) << (8 * i);
59 channelId = id;
60 payload =
61 reinterpret_cast<const uint8_t *>(data.data()) + kDataFrameHeaderSize;
62 payloadSize = data.size() - kDataFrameHeaderSize;
63 return true;
64}
65
66/// Cross-thread error channel for the IXWebSocket network thread.
67///
68/// IXWebSocket invokes user callbacks from its internal network thread; any
69/// exception escaping that callback kills the process. Call sites catch and
70/// `record()` the first fault; the next public method on the owning
71/// RpcServer/RpcClient calls `check()`, which consumes the stash and rethrows
72/// on the user's thread.
74public:
75 /// Stash the first exception we see (subsequent ones are dropped -- the
76 /// first is the most informative). Safe to call from any thread.
77 void record(std::exception_ptr ep) noexcept {
78 std::lock_guard<std::mutex> lock(mutex);
79 if (!fault)
80 fault = ep;
81 }
82
83 /// Consume and rethrow the stored fault on the caller's thread, if any.
84 void check() {
85 std::exception_ptr ep;
86 {
87 std::lock_guard<std::mutex> lock(mutex);
88 // `std::exception_ptr` has no member `swap()`; use the free function.
89 std::swap(ep, fault);
90 }
91 if (ep)
92 std::rethrow_exception(ep);
93 }
94
95private:
96 std::mutex mutex;
97 std::exception_ptr fault;
98};
99
100} // namespace cosim
101} // namespace esi
102
103#endif // ESI_BACKENDS_RPC_WIRE_H
Cross-thread error channel for the IXWebSocket network thread.
Definition RpcWire.h:73
std::exception_ptr fault
Definition RpcWire.h:97
void record(std::exception_ptr ep) noexcept
Stash the first exception we see (subsequent ones are dropped – the first is the most informative).
Definition RpcWire.h:77
void check()
Consume and rethrow the stored fault on the caller's thread, if any.
Definition RpcWire.h:84
std::string buildDataFrame(uint64_t channelId, const uint8_t *bytes, size_t size)
Pack a cosim binary data frame: [u64 LE channel_id][payload].
Definition RpcWire.h:33
constexpr uint64_t kProtocolVersion
Wire protocol version.
Definition RpcWire.h:30
bool parseDataFrame(const std::string &data, uint64_t &channelId, const uint8_t *&payload, size_t &payloadSize)
Parse a cosim binary data frame.
Definition RpcWire.h:52
constexpr size_t kDataFrameHeaderSize
Size of the binary data-frame header (LE channel_id).
Definition RpcWire.h:46
Definition esi.py:1