21#if NETWORK_GRPC_OFFICIAL
23#include <grpcpp/grpcpp.h>
24#include <grpcpp/ext/proto_server_reflection_plugin.h>
25#include <grpcpp/security/credentials.h>
26#include <grpcpp/support/byte_buffer.h>
38auto map_grpc_code_to_error(
int code) ->
int
40 switch (
static_cast<::grpc::StatusCode
>(code))
42 case ::grpc::StatusCode::OK:
44 case ::grpc::StatusCode::CANCELLED:
45 return static_cast<int>(status_code::cancelled);
46 case ::grpc::StatusCode::UNKNOWN:
47 return static_cast<int>(status_code::unknown);
48 case ::grpc::StatusCode::INVALID_ARGUMENT:
49 return static_cast<int>(status_code::invalid_argument);
50 case ::grpc::StatusCode::DEADLINE_EXCEEDED:
51 return static_cast<int>(status_code::deadline_exceeded);
52 case ::grpc::StatusCode::NOT_FOUND:
53 return static_cast<int>(status_code::not_found);
54 case ::grpc::StatusCode::ALREADY_EXISTS:
55 return static_cast<int>(status_code::already_exists);
56 case ::grpc::StatusCode::PERMISSION_DENIED:
57 return static_cast<int>(status_code::permission_denied);
58 case ::grpc::StatusCode::RESOURCE_EXHAUSTED:
59 return static_cast<int>(status_code::resource_exhausted);
60 case ::grpc::StatusCode::FAILED_PRECONDITION:
61 return static_cast<int>(status_code::failed_precondition);
62 case ::grpc::StatusCode::ABORTED:
63 return static_cast<int>(status_code::aborted);
64 case ::grpc::StatusCode::OUT_OF_RANGE:
65 return static_cast<int>(status_code::out_of_range);
66 case ::grpc::StatusCode::UNIMPLEMENTED:
67 return static_cast<int>(status_code::unimplemented);
68 case ::grpc::StatusCode::INTERNAL:
69 return static_cast<int>(status_code::internal);
70 case ::grpc::StatusCode::UNAVAILABLE:
71 return static_cast<int>(status_code::unavailable);
72 case ::grpc::StatusCode::DATA_LOSS:
73 return static_cast<int>(status_code::data_loss);
74 case ::grpc::StatusCode::UNAUTHENTICATED:
75 return static_cast<int>(status_code::unauthenticated);
77 return static_cast<int>(status_code::unknown);
81auto map_status_to_grpc_code(status_code code) ->
int
86 return static_cast<int>(::grpc::StatusCode::OK);
87 case status_code::cancelled:
88 return static_cast<int>(::grpc::StatusCode::CANCELLED);
89 case status_code::unknown:
90 return static_cast<int>(::grpc::StatusCode::UNKNOWN);
91 case status_code::invalid_argument:
92 return static_cast<int>(::grpc::StatusCode::INVALID_ARGUMENT);
93 case status_code::deadline_exceeded:
94 return static_cast<int>(::grpc::StatusCode::DEADLINE_EXCEEDED);
95 case status_code::not_found:
96 return static_cast<int>(::grpc::StatusCode::NOT_FOUND);
97 case status_code::already_exists:
98 return static_cast<int>(::grpc::StatusCode::ALREADY_EXISTS);
99 case status_code::permission_denied:
100 return static_cast<int>(::grpc::StatusCode::PERMISSION_DENIED);
101 case status_code::resource_exhausted:
102 return static_cast<int>(::grpc::StatusCode::RESOURCE_EXHAUSTED);
103 case status_code::failed_precondition:
104 return static_cast<int>(::grpc::StatusCode::FAILED_PRECONDITION);
105 case status_code::aborted:
106 return static_cast<int>(::grpc::StatusCode::ABORTED);
107 case status_code::out_of_range:
108 return static_cast<int>(::grpc::StatusCode::OUT_OF_RANGE);
109 case status_code::unimplemented:
110 return static_cast<int>(::grpc::StatusCode::UNIMPLEMENTED);
111 case status_code::internal:
112 return static_cast<int>(::grpc::StatusCode::INTERNAL);
113 case status_code::unavailable:
114 return static_cast<int>(::grpc::StatusCode::UNAVAILABLE);
115 case status_code::data_loss:
116 return static_cast<int>(::grpc::StatusCode::DATA_LOSS);
117 case status_code::unauthenticated:
118 return static_cast<int>(::grpc::StatusCode::UNAUTHENTICATED);
120 return static_cast<int>(::grpc::StatusCode::UNKNOWN);
130auto from_grpc_status(const ::grpc::Status& status) ->
grpc_status
137 auto code =
static_cast<status_code>(detail::map_grpc_code_to_error(
138 static_cast<int>(status.error_code())));
142auto to_grpc_status(
const grpc_status& status) -> ::grpc::Status
146 return ::grpc::Status::OK;
149 auto grpc_code =
static_cast<::grpc::StatusCode
>(
150 detail::map_status_to_grpc_code(status.code));
151 return ::grpc::Status(grpc_code, status.message);
155auto result_to_grpc_status(
const Result<T>& result) -> ::grpc::Status
159 return ::grpc::Status::OK;
162 const auto& err = result.error();
165 ::grpc::StatusCode grpc_code = ::grpc::StatusCode::INTERNAL;
170 grpc_code = ::grpc::StatusCode::INVALID_ARGUMENT;
174 grpc_code = ::grpc::StatusCode::NOT_FOUND;
178 grpc_code = ::grpc::StatusCode::ALREADY_EXISTS;
182 grpc_code = ::grpc::StatusCode::PERMISSION_DENIED;
186 grpc_code = ::grpc::StatusCode::UNAVAILABLE;
190 grpc_code = ::grpc::StatusCode::DEADLINE_EXCEEDED;
194 grpc_code = ::grpc::StatusCode::CANCELLED;
198 grpc_code = ::grpc::StatusCode::UNAUTHENTICATED;
202 grpc_code = ::grpc::StatusCode::RESOURCE_EXHAUSTED;
206 grpc_code = ::grpc::StatusCode::UNIMPLEMENTED;
209 return ::grpc::Status(grpc_code, err.message);
212auto void_result_to_grpc_status(
const VoidResult& result) -> ::grpc::Status
216 return ::grpc::Status::OK;
219 const auto& err = result.error();
222 ::grpc::StatusCode grpc_code = ::grpc::StatusCode::INTERNAL;
226 grpc_code = ::grpc::StatusCode::INVALID_ARGUMENT;
230 grpc_code = ::grpc::StatusCode::NOT_FOUND;
234 grpc_code = ::grpc::StatusCode::ALREADY_EXISTS;
238 grpc_code = ::grpc::StatusCode::PERMISSION_DENIED;
242 grpc_code = ::grpc::StatusCode::UNAVAILABLE;
245 return ::grpc::Status(grpc_code, err.message);
248auto grpc_status_to_void_result(const ::grpc::Status& status) ->
VoidResult
256 detail::map_grpc_code_to_error(
static_cast<int>(status.error_code())),
257 std::string(status.error_message()),
262template auto result_to_grpc_status(
const Result<std::vector<uint8_t>>&) -> ::grpc::Status;
263template auto result_to_grpc_status(
const Result<grpc_message>&) -> ::grpc::Status;
264template auto result_to_grpc_status(
const Result<std::string>&) -> ::grpc::Status;
270auto set_deadline(::grpc::ClientContext* ctx,
271 std::chrono::system_clock::time_point deadline) ->
void
275 ctx->set_deadline(deadline);
279auto get_remaining_time(const ::grpc::ServerContext* ctx)
280 -> std::optional<std::chrono::milliseconds>
287 auto deadline = ctx->deadline();
290 if (deadline == std::chrono::system_clock::time_point::max())
295 auto now = std::chrono::system_clock::now();
298 return std::chrono::milliseconds(0);
301 return std::chrono::duration_cast<std::chrono::milliseconds>(deadline - now);
308auto create_channel(
const std::string& target,
309 const channel_credentials_config& config)
310 -> std::shared_ptr<::grpc::Channel>
314 return create_insecure_channel(target);
318 ::grpc::SslCredentialsOptions ssl_opts;
320 if (!
config.root_certificates.empty())
322 ssl_opts.pem_root_certs =
config.root_certificates;
325 if (
config.client_certificate.has_value() &&
config.client_key.has_value())
327 ssl_opts.pem_cert_chain =
config.client_certificate.value();
328 ssl_opts.pem_private_key =
config.client_key.value();
331 auto creds = ::grpc::SslCredentials(ssl_opts);
334 ::grpc::ChannelArguments args;
336 return ::grpc::CreateCustomChannel(target, creds, args);
339auto create_insecure_channel(
const std::string& target)
340 -> std::shared_ptr<::grpc::Channel>
342 return ::grpc::CreateChannel(target, ::grpc::InsecureChannelCredentials());
345auto wait_for_channel_ready(
const std::shared_ptr<::grpc::Channel>& channel,
346 std::chrono::milliseconds timeout) ->
bool
353 auto deadline = std::chrono::system_clock::now() +
timeout;
354 return channel->WaitForConnected(deadline);
369auto vector_to_byte_buffer(
const std::vector<uint8_t>& data) -> ::grpc::ByteBuffer
371 ::grpc::Slice slice(
data.data(),
data.size());
372 return ::grpc::ByteBuffer(&slice, 1);
380auto byte_buffer_to_vector(const ::grpc::ByteBuffer& buffer) -> std::vector<uint8_t>
382 std::vector<::grpc::Slice> slices;
383 buffer.Dump(&slices);
385 std::vector<uint8_t> result;
386 result.reserve(buffer.Length());
388 for (
const auto& slice : slices)
390 const auto* begin =
reinterpret_cast<const uint8_t*
>(slice.begin());
391 result.insert(result.end(), begin, begin + slice.size());
402auto message_to_byte_buffer(
const grpc_message& msg) -> ::grpc::ByteBuffer
404 auto serialized = msg.serialize();
405 return vector_to_byte_buffer(serialized);
413auto byte_buffer_to_message(const ::grpc::ByteBuffer& buffer) -> Result<grpc_message>
415 auto data = byte_buffer_to_vector(buffer);
430class official_server_writer_impl :
public server_writer
433 explicit official_server_writer_impl(W* writer)
440 if (writer_ ==
nullptr)
445 "grpc::server_writer");
448 ::grpc::ByteBuffer buffer = detail::vector_to_byte_buffer(
message);
449 bool success = writer_->Write(buffer);
455 "Failed to write message",
456 "grpc::server_writer");
471class official_server_reader_impl :
public server_reader
474 explicit official_server_reader_impl(R* reader)
480 auto read() -> Result<std::vector<uint8_t>>
override
482 if (reader_ ==
nullptr)
487 "grpc::server_reader");
490 ::grpc::ByteBuffer buffer;
491 bool success = reader_->Read(&buffer);
499 "grpc::server_reader");
502 return ok(detail::byte_buffer_to_vector(buffer));
505 auto has_more() const ->
bool override
520class official_server_reader_writer_impl :
public server_reader_writer
523 explicit official_server_reader_writer_impl(RW* stream)
529 auto read() -> Result<std::vector<uint8_t>>
override
531 if (stream_ ==
nullptr)
533 return error<std::vector<uint8_t>>(
534 error_codes::common_errors::invalid_argument,
536 "grpc::server_reader_writer");
539 ::grpc::ByteBuffer buffer;
540 bool success = stream_->Read(&buffer);
545 return error<std::vector<uint8_t>>(
546 static_cast<int>(status_code::ok),
548 "grpc::server_reader_writer");
551 return ok(detail::byte_buffer_to_vector(buffer));
554 auto write(
const std::vector<uint8_t>& message) ->
VoidResult override
556 if (stream_ ==
nullptr)
559 error_codes::common_errors::invalid_argument,
561 "grpc::server_reader_writer");
564 ::grpc::ByteBuffer buffer = detail::vector_to_byte_buffer(message);
565 bool success = stream_->Write(buffer);
570 error_codes::network_system::connection_failed,
571 "Failed to write message",
572 "grpc::server_reader_writer");
578 auto has_more() const ->
bool override
Official gRPC library wrapper interfaces.
gRPC message framing and serialization.
constexpr int invalid_argument
constexpr int permission_denied
constexpr int already_exists
constexpr int connection_failed
constexpr const char * grpc_status
gRPC protocol implementation
status_code
gRPC status codes (as defined in grpc/status.h)
@ cancelled
The operation was cancelled.
@ deadline_exceeded
Deadline expired before operation completed.
@ unimplemented
Operation not implemented.
@ ok
Not an error; returned on success.
@ unauthenticated
Request lacks valid authentication.
@ resource_exhausted
Resource exhausted.
Result< std::monostate > VoidResult
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
Network-specific error and result type definitions.
gRPC status codes and error representation.
static auto parse(std::span< const uint8_t > input) -> Result< grpc_message >
Parse gRPC message from raw bytes.
static auto ok_status() -> grpc_status
Create OK status.
static auto error_status(status_code c, std::string msg) -> grpc_status
Create error status.