ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

183 lines
4.2 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // See accompanying file COPYING.TXT file for licensing details.
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #ifndef CPPCMS_CGI_ACCEPTOR_H
  9. #define CPPCMS_CGI_ACCEPTOR_H
  10. #include "cgi_api.h"
  11. #include <cppcms/service.h>
  12. #include "service_impl.h"
  13. #include <cppcms/http_context.h>
  14. #include <cppcms/config.h>
  15. #include <booster/aio/socket.h>
  16. #include <booster/aio/endpoint.h>
  17. #ifndef CPPCMS_WIN32
  18. #include <unistd.h>
  19. #endif
  20. namespace io = booster::aio;
  21. namespace cppcms {
  22. namespace impl {
  23. namespace cgi {
  24. template<typename API>
  25. struct server_api_factory {
  26. API *operator()(cppcms::service &srv) const
  27. {
  28. return new API(srv);
  29. }
  30. };
  31. template<class ServerAPI,class Factory = server_api_factory<ServerAPI> >
  32. class socket_acceptor : public acceptor {
  33. public:
  34. socket_acceptor(cppcms::service &srv,std::string ip,int port,int backlog) :
  35. srv_(srv),
  36. acceptor_(srv_.get_io_service()),
  37. stopped_(false),
  38. tcp_(true),
  39. sndbuf_(-1),
  40. rcvbuf_(-1)
  41. {
  42. io::endpoint ep(ip,port);
  43. acceptor_.open(ep.family());
  44. #ifndef CPPCMS_WIN32
  45. acceptor_.set_option(io::basic_socket::reuse_address,true);
  46. #endif
  47. acceptor_.bind(ep);
  48. acceptor_.listen(backlog);
  49. }
  50. void factory(Factory const &f)
  51. {
  52. factory_ = f;
  53. }
  54. #if !defined(CPPCMS_WIN32)
  55. socket_acceptor(cppcms::service &srv,int backlog) :
  56. srv_(srv),
  57. acceptor_(srv_.get_io_service()),
  58. stopped_(false),
  59. tcp_(false)
  60. {
  61. acceptor_.attach(0);
  62. acceptor_.listen(backlog);
  63. }
  64. socket_acceptor(cppcms::service &srv,std::string path,int backlog) :
  65. srv_(srv),
  66. acceptor_(srv_.get_io_service()),
  67. stopped_(false),
  68. tcp_(false)
  69. {
  70. io::endpoint ep(path);
  71. acceptor_.open(io::pf_unix);
  72. acceptor_.set_option(io::basic_socket::reuse_address,true);
  73. ::unlink(path.c_str());
  74. acceptor_.bind(ep);
  75. acceptor_.listen(backlog);
  76. }
  77. #endif
  78. struct accept_binder {
  79. socket_acceptor *self;
  80. accept_binder(socket_acceptor *s=0) : self(s) {}
  81. void operator()(booster::system::error_code const &e)
  82. {
  83. self->on_accept(e);
  84. }
  85. };
  86. #ifndef CPPCMS_WIN32
  87. virtual booster::shared_ptr< ::cppcms::http::context> accept(int fd)
  88. {
  89. booster::shared_ptr<ServerAPI> api;
  90. try {
  91. api.reset(factory_(srv_));
  92. api->socket_.assign(fd);
  93. fd=-1;
  94. }
  95. catch(...) {
  96. ::close(fd);
  97. throw;
  98. }
  99. if(tcp_)
  100. api->socket_.set_option(io::basic_socket::tcp_no_delay,true);
  101. booster::shared_ptr< ::cppcms::http::context> cnt(new ::cppcms::http::context(api));
  102. return cnt;
  103. }
  104. #endif
  105. virtual booster::aio::acceptor &socket()
  106. {
  107. return acceptor_;
  108. }
  109. virtual void async_accept()
  110. {
  111. if(stopped_)
  112. return;
  113. booster::shared_ptr<ServerAPI> api(factory_(srv_));
  114. api_=api;
  115. asio_socket_ = &api->socket_;
  116. acceptor_.async_accept(*asio_socket_,accept_binder(this));
  117. }
  118. virtual void stop()
  119. {
  120. stopped_=true;
  121. acceptor_.cancel();
  122. }
  123. void sndbuf(int v)
  124. {
  125. sndbuf_ = v;
  126. }
  127. void rcvbuf(int v)
  128. {
  129. rcvbuf_ = v;
  130. }
  131. private:
  132. void on_accept(booster::system::error_code const &e)
  133. {
  134. if(!e) {
  135. if(tcp_)
  136. asio_socket_->set_option(io::basic_socket::tcp_no_delay,true);
  137. if(sndbuf_!=-1)
  138. asio_socket_->set_option(io::basic_socket::send_buffer_size,sndbuf_);
  139. if(rcvbuf_!=-1)
  140. asio_socket_->set_option(io::basic_socket::receive_buffer_size,rcvbuf_);
  141. booster::shared_ptr< ::cppcms::http::context> cnt(new ::cppcms::http::context(api_));
  142. api_.reset();
  143. cnt->run();
  144. }
  145. async_accept();
  146. }
  147. cppcms::service &srv_;
  148. booster::shared_ptr<connection> api_;
  149. booster::aio::stream_socket *asio_socket_;
  150. booster::aio::acceptor acceptor_;
  151. bool stopped_;
  152. bool tcp_;
  153. int sndbuf_,rcvbuf_;
  154. Factory factory_;
  155. };
  156. } // cgi
  157. } // impl
  158. } // cppcms
  159. #endif