server.h
Go to the documentation of this file.
1 //-------------------------------------------------------------------
2 // Nano RPC
3 // https://github.com/tdv/nanorpc
4 // Created: 05.2018
5 // Copyright (C) 2018 tdv
6 //-------------------------------------------------------------------
7 
8 #ifndef __NANO_RPC_CORE_SERVER_H__
9 #define __NANO_RPC_CORE_SERVER_H__
10 
11 // STD
12 #include <functional>
13 #include <map>
14 #include <stdexcept>
15 #include <string>
16 #include <tuple>
17 #include <utility>
18 #include <type_traits>
19 
20 // C++17 backwards compatibility
21 #include <invoke_hpp/invoke.hpp>
22 
23 // NANORPC
26 #include "nanorpc/core/exception.h"
27 #include "nanorpc/core/type.h"
28 #include "nanorpc/core/hash.h"
29 #include "nanorpc/version/core.h"
30 
31 
32 namespace nanorpc::core
33 {
34 
35 // Helper
36 template< class T, class U >
37 constexpr bool is_same_v = std::is_same<T, U>::value;
38 
39 template <typename TPacker>
40 class server final
41 {
42 public:
43  template <typename TFunc>
44  void handle(std::string name, TFunc func)
45  {
46  handle(hash_id(name), std::move(func));
47  }
48 
49  template <typename TFunc>
50  void handle(type::id id, TFunc func)
51  {
52  if (handlers_.find(id) != std::end(handlers_))
53  {
54  throw std::invalid_argument{"[" + std::string{__func__ } + "] Failed to add handler. "
55  "The id \"" + std::to_string(id) + "\" already exists."};
56  }
57 
58  auto wrapper = [f = std::move(func)] (deserializer_type &request, serializer_type &response)
59  {
60  auto func = detail::lambdaToFunction(std::move(f));
61  using function_meta = detail::function_meta<decltype(func)>;
62  using arguments_tuple_type = typename function_meta::arguments_tuple_type;
63  arguments_tuple_type data;
64  request.unpack(data);
65 
66  apply(std::move(func), std::move(data), response);
67  };
68 
69  handlers_.emplace(std::move(id), std::move(wrapper));
70  }
71 
73  try
74  {
75  if (handlers_.empty())
76  throw exception::server{"[nanorpc::core::server::execute] No handlers."};
77 
78  packer_type packer;
79 
80  auto request = packer.from_buffer(std::move(buffer));
81 
82  {
83  version::core::protocol::value_type protocol{};
84  request = request.unpack(protocol);
85  if (protocol != version::core::protocol::value)
86  {
87  throw exception::server{"[nanorpc::core::server::execute] Unsupported protocol version \"" +
88  std::to_string(protocol) + "\"."};
89  }
90  }
91 
92  {
94  request = request.unpack(type);
96  throw exception::server{"[nanorpc::core::server::execute] Bad response type."};
97  }
98 
99  type::id function_id{};
100  request = request.unpack(function_id);
101 
102  auto response = packer
103  .pack(version::core::protocol::value)
105 
106  auto const iter = handlers_.find(function_id);
107  if (iter == std::end(handlers_))
108  throw exception::server{"[nanorpc::core::server::execute] Function not found."};
109 
110  try
111  {
112  iter->second(request, response);
113  }
114  catch (std::exception const &e)
115  {
116  response = response
118  .pack(e.what());
119  }
120 
121  return response.to_buffer();
122  }
123  catch (std::exception const &e)
124  {
125  return packer_type{}
126  .pack(version::core::protocol::value)
129  .pack(e.what())
130  .to_buffer();
131  }
132 
133 private:
134  using packer_type = TPacker;
135  using serializer_type = typename packer_type::serializer_type;
136  using deserializer_type = typename packer_type::deserializer_type;
137  using handler_type = std::function<void (deserializer_type &, serializer_type &)>;
138  using handlers_type = std::map<type::id, handler_type>;
139 
141 
142  template <typename TFunc, typename TArgs>
143  static
144  std::enable_if_t<!is_same_v<std::decay_t< decltype( invoke_hpp::apply(std::declval<TFunc>(), std::declval<TArgs>()) ) >, void>, void>
145  apply(TFunc func, TArgs args, serializer_type &serializer)
146  {
147  auto data = invoke_hpp::apply(std::move(func), std::move(args));
148  serializer = serializer.pack(detail::pack::meta::status::good);
149  serializer = serializer.pack(data);
150  }
151 
152  template <typename TFunc, typename TArgs>
153  static
154  std::enable_if_t<is_same_v< std::decay_t< decltype( invoke_hpp::apply(std::declval<TFunc>(), std::declval<TArgs>()) ) > , void>, void>
155  apply(TFunc func, TArgs args, serializer_type &serializer)
156  {
157  invoke_hpp::apply(std::move(func), std::move(args));
158  serializer = serializer.pack(detail::pack::meta::status::good);
159  }
160 
161 
162 };
163 
164 } // namespace nanorpc::core
165 
166 #endif // !__NANO_RPC_CORE_SERVER_H__
nanorpc::core::detail::pack::meta::status::good
@ good
nanorpc::core::hash_id
type::id hash_id(const std::string &str)
Definition: hash.h:14
nanorpc::core::server::handle
void handle(std::string name, TFunc func)
Definition: server.h:44
nanorpc::core::server::handle
void handle(type::id id, TFunc func)
Definition: server.h:50
nanorpc::core::server::execute
type::buffer execute(type::buffer buffer)
Definition: server.h:72
nanorpc::version::core::protocol
std::integral_constant< std::uint32_t, 1 > protocol
Definition: core.h:22
nanorpc::core::detail::function_meta
Definition: function_meta.h:20
nanorpc::core::server::handlers_
handlers_type handlers_
Definition: server.h:140
nanorpc::core::server
Definition: server.h:40
nanorpc::core::detail::lambdaToFunction
memfun_type< decltype(&F::operator())>::type lambdaToFunction(F const &func)
Definition: function_meta.h:43
DAI_SPAN_NAMESPACE_NAME::detail::data
constexpr auto data(C &c) -> decltype(c.data())
Definition: span.hpp:177
type.h
nanorpc::core::type::buffer
std::vector< std::uint8_t > buffer
Definition: type.h:28
nanorpc::core::detail::pack::meta::type::response
@ response
nanorpc::core::server::deserializer_type
typename packer_type::deserializer_type deserializer_type
Definition: server.h:136
nanorpc::core::is_same_v
constexpr bool is_same_v
Definition: server.h:37
function_meta.h
nanorpc::core::type::id
std::uint64_t id
Definition: type.h:27
invoke.hpp
nanorpc::core::server::apply
static std::enable_if_t< is_same_v< std::decay_t< decltype(invoke_hpp::apply(std::declval< TFunc >), std::declval< TArgs >))) >, void >, void > apply(TFunc func, TArgs args, serializer_type &serializer)
Definition: server.h:155
nanorpc::core::exception::to_string
std::string to_string(std::exception const &e)
Definition: exception.h:46
nanorpc::core::detail::pack::meta::type
type
Definition: pack_meta.h:26
nanorpc::core::server::packer_type
TPacker packer_type
Definition: server.h:134
nanorpc::core::server::serializer_type
typename packer_type::serializer_type serializer_type
Definition: server.h:135
nanorpc::core
Definition: client.h:32
nanorpc::core::detail::pack::meta::type::request
@ request
core.h
hash.h
nanorpc::core::server::handler_type
std::function< void(deserializer_type &, serializer_type &)> handler_type
Definition: server.h:137
nanorpc::core::server::apply
static std::enable_if_t<!is_same_v< std::decay_t< decltype(invoke_hpp::apply(std::declval< TFunc >), std::declval< TArgs >))) >, void >, void > apply(TFunc func, TArgs args, serializer_type &serializer)
Definition: server.h:145
nanorpc::core::detail::pack::meta::status::fail
@ fail
exception.h
nanorpc::core::server::handlers_type
std::map< type::id, handler_type > handlers_type
Definition: server.h:138
pack_meta.h


depthai
Author(s): Martin Peterlin
autogenerated on Sat Mar 22 2025 02:58:19