root/core/socket_wrapper_asio_impl.hpp

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. set_options
  2. connect
  3. write
  4. write
  5. read
  6. read
  7. read
  8. to_string

   1 /******************************************************************************
   2 ** $Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/core/socket_wrapper_asio_impl.hpp 2323 2018-09-16 19:31:20Z jmmcg $
   3 **
   4 ** Copyright (C) 2015 by J.M.McGuiness, coder@hussar.me.uk
   5 **
   6 ** This library is free software; you can redistribute it and/or
   7 ** modify it under the terms of the GNU Lesser General Public
   8 ** License as published by the Free Software Foundation; either
   9 ** version 2.1 of the License, or (at your option) any later version.
  10 **
  11 ** This library is distributed in the hope that it will be useful,
  12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 ** Lesser General Public License for more details.
  15 **
  16 ** You should have received a copy of the GNU Lesser General Public
  17 ** License along with this library; if not, write to the Free Software
  18 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 */
  20 
  21 namespace jmmcg { namespace socket { namespace asio {
  22 
  23 inline void
  24 socket_wrapper::set_options(std::size_t /*min_message_size*/, std::size_t max_message_size) {
  25         socket_.set_option(boost::asio::socket_base::send_buffer_size(max_message_size));
  26 // TODO: not supported  socket_.set_option(boost::asio::socket_base::receive_low_watermark(min_message_size));
  27         socket_.set_option(boost::asio::socket_base::receive_buffer_size(max_message_size));
  28         socket_.set_option(boost::asio::ip::tcp::no_delay(true));
  29 }
  30 
  31 inline
  32 socket_wrapper::socket_wrapper(boost::asio::io_service &io_service)
  33 : socket_(io_service) {
  34 }
  35 
  36 inline void
  37 socket_wrapper::connect(boost::asio::ip::tcp::endpoint const &endpoint) {
  38         socket_.connect(endpoint);
  39 }
  40 
  41 template<class MsgT> inline void
  42 socket_wrapper::write(MsgT const &message) {
  43         if (MsgT::has_static_size) {
  44                 using raw_buff_t=char const [sizeof(MsgT)];
  45                 assert(message.length()==sizeof(MsgT));
  46                 [[maybe_unused]] const std::size_t bytes_written=boost::asio::write(socket_, boost::asio::buffer(reinterpret_cast<raw_buff_t &>(message)), io_error);
  47                 if (UNLIKELY(io_error==boost::asio::error::eof)) {
  48                         return; // Connection closed cleanly by peer.
  49                 } else if (UNLIKELY(io_error)) {
  50                         return; // Some other error.
  51                 }
  52                 assert(bytes_written>=sizeof(MsgT));
  53         } else {
  54                 [[maybe_unused]] const std::size_t bytes_written=boost::asio::write(socket_, boost::asio::buffer(reinterpret_cast<std::uint8_t const *>(&message), message.length()), io_error);
  55                 if (UNLIKELY(io_error==boost::asio::error::eof)) {
  56                         return; // Connection closed cleanly by peer.
  57                 } else if (UNLIKELY(io_error)) {
  58                         return; // Some other error.
  59                 }
  60                 assert(bytes_written<=sizeof(MsgT));
  61                 assert(bytes_written>=message.length());
  62         }
  63 }
  64 
  65 template<class V, std::size_t N> inline void
  66 socket_wrapper::write(std::array<V, N> const &message) {
  67         [[maybe_unused]] const std::size_t bytes_written=boost::asio::write(socket_, boost::asio::buffer(message), io_error);
  68         if (UNLIKELY(io_error==boost::asio::error::eof)) {
  69                 return; // Connection closed cleanly by peer.
  70         } else if (UNLIKELY(io_error)) {
  71                 return; // Some other error.
  72         }
  73         assert(bytes_written>=sizeof(V)*N);
  74 }
  75 
  76 template<class MsgT> inline void
  77 socket_wrapper::read(MsgT &dest) {
  78         if (MsgT::has_static_size) {
  79                 using raw_buff_t=char [sizeof(MsgT)];
  80                 assert(dest.length()==sizeof(MsgT));
  81                 [[maybe_unused]] const std::size_t bytes_read=boost::asio::read(socket_, boost::asio::buffer(reinterpret_cast<raw_buff_t &>(dest)), io_error);
  82                 if (UNLIKELY(io_error==boost::asio::error::eof)) {
  83                         return; // Connection closed cleanly by peer.
  84                 } else if (UNLIKELY(io_error)) {
  85                         throw boost::system::system_error(io_error); // Some other error.
  86                 }
  87                 assert(bytes_read>0);
  88                 assert(bytes_read==sizeof(MsgT));
  89         } else {
  90                 [[maybe_unused]] const std::size_t bytes_read=boost::asio::read(socket_, boost::asio::buffer(reinterpret_cast<std::uint8_t *>(&dest), MsgT::header_t_size), io_error);
  91                 if (UNLIKELY(io_error==boost::asio::error::eof)) {
  92                         return; // Connection closed cleanly by peer.
  93                 } else if (UNLIKELY(io_error)) {
  94                         throw boost::system::system_error(io_error); // Some other error.
  95                 }
  96                 assert(bytes_read>0);
  97                 typename MsgT::Header_t const *hdr=reinterpret_cast<typename MsgT::Header_t const *>(&dest);
  98                 const std::size_t length=hdr->length();
  99                 const std::size_t header_t_sz=MsgT::header_t_size;
 100                 assert(length>=header_t_sz);
 101                 const std::size_t body_size=length-header_t_sz;
 102                 [[maybe_unused]] const std::size_t bytes_read1=boost::asio::read(socket_, boost::asio::buffer(reinterpret_cast<std::uint8_t *>(&dest)+MsgT::header_t_size, body_size), io_error);
 103                 if (UNLIKELY(io_error==boost::asio::error::eof)) {
 104                         return; // Connection closed cleanly by peer.
 105                 } else if (UNLIKELY(io_error)) {
 106                         throw boost::system::system_error(io_error); // Some other error.
 107                 }
 108                 assert(bytes_read1<=dest.length());
 109         }
 110 }
 111 
 112 template<class V, std::size_t SrcSz> inline void
 113 socket_wrapper::read(V (& dest)[SrcSz]) {
 114         [[maybe_unused]] const std::size_t bytes_read=boost::asio::read(socket_, boost::asio::buffer(dest));
 115         assert(bytes_read==sizeof(V)*SrcSz);
 116 }
 117 
 118 template<class MsgDetails, class V, std::size_t N> inline bool
 119 socket_wrapper::read(std::array<V, N> &buff) noexcept(false) {
 120         using msg_details_t=MsgDetails;
 121 
 122         assert(socket_.is_open());
 123         BOOST_MPL_ASSERT_RELATION(msg_details_t::max_msg_size, >=, msg_details_t::header_t_size);
 124         [[maybe_unused]] std::size_t len_read=boost::asio::read(socket_, boost::asio::buffer(buff, msg_details_t::header_t_size), io_error);
 125         if (UNLIKELY(io_error==boost::asio::error::eof)) {
 126 
 127                 return true; // Connection closed cleanly by peer.
 128         } else if (UNLIKELY(io_error)) {
 129                 throw boost::system::system_error(io_error); // Some other error.
 130         }
 131         assert(len_read>=msg_details_t::header_t_size);
 132         assert(len_read<=msg_details_t::max_msg_size);
 133         typename msg_details_t::Header_t const *hdr=reinterpret_cast<typename msg_details_t::Header_t const *>(buff.data());
 134         const std::size_t length=hdr->length();
 135         assert(length>=msg_details_t::header_t_size);
 136         const std::size_t body_size=length-msg_details_t::header_t_size;
 137         if (body_size) {
 138                 len_read=boost::asio::read(socket_, boost::asio::buffer(&*std::next(buff.begin(), msg_details_t::header_t_size), body_size), io_error);
 139                 if (io_error==boost::asio::error::eof) {
 140                         return true; // Connection closed cleanly by peer.
 141                 } else if (io_error) {
 142                         throw boost::system::system_error(io_error); // Some other error.
 143                 }
 144                 assert(len_read>=body_size);
 145                 assert(len_read<=msg_details_t::max_msg_size);
 146         }
 147         return false;
 148 }
 149 
 150 inline std::string
 151 socket_wrapper::to_string() const noexcept(false) {
 152         std::ostringstream ss;
 153         ss
 154                 <<"socket_="<<const_cast<boost::asio::ip::tcp::socket &>(socket_).native_handle();
 155         return ss.str();
 156 }
 157 
 158 inline std::ostream &
 159 operator<<(std::ostream &os, socket_wrapper const &ec) noexcept(false) {
 160         os<<ec.to_string();
 161         return os;
 162 }
 163 
 164 } } }

/* [<][>][^][v][top][bottom][index][help] */