10 #ifndef __PION_TCP_CONNECTION_HEADER__
11 #define __PION_TCP_CONNECTION_HEADER__
16 #pragma GCC system_header
18 #include <boost/asio/ssl.hpp>
21 #include <boost/noncopyable.hpp>
22 #include <boost/shared_ptr.hpp>
23 #include <boost/lexical_cast.hpp>
24 #include <boost/enable_shared_from_this.hpp>
25 #include <boost/asio.hpp>
26 #include <boost/array.hpp>
27 #include <boost/function.hpp>
28 #include <boost/function/function1.hpp>
29 #include <pion/config.hpp>
41 public boost::enable_shared_from_this<connection>,
42 private boost::noncopyable
48 LIFECYCLE_CLOSE, LIFECYCLE_KEEPALIVE, LIFECYCLE_PIPELINED
52 enum { READ_BUFFER_SIZE = 8192 };
64 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket>
ssl_socket_type;
68 typedef boost::asio::ssl::context ssl_context_type;
70 class ssl_socket_type {
72 ssl_socket_type(boost::asio::io_service& io_service) : m_socket(io_service) {}
73 inline socket_type& next_layer(
void) {
return m_socket; }
74 inline const socket_type& next_layer(
void)
const {
return m_socket; }
75 inline socket_type::lowest_layer_type& lowest_layer(
void) {
return m_socket.lowest_layer(); }
76 inline const socket_type::lowest_layer_type& lowest_layer(
void)
const {
return m_socket.lowest_layer(); }
77 inline void shutdown(
void) {}
81 typedef int ssl_context_type;
94 static inline boost::shared_ptr<connection>
create(boost::asio::io_service& io_service,
95 ssl_context_type& ssl_context,
97 connection_handler finished_handler)
99 return boost::shared_ptr<connection>(
new connection(io_service, ssl_context,
100 ssl_flag, finished_handler));
109 explicit connection(boost::asio::io_service& io_service,
const bool ssl_flag =
false)
112 m_ssl_context(io_service, boost::asio::ssl::context::sslv23),
113 m_ssl_socket(io_service, m_ssl_context),
114 m_ssl_flag(ssl_flag),
117 m_ssl_socket(io_service),
120 m_lifecycle(LIFECYCLE_CLOSE)
131 connection(boost::asio::io_service& io_service, ssl_context_type& ssl_context)
134 m_ssl_context(io_service, boost::asio::ssl::context::sslv23),
135 m_ssl_socket(io_service, ssl_context), m_ssl_flag(true),
138 m_ssl_socket(io_service), m_ssl_flag(false),
140 m_lifecycle(LIFECYCLE_CLOSE)
147 return const_cast<ssl_socket_type&
>(m_ssl_socket).lowest_layer().is_open();
161 m_ssl_socket.next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both);
166 boost::system::error_code ec;
167 m_ssl_socket.next_layer().close(ec);
177 #if !defined(_MSC_VER) || (_WIN32_WINNT >= 0x0600)
178 boost::system::error_code ec;
179 m_ssl_socket.next_layer().cancel(ec);
194 template <
typename AcceptHandler>
196 AcceptHandler handler)
198 tcp_acceptor.async_accept(m_ssl_socket.lowest_layer(), handler);
209 inline boost::system::error_code
accept(boost::asio::ip::tcp::acceptor& tcp_acceptor)
211 boost::system::error_code ec;
212 tcp_acceptor.accept(m_ssl_socket.lowest_layer(), ec);
224 template <
typename ConnectHandler>
225 inline void async_connect(
const boost::asio::ip::tcp::endpoint& tcp_endpoint,
226 ConnectHandler handler)
228 m_ssl_socket.lowest_layer().async_connect(tcp_endpoint, handler);
240 template <
typename ConnectHandler>
242 const unsigned int remote_port,
243 ConnectHandler handler)
245 boost::asio::ip::tcp::endpoint tcp_endpoint(remote_addr, remote_port);
257 inline boost::system::error_code
connect(boost::asio::ip::tcp::endpoint& tcp_endpoint)
259 boost::system::error_code ec;
260 m_ssl_socket.lowest_layer().connect(tcp_endpoint, ec);
273 inline boost::system::error_code
connect(
const boost::asio::ip::address& remote_addr,
274 const unsigned int remote_port)
276 boost::asio::ip::tcp::endpoint tcp_endpoint(remote_addr, remote_port);
289 inline boost::system::error_code
connect(
const std::string& remote_server,
290 const unsigned int remote_port)
293 boost::system::error_code ec;
294 boost::asio::ip::tcp::resolver resolver(m_ssl_socket.lowest_layer().get_io_service());
295 boost::asio::ip::tcp::resolver::query query(remote_server,
296 boost::lexical_cast<std::string>(remote_port),
297 boost::asio::ip::tcp::resolver::query::numeric_service);
298 boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, ec);
303 ec = boost::asio::error::host_not_found;
304 boost::asio::ip::tcp::resolver::iterator end;
305 while (ec && endpoint_iterator != end) {
306 boost::asio::ip::tcp::endpoint ep(endpoint_iterator->endpoint());
323 template <
typename SSLHandshakeHandler>
326 m_ssl_socket.async_handshake(boost::asio::ssl::stream_base::client, handler);
338 template <
typename SSLHandshakeHandler>
341 m_ssl_socket.async_handshake(boost::asio::ssl::stream_base::server, handler);
354 boost::system::error_code ec;
356 m_ssl_socket.handshake(boost::asio::ssl::stream_base::client, ec);
370 boost::system::error_code ec;
372 m_ssl_socket.handshake(boost::asio::ssl::stream_base::server, ec);
385 template <
typename ReadHandler>
389 m_ssl_socket.async_read_some(boost::asio::buffer(m_read_buffer),
393 m_ssl_socket.next_layer().async_read_some(boost::asio::buffer(m_read_buffer),
405 template <
typename ReadBufferType,
typename ReadHandler>
407 ReadHandler handler) {
410 m_ssl_socket.async_read_some(read_buffer, handler);
413 m_ssl_socket.next_layer().async_read_some(read_buffer, handler);
424 inline std::size_t
read_some(boost::system::error_code& ec) {
427 return m_ssl_socket.read_some(boost::asio::buffer(m_read_buffer), ec);
430 return m_ssl_socket.next_layer().read_some(boost::asio::buffer(m_read_buffer), ec);
442 template <
typename ReadBufferType>
443 inline std::size_t
read_some(ReadBufferType read_buffer,
444 boost::system::error_code& ec)
448 return m_ssl_socket.read_some(read_buffer, ec);
451 return m_ssl_socket.next_layer().read_some(read_buffer, ec);
463 template <
typename CompletionCondition,
typename ReadHandler>
464 inline void async_read(CompletionCondition completion_condition,
469 boost::asio::async_read(m_ssl_socket, boost::asio::buffer(m_read_buffer),
470 completion_condition, handler);
473 boost::asio::async_read(m_ssl_socket.next_layer(), boost::asio::buffer(m_read_buffer),
474 completion_condition, handler);
487 template <
typename MutableBufferSequence,
typename CompletionCondition,
typename ReadHandler>
489 CompletionCondition completion_condition,
494 boost::asio::async_read(m_ssl_socket, buffers,
495 completion_condition, handler);
498 boost::asio::async_read(m_ssl_socket.next_layer(), buffers,
499 completion_condition, handler);
512 template <
typename CompletionCondition>
513 inline std::size_t
read(CompletionCondition completion_condition,
514 boost::system::error_code& ec)
518 return boost::asio::async_read(m_ssl_socket, boost::asio::buffer(m_read_buffer),
519 completion_condition, ec);
522 return boost::asio::async_read(m_ssl_socket.next_layer(), boost::asio::buffer(m_read_buffer),
523 completion_condition, ec);
537 template <
typename MutableBufferSequence,
typename CompletionCondition>
538 inline std::size_t
read(
const MutableBufferSequence& buffers,
539 CompletionCondition completion_condition,
540 boost::system::error_code& ec)
544 return boost::asio::read(m_ssl_socket, buffers,
545 completion_condition, ec);
548 return boost::asio::read(m_ssl_socket.next_layer(), buffers,
549 completion_condition, ec);
560 template <
typename ConstBufferSequence,
typename write_handler_t>
561 inline void async_write(
const ConstBufferSequence& buffers, write_handler_t handler) {
564 boost::asio::async_write(m_ssl_socket, buffers, handler);
567 boost::asio::async_write(m_ssl_socket.next_layer(), buffers, handler);
579 template <
typename ConstBufferSequence>
580 inline std::size_t
write(
const ConstBufferSequence& buffers,
581 boost::system::error_code& ec)
585 return boost::asio::write(m_ssl_socket, buffers,
586 boost::asio::transfer_all(), ec);
589 return boost::asio::write(m_ssl_socket.next_layer(), buffers,
590 boost::asio::transfer_all(), ec);
596 inline void finish(
void) {
if (m_finished_handler) m_finished_handler(shared_from_this()); }
608 inline bool get_keep_alive(
void)
const {
return m_lifecycle != LIFECYCLE_CLOSE; }
611 inline bool get_pipelined(
void)
const {
return m_lifecycle == LIFECYCLE_PIPELINED; }
623 m_read_position.first = read_ptr;
624 m_read_position.second = read_end_ptr;
633 inline void load_read_pos(
const char *&read_ptr,
const char *&read_end_ptr)
const {
634 read_ptr = m_read_position.first;
635 read_end_ptr = m_read_position.second;
640 boost::asio::ip::tcp::endpoint remote_endpoint;
643 remote_endpoint =
const_cast<ssl_socket_type&
>(m_ssl_socket).lowest_layer().remote_endpoint();
644 }
catch (boost::system::system_error& ) {
647 return remote_endpoint;
662 return m_ssl_socket.lowest_layer().get_io_service();
666 inline socket_type&
get_socket(
void) {
return m_ssl_socket.next_layer(); }
672 inline const socket_type&
get_socket(
void)
const {
return const_cast<ssl_socket_type&
>(m_ssl_socket).next_layer(); }
675 inline const ssl_socket_type&
get_ssl_socket(
void)
const {
return m_ssl_socket; }
690 ssl_context_type& ssl_context,
692 connection_handler finished_handler)
695 m_ssl_context(io_service, boost::asio::ssl::context::sslv23),
696 m_ssl_socket(io_service, ssl_context), m_ssl_flag(ssl_flag),
699 m_ssl_socket(io_service), m_ssl_flag(false),
701 m_lifecycle(LIFECYCLE_CLOSE),
702 m_finished_handler(finished_handler)
711 typedef std::pair<const char*, const char*> read_pos_type;
715 ssl_context_type m_ssl_context;
718 ssl_socket_type m_ssl_socket;
724 read_buffer_type m_read_buffer;
727 read_pos_type m_read_position;
733 connection_handler m_finished_handler;
738 typedef boost::shared_ptr<connection> connection_ptr;
const ssl_socket_type & get_ssl_socket(void) const
returns const reference to underlying SSL socket object
void save_read_pos(const char *read_ptr, const char *read_end_ptr)
boost::system::error_code handshake_client(void)
connection(boost::asio::io_service &io_service, ssl_context_type &ssl_context, const bool ssl_flag, connection_handler finished_handler)
boost::system::error_code handshake_server(void)
static boost::shared_ptr< connection > create(boost::asio::io_service &io_service, ssl_context_type &ssl_context, const bool ssl_flag, connection_handler finished_handler)
boost::asio::ip::tcp::endpoint get_remote_endpoint(void) const
returns an ASIO endpoint for the client connection
bool get_keep_alive(void) const
returns true if the connection should be kept alive
lifecycle_type get_lifecycle(void) const
returns the lifecycle type for the connection
boost::function1< void, boost::shared_ptr< connection > > connection_handler
data type for a function that handles TCP connection objects
void async_handshake_client(SSLHandshakeHandler handler)
boost::asio::ip::tcp::socket socket_type
data type for a socket connection
std::size_t read(const MutableBufferSequence &buffers, CompletionCondition completion_condition, boost::system::error_code &ec)
boost::asio::ip::address get_remote_ip(void) const
returns the client's IP address
void async_read(CompletionCondition completion_condition, ReadHandler handler)
std::size_t read(CompletionCondition completion_condition, boost::system::error_code &ec)
void async_read(const MutableBufferSequence &buffers, CompletionCondition completion_condition, ReadHandler handler)
boost::asio::io_service & get_io_service(void)
returns reference to the io_service used for async operations
bool get_pipelined(void) const
returns true if the HTTP requests are pipelined
void async_handshake_server(SSLHandshakeHandler handler)
std::size_t read_some(ReadBufferType read_buffer, boost::system::error_code &ec)
virtual ~connection()
virtual destructor
const socket_type & get_socket(void) const
returns const reference to underlying TCP socket object
void close(void)
closes the tcp socket and cancels any pending asynchronous operations
std::size_t read_some(boost::system::error_code &ec)
read_buffer_type & get_read_buffer(void)
returns the buffer used for reading data from the TCP connection
void async_connect(const boost::asio::ip::address &remote_addr, const unsigned int remote_port, ConnectHandler handler)
void async_read_some(ReadBufferType read_buffer, ReadHandler handler)
boost::array< char, READ_BUFFER_SIZE > read_buffer_type
data type for an I/O read buffer
socket_type & get_socket(void)
returns non-const reference to underlying TCP socket object
void load_read_pos(const char *&read_ptr, const char *&read_end_ptr) const
bool is_open(void) const
returns true if the connection is currently open
void async_accept(boost::asio::ip::tcp::acceptor &tcp_acceptor, AcceptHandler handler)
void async_read_some(ReadHandler handler)
unsigned short get_remote_port(void) const
returns the client's port number
void set_lifecycle(lifecycle_type t)
sets the lifecycle type for the connection
ssl_socket_type & get_ssl_socket(void)
returns non-const reference to underlying SSL socket object
boost::system::error_code connect(const boost::asio::ip::address &remote_addr, const unsigned int remote_port)
lifecycle_type
data type for the connection's lifecycle state
void async_write(const ConstBufferSequence &buffers, write_handler_t handler)
void async_connect(const boost::asio::ip::tcp::endpoint &tcp_endpoint, ConnectHandler handler)
connection(boost::asio::io_service &io_service, ssl_context_type &ssl_context)
std::size_t write(const ConstBufferSequence &buffers, boost::system::error_code &ec)
bool get_ssl_flag(void) const
returns true if the connection is encrypted using SSL
boost::system::error_code accept(boost::asio::ip::tcp::acceptor &tcp_acceptor)
boost::system::error_code connect(const std::string &remote_server, const unsigned int remote_port)
boost::system::error_code connect(boost::asio::ip::tcp::endpoint &tcp_endpoint)
connection(boost::asio::io_service &io_service, const bool ssl_flag=false)