Branch data Line data Source code
1 : : // Copyright 2026 HPActor Contributors
2 : : #include <hpactor/net/frame.hpp>
3 : :
4 : : #include <hpactor/common.pb.h>
5 : : #include <hpactor/frame.pb.h>
6 : :
7 : : namespace hpactor {
8 : : namespace net {
9 : :
10 : : // Helper: convert HPActor Ipv4Endpoint to protobuf PbIpv4Endpoint
11 : : static void
12 : 6 : to_proto(::hpactor::PbIpv4Endpoint* pb_ep, const ::hpactor::Ipv4Endpoint& ep) {
13 : 6 : pb_ep->set_addr(ep.addr); // Network byte order
14 : 6 : pb_ep->set_port(ep.port_nw);
15 : 6 : }
16 : :
17 : : // Helper: convert HPActor Ipv6Endpoint to protobuf PbIpv6Endpoint
18 : : static void
19 : 2 : to_proto(::hpactor::PbIpv6Endpoint* pb_ep, const ::hpactor::Ipv6Endpoint& ep) {
20 : 4 : pb_ep->set_addr(ep.addr.data(), ep.addr.size());
21 : 2 : pb_ep->set_port(ep.port_nw);
22 : 2 : }
23 : :
24 : : // Helper: convert HPActor EndPoint to protobuf PbEndpoint
25 : : static void
26 : 8 : to_proto(::hpactor::PbEndpoint* pb_endpoint, const ::hpactor::EndPoint& ep) {
27 : 8 : if (const auto* ipv4 = std::get_if<::hpactor::Ipv4Endpoint>(&ep)) {
28 : 6 : to_proto(pb_endpoint->mutable_ipv4(), *ipv4);
29 : 2 : } else if (const auto* ipv6 = std::get_if<::hpactor::Ipv6Endpoint>(&ep)) {
30 : 2 : to_proto(pb_endpoint->mutable_ipv6(), *ipv6);
31 : : }
32 : 8 : }
33 : :
34 : : // Helper: fill PbLocalActorAddress from C++ ActorAddress fields
35 : : static void
36 : 36 : fill_local_addr(::hpactor::PbLocalActorAddress* local, const ActorAddress& addr) {
37 : 36 : local->set_actor_type(addr.type);
38 : 36 : local->set_actor_id(addr.id.value());
39 : 36 : local->set_incarnation(addr.incarnation);
40 : 36 : }
41 : :
42 : : // Helper: fill PbGlobalActorAddress from C++ ActorAddress fields
43 : 8 : static void fill_global_addr(::hpactor::PbGlobalActorAddress* global,
44 : : const ActorAddress& addr) {
45 : 8 : to_proto(global->mutable_endpoint(), addr.endpoint);
46 : 8 : fill_local_addr(global->mutable_local_addr(), addr);
47 : 8 : }
48 : :
49 : : // Returns true if the endpoint is the default localhost:0 (no real endpoint).
50 : 36 : static bool is_default_local_endpoint(const EndPoint& ep) {
51 : 36 : if (const auto* ipv4 = std::get_if<Ipv4Endpoint>(&ep)) {
52 : 34 : return ipv4->is_loopback() && ipv4->port() == 0;
53 : : }
54 : 2 : if (const auto* ipv6 = std::get_if<Ipv6Endpoint>(&ep)) {
55 : 2 : return ipv6->is_loopback() && ipv6->port() == 0;
56 : : }
57 : 0 : return false;
58 : : }
59 : :
60 : : // Helper: convert C++ ActorAddress to protobuf PbActorAddress
61 : : // Uses local_addr only for the default localhost:0 endpoint;
62 : : // all other addresses (including IPv6 loopback) use global_addr
63 : : // to preserve full endpoint information.
64 : 36 : void to_proto(::hpactor::PbActorAddress* pb_addr, const ActorAddress& addr) {
65 : 36 : if (is_default_local_endpoint(addr.endpoint) || !addr) {
66 : 28 : fill_local_addr(pb_addr->mutable_local_addr(), addr);
67 : : } else {
68 : 8 : fill_global_addr(pb_addr->mutable_global_addr(), addr);
69 : : }
70 : 36 : }
71 : :
72 : : // Helper: convert C++ ActorAddress to protobuf PbActorRef (same structure)
73 : 0 : void to_proto(::hpactor::PbActorRef* pb_ref, const ActorAddress& addr) {
74 : 0 : if (is_default_local_endpoint(addr.endpoint) || !addr) {
75 : 0 : fill_local_addr(pb_ref->mutable_local_addr(), addr);
76 : : } else {
77 : 0 : fill_global_addr(pb_ref->mutable_global_addr(), addr);
78 : : }
79 : 0 : }
80 : :
81 : : // Helper: convert protobuf PbIpv4Endpoint to HPActor Ipv4Endpoint
82 : 6 : static ::hpactor::Ipv4Endpoint from_proto(const ::hpactor::PbIpv4Endpoint& pb_ep) {
83 : 12 : return ::hpactor::Ipv4Endpoint{pb_ep.addr(),
84 : 12 : static_cast<uint16_t>(pb_ep.port())};
85 : : }
86 : :
87 : : // Helper: convert protobuf PbIpv6Endpoint to HPActor Ipv6Endpoint
88 : 1 : static ::hpactor::Ipv6Endpoint from_proto(const ::hpactor::PbIpv6Endpoint& pb_ep) {
89 : 1 : std::array<uint8_t, 16> addr{};
90 : 1 : std::memcpy(addr.data(), pb_ep.addr().data(), addr.size());
91 : 1 : return ::hpactor::Ipv6Endpoint{addr, static_cast<uint16_t>(pb_ep.port())};
92 : : }
93 : :
94 : : // Helper: convert protobuf PbEndpoint to HPActor EndPoint
95 : 7 : static ::hpactor::EndPoint from_proto(const ::hpactor::PbEndpoint& pb_endpoint) {
96 : 7 : if (pb_endpoint.has_ipv4()) {
97 : 6 : return from_proto(pb_endpoint.ipv4());
98 : : }
99 : 1 : if (pb_endpoint.has_ipv6()) {
100 : 1 : return from_proto(pb_endpoint.ipv6());
101 : : }
102 : 0 : return ::hpactor::Ipv4Endpoint{};
103 : : }
104 : :
105 : : // Helper: build ActorAddress from PbLocalActorAddress fields
106 : 0 : static ActorAddress from_local_addr(const ::hpactor::PbLocalActorAddress& local) {
107 : 0 : return ActorAddress{Ipv4Endpoint{0x7F000001, 0},
108 : 0 : static_cast<ActorType>(local.actor_type()),
109 : 0 : ActorId{local.actor_id()}, local.incarnation()};
110 : : }
111 : :
112 : : // Helper: build ActorAddress from PbGlobalActorAddress fields
113 : : static ActorAddress
114 : 7 : from_global_addr(const ::hpactor::PbGlobalActorAddress& global) {
115 : 7 : const auto& local = global.local_addr();
116 : 7 : return ActorAddress{from_proto(global.endpoint()),
117 : 7 : static_cast<ActorType>(local.actor_type()),
118 : 7 : ActorId{local.actor_id()}, local.incarnation()};
119 : : }
120 : :
121 : : // Helper: convert protobuf PbActorAddress to HPActor ActorAddress
122 : 7 : ActorAddress from_proto(const ::hpactor::PbActorAddress& pb_addr) {
123 : 7 : if (pb_addr.has_local_addr()) {
124 : 0 : return from_local_addr(pb_addr.local_addr());
125 : : }
126 : 7 : if (pb_addr.has_global_addr()) {
127 : 7 : return from_global_addr(pb_addr.global_addr());
128 : : }
129 : 0 : return ActorAddress{};
130 : : }
131 : :
132 : : // Helper: convert protobuf PbActorRef to HPActor ActorAddress
133 : 0 : ActorAddress from_proto(const ::hpactor::PbActorRef& pb_ref) {
134 : 0 : if (pb_ref.has_local_addr()) {
135 : 0 : return from_local_addr(pb_ref.local_addr());
136 : : }
137 : 0 : if (pb_ref.has_global_addr()) {
138 : 0 : return from_global_addr(pb_ref.global_addr());
139 : : }
140 : 0 : return ActorAddress{};
141 : : }
142 : :
143 : 1 : void to_proto(::hpactor::net::PbTraceContext* pb, const TraceContext& context) {
144 : 2 : pb->set_trace_id(reinterpret_cast<const char*>(context.trace_id.bytes.data()),
145 : : context.trace_id.bytes.size());
146 : 2 : pb->set_span_id(reinterpret_cast<const char*>(context.span_id.bytes.data()),
147 : : context.span_id.bytes.size());
148 : 1 : pb->set_flags(context.flags.value);
149 : 1 : if (context.tracestate_len > 0) {
150 : 0 : pb->set_tracestate(context.tracestate.data(), context.tracestate_len);
151 : : }
152 : 1 : }
153 : :
154 : : result<TraceContext>
155 : 1 : trace_context_from_proto(const ::hpactor::net::PbTraceContext& pb,
156 : : uint16_t max_tracestate_len) {
157 : 1 : TraceContext ctx;
158 : 2 : if (pb.trace_id().size() != ctx.trace_id.bytes.size()) {
159 : 0 : return result<TraceContext>::make(error(errors::invalid_argument));
160 : : }
161 : 2 : if (pb.span_id().size() != ctx.span_id.bytes.size()) {
162 : 0 : return result<TraceContext>::make(error(errors::invalid_argument));
163 : : }
164 : 2 : std::memcpy(ctx.trace_id.bytes.data(), pb.trace_id().data(),
165 : : ctx.trace_id.bytes.size());
166 : 1 : std::memcpy(ctx.span_id.bytes.data(), pb.span_id().data(),
167 : : ctx.span_id.bytes.size());
168 : 1 : if (!ctx.trace_id.valid() || !ctx.span_id.valid()) {
169 : 0 : return result<TraceContext>::make(error(errors::invalid_argument));
170 : : }
171 : 1 : ctx.flags.value = static_cast<uint8_t>(pb.flags() & 0xFF);
172 : 2 : if (pb.tracestate().size() > max_tracestate_len ||
173 : 2 : pb.tracestate().size() > ctx.tracestate.size()) {
174 : 0 : return result<TraceContext>::make(error(errors::invalid_argument));
175 : : }
176 : 1 : if (!pb.tracestate().empty()) {
177 : 0 : std::memcpy(ctx.tracestate.data(), pb.tracestate().data(),
178 : 0 : pb.tracestate().size());
179 : 0 : ctx.tracestate_len = static_cast<uint16_t>(pb.tracestate().size());
180 : : }
181 : 1 : return result<TraceContext>::make(std::move(ctx));
182 : : }
183 : :
184 : : } // namespace net
185 : : } // namespace hpactor
|