00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef SERVICES_STREAM_SOCKET_SERVICE_HPP
00012 #define SERVICES_STREAM_SOCKET_SERVICE_HPP
00013
00014 #include <asio.hpp>
00015 #include <boost/noncopyable.hpp>
00016 #include <boost/lexical_cast.hpp>
00017 #include "logger.hpp"
00018
00019 namespace services {
00020
00022 template <typename Protocol>
00023 class stream_socket_service
00024 : public asio::io_service::service
00025 {
00026 private:
00028 typedef asio::stream_socket_service<Protocol> service_impl_type;
00029
00030 public:
00032 static asio::io_service::id id;
00033
00035 typedef Protocol protocol_type;
00036
00038 typedef typename Protocol::endpoint endpoint_type;
00039
00041 typedef typename service_impl_type::implementation_type implementation_type;
00042
00044 typedef typename service_impl_type::native_type native_type;
00045
00047 explicit stream_socket_service(asio::io_service& io_service)
00048 : asio::io_service::service(io_service),
00049 service_impl_(asio::use_service<service_impl_type>(io_service)),
00050 logger_(io_service, "stream_socket")
00051 {
00052 }
00053
00055 void shutdown_service()
00056 {
00057 }
00058
00060 void construct(implementation_type& impl)
00061 {
00062 service_impl_.construct(impl);
00063 }
00064
00066 void destroy(implementation_type& impl)
00067 {
00068 service_impl_.destroy(impl);
00069 }
00070
00072 asio::error_code open(implementation_type& impl,
00073 const protocol_type& protocol, asio::error_code& ec)
00074 {
00075 logger_.log("Opening new socket");
00076 return service_impl_.open(impl, protocol, ec);
00077 }
00078
00080 asio::error_code assign(implementation_type& impl,
00081 const protocol_type& protocol, const native_type& native_socket,
00082 asio::error_code& ec)
00083 {
00084 logger_.log("Assigning from a native socket");
00085 return service_impl_.assign(impl, protocol, native_socket, ec);
00086 }
00087
00089 bool is_open(const implementation_type& impl) const
00090 {
00091 logger_.log("Checking if socket is open");
00092 return service_impl_.is_open(impl);
00093 }
00094
00096 asio::error_code close(implementation_type& impl,
00097 asio::error_code& ec)
00098 {
00099 logger_.log("Closing socket");
00100 return service_impl_.close(impl, ec);
00101 }
00102
00104 bool at_mark(const implementation_type& impl,
00105 asio::error_code& ec) const
00106 {
00107 logger_.log("Checking if socket is at out-of-band data mark");
00108 return service_impl_.at_mark(impl, ec);
00109 }
00110
00112 std::size_t available(const implementation_type& impl,
00113 asio::error_code& ec) const
00114 {
00115 logger_.log("Determining number of bytes available for reading");
00116 return service_impl_.available(impl, ec);
00117 }
00118
00120 asio::error_code bind(implementation_type& impl,
00121 const endpoint_type& endpoint, asio::error_code& ec)
00122 {
00123 logger_.log("Binding socket");
00124 return service_impl_.bind(impl, endpoint, ec);
00125 }
00126
00128 asio::error_code connect(implementation_type& impl,
00129 const endpoint_type& peer_endpoint, asio::error_code& ec)
00130 {
00131 logger_.log("Connecting socket to " +
00132 boost::lexical_cast<std::string>(peer_endpoint));
00133 return service_impl_.connect(impl, peer_endpoint, ec);
00134 }
00135
00137 template <typename Handler>
00138 class connect_handler
00139 {
00140 public:
00141 connect_handler(Handler h, logger& l)
00142 : handler_(h),
00143 logger_(l)
00144 {
00145 }
00146
00147 void operator()(const asio::error_code& e)
00148 {
00149 if (e)
00150 {
00151 std::string msg = "Asynchronous connect failed: ";
00152 msg += e.message();
00153 logger_.log(msg);
00154 }
00155 else
00156 {
00157 logger_.log("Asynchronous connect succeeded");
00158 }
00159
00160 handler_(e);
00161 }
00162
00163 private:
00164 Handler handler_;
00165 logger& logger_;
00166 };
00167
00169 template <typename Handler>
00170 void async_connect(implementation_type& impl,
00171 const endpoint_type& peer_endpoint, Handler handler)
00172 {
00173 logger_.log("Starting asynchronous connect to " +
00174 boost::lexical_cast<std::string>(peer_endpoint));
00175 service_impl_.async_connect(impl, peer_endpoint,
00176 connect_handler<Handler>(handler, logger_));
00177 }
00178
00180 template <typename Option>
00181 asio::error_code set_option(implementation_type& impl,
00182 const Option& option, asio::error_code& ec)
00183 {
00184 logger_.log("Setting socket option");
00185 return service_impl_.set_option(impl, option, ec);
00186 }
00187
00189 template <typename Option>
00190 asio::error_code get_option(const implementation_type& impl,
00191 Option& option, asio::error_code& ec) const
00192 {
00193 logger_.log("Getting socket option");
00194 return service_impl_.get_option(impl, option, ec);
00195 }
00196
00198 template <typename IO_Control_Command>
00199 asio::error_code io_control(implementation_type& impl,
00200 IO_Control_Command& command, asio::error_code& ec)
00201 {
00202 logger_.log("Performing IO control command on socket");
00203 return service_impl_.io_control(impl, command, ec);
00204 }
00205
00207 endpoint_type local_endpoint(const implementation_type& impl,
00208 asio::error_code& ec) const
00209 {
00210 logger_.log("Getting socket's local endpoint");
00211 return service_impl_.local_endpoint(impl, ec);
00212 }
00213
00215 endpoint_type remote_endpoint(const implementation_type& impl,
00216 asio::error_code& ec) const
00217 {
00218 logger_.log("Getting socket's remote endpoint");
00219 return service_impl_.remote_endpoint(impl, ec);
00220 }
00221
00223 asio::error_code shutdown(implementation_type& impl,
00224 asio::socket_base::shutdown_type what,
00225 asio::error_code& ec)
00226 {
00227 logger_.log("Shutting down socket");
00228 return service_impl_.shutdown(impl, what, ec);
00229 }
00230
00232 template <typename Const_Buffers>
00233 std::size_t send(implementation_type& impl, const Const_Buffers& buffers,
00234 asio::socket_base::message_flags flags,
00235 asio::error_code& ec)
00236 {
00237 logger_.log("Sending data on socket");
00238 return service_impl_.send(impl, buffers, flags, ec);
00239 }
00240
00242 template <typename Handler>
00243 class send_handler
00244 {
00245 public:
00246 send_handler(Handler h, logger& l)
00247 : handler_(h),
00248 logger_(l)
00249 {
00250 }
00251
00252 void operator()(const asio::error_code& e,
00253 std::size_t bytes_transferred)
00254 {
00255 if (e)
00256 {
00257 std::string msg = "Asynchronous send failed: ";
00258 msg += e.message();
00259 logger_.log(msg);
00260 }
00261 else
00262 {
00263 logger_.log("Asynchronous send succeeded");
00264 }
00265
00266 handler_(e, bytes_transferred);
00267 }
00268
00269 private:
00270 Handler handler_;
00271 logger& logger_;
00272 };
00273
00275 template <typename Const_Buffers, typename Handler>
00276 void async_send(implementation_type& impl, const Const_Buffers& buffers,
00277 asio::socket_base::message_flags flags, Handler handler)
00278 {
00279 logger_.log("Starting asynchronous send");
00280 service_impl_.async_send(impl, buffers, flags,
00281 send_handler<Handler>(handler, logger_));
00282 }
00283
00285 template <typename Mutable_Buffers>
00286 std::size_t receive(implementation_type& impl,
00287 const Mutable_Buffers& buffers,
00288 asio::socket_base::message_flags flags,
00289 asio::error_code& ec)
00290 {
00291 logger_.log("Receiving data on socket");
00292 return service_impl_.receive(impl, buffers, flags, ec);
00293 }
00294
00296 template <typename Handler>
00297 class receive_handler
00298 {
00299 public:
00300 receive_handler(Handler h, logger& l)
00301 : handler_(h),
00302 logger_(l)
00303 {
00304 }
00305
00306 void operator()(const asio::error_code& e,
00307 std::size_t bytes_transferred)
00308 {
00309 if (e)
00310 {
00311 std::string msg = "Asynchronous receive failed: ";
00312 msg += e.message();
00313 logger_.log(msg);
00314 }
00315 else
00316 {
00317 logger_.log("Asynchronous receive succeeded");
00318 }
00319
00320 handler_(e, bytes_transferred);
00321 }
00322
00323 private:
00324 Handler handler_;
00325 logger& logger_;
00326 };
00327
00329 template <typename Mutable_Buffers, typename Handler>
00330 void async_receive(implementation_type& impl, const Mutable_Buffers& buffers,
00331 asio::socket_base::message_flags flags, Handler handler)
00332 {
00333 logger_.log("Starting asynchronous receive");
00334 service_impl_.async_receive(impl, buffers, flags,
00335 receive_handler<Handler>(handler, logger_));
00336 }
00337
00338 private:
00340 service_impl_type& service_impl_;
00341
00343 mutable logger logger_;
00344 };
00345
00346 template <typename Protocol>
00347 asio::io_service::id stream_socket_service<Protocol>::id;
00348
00349 }
00350
00351 #endif // SERVICES_STREAM_SOCKET_SERVICE_HPP