00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __PION_TCP_SERVER_HEADER__
00011 #define __PION_TCP_SERVER_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/config.hpp>
00020 #include <pion/logger.hpp>
00021 #include <pion/scheduler.hpp>
00022 #include <pion/tcp/connection.hpp>
00023
00024
00025 namespace pion {
00026 namespace tcp {
00027
00028
00032 class PION_API server :
00033 private boost::noncopyable
00034 {
00035 public:
00036
00038 virtual ~server() { if (m_is_listening) stop(false); }
00039
00041 void start(void);
00042
00048 void stop(bool wait_until_finished = false);
00049
00051 void join(void);
00052
00058 void set_ssl_key_file(const std::string& pem_key_file);
00059
00061 std::size_t get_connections(void) const;
00062
00064 inline unsigned int get_port(void) const { return m_endpoint.port(); }
00065
00067 inline void set_port(unsigned int p) { m_endpoint.port(p); }
00068
00070 inline boost::asio::ip::address get_address(void) const { return m_endpoint.address(); }
00071
00073 inline void set_address(const boost::asio::ip::address& addr) { m_endpoint.address(addr); }
00074
00076 inline const boost::asio::ip::tcp::endpoint& get_endpoint(void) const { return m_endpoint; }
00077
00079 inline void set_endpoint(const boost::asio::ip::tcp::endpoint& ep) { m_endpoint = ep; }
00080
00082 inline bool get_ssl_flag(void) const { return m_ssl_flag; }
00083
00085 inline void set_ssl_flag(bool b = true) { m_ssl_flag = b; }
00086
00088 inline connection::ssl_context_type& get_ssl_context_type(void) { return m_ssl_context; }
00089
00091 inline bool is_listening(void) const { return m_is_listening; }
00092
00094 inline void set_logger(logger log_ptr) { m_logger = log_ptr; }
00095
00097 inline logger get_logger(void) { return m_logger; }
00098
00100 inline boost::asio::ip::tcp::acceptor& get_acceptor(void) { return m_tcp_acceptor; }
00101
00103 inline const boost::asio::ip::tcp::acceptor& get_acceptor(void) const { return m_tcp_acceptor; }
00104
00105
00106 protected:
00107
00113 explicit server(const unsigned int tcp_port);
00114
00120 explicit server(const boost::asio::ip::tcp::endpoint& endpoint);
00121
00128 explicit server(scheduler& sched, const unsigned int tcp_port = 0);
00129
00136 server(scheduler& sched, const boost::asio::ip::tcp::endpoint& endpoint);
00137
00144 virtual void handle_connection(tcp::connection_ptr& tcp_conn) {
00145 tcp_conn->set_lifecycle(connection::LIFECYCLE_CLOSE);
00146 tcp_conn->finish();
00147 }
00148
00150 virtual void before_starting(void) {}
00151
00153 virtual void after_stopping(void) {}
00154
00156 inline boost::asio::io_service& get_io_service(void) { return m_active_scheduler.get_io_service(); }
00157
00158
00160 logger m_logger;
00161
00162
00163 private:
00164
00166 void handle_stop_request(void);
00167
00169 void listen(void);
00170
00177 void handle_accept(tcp::connection_ptr& tcp_conn,
00178 const boost::system::error_code& accept_error);
00179
00186 void handle_ssl_handshake(tcp::connection_ptr& tcp_conn,
00187 const boost::system::error_code& handshake_error);
00188
00193 void finish_connection(tcp::connection_ptr& tcp_conn);
00194
00197 std::size_t prune_connections(void);
00198
00199
00201 typedef std::set<tcp::connection_ptr> ConnectionPool;
00202
00203
00205 single_service_scheduler m_default_scheduler;
00206
00208 scheduler & m_active_scheduler;
00209
00211 boost::asio::ip::tcp::acceptor m_tcp_acceptor;
00212
00214 connection::ssl_context_type m_ssl_context;
00215
00217 boost::condition m_server_has_stopped;
00218
00220 boost::condition m_no_more_connections;
00221
00223 ConnectionPool m_conn_pool;
00224
00226 boost::asio::ip::tcp::endpoint m_endpoint;
00227
00229 bool m_ssl_flag;
00230
00232 bool m_is_listening;
00233
00235 mutable boost::mutex m_mutex;
00236 };
00237
00238
00240 typedef boost::shared_ptr<server> server_ptr;
00241
00242
00243 }
00244 }
00245
00246 #endif