00001
00002
00003
00004
00005
00006
00007
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 {
00026 namespace net {
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);
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 }
00236 }
00237
00238 #endif