Advertisement
Guest User

Untitled

a guest
Mar 10th, 2012
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.09 KB | None | 0 0
  1. // file  -  Server.h
  2.   class Server
  3.   {
  4.   public:
  5.     explicit Server(const std::string &address,
  6.                int port,
  7.                std::size_t threadPoolSize);
  8.  
  9.     // run the io_service loop
  10.     void run();
  11.  
  12.     // stop the server
  13.     void stop();
  14.  
  15.   private:
  16.     //handle async accept operation
  17.     void handleAccept(const boost::system::error_code &e);
  18.  
  19.     // number of threads in thread pool
  20.     std::size_t _threadPoolSize;
  21.  
  22.     // the io_service
  23.     boost::asio::io_service _ioService;
  24.    
  25.     // acceptor to listen for incoming connections
  26.     boost::asio::ip::tcp::acceptor _acceptor;
  27.  
  28.     std::string get_password()
  29.     {
  30.       return "password";
  31.     }
  32.  
  33.     // ssl context
  34.     boost::asio::ssl::context _context;    
  35.     ConnectionPtr _connection;
  36.  
  37.   };
  38.  
  39. //////////////////////////////////////////////////////////////////////////
  40. // file  -  Server.cpp
  41. //////////////////////////////////////////////////////////////////////////
  42.   Server::Server(const std::string& address,
  43.                int port,
  44.                std::size_t threadPoolSize)
  45.     : _threadPoolSize(threadPoolSize),
  46.       _acceptor(_ioService),
  47.       _context(_ioService, boost::asio::ssl::context::sslv23),
  48.       _connection()
  49.   {
  50.     try {
  51.       DEBUG_2("Starting server on port: ", port);
  52.       boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
  53.       _acceptor.open(endpoint.protocol());
  54.       _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
  55.       _acceptor.bind(endpoint);
  56.       _acceptor.listen();
  57.       _context.set_options(
  58.         boost::asio::ssl::context::default_workarounds
  59.         | boost::asio::ssl::context::no_sslv2
  60.         | boost::asio::ssl::context::single_dh_use);
  61.       _context.set_password_callback(boost::bind(&Server::get_password, this));
  62.       _context.use_certificate_chain_file("./demoCA/cacert.pem");
  63.       _context.use_private_key_file("./demoCA/private/cakey.pem",
  64.                                     boost::asio::ssl::context::pem);
  65.       // _context.use_tmp_dh_file("dh512.pem");
  66.       _connection.reset(new CclConnection(_ioService, _context));
  67.       _acceptor.async_accept(_connection->socket(),
  68.                              boost::bind(&Server::handleAccept,
  69.                                          this,
  70.                                          boost::asio::placeholders::error));
  71.     }
  72.     catch(std::exception& e)
  73.     {
  74.       STD_EXCEPTION_MESSAGE;
  75.       throw;
  76.     }
  77.      
  78.   }
  79.  
  80.   void Server::run()
  81.   {
  82.     // Create a pool of threads to run all of the io_services.
  83.     std::vector<boost::shared_ptr<boost::thread> > threads;
  84.     for (std::size_t i = 0; i < _threadPoolSize; ++i)
  85.     {
  86.       boost::shared_ptr<boost::thread>
  87.     thread(new boost::thread(
  88.          boost::bind(&boost::asio::io_service::run,
  89.                  &_ioService)
  90.          )
  91.       );
  92.       threads.push_back(thread);
  93.     }
  94.  
  95.     // Wait for all threads in the pool to exit.
  96.     for (std::size_t i = 0; i < threads.size(); ++i)
  97.       threads[i]->join();
  98.   }
  99.  
  100.   void Server::stop()
  101.   {
  102.     _ioService.stop();
  103.   }
  104.  
  105.   void Server::handleAccept(const boost::system::error_code& e)
  106.   {
  107.     if (!e)
  108.     {
  109.       _connection->handshake();
  110.       _connection.reset(new CclConnection(_ioService, _context));
  111.       _acceptor.async_accept(_connection->socket(),
  112.                  boost::bind(&Server::handleAccept,
  113.                      this,
  114.                      boost::asio::placeholders::error));
  115.     }
  116.   }
  117.  
  118. ////////////////////////////////////////////////////////////
  119. // file  -  Connection.h
  120. ////////////////////////////////////////////////////////////
  121.  
  122. #include <boost/asio.hpp>
  123. #include <boost/asio/ssl.hpp>
  124. #include <boost/shared_ptr.hpp>
  125. #include <boost/enable_shared_from_this.hpp>
  126.  
  127.   typedef boost::asio::ssl::stream< boost::asio::ip::tcp::socket >
  128.     ssl_socket;
  129.  
  130.   class Connection
  131.     : public boost::enable_shared_from_this<Connection>
  132.   {
  133.   public:
  134.     explicit Connection(boost::asio::io_service& io_service,
  135.                            boost::asio::ssl::context& context);
  136.  
  137.     //get socket from the connection
  138.     ssl_socket::lowest_layer_type& socket();
  139.  
  140.     // do an SSL handshake
  141.     void handshake();
  142.  
  143.     //get socket from the connection
  144.     boost::asio::io_service::strand& strand();
  145.  
  146.     // start first async operation
  147.     void start();
  148.  
  149.     void sendResponse(const Response& response);
  150.  
  151.     void close();
  152.  
  153.     // get remote IP address for this connection
  154.     std::string getIPAddress();
  155.  
  156.   private:
  157.     void handleRead(const boost::system::error_code& e,
  158.             std::size_t bytesTransferred);
  159.  
  160.     void handleWrite(const boost::system::error_code& e);
  161.  
  162.     boost::asio::io_service::strand _strand;
  163.  
  164.     ssl_socket _socket;
  165.  
  166.     void handleHandshake(const boost::system::error_code& e);
  167.  
  168.     boost::array<char, 8192> _buffer;
  169.   };
  170.  
  171.   typedef boost::shared_ptr<Connection> ConnectionPtr;
  172.  
  173. ///////////////////////////////////////////////////////////////
  174. // File - Connection.cpp
  175. ///////////////////////////////////////////////////////////////
  176.  
  177.  
  178.   Connection::Connection(boost::asio::io_service& io_service,
  179.                                boost::asio::ssl::context& context)
  180.     : _strand(io_service),
  181.       _socket(io_service, context)
  182.   {
  183.   }
  184.  
  185.   ssl_socket::lowest_layer_type& Connection::socket()
  186.   {
  187.     return _socket.lowest_layer();
  188.   }
  189.  
  190.   boost::asio::io_service::strand& Connection::strand()
  191.   {
  192.     return _strand;
  193.   }
  194.  
  195.   void Connection::start()
  196.   {
  197.     _socket.async_read_some(boost::asio::buffer(_buffer),
  198.                 _strand.wrap(
  199.                   boost::bind(
  200.                 &Connection::handleRead,
  201.                 shared_from_this(),
  202.                 boost::asio::placeholders::error,
  203.                 boost::asio::placeholders::bytes_transferred
  204.                 )
  205.                   )
  206.       );
  207.   }
  208.  
  209.   void Connection::handshake()
  210.   {
  211.     std::cout << "doing ssl handshake" << std::endl;
  212.     _socket.async_handshake(boost::asio::ssl::stream_base::server,
  213.                             _strand.wrap(
  214.                               boost::bind(
  215.                                 &Connection::handleHandshake,
  216.                                 shared_from_this(),
  217.                                 boost::asio::placeholders::error
  218.                                 )
  219.                               )
  220.       );
  221.   }
  222.  
  223.   void Connection::handleHandshake(const boost::system::error_code& error)
  224.   {
  225.     if (!error)
  226.     {
  227.       _socket.async_read_some(boost::asio::buffer(_buffer),
  228.                               _strand.wrap(
  229.                                 boost::bind(
  230.                                   &Connection::handleRead,
  231.                                   shared_from_this(),
  232.                                   boost::asio::placeholders::error,
  233.                                   boost::asio::placeholders::bytes_transferred
  234.                                   )
  235.                                 )
  236.         );
  237.     }
  238.     else
  239.     {
  240.       std::cout << "error occured: " << error.message();
  241.       this->close();
  242.     }
  243.   }
  244.  
  245.   void Connection::handleRead(const boost::system::error_code& e,
  246.                  std::size_t bytesTransferred)
  247.   {
  248.     if (!e) {
  249.  
  250.       // handle read data
  251.       this->start();
  252.     }
  253.     else {
  254.       this->close();
  255.     }
  256.   }
  257.  
  258.   void Connection::handleWrite(const boost::system::error_code& e)
  259.   {
  260.     if (!e) {
  261.        this->start();
  262.     }
  263.     else {
  264.       this->close();
  265.     }
  266.   }
  267.  
  268.   void Connection::sendResponse(const Response& response)
  269.   {
  270.     boost::asio::async_write(_socket,
  271.                              boost::asio::buffer(convertToString(response)),
  272.                              _strand.wrap(
  273.                                boost::bind(
  274.                                  &Connection::handleWrite,
  275.                                  shared_from_this(),
  276.                                  boost::asio::placeholders::error
  277.                                  )
  278.                                )
  279.       );
  280.  
  281.   }
  282.  
  283.   void Connection::close()
  284.   {
  285.     boost::system::error_code ignoredCode;
  286.     socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
  287.                      ignoredCode);
  288.   }
  289.  
  290.   std::string Connection::getIPAddress()
  291.   {
  292.     return socket().remote_endpoint().address().to_string();
  293.   }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement