Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
server.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
10
11#include <atomic>
12#include <condition_variable>
13#include <mutex>
14#include <thread>
15#include <unordered_map>
16
17#if NETWORK_GRPC_OFFICIAL
18#include <fstream>
19#include <grpcpp/grpcpp.h>
20#include <grpcpp/ext/proto_server_reflection_plugin.h>
21#include <grpcpp/health_check_service_interface.h>
22#endif
23
25{
26
27#if NETWORK_GRPC_OFFICIAL
28
29// ============================================================================
30// Official gRPC Library Implementation
31// ============================================================================
32
33// Generic service that adapts our handler-based API to gRPC's service model
34class generic_service_impl : public ::grpc::Service
35{
36public:
37 using unary_method_handler = std::function<
38 ::grpc::Status(::grpc::ServerContext*, const ::grpc::ByteBuffer*, ::grpc::ByteBuffer*)>;
39
40 auto add_method(const std::string& method_name, unary_method_handler handler) -> void
41 {
42 // Register method with gRPC
43 auto* method = AddMethod(new ::grpc::internal::RpcServiceMethod(
44 method_name.c_str(),
45 ::grpc::internal::RpcMethod::NORMAL_RPC,
46 nullptr));
47
48 handlers_[method_name] = std::move(handler);
49 }
50
51private:
52 std::unordered_map<std::string, unary_method_handler> handlers_;
53};
54
55// Server context adapter
56class official_server_context : public server_context
57{
58public:
59 explicit official_server_context(::grpc::ServerContext* ctx)
60 : ctx_(ctx)
61 {
62 // Copy client metadata
63 for (const auto& md : ctx_->client_metadata())
64 {
65 metadata_.emplace_back(
66 std::string(md.first.data(), md.first.size()),
67 std::string(md.second.data(), md.second.size()));
68 }
69 }
70
71 auto client_metadata() const -> const grpc_metadata& override
72 {
73 return metadata_;
74 }
75
76 auto add_trailing_metadata(const std::string& key,
77 const std::string& value) -> void override
78 {
79 ctx_->AddTrailingMetadata(key, value);
80 }
81
82 auto set_trailing_metadata(grpc_metadata metadata) -> void override
83 {
84 for (const auto& [key, value] : metadata)
85 {
86 ctx_->AddTrailingMetadata(key, value);
87 }
88 }
89
90 auto is_cancelled() const -> bool override
91 {
92 return ctx_->IsCancelled();
93 }
94
95 auto deadline() const
96 -> std::optional<std::chrono::system_clock::time_point> override
97 {
98 auto deadline = ctx_->deadline();
99 if (deadline == std::chrono::system_clock::time_point::max())
100 {
101 return std::nullopt;
102 }
103 return deadline;
104 }
105
106 auto peer() const -> std::string override
107 {
108 return ctx_->peer();
109 }
110
111 auto auth_context() const -> std::string override
112 {
113 auto auth = ctx_->auth_context();
114 if (auth)
115 {
116 auto peer_identity = auth->GetPeerIdentity();
117 if (!peer_identity.empty())
118 {
119 return std::string(peer_identity[0].data(), peer_identity[0].size());
120 }
121 }
122 return "";
123 }
124
125private:
126 ::grpc::ServerContext* ctx_;
127 grpc_metadata metadata_;
128};
129
130// Implementation class using official gRPC
131class grpc_server::impl
132{
133public:
134 explicit impl(grpc_server_config config)
135 : config_(std::move(config))
136 , running_(false)
137 , port_(0)
138 {
139 }
140
141 ~impl()
142 {
143 stop();
144 }
145
146 auto start(uint16_t port) -> VoidResult
147 {
148 auto span = tracing::is_tracing_enabled()
149 ? std::make_optional(tracing::trace_context::create_span("grpc.server.start"))
150 : std::nullopt;
151 if (span)
152 {
153 span->set_attribute("rpc.system", "grpc")
154 .set_attribute("net.host.port", static_cast<int64_t>(port))
155 .set_attribute("rpc.grpc.use_tls", false);
156 }
157
158 std::lock_guard<std::mutex> lock(mutex_);
159
160 if (running_.load())
161 {
162 if (span)
163 {
164 span->set_error("Server is already running");
165 }
166 return error_void(
168 "Server is already running",
169 "grpc::server");
170 }
171
172 if (port == 0)
173 {
174 if (span)
175 {
176 span->set_error("Invalid port number");
177 }
178 return error_void(
180 "Invalid port number",
181 "grpc::server");
182 }
183
184 ::grpc::ServerBuilder builder;
185
186 // Configure server address
187 std::string server_address = "0.0.0.0:" + std::to_string(port);
188 builder.AddListeningPort(server_address, ::grpc::InsecureServerCredentials(), &bound_port_);
189
190 // Apply configuration
191 builder.SetMaxReceiveMessageSize(static_cast<int>(config_.max_message_size));
192 builder.SetMaxSendMessageSize(static_cast<int>(config_.max_message_size));
193
195 {
196 builder.AddChannelArgument(GRPC_ARG_MAX_CONCURRENT_STREAMS,
197 static_cast<int>(config_.max_concurrent_streams));
198 }
199
200 // Enable reflection for debugging
201 ::grpc::reflection::InitProtoReflectionServerBuilderPlugin();
202 ::grpc::EnableDefaultHealthCheckService(true);
203
204 // Build and start the server
205 server_ = builder.BuildAndStart();
206
207 if (!server_)
208 {
209 if (span)
210 {
211 span->set_error("Failed to start gRPC server");
212 }
213 return error_void(
215 "Failed to start gRPC server",
216 "grpc::server");
217 }
218
219 port_ = static_cast<uint16_t>(bound_port_);
220 running_.store(true);
221
222 // Start server thread
223 server_thread_ = std::thread([this]() {
224 server_->Wait();
225 });
226
227 if (span)
228 {
229 span->set_attribute("net.host.port.bound", static_cast<int64_t>(bound_port_));
230 }
231
232 return ok();
233 }
234
235 auto start_tls(uint16_t port,
236 const std::string& cert_path,
237 const std::string& key_path,
238 const std::string& ca_path) -> VoidResult
239 {
240 std::lock_guard<std::mutex> lock(mutex_);
241
242 if (running_.load())
243 {
244 return error_void(
246 "Server is already running",
247 "grpc::server");
248 }
249
250 if (cert_path.empty() || key_path.empty())
251 {
252 return error_void(
254 "Certificate and key paths are required for TLS",
255 "grpc::server");
256 }
257
258 // Read certificate files
259 std::string cert_contents, key_contents, ca_contents;
260
261 {
262 std::ifstream cert_file(cert_path);
263 if (!cert_file)
264 {
265 return error_void(
267 "Failed to read certificate file",
268 "grpc::server",
269 cert_path);
270 }
271 cert_contents = std::string(
272 std::istreambuf_iterator<char>(cert_file),
273 std::istreambuf_iterator<char>());
274 }
275
276 {
277 std::ifstream key_file(key_path);
278 if (!key_file)
279 {
280 return error_void(
282 "Failed to read key file",
283 "grpc::server",
284 key_path);
285 }
286 key_contents = std::string(
287 std::istreambuf_iterator<char>(key_file),
288 std::istreambuf_iterator<char>());
289 }
290
291 if (!ca_path.empty())
292 {
293 std::ifstream ca_file(ca_path);
294 if (ca_file)
295 {
296 ca_contents = std::string(
297 std::istreambuf_iterator<char>(ca_file),
298 std::istreambuf_iterator<char>());
299 }
300 }
301
302 // Create SSL credentials
303 ::grpc::SslServerCredentialsOptions ssl_opts;
304 ssl_opts.pem_key_cert_pairs.push_back({key_contents, cert_contents});
305
306 if (!ca_contents.empty())
307 {
308 ssl_opts.pem_root_certs = ca_contents;
309 ssl_opts.client_certificate_request =
310 GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY;
311 }
312
313 auto creds = ::grpc::SslServerCredentials(ssl_opts);
314
315 ::grpc::ServerBuilder builder;
316 std::string server_address = "0.0.0.0:" + std::to_string(port);
317 builder.AddListeningPort(server_address, creds, &bound_port_);
318
319 // Apply configuration
320 builder.SetMaxReceiveMessageSize(static_cast<int>(config_.max_message_size));
321 builder.SetMaxSendMessageSize(static_cast<int>(config_.max_message_size));
322
323 // Enable reflection
324 ::grpc::reflection::InitProtoReflectionServerBuilderPlugin();
325 ::grpc::EnableDefaultHealthCheckService(true);
326
327 server_ = builder.BuildAndStart();
328
329 if (!server_)
330 {
331 return error_void(
333 "Failed to start gRPC TLS server",
334 "grpc::server");
335 }
336
337 port_ = static_cast<uint16_t>(bound_port_);
338 running_.store(true);
339
340 server_thread_ = std::thread([this]() {
341 server_->Wait();
342 });
343
344 return ok();
345 }
346
347 auto stop() -> void
348 {
349 std::lock_guard<std::mutex> lock(mutex_);
350
351 if (!running_.load())
352 {
353 return;
354 }
355
356 if (server_)
357 {
358 server_->Shutdown();
359 }
360
361 if (server_thread_.joinable())
362 {
363 server_thread_.join();
364 }
365
366 running_.store(false);
367 port_ = 0;
368 stop_cv_.notify_all();
369 }
370
371 auto wait() -> void
372 {
373 std::unique_lock<std::mutex> lock(mutex_);
374 stop_cv_.wait(lock, [this] { return !running_.load(); });
375 }
376
377 auto is_running() const -> bool
378 {
379 return running_.load();
380 }
381
382 auto port() const -> uint16_t
383 {
384 return port_;
385 }
386
387 auto register_service(grpc_service* service) -> VoidResult
388 {
389 if (service == nullptr)
390 {
391 return error_void(
393 "Service cannot be null",
394 "grpc::server");
395 }
396
397 std::lock_guard<std::mutex> lock(mutex_);
398 services_.push_back(service);
399
400 return ok();
401 }
402
403 auto register_unary_method(const std::string& full_method_name,
404 unary_handler handler) -> VoidResult
405 {
406 if (full_method_name.empty() || full_method_name[0] != '/')
407 {
408 return error_void(
410 "Invalid method name format",
411 "grpc::server",
412 "Method name must start with '/'");
413 }
414
415 if (!handler)
416 {
417 return error_void(
419 "Handler cannot be null",
420 "grpc::server");
421 }
422
423 std::lock_guard<std::mutex> lock(mutex_);
424
425 if (methods_.find(full_method_name) != methods_.end())
426 {
427 return error_void(
429 "Method already registered",
430 "grpc::server",
431 full_method_name);
432 }
433
434 method_handler mh;
435 mh.type = method_type::unary;
436 mh.unary = std::move(handler);
437 methods_[full_method_name] = std::move(mh);
438
439 return ok();
440 }
441
442 auto register_server_streaming_method(const std::string& full_method_name,
444 {
445 if (full_method_name.empty() || full_method_name[0] != '/')
446 {
447 return error_void(
449 "Invalid method name format",
450 "grpc::server");
451 }
452
453 if (!handler)
454 {
455 return error_void(
457 "Handler cannot be null",
458 "grpc::server");
459 }
460
461 std::lock_guard<std::mutex> lock(mutex_);
462
463 if (methods_.find(full_method_name) != methods_.end())
464 {
465 return error_void(
467 "Method already registered",
468 "grpc::server");
469 }
470
471 method_handler mh;
473 mh.server_streaming = std::move(handler);
474 methods_[full_method_name] = std::move(mh);
475
476 return ok();
477 }
478
479 auto register_client_streaming_method(const std::string& full_method_name,
481 {
482 if (full_method_name.empty() || full_method_name[0] != '/')
483 {
484 return error_void(
486 "Invalid method name format",
487 "grpc::server");
488 }
489
490 if (!handler)
491 {
492 return error_void(
494 "Handler cannot be null",
495 "grpc::server");
496 }
497
498 std::lock_guard<std::mutex> lock(mutex_);
499
500 if (methods_.find(full_method_name) != methods_.end())
501 {
502 return error_void(
504 "Method already registered",
505 "grpc::server");
506 }
507
508 method_handler mh;
510 mh.client_streaming = std::move(handler);
511 methods_[full_method_name] = std::move(mh);
512
513 return ok();
514 }
515
516 auto register_bidi_streaming_method(const std::string& full_method_name,
518 {
519 if (full_method_name.empty() || full_method_name[0] != '/')
520 {
521 return error_void(
523 "Invalid method name format",
524 "grpc::server");
525 }
526
527 if (!handler)
528 {
529 return error_void(
531 "Handler cannot be null",
532 "grpc::server");
533 }
534
535 std::lock_guard<std::mutex> lock(mutex_);
536
537 if (methods_.find(full_method_name) != methods_.end())
538 {
539 return error_void(
541 "Method already registered",
542 "grpc::server");
543 }
544
545 method_handler mh;
547 mh.bidi_streaming = std::move(handler);
548 methods_[full_method_name] = std::move(mh);
549
550 return ok();
551 }
552
553private:
554 // Method type enumeration (same as prototype)
555 enum class method_type
556 {
557 unary,
561 };
562
563 struct method_handler
564 {
565 method_type type;
570 };
571
572 grpc_server_config config_;
573 std::atomic<bool> running_;
574 uint16_t port_;
575 int bound_port_ = 0;
576
577 std::unique_ptr<::grpc::Server> server_;
578 std::thread server_thread_;
579
580 std::vector<grpc_service*> services_;
581 std::unordered_map<std::string, method_handler> methods_;
582
583 mutable std::mutex mutex_;
584 std::condition_variable stop_cv_;
585};
586
587#else // !NETWORK_GRPC_OFFICIAL
588
589// ============================================================================
590// Prototype Implementation (existing code)
591// ============================================================================
592
593// Method type enumeration
594enum class method_type
595{
596 unary,
600};
601
602// Method handler variant
611
612// Implementation class (PIMPL pattern)
614{
615public:
616 explicit impl(grpc_server_config config)
617 : config_(std::move(config))
618 , running_(false)
619 , port_(0)
620 {
621 }
622
624 {
625 stop();
626 }
627
628 auto start(uint16_t port) -> VoidResult
629 {
630 auto span = tracing::is_tracing_enabled()
631 ? std::make_optional(tracing::trace_context::create_span("grpc.server.start"))
632 : std::nullopt;
633 if (span)
634 {
635 span->set_attribute("rpc.system", "grpc")
636 .set_attribute("net.host.port", static_cast<int64_t>(port))
637 .set_attribute("rpc.grpc.use_tls", false);
638 }
639
640 std::lock_guard<std::mutex> lock(mutex_);
641
642 if (running_.load())
643 {
644 if (span)
645 {
646 span->set_error("Server is already running");
647 }
648 return error_void(
650 "Server is already running",
651 "grpc::server");
652 }
653
654 if (port == 0)
655 {
656 if (span)
657 {
658 span->set_error("Invalid port number");
659 }
660 return error_void(
662 "Invalid port number",
663 "grpc::server");
664 }
665
666 // In a full implementation, this would:
667 // 1. Create HTTP/2 server socket
668 // 2. Start accepting connections
669 // 3. Spawn worker threads
670
671 port_ = port;
672 running_.store(true);
673
674 return ok();
675 }
676
677 auto start_tls(uint16_t port,
678 const std::string& cert_path,
679 const std::string& key_path,
680 const std::string& ca_path) -> VoidResult
681 {
682 std::lock_guard<std::mutex> lock(mutex_);
683
684 if (running_.load())
685 {
686 return error_void(
688 "Server is already running",
689 "grpc::server");
690 }
691
692 if (cert_path.empty() || key_path.empty())
693 {
694 return error_void(
696 "Certificate and key paths are required for TLS",
697 "grpc::server");
698 }
699
700 // In a full implementation, this would configure TLS context
701 cert_path_ = cert_path;
702 key_path_ = key_path;
703 ca_path_ = ca_path;
704
705 port_ = port;
706 running_.store(true);
707
708 return ok();
709 }
710
711 auto stop() -> void
712 {
713 std::lock_guard<std::mutex> lock(mutex_);
714
715 if (!running_.load())
716 {
717 return;
718 }
719
720 running_.store(false);
721 port_ = 0;
722
723 // Notify waiting threads
724 stop_cv_.notify_all();
725 }
726
727 auto wait() -> void
728 {
729 std::unique_lock<std::mutex> lock(mutex_);
730 stop_cv_.wait(lock, [this] { return !running_.load(); });
731 }
732
733 auto is_running() const -> bool
734 {
735 return running_.load();
736 }
737
738 auto port() const -> uint16_t
739 {
740 return port_;
741 }
742
744 {
745 if (service == nullptr)
746 {
747 return error_void(
749 "Service cannot be null",
750 "grpc::server");
751 }
752
753 std::lock_guard<std::mutex> lock(mutex_);
754 services_.push_back(service);
755
756 return ok();
757 }
758
759 auto register_unary_method(const std::string& full_method_name,
760 unary_handler handler) -> VoidResult
761 {
762 if (full_method_name.empty() || full_method_name[0] != '/')
763 {
764 return error_void(
766 "Invalid method name format",
767 "grpc::server",
768 "Method name must start with '/'");
769 }
770
771 if (!handler)
772 {
773 return error_void(
775 "Handler cannot be null",
776 "grpc::server");
777 }
778
779 std::lock_guard<std::mutex> lock(mutex_);
780
781 if (methods_.find(full_method_name) != methods_.end())
782 {
783 return error_void(
785 "Method already registered",
786 "grpc::server",
787 full_method_name);
788 }
789
791 mh.type = method_type::unary;
792 mh.unary = std::move(handler);
793 methods_[full_method_name] = std::move(mh);
794
795 return ok();
796 }
797
798 auto register_server_streaming_method(const std::string& full_method_name,
800 {
801 if (full_method_name.empty() || full_method_name[0] != '/')
802 {
803 return error_void(
805 "Invalid method name format",
806 "grpc::server");
807 }
808
809 if (!handler)
810 {
811 return error_void(
813 "Handler cannot be null",
814 "grpc::server");
815 }
816
817 std::lock_guard<std::mutex> lock(mutex_);
818
819 if (methods_.find(full_method_name) != methods_.end())
820 {
821 return error_void(
823 "Method already registered",
824 "grpc::server");
825 }
826
829 mh.server_streaming = std::move(handler);
830 methods_[full_method_name] = std::move(mh);
831
832 return ok();
833 }
834
835 auto register_client_streaming_method(const std::string& full_method_name,
837 {
838 if (full_method_name.empty() || full_method_name[0] != '/')
839 {
840 return error_void(
842 "Invalid method name format",
843 "grpc::server");
844 }
845
846 if (!handler)
847 {
848 return error_void(
850 "Handler cannot be null",
851 "grpc::server");
852 }
853
854 std::lock_guard<std::mutex> lock(mutex_);
855
856 if (methods_.find(full_method_name) != methods_.end())
857 {
858 return error_void(
860 "Method already registered",
861 "grpc::server");
862 }
863
866 mh.client_streaming = std::move(handler);
867 methods_[full_method_name] = std::move(mh);
868
869 return ok();
870 }
871
872 auto register_bidi_streaming_method(const std::string& full_method_name,
874 {
875 if (full_method_name.empty() || full_method_name[0] != '/')
876 {
877 return error_void(
879 "Invalid method name format",
880 "grpc::server");
881 }
882
883 if (!handler)
884 {
885 return error_void(
887 "Handler cannot be null",
888 "grpc::server");
889 }
890
891 std::lock_guard<std::mutex> lock(mutex_);
892
893 if (methods_.find(full_method_name) != methods_.end())
894 {
895 return error_void(
897 "Method already registered",
898 "grpc::server");
899 }
900
903 mh.bidi_streaming = std::move(handler);
904 methods_[full_method_name] = std::move(mh);
905
906 return ok();
907 }
908
909private:
911 std::atomic<bool> running_;
912 uint16_t port_;
913
914 std::string cert_path_;
915 std::string key_path_;
916 std::string ca_path_;
917
918 std::vector<grpc_service*> services_;
919 std::unordered_map<std::string, method_handler> methods_;
920
921 mutable std::mutex mutex_;
922 std::condition_variable stop_cv_;
923};
924
925#endif // !NETWORK_GRPC_OFFICIAL
926
927// grpc_server implementation
928
930 : impl_(std::make_unique<impl>(config))
931{
932}
933
934grpc_server::~grpc_server() = default;
935
936grpc_server::grpc_server(grpc_server&&) noexcept = default;
937grpc_server& grpc_server::operator=(grpc_server&&) noexcept = default;
938
939auto grpc_server::start(uint16_t port) -> VoidResult
940{
941 return impl_->start(port);
942}
943
944auto grpc_server::start_tls(uint16_t port,
945 const std::string& cert_path,
946 const std::string& key_path,
947 const std::string& ca_path) -> VoidResult
948{
949 return impl_->start_tls(port, cert_path, key_path, ca_path);
950}
951
952auto grpc_server::stop() -> void
953{
954 impl_->stop();
955}
956
957auto grpc_server::wait() -> void
958{
959 impl_->wait();
960}
961
962auto grpc_server::is_running() const -> bool
963{
964 return impl_->is_running();
965}
966
967auto grpc_server::port() const -> uint16_t
968{
969 return impl_->port();
970}
971
973{
974 return impl_->register_service(service);
975}
976
977auto grpc_server::register_unary_method(const std::string& full_method_name,
978 unary_handler handler) -> VoidResult
979{
980 return impl_->register_unary_method(full_method_name, std::move(handler));
981}
982
983auto grpc_server::register_server_streaming_method(const std::string& full_method_name,
985{
986 return impl_->register_server_streaming_method(full_method_name, std::move(handler));
987}
988
989auto grpc_server::register_client_streaming_method(const std::string& full_method_name,
991{
992 return impl_->register_client_streaming_method(full_method_name, std::move(handler));
993}
994
995auto grpc_server::register_bidi_streaming_method(const std::string& full_method_name,
997{
998 return impl_->register_bidi_streaming_method(full_method_name, std::move(handler));
999}
1000
1001} // namespace kcenon::network::protocols::grpc
auto register_bidi_streaming_method(const std::string &full_method_name, bidi_streaming_handler handler) -> VoidResult
Definition server.cpp:872
auto register_unary_method(const std::string &full_method_name, unary_handler handler) -> VoidResult
Definition server.cpp:759
std::unordered_map< std::string, method_handler > methods_
Definition server.cpp:919
auto start(uint16_t port) -> VoidResult
Definition server.cpp:628
auto start_tls(uint16_t port, const std::string &cert_path, const std::string &key_path, const std::string &ca_path) -> VoidResult
Definition server.cpp:677
auto register_client_streaming_method(const std::string &full_method_name, client_streaming_handler handler) -> VoidResult
Definition server.cpp:835
auto register_service(grpc_service *service) -> VoidResult
Definition server.cpp:743
auto register_server_streaming_method(const std::string &full_method_name, server_streaming_handler handler) -> VoidResult
Definition server.cpp:798
gRPC server for handling RPC requests
Definition server.h:273
grpc_server(const grpc_server_config &config={})
Construct gRPC server.
Definition server.cpp:929
auto stop() -> void
Stop the server.
Definition server.cpp:952
auto register_bidi_streaming_method(const std::string &full_method_name, bidi_streaming_handler handler) -> VoidResult
Register a bidirectional streaming RPC method handler.
Definition server.cpp:995
auto wait() -> void
Wait for server to finish (blocks)
Definition server.cpp:957
auto register_unary_method(const std::string &full_method_name, unary_handler handler) -> VoidResult
Register a unary RPC method handler.
Definition server.cpp:977
auto is_running() const -> bool
Check if server is running.
Definition server.cpp:962
auto register_service(grpc_service *service) -> VoidResult
Register a service.
Definition server.cpp:972
auto port() const -> uint16_t
Get the port the server is listening on.
Definition server.cpp:967
auto start_tls(uint16_t port, const std::string &cert_path, const std::string &key_path, const std::string &ca_path="") -> VoidResult
Start the server with TLS.
Definition server.cpp:944
auto register_client_streaming_method(const std::string &full_method_name, client_streaming_handler handler) -> VoidResult
Register a client streaming RPC method handler.
Definition server.cpp:989
auto register_server_streaming_method(const std::string &full_method_name, server_streaming_handler handler) -> VoidResult
Register a server streaming RPC method handler.
Definition server.cpp:983
Base class for gRPC service implementations.
Definition server.h:236
static auto create_span(std::string_view name) -> span
Create a new root span with a new trace context.
tracing_config config
Definition exporters.cpp:29
@ peer
Verify peer certificate.
gRPC protocol implementation
Definition client.h:34
@ server_streaming
Server streaming (single request, multiple responses)
@ client_streaming
Client streaming (multiple requests, single response)
@ bidi_streaming
Bidirectional streaming (multiple requests and responses)
@ unary
Unary RPC (single request, single response)
std::function< std::pair< grpc_status, std::vector< uint8_t > >( server_context &ctx, const std::vector< uint8_t > &request)> unary_handler
Handler function type for unary RPC.
Definition server.h:134
std::vector< std::pair< std::string, std::string > > grpc_metadata
Metadata key-value pair for gRPC requests/responses.
Definition client.h:38
std::function< grpc_status( server_context &ctx, const std::vector< uint8_t > &request, server_writer &writer)> server_streaming_handler
Handler function type for server streaming RPC.
Definition server.h:163
@ ok
Not an error; returned on success.
std::function< grpc_status( server_context &ctx, server_reader_writer &stream)> bidi_streaming_handler
Handler function type for bidirectional streaming RPC.
Definition server.h:222
std::function< std::pair< grpc_status, std::vector< uint8_t > >( server_context &ctx, server_reader &reader)> client_streaming_handler
Handler function type for client streaming RPC.
Definition server.h:197
auto is_tracing_enabled() -> bool
Check if tracing is enabled.
Result< std::monostate > VoidResult
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
gRPC server configuration and service hosting.
RAII span implementation for distributed tracing.
size_t max_concurrent_streams
Maximum number of concurrent streams per connection.
Definition server.h:48
size_t max_message_size
Maximum message size in bytes.
Definition server.h:51
Distributed tracing context for OpenTelemetry-compatible tracing.
Configuration structures for OpenTelemetry tracing.