00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __PION_TCPCONNECTION_HEADER__
00011 #define __PION_TCPCONNECTION_HEADER__
00012
00013 #ifdef PION_HAVE_SSL
00014 #ifdef PION_XCODE
00015
00016 #pragma GCC system_header
00017 #endif
00018 #include <boost/asio/ssl.hpp>
00019 #endif
00020
00021 #include <boost/noncopyable.hpp>
00022 #include <boost/shared_ptr.hpp>
00023 #include <boost/lexical_cast.hpp>
00024 #include <boost/enable_shared_from_this.hpp>
00025 #include <boost/asio.hpp>
00026 #include <boost/array.hpp>
00027 #include <boost/function.hpp>
00028 #include <boost/function/function1.hpp>
00029 #include <pion/PionConfig.hpp>
00030 #include <string>
00031
00032
00033 namespace pion {
00034 namespace net {
00035
00039 class TCPConnection :
00040 public boost::enable_shared_from_this<TCPConnection>,
00041 private boost::noncopyable
00042 {
00043 public:
00044
00046 enum LifecycleType {
00047 LIFECYCLE_CLOSE, LIFECYCLE_KEEPALIVE, LIFECYCLE_PIPELINED
00048 };
00049
00051 enum { READ_BUFFER_SIZE = 8192 };
00052
00054 typedef boost::function1<void, boost::shared_ptr<TCPConnection> > ConnectionHandler;
00055
00057 typedef boost::array<char, READ_BUFFER_SIZE> ReadBuffer;
00058
00060 typedef boost::asio::ip::tcp::socket Socket;
00061
00062 #ifdef PION_HAVE_SSL
00064 typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLSocket;
00065
00067 typedef boost::asio::ssl::context SSLContext;
00068 #else
00069 class SSLSocket {
00070 public:
00071 SSLSocket(boost::asio::io_service& io_service) : m_socket(io_service) {}
00072 inline Socket& next_layer(void) { return m_socket; }
00073 inline const Socket& next_layer(void) const { return m_socket; }
00074 inline Socket& lowest_layer(void) { return m_socket.lowest_layer(); }
00075 inline const Socket& lowest_layer(void) const { return m_socket.lowest_layer(); }
00076 private:
00077 Socket m_socket;
00078 };
00079 typedef int SSLContext;
00080 #endif
00081
00082
00092 static inline boost::shared_ptr<TCPConnection> create(boost::asio::io_service& io_service,
00093 SSLContext& ssl_context,
00094 const bool ssl_flag,
00095 ConnectionHandler finished_handler)
00096 {
00097 return boost::shared_ptr<TCPConnection>(new TCPConnection(io_service, ssl_context,
00098 ssl_flag, finished_handler));
00099 }
00100
00107 explicit TCPConnection(boost::asio::io_service& io_service, const bool ssl_flag = false)
00108 :
00109 #ifdef PION_HAVE_SSL
00110 m_ssl_context(io_service, boost::asio::ssl::context::sslv23),
00111 m_ssl_socket(io_service, m_ssl_context),
00112 m_ssl_flag(ssl_flag),
00113 #else
00114 m_ssl_context(0),
00115 m_ssl_socket(io_service),
00116 m_ssl_flag(false),
00117 #endif
00118 m_lifecycle(LIFECYCLE_CLOSE)
00119 {
00120 saveReadPosition(NULL, NULL);
00121 }
00122
00129 TCPConnection(boost::asio::io_service& io_service, SSLContext& ssl_context)
00130 :
00131 #ifdef PION_HAVE_SSL
00132 m_ssl_context(io_service, boost::asio::ssl::context::sslv23),
00133 m_ssl_socket(io_service, ssl_context), m_ssl_flag(true),
00134 #else
00135 m_ssl_context(0),
00136 m_ssl_socket(io_service), m_ssl_flag(false),
00137 #endif
00138 m_lifecycle(LIFECYCLE_CLOSE)
00139 {
00140 saveReadPosition(NULL, NULL);
00141 }
00142
00144 inline bool is_open(void) const {
00145 return const_cast<SSLSocket&>(m_ssl_socket).lowest_layer().is_open();
00146 }
00147
00149 inline void close(void) {
00150 if (m_ssl_socket.lowest_layer().is_open())
00151 m_ssl_socket.lowest_layer().close();
00152 }
00153
00154
00155
00156
00158
00159
00160
00161
00162
00164 virtual ~TCPConnection() { close(); }
00165
00174 template <typename AcceptHandler>
00175 inline void async_accept(boost::asio::ip::tcp::acceptor& tcp_acceptor,
00176 AcceptHandler handler)
00177 {
00178 tcp_acceptor.async_accept(m_ssl_socket.lowest_layer(), handler);
00179 }
00180
00189 inline boost::system::error_code accept(boost::asio::ip::tcp::acceptor& tcp_acceptor)
00190 {
00191 boost::system::error_code ec;
00192 tcp_acceptor.accept(m_ssl_socket.lowest_layer(), ec);
00193 return ec;
00194 }
00195
00204 template <typename ConnectHandler>
00205 inline void async_connect(boost::asio::ip::tcp::endpoint& tcp_endpoint,
00206 ConnectHandler handler)
00207 {
00208 m_ssl_socket.lowest_layer().async_connect(tcp_endpoint, handler);
00209 }
00210
00220 template <typename ConnectHandler>
00221 inline void async_connect(const boost::asio::ip::address& remote_addr,
00222 const unsigned int remote_port,
00223 ConnectHandler handler)
00224 {
00225 boost::asio::ip::tcp::endpoint tcp_endpoint(remote_addr, remote_port);
00226 async_connect(tcp_endpoint, handler);
00227 }
00228
00237 inline boost::system::error_code connect(boost::asio::ip::tcp::endpoint& tcp_endpoint)
00238 {
00239 boost::system::error_code ec;
00240 m_ssl_socket.lowest_layer().connect(tcp_endpoint, ec);
00241 return ec;
00242 }
00243
00253 inline boost::system::error_code connect(const boost::asio::ip::address& remote_addr,
00254 const unsigned int remote_port)
00255 {
00256 boost::asio::ip::tcp::endpoint tcp_endpoint(remote_addr, remote_port);
00257 return connect(tcp_endpoint);
00258 }
00259
00269 inline boost::system::error_code connect(const std::string& remote_server,
00270 const unsigned int remote_port)
00271 {
00272
00273 boost::system::error_code ec;
00274 boost::asio::ip::tcp::resolver resolver(m_ssl_socket.lowest_layer().get_io_service());
00275 boost::asio::ip::tcp::resolver::query query(remote_server,
00276 boost::lexical_cast<std::string>(remote_port),
00277 boost::asio::ip::tcp::resolver::query::numeric_service);
00278 boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, ec);
00279 if (ec)
00280 return ec;
00281
00282
00283 ec = boost::asio::error::host_not_found;
00284 boost::asio::ip::tcp::resolver::iterator end;
00285 while (ec && endpoint_iterator != end) {
00286 boost::asio::ip::tcp::endpoint ep(endpoint_iterator->endpoint());
00287 ++endpoint_iterator;
00288 ec = connect(ep);
00289 if (ec)
00290 close();
00291 }
00292
00293 return ec;
00294 }
00295
00303 template <typename SSLHandshakeHandler>
00304 inline void async_handshake_client(SSLHandshakeHandler handler) {
00305 #ifdef PION_HAVE_SSL
00306 m_ssl_socket.async_handshake(boost::asio::ssl::stream_base::client, handler);
00307 m_ssl_flag = true;
00308 #endif
00309 }
00310
00318 template <typename SSLHandshakeHandler>
00319 inline void async_handshake_server(SSLHandshakeHandler handler) {
00320 #ifdef PION_HAVE_SSL
00321 m_ssl_socket.async_handshake(boost::asio::ssl::stream_base::server, handler);
00322 m_ssl_flag = true;
00323 #endif
00324 }
00325
00333 inline boost::system::error_code handshake_client(void) {
00334 boost::system::error_code ec;
00335 #ifdef PION_HAVE_SSL
00336 m_ssl_socket.handshake(boost::asio::ssl::stream_base::client, ec);
00337 m_ssl_flag = true;
00338 #endif
00339 return ec;
00340 }
00341
00349 inline boost::system::error_code handshake_server(void) {
00350 boost::system::error_code ec;
00351 #ifdef PION_HAVE_SSL
00352 m_ssl_socket.handshake(boost::asio::ssl::stream_base::server, ec);
00353 m_ssl_flag = true;
00354 #endif
00355 return ec;
00356 }
00357
00365 template <typename ReadHandler>
00366 inline void async_read_some(ReadHandler handler) {
00367 #ifdef PION_HAVE_SSL
00368 if (getSSLFlag())
00369 m_ssl_socket.async_read_some(boost::asio::buffer(m_read_buffer),
00370 handler);
00371 else
00372 #endif
00373 m_ssl_socket.next_layer().async_read_some(boost::asio::buffer(m_read_buffer),
00374 handler);
00375 }
00376
00385 template <typename ReadBufferType, typename ReadHandler>
00386 inline void async_read_some(ReadBufferType read_buffer,
00387 ReadHandler handler) {
00388 #ifdef PION_HAVE_SSL
00389 if (getSSLFlag())
00390 m_ssl_socket.async_read_some(read_buffer, handler);
00391 else
00392 #endif
00393 m_ssl_socket.next_layer().async_read_some(read_buffer, handler);
00394 }
00395
00404 inline std::size_t read_some(boost::system::error_code& ec) {
00405 #ifdef PION_HAVE_SSL
00406 if (getSSLFlag())
00407 return m_ssl_socket.read_some(boost::asio::buffer(m_read_buffer), ec);
00408 else
00409 #endif
00410 return m_ssl_socket.next_layer().read_some(boost::asio::buffer(m_read_buffer), ec);
00411 }
00412
00422 template <typename ReadBufferType>
00423 inline std::size_t read_some(ReadBufferType read_buffer,
00424 boost::system::error_code& ec)
00425 {
00426 #ifdef PION_HAVE_SSL
00427 if (getSSLFlag())
00428 return m_ssl_socket.read_some(read_buffer, ec);
00429 else
00430 #endif
00431 return m_ssl_socket.next_layer().read_some(read_buffer, ec);
00432 }
00433
00443 template <typename CompletionCondition, typename ReadHandler>
00444 inline void async_read(CompletionCondition completion_condition,
00445 ReadHandler handler)
00446 {
00447 #ifdef PION_HAVE_SSL
00448 if (getSSLFlag())
00449 boost::asio::async_read(m_ssl_socket, boost::asio::buffer(m_read_buffer),
00450 completion_condition, handler);
00451 else
00452 #endif
00453 boost::asio::async_read(m_ssl_socket.next_layer(), boost::asio::buffer(m_read_buffer),
00454 completion_condition, handler);
00455 }
00456
00467 template <typename MutableBufferSequence, typename CompletionCondition, typename ReadHandler>
00468 inline void async_read(const MutableBufferSequence& buffers,
00469 CompletionCondition completion_condition,
00470 ReadHandler handler)
00471 {
00472 #ifdef PION_HAVE_SSL
00473 if (getSSLFlag())
00474 boost::asio::async_read(m_ssl_socket, buffers,
00475 completion_condition, handler);
00476 else
00477 #endif
00478 boost::asio::async_read(m_ssl_socket.next_layer(), buffers,
00479 completion_condition, handler);
00480 }
00481
00492 template <typename CompletionCondition>
00493 inline std::size_t read(CompletionCondition completion_condition,
00494 boost::system::error_code& ec)
00495 {
00496 #ifdef PION_HAVE_SSL
00497 if (getSSLFlag())
00498 return boost::asio::async_read(m_ssl_socket, boost::asio::buffer(m_read_buffer),
00499 completion_condition, ec);
00500 else
00501 #endif
00502 return boost::asio::async_read(m_ssl_socket.next_layer(), boost::asio::buffer(m_read_buffer),
00503 completion_condition, ec);
00504 }
00505
00517 template <typename MutableBufferSequence, typename CompletionCondition>
00518 inline std::size_t read(const MutableBufferSequence& buffers,
00519 CompletionCondition completion_condition,
00520 boost::system::error_code& ec)
00521 {
00522 #ifdef PION_HAVE_SSL
00523 if (getSSLFlag())
00524 return boost::asio::read(m_ssl_socket, buffers,
00525 completion_condition, ec);
00526 else
00527 #endif
00528 return boost::asio::read(m_ssl_socket.next_layer(), buffers,
00529 completion_condition, ec);
00530 }
00531
00540 template <typename ConstBufferSequence, typename WriteHandler>
00541 inline void async_write(const ConstBufferSequence& buffers, WriteHandler handler) {
00542 #ifdef PION_HAVE_SSL
00543 if (getSSLFlag())
00544 boost::asio::async_write(m_ssl_socket, buffers, handler);
00545 else
00546 #endif
00547 boost::asio::async_write(m_ssl_socket.next_layer(), buffers, handler);
00548 }
00549
00559 template <typename ConstBufferSequence>
00560 inline std::size_t write(const ConstBufferSequence& buffers,
00561 boost::system::error_code& ec)
00562 {
00563 #ifdef PION_HAVE_SSL
00564 if (getSSLFlag())
00565 return boost::asio::write(m_ssl_socket, buffers,
00566 boost::asio::transfer_all(), ec);
00567 else
00568 #endif
00569 return boost::asio::write(m_ssl_socket.next_layer(), buffers,
00570 boost::asio::transfer_all(), ec);
00571 }
00572
00573
00576 inline void finish(void) { if (m_finished_handler) m_finished_handler(shared_from_this()); }
00577
00579 inline bool getSSLFlag(void) const { return m_ssl_flag; }
00580
00582 inline void setLifecycle(LifecycleType t) { m_lifecycle = t; }
00583
00585 inline LifecycleType getLifecycle(void) const { return m_lifecycle; }
00586
00588 inline bool getKeepAlive(void) const { return m_lifecycle != LIFECYCLE_CLOSE; }
00589
00591 inline bool getPipelined(void) const { return m_lifecycle == LIFECYCLE_PIPELINED; }
00592
00594 inline ReadBuffer& getReadBuffer(void) { return m_read_buffer; }
00595
00602 inline void saveReadPosition(const char *read_ptr, const char *read_end_ptr) {
00603 m_read_position.first = read_ptr;
00604 m_read_position.second = read_end_ptr;
00605 }
00606
00613 inline void loadReadPosition(const char *&read_ptr, const char *&read_end_ptr) const {
00614 read_ptr = m_read_position.first;
00615 read_end_ptr = m_read_position.second;
00616 }
00617
00619 inline boost::asio::ip::tcp::endpoint getRemoteEndpoint(void) const {
00620 boost::asio::ip::tcp::endpoint remote_endpoint;
00621 try {
00622
00623 remote_endpoint = const_cast<SSLSocket&>(m_ssl_socket).lowest_layer().remote_endpoint();
00624 } catch (boost::system::system_error& ) {
00625
00626 }
00627 return remote_endpoint;
00628 }
00629
00631 inline boost::asio::ip::address getRemoteIp(void) const {
00632 return getRemoteEndpoint().address();
00633 }
00634
00636 inline unsigned short getRemotePort(void) const {
00637 return getRemoteEndpoint().port();
00638 }
00639
00641 inline boost::asio::io_service& getIOService(void) {
00642 return m_ssl_socket.lowest_layer().get_io_service();
00643 }
00644
00646 inline Socket& getSocket(void) { return m_ssl_socket.next_layer(); }
00647
00649 inline SSLSocket& getSSLSocket(void) { return m_ssl_socket; }
00650
00652 inline const Socket& getSocket(void) const { return const_cast<SSLSocket&>(m_ssl_socket).next_layer(); }
00653
00655 inline const SSLSocket& getSSLSocket(void) const { return m_ssl_socket; }
00656
00657
00658 protected:
00659
00669 TCPConnection(boost::asio::io_service& io_service,
00670 SSLContext& ssl_context,
00671 const bool ssl_flag,
00672 ConnectionHandler finished_handler)
00673 :
00674 #ifdef PION_HAVE_SSL
00675 m_ssl_context(io_service, boost::asio::ssl::context::sslv23),
00676 m_ssl_socket(io_service, ssl_context), m_ssl_flag(ssl_flag),
00677 #else
00678 m_ssl_context(0),
00679 m_ssl_socket(io_service), m_ssl_flag(false),
00680 #endif
00681 m_lifecycle(LIFECYCLE_CLOSE),
00682 m_finished_handler(finished_handler)
00683 {
00684 saveReadPosition(NULL, NULL);
00685 }
00686
00687
00688 private:
00689
00691 typedef std::pair<const char*, const char*> ReadPosition;
00692
00693
00695 SSLContext m_ssl_context;
00696
00698 SSLSocket m_ssl_socket;
00699
00701 bool m_ssl_flag;
00702
00704 ReadBuffer m_read_buffer;
00705
00707 ReadPosition m_read_position;
00708
00710 LifecycleType m_lifecycle;
00711
00713 ConnectionHandler m_finished_handler;
00714 };
00715
00716
00718 typedef boost::shared_ptr<TCPConnection> TCPConnectionPtr;
00719
00720
00721 }
00722 }
00723
00724 #endif