00001 #ifndef SERVICES_STREAM_SOCKET_SERVICE_HPP
00002 #define SERVICES_STREAM_SOCKET_SERVICE_HPP
00003
00004 #include <asio.hpp>
00005 #include <boost/noncopyable.hpp>
00006 #include <boost/lexical_cast.hpp>
00007 #include "logger.hpp"
00008
00009 namespace services {
00010
00012 template <typename Protocol>
00013 class stream_socket_service
00014 : public asio::io_service::service
00015 {
00016 private:
00018 typedef asio::stream_socket_service<Protocol> service_impl_type;
00019
00020 public:
00022 typedef Protocol protocol_type;
00023
00025 typedef typename Protocol::endpoint endpoint_type;
00026
00028 typedef typename service_impl_type::implementation_type implementation_type;
00029
00031 typedef typename service_impl_type::native_type native_type;
00032
00034 explicit stream_socket_service(asio::io_service& io_service)
00035 : asio::io_service::service(io_service),
00036 service_impl_(asio::use_service<service_impl_type>(io_service)),
00037 logger_(io_service, "stream_socket")
00038 {
00039 }
00040
00042 void shutdown_service()
00043 {
00044 }
00045
00047 void construct(implementation_type& impl)
00048 {
00049 service_impl_.construct(impl);
00050 }
00051
00053 void destroy(implementation_type& impl)
00054 {
00055 service_impl_.destroy(impl);
00056 }
00057
00059 template <typename Error_Handler>
00060 void open(implementation_type& impl, const protocol_type& protocol,
00061 Error_Handler error_handler)
00062 {
00063 logger_.log("Opening new socket");
00064 service_impl_.open(impl, protocol, error_handler);
00065 }
00066
00068 template <typename Error_Handler>
00069 void open(implementation_type& impl, const native_type& native_socket,
00070 Error_Handler error_handler)
00071 {
00072 logger_.log("Opening native socket");
00073 service_impl_.open(impl, native_socket, error_handler);
00074 }
00075
00077 template <typename Error_Handler>
00078 void close(implementation_type& impl, Error_Handler error_handler)
00079 {
00080 logger_.log("Closing socket");
00081 service_impl_.close(impl, error_handler);
00082 }
00083
00085 template <typename Error_Handler>
00086 void bind(implementation_type& impl, const endpoint_type& endpoint,
00087 Error_Handler error_handler)
00088 {
00089 logger_.log("Binding socket");
00090 service_impl_.bind(impl, endpoint, error_handler);
00091 }
00092
00094 template <typename Error_Handler>
00095 void connect(implementation_type& impl, const endpoint_type& peer_endpoint,
00096 Error_Handler error_handler)
00097 {
00098 logger_.log("Connecting socket to " +
00099 boost::lexical_cast<std::string>(peer_endpoint));
00100 service_impl_.connect(impl, peer_endpoint, error_handler);
00101 }
00102
00104 template <typename Handler>
00105 class connect_handler
00106 {
00107 public:
00108 connect_handler(Handler h, logger& l)
00109 : handler_(h),
00110 logger_(l)
00111 {
00112 }
00113
00114 void operator()(const asio::error& e)
00115 {
00116 if (e)
00117 {
00118 std::string msg = "Asynchronous connect failed: ";
00119 msg += e.what();
00120 logger_.log(msg);
00121 }
00122 else
00123 {
00124 logger_.log("Asynchronous connect succeeded");
00125 }
00126
00127 handler_(e);
00128 }
00129
00130 private:
00131 Handler handler_;
00132 logger& logger_;
00133 };
00134
00136 template <typename Handler>
00137 void async_connect(implementation_type& impl,
00138 const endpoint_type& peer_endpoint, Handler handler)
00139 {
00140 logger_.log("Starting asynchronous connect to " +
00141 boost::lexical_cast<std::string>(peer_endpoint));
00142 service_impl_.async_connect(impl, peer_endpoint,
00143 connect_handler<Handler>(handler, logger_));
00144 }
00145
00147 template <typename Option, typename Error_Handler>
00148 void set_option(implementation_type& impl, const Option& option,
00149 Error_Handler error_handler)
00150 {
00151 logger_.log("Setting socket option");
00152 service_impl_.set_option(impl, option, error_handler);
00153 }
00154
00156 template <typename Option, typename Error_Handler>
00157 void get_option(const implementation_type& impl, Option& option,
00158 Error_Handler error_handler) const
00159 {
00160 logger_.log("Getting socket option");
00161 service_impl_.get_option(impl, option, error_handler);
00162 }
00163
00165 template <typename IO_Control_Command, typename Error_Handler>
00166 void io_control(implementation_type& impl, IO_Control_Command& command,
00167 Error_Handler error_handler)
00168 {
00169 logger_.log("Performing IO control command on socket");
00170 service_impl_.io_control(impl, command, error_handler);
00171 }
00172
00174 template <typename Error_Handler>
00175 void local_endpoint(const implementation_type& impl,
00176 Error_Handler error_handler) const
00177 {
00178 logger_.log("Getting socket's local endpoint");
00179 return service_impl_.local_endpoint(impl, error_handler);
00180 }
00181
00183 template <typename Error_Handler>
00184 endpoint_type remote_endpoint(const implementation_type& impl,
00185 Error_Handler error_handler) const
00186 {
00187 logger_.log("Getting socket's remote endpoint");
00188 return service_impl_.remote_endpoint(impl, error_handler);
00189 }
00190
00192 template <typename Error_Handler>
00193 void shutdown(implementation_type& impl,
00194 asio::socket_base::shutdown_type what, Error_Handler error_handler)
00195 {
00196 logger_.log("Shutting down socket");
00197 service_impl_.shutdown(impl, what, error_handler);
00198 }
00199
00201 template <typename Const_Buffers, typename Error_Handler>
00202 std::size_t send(implementation_type& impl, const Const_Buffers& buffers,
00203 asio::socket_base::message_flags flags,
00204 Error_Handler error_handler)
00205 {
00206 logger_.log("Sending data on socket");
00207 return service_impl_.send(impl, buffers, flags, error_handler);
00208 }
00209
00211 template <typename Handler>
00212 class send_handler
00213 {
00214 public:
00215 send_handler(Handler h, logger& l)
00216 : handler_(h),
00217 logger_(l)
00218 {
00219 }
00220
00221 void operator()(const asio::error& e, std::size_t bytes_transferred)
00222 {
00223 if (e)
00224 {
00225 std::string msg = "Asynchronous send failed: ";
00226 msg += e.what();
00227 logger_.log(msg);
00228 }
00229 else
00230 {
00231 logger_.log("Asynchronous send succeeded");
00232 }
00233
00234 handler_(e, bytes_transferred);
00235 }
00236
00237 private:
00238 Handler handler_;
00239 logger& logger_;
00240 };
00241
00243 template <typename Const_Buffers, typename Handler>
00244 void async_send(implementation_type& impl, const Const_Buffers& buffers,
00245 asio::socket_base::message_flags flags, Handler handler)
00246 {
00247 logger_.log("Starting asynchronous send");
00248 service_impl_.async_send(impl, buffers, flags,
00249 send_handler<Handler>(handler, logger_));
00250 }
00251
00253 template <typename Mutable_Buffers, typename Error_Handler>
00254 std::size_t receive(implementation_type& impl, const Mutable_Buffers& buffers,
00255 asio::socket_base::message_flags flags,
00256 Error_Handler error_handler)
00257 {
00258 logger_.log("Receiving data on socket");
00259 return service_impl_.receive(impl, buffers, flags, error_handler);
00260 }
00261
00263 template <typename Handler>
00264 class receive_handler
00265 {
00266 public:
00267 receive_handler(Handler h, logger& l)
00268 : handler_(h),
00269 logger_(l)
00270 {
00271 }
00272
00273 void operator()(const asio::error& e, std::size_t bytes_transferred)
00274 {
00275 if (e)
00276 {
00277 std::string msg = "Asynchronous receive failed: ";
00278 msg += e.what();
00279 logger_.log(msg);
00280 }
00281 else
00282 {
00283 logger_.log("Asynchronous receive succeeded");
00284 }
00285
00286 handler_(e, bytes_transferred);
00287 }
00288
00289 private:
00290 Handler handler_;
00291 logger& logger_;
00292 };
00293
00295 template <typename Mutable_Buffers, typename Handler>
00296 void async_receive(implementation_type& impl, const Mutable_Buffers& buffers,
00297 asio::socket_base::message_flags flags, Handler handler)
00298 {
00299 logger_.log("Starting asynchronous receive");
00300 service_impl_.async_receive(impl, buffers, flags,
00301 receive_handler<Handler>(handler, logger_));
00302 }
00303
00304 private:
00306 service_impl_type& service_impl_;
00307
00309 logger logger_;
00310 };
00311
00312 }
00313
00314 #endif // SERVICES_STREAM_SOCKET_SERVICE_HPP