19 #ifndef IRCCD_STREAM_HPP
20 #define IRCCD_STREAM_HPP
27 #include <irccd/sysconfig.hpp>
34 #include <system_error>
37 #include <boost/asio.hpp>
39 #if defined(IRCCD_HAVE_SSL)
40 # include <boost/asio/ssl.hpp>
63 using recv_handler = std::function<void (std::error_code, nlohmann::json)>;
110 template <
typename Socket>
113 boost::asio::streambuf input_{2048};
114 boost::asio::streambuf output_;
117 bool is_receiving_{
false};
118 bool is_sending_{
false};
121 void handle_recv(boost::system::error_code, std::size_t,
recv_handler);
122 void handle_send(boost::system::error_code, std::size_t,
send_handler);
132 template <
typename... Args>
140 auto get_socket()
const noexcept ->
const Socket&;
170 template <
typename Socket>
171 template <
typename... Args>
173 : socket_(
std::forward<Args>(args)...)
177 template <
typename Socket>
183 template <
typename Socket>
189 template <
typename Socket>
190 inline void basic_socket_stream<Socket>::handle_recv(boost::system::error_code code,
192 recv_handler handler)
195 is_receiving_ =
false;
198 if (code == boost::asio::error::not_found) {
199 handler(make_error_code(std::errc::argument_list_too_long),
nullptr);
202 if (code == boost::asio::error::eof || xfer == 0) {
207 handler(std::move(code),
nullptr);
215 buffer = std::string(
216 boost::asio::buffers_begin(input_.data()),
217 boost::asio::buffers_begin(input_.data()) + xfer - 4
220 input_.consume(xfer);
221 }
catch (
const std::bad_alloc&) {
230 doc = nlohmann::json::parse(buffer);
231 }
catch (
const std::exception&) {
236 if (!doc.is_object())
239 handler(std::error_code(), std::move(doc));
242 template <
typename Socket>
243 inline void basic_socket_stream<Socket>::handle_send(boost::system::error_code code,
245 send_handler handler)
251 if (code == boost::asio::error::eof || xfer == 0) {
256 handler(std::move(code));
259 template <
typename Socket>
263 assert(!is_receiving_);
265 is_receiving_ =
true;
270 async_read_until(socket_, input_,
"\r\n\r\n", [
this, handler] (
auto code,
auto xfer) {
271 handle_recv(code, xfer, handler);
275 template <
typename Socket>
279 assert(!is_sending_);
284 assert(json.is_object());
287 std::ostream out(&output_);
293 async_write(socket_, output_, [
this, handler] (
auto code,
auto xfer) {
294 handle_send(code, xfer, handler);
312 #if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
320 #endif // !BOOST_ASIO_HAS_LOCAL_SOCKETS
326 #if defined(IRCCD_HAVE_SSL)
333 template <
typename Socket>
336 std::shared_ptr<boost::asio::ssl::context> context_;
348 tls_stream(boost::asio::io_context& service, std::shared_ptr<boost::asio::ssl::context> ctx);
351 template <
typename Socket>
354 , context_(
std::move(ctx))
363 #if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
370 #endif // !BOOST_ASIO_HAS_LOCAL_SOCKETS
372 #endif // !IRCCD_HAVE_SSL
378 #endif // !IRCCD_STREAM_HPP