# net/include/pion/net/TCPServer.hpp

    00001 // ------------------------------------------------------------------
    00002 // pion-net: a C++ framework for building lightweight HTTP interfaces
    00003 // ------------------------------------------------------------------
    00004 // Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
    00005 //
    00006 // Distributed under the Boost Software License, Version 1.0.
    00007 // See http://www.boost.org/LICENSE_1_0.txt
    00008 //
    00009
    00010 #ifndef __PION_TCPSERVER_HEADER__
    00011 #define __PION_TCPSERVER_HEADER__
    00012
    00013 #include <set>
    00014 #include <boost/asio.hpp>
    00015 #include <boost/noncopyable.hpp>
    00016 #include <boost/shared_ptr.hpp>
    00017 #include <boost/thread/mutex.hpp>
    00018 #include <boost/thread/condition.hpp>
    00019 #include <pion/PionConfig.hpp>
    00020 #include <pion/PionLogger.hpp>
    00021 #include <pion/PionScheduler.hpp>
    00022 #include <pion/net/TCPConnection.hpp>
    00023
    00024
    00025 namespace pion {    // begin namespace pion
    00026 namespace net {     // begin namespace net (Pion Network Library)
    00027
    00031 class PION_NET_API TCPServer :
    00032     private boost::noncopyable
    00033 {
    00034 public:
    00035
    00037     virtual ~TCPServer() { if (m_is_listening) stop(false); }
    00038
    00040     void start(void);
    00041
    00047     void stop(bool wait_until_finished = false);
    00048
    00050     void join(void);
    00051
    00057     void setSSLKeyFile(const std::string& pem_key_file);
    00058
    00060     std::size_t getConnections(void) const;
    00061
    00063     inline unsigned int getPort(void) const { return m_endpoint.port(); }
    00064
    00066     inline void setPort(unsigned int p) { m_endpoint.port(p); }
    00067
    00069     inline boost::asio::ip::address getAddress(void) const { return m_endpoint.address(); }
    00070
    00072     inline void setAddress(const boost::asio::ip::address& addr) { m_endpoint.address(addr); }
    00073
    00075     inline const boost::asio::ip::tcp::endpoint& getEndpoint(void) const { return m_endpoint; }
    00076
    00078     inline void setEndpoint(const boost::asio::ip::tcp::endpoint& ep) { m_endpoint = ep; }
    00079
    00081     inline bool getSSLFlag(void) const { return m_ssl_flag; }
    00082
    00084     inline void setSSLFlag(bool b = true) { m_ssl_flag = b; }
    00085
    00087     inline TCPConnection::SSLContext& getSSLContext(void) { return m_ssl_context; }
    00088
    00090     inline bool isListening(void) const { return m_is_listening; }
    00091
    00093     inline void setLogger(PionLogger log_ptr) { m_logger = log_ptr; }
    00094
    00096     inline PionLogger getLogger(void) { return m_logger; }
    00097
    00098
    00099 protected:
    00100
    00106     explicit TCPServer(const unsigned int tcp_port);
    00107
    00113     explicit TCPServer(const boost::asio::ip::tcp::endpoint& endpoint);
    00114
    00121     explicit TCPServer(PionScheduler& scheduler, const unsigned int tcp_port = 0);
    00122
    00129     TCPServer(PionScheduler& scheduler, const boost::asio::ip::tcp::endpoint& endpoint);
    00130
    00137     virtual void handleConnection(TCPConnectionPtr& tcp_conn) {
    00138         tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE); // make sure it will get closed
    00139         tcp_conn->finish();
    00140     }
    00141
    00143     virtual void beforeStarting(void) {}
    00144
    00146     virtual void afterStopping(void) {}
    00147
    00149     inline boost::asio::io_service& getIOService(void) { return m_active_scheduler.getIOService(); }
    00150
    00151
    00153     PionLogger                  m_logger;
    00154
    00155
    00156 private:
    00157
    00159     void handleStopRequest(void);
    00160
    00162     void listen(void);
    00163
    00170     void handleAccept(TCPConnectionPtr& tcp_conn,
    00171                       const boost::system::error_code& accept_error);
    00172
    00179     void handleSSLHandshake(TCPConnectionPtr& tcp_conn,
    00180                             const boost::system::error_code& handshake_error);
    00181
    00186     void finishConnection(TCPConnectionPtr& tcp_conn);
    00187
    00190     std::size_t pruneConnections(void);
    00191
    00193     typedef std::set<TCPConnectionPtr>      ConnectionPool;
    00194
    00195
    00197     PionSingleServiceScheduler              m_default_scheduler;
    00198
    00200     PionScheduler &                         m_active_scheduler;
    00201
    00203     boost::asio::ip::tcp::acceptor          m_tcp_acceptor;
    00204
    00206     TCPConnection::SSLContext               m_ssl_context;
    00207
    00209     boost::condition                        m_server_has_stopped;
    00210
    00212     boost::condition                        m_no_more_connections;
    00213
    00215     ConnectionPool                          m_conn_pool;
    00216
    00218     boost::asio::ip::tcp::endpoint          m_endpoint;
    00219
    00221     bool                                    m_ssl_flag;
    00222
    00224     bool                                    m_is_listening;
    00225
    00227     mutable boost::mutex                    m_mutex;
    00228 };
    00229
    00230
    00232 typedef boost::shared_ptr<TCPServer>    TCPServerPtr;
    00233
    00234
    00235 }   // end namespace net
    00236 }   // end namespace pion
    00237
    00238 #endif