Advertisement
Guest User

Untitled

a guest
Apr 29th, 2016
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.61 KB | None | 0 0
  1. #pragma once
  2. #include <warpcoil/cpp/helpers.hpp>
  3. #include <silicium/source/source.hpp>
  4. #include <silicium/sink/iterator_sink.hpp>
  5. #include <silicium/sink/append.hpp>
  6. #include <silicium/variant.hpp>
  7. #include <boost/asio/write.hpp>
  8. #include <boost/range/algorithm/equal.hpp>
  9. #include <cstdint>
  10. #include <tuple>
  11.  
  12. struct async_hello_as_a_service
  13. {
  14. virtual ~async_hello_as_a_service()
  15. {
  16. }
  17.  
  18. virtual void hello(std::string name, std::function<void(boost::system::error_code, std::string)> on_result) = 0;
  19. };
  20.  
  21. template <class Client>
  22. struct async_type_erased_hello_as_a_service : async_hello_as_a_service
  23. {
  24. Client &client;
  25.  
  26. explicit async_type_erased_hello_as_a_service(Client &client)
  27. : client(client)
  28. {
  29. }
  30.  
  31. virtual ~async_type_erased_hello_as_a_service()
  32. {
  33. }
  34.  
  35. void hello(std::string name, std::function<void(boost::system::error_code, std::string)> on_result) override
  36. {
  37. return client.hello(std::move(name), std::move(on_result));
  38. }
  39. };
  40.  
  41. template <class AsyncWriteStream, class AsyncReadStream>
  42. struct async_hello_as_a_service_client
  43. {
  44. explicit async_hello_as_a_service_client(AsyncWriteStream &requests, AsyncReadStream &responses)
  45. : requests(requests)
  46. , responses(responses)
  47. , response_buffer_used(0)
  48. {
  49. }
  50.  
  51. template <class CompletionToken>
  52. auto hello(std::string name, CompletionToken &&token)
  53. {
  54. using handler_type =
  55. typename boost::asio::handler_type<decltype(token), void(boost::system::error_code, std::string)>::type;
  56. handler_type handler(std::forward<CompletionToken>(token));
  57. boost::asio::async_result<handler_type> result(handler);
  58. request_buffer.clear();
  59. auto request_writer = Si::Sink<std::uint8_t, Si::success>::erase(Si::make_container_sink(request_buffer));
  60. append(request_writer, 5u);
  61. append(request_writer, Si::make_c_str_range(reinterpret_cast<std::uint8_t const *>("hello")));
  62. if (!utf8::is_valid(name.begin(), name.end()))
  63. {
  64. handler(warpcoil::cpp::make_invalid_input_error(), {});
  65. return result.get();
  66. }
  67. if ((name.size()) > 255u)
  68. {
  69. handler(warpcoil::cpp::make_invalid_input_error(), {});
  70. return result.get();
  71. }
  72. warpcoil::cpp::write_integer(request_writer, static_cast<std::uint8_t>(name.size()));
  73. Si::append(request_writer,
  74. Si::make_iterator_range(reinterpret_cast<std::uint8_t const *>(name.data()),
  75. reinterpret_cast<std::uint8_t const *>(name.data() + name.size())));
  76. boost::asio::async_write(
  77. requests, boost::asio::buffer(request_buffer),
  78. [ this, handler = std::move(handler) ](boost::system::error_code ec, std::size_t) mutable
  79. {
  80. if (!!ec)
  81. {
  82. std::move(handler)(ec, {});
  83. return;
  84. }
  85. begin_parse_value(responses, boost::asio::buffer(response_buffer), response_buffer_used,
  86. warpcoil::cpp::utf8_parser<warpcoil::cpp::integer_parser<std::uint8_t>>{},
  87. std::move(handler));
  88. });
  89. return result.get();
  90. }
  91.  
  92. private:
  93. std::vector<std::uint8_t> request_buffer;
  94. AsyncWriteStream &requests;
  95. std::array<std::uint8_t, 512> response_buffer;
  96. AsyncReadStream &responses;
  97. std::size_t response_buffer_used;
  98. };
  99.  
  100. template <class AsyncReadStream, class AsyncWriteStream>
  101. struct async_hello_as_a_service_server
  102. {
  103. explicit async_hello_as_a_service_server(async_hello_as_a_service &implementation, AsyncReadStream &requests,
  104. AsyncWriteStream &responses)
  105. : implementation(implementation)
  106. , requests(requests)
  107. , request_buffer_used(0)
  108. , responses(responses)
  109. {
  110. }
  111.  
  112. template <class CompletionToken>
  113. auto serve_one_request(CompletionToken &&token)
  114. {
  115. using handler_type = typename boost::asio::handler_type<decltype(token), void(boost::system::error_code)>::type;
  116. handler_type handler(std::forward<CompletionToken>(token));
  117. boost::asio::async_result<handler_type> result(handler);
  118. begin_receive_method_name(std::move(handler));
  119. return result.get();
  120. }
  121.  
  122. private:
  123. async_hello_as_a_service &implementation;
  124. AsyncReadStream &requests;
  125. std::array<std::uint8_t, 512> request_buffer;
  126. std::size_t request_buffer_used;
  127. std::vector<std::uint8_t> response_buffer;
  128. AsyncWriteStream &responses;
  129.  
  130. typedef warpcoil::cpp::utf8_parser<warpcoil::cpp::integer_parser<std::uint8_t>> method_name_parser;
  131.  
  132. template <class Handler>
  133. void begin_receive_method_name(Handler &&handle_result)
  134. {
  135. begin_parse_value(requests, boost::asio::buffer(request_buffer), request_buffer_used, method_name_parser(),
  136. [ this, handle_result = std::forward<Handler>(handle_result) ](boost::system::error_code ec,
  137. std::string name) mutable
  138. {
  139. if (!!ec)
  140. {
  141. std::forward<Handler>(handle_result)(ec);
  142. return;
  143. }
  144. if (boost::range::equal(name, Si::make_c_str_range("hello")))
  145. {
  146. begin_receive_method_argument_of_hello(std::forward<Handler>(handle_result));
  147. }
  148. else
  149. {
  150. throw std::logic_error("to do: handle unknown method name");
  151. }
  152. });
  153. }
  154.  
  155. template <class Handler>
  156. void begin_receive_method_argument_of_hello(Handler &&handle_result)
  157. {
  158. begin_parse_value(
  159. requests, boost::asio::buffer(request_buffer), request_buffer_used,
  160. warpcoil::cpp::tuple_parser<warpcoil::cpp::utf8_parser<warpcoil::cpp::integer_parser<std::uint8_t>>>{},
  161. [ this, handle_result = std::forward<Handler>(handle_result) ](boost::system::error_code ec,
  162. std::tuple<std::string> argument) mutable
  163. {
  164. if (!!ec)
  165. {
  166. std::forward<Handler>(handle_result)(ec);
  167. return;
  168. }
  169. implementation.hello(
  170. std::get<0>(std::move(argument)), [ this, handle_result = std::forward<Handler>(handle_result) ](
  171. boost::system::error_code ec, std::string result) mutable
  172. {
  173. if (!!ec)
  174. {
  175. std::forward<Handler>(handle_result)(ec);
  176. return;
  177. }
  178. response_buffer.clear();
  179. auto response_writer =
  180. Si::Sink<std::uint8_t, Si::success>::erase(Si::make_container_sink(response_buffer));
  181. if (!utf8::is_valid(result.begin(), result.end()))
  182. {
  183. return std::forward<Handler>(handle_result)(warpcoil::cpp::make_invalid_input_error());
  184. }
  185. if ((result.size()) > 255u)
  186. {
  187. return std::forward<Handler>(handle_result)(warpcoil::cpp::make_invalid_input_error());
  188. }
  189. warpcoil::cpp::write_integer(response_writer, static_cast<std::uint8_t>(result.size()));
  190. Si::append(response_writer,
  191. Si::make_iterator_range(
  192. reinterpret_cast<std::uint8_t const *>(result.data()),
  193. reinterpret_cast<std::uint8_t const *>(result.data() + result.size())));
  194. boost::asio::async_write(responses, boost::asio::buffer(response_buffer),
  195. [handle_result = std::forward<Handler>(handle_result)](
  196. boost::system::error_code ec, std::size_t) mutable
  197. {
  198. std::forward<Handler>(handle_result)(ec);
  199. });
  200. });
  201. });
  202. }
  203. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement