pion  5.0.6
include/pion/tcp/server.hpp
00001 // ---------------------------------------------------------------------
00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
00003 // ---------------------------------------------------------------------
00004 // Copyright (C) 2007-2014 Splunk Inc.  (https://github.com/splunk/pion)
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_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 {    // begin namespace pion
00026 namespace tcp {     // begin 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); // make sure it will get closed
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 }   // end namespace tcp
00244 }   // end namespace pion
00245 
00246 #endif