|
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
- //
- // See accompanying file COPYING.TXT file for licensing details.
- //
- ///////////////////////////////////////////////////////////////////////////////
- #ifndef CPPCMS_CGI_ACCEPTOR_H
- #define CPPCMS_CGI_ACCEPTOR_H
-
- #include "cgi_api.h"
- #include <cppcms/service.h>
- #include "service_impl.h"
- #include <cppcms/http_context.h>
-
- #include <cppcms/config.h>
-
- #include <booster/aio/socket.h>
- #include <booster/aio/endpoint.h>
-
- #ifndef CPPCMS_WIN32
- #include <unistd.h>
- #endif
-
- namespace io = booster::aio;
-
- namespace cppcms {
- namespace impl {
- namespace cgi {
-
- template<typename API>
- struct server_api_factory {
- API *operator()(cppcms::service &srv) const
- {
- return new API(srv);
- }
- };
-
- template<class ServerAPI,class Factory = server_api_factory<ServerAPI> >
- class socket_acceptor : public acceptor {
- public:
- socket_acceptor(cppcms::service &srv,std::string ip,int port,int backlog) :
- srv_(srv),
- acceptor_(srv_.get_io_service()),
- stopped_(false),
- tcp_(true),
- sndbuf_(-1),
- rcvbuf_(-1)
- {
- io::endpoint ep(ip,port);
- acceptor_.open(ep.family());
- #ifndef CPPCMS_WIN32
- acceptor_.set_option(io::basic_socket::reuse_address,true);
- #endif
- acceptor_.bind(ep);
- acceptor_.listen(backlog);
- }
-
- void factory(Factory const &f)
- {
- factory_ = f;
- }
-
- #if !defined(CPPCMS_WIN32)
- socket_acceptor(cppcms::service &srv,int backlog) :
- srv_(srv),
- acceptor_(srv_.get_io_service()),
- stopped_(false),
- tcp_(false)
- {
- acceptor_.attach(0);
- acceptor_.listen(backlog);
- }
-
- socket_acceptor(cppcms::service &srv,std::string path,int backlog) :
- srv_(srv),
- acceptor_(srv_.get_io_service()),
- stopped_(false),
- tcp_(false)
- {
- io::endpoint ep(path);
- acceptor_.open(io::pf_unix);
- acceptor_.set_option(io::basic_socket::reuse_address,true);
- ::unlink(path.c_str());
- acceptor_.bind(ep);
- acceptor_.listen(backlog);
- }
- #endif
-
- struct accept_binder {
- socket_acceptor *self;
- accept_binder(socket_acceptor *s=0) : self(s) {}
- void operator()(booster::system::error_code const &e)
- {
- self->on_accept(e);
- }
- };
-
- #ifndef CPPCMS_WIN32
- virtual booster::shared_ptr< ::cppcms::http::context> accept(int fd)
- {
- booster::shared_ptr<ServerAPI> api;
- try {
- api.reset(factory_(srv_));
- api->socket_.assign(fd);
- fd=-1;
- }
- catch(...) {
- ::close(fd);
- throw;
- }
- if(tcp_)
- api->socket_.set_option(io::basic_socket::tcp_no_delay,true);
- booster::shared_ptr< ::cppcms::http::context> cnt(new ::cppcms::http::context(api));
- return cnt;
- }
- #endif
- virtual booster::aio::acceptor &socket()
- {
- return acceptor_;
- }
- virtual void async_accept()
- {
- if(stopped_)
- return;
- booster::shared_ptr<ServerAPI> api(factory_(srv_));
- api_=api;
- asio_socket_ = &api->socket_;
- acceptor_.async_accept(*asio_socket_,accept_binder(this));
- }
-
- virtual void stop()
- {
- stopped_=true;
- acceptor_.cancel();
- }
-
- void sndbuf(int v)
- {
- sndbuf_ = v;
- }
- void rcvbuf(int v)
-
- {
- rcvbuf_ = v;
- }
-
- private:
- void on_accept(booster::system::error_code const &e)
- {
- if(!e) {
-
- if(tcp_)
- asio_socket_->set_option(io::basic_socket::tcp_no_delay,true);
- if(sndbuf_!=-1)
- asio_socket_->set_option(io::basic_socket::send_buffer_size,sndbuf_);
- if(rcvbuf_!=-1)
- asio_socket_->set_option(io::basic_socket::receive_buffer_size,rcvbuf_);
- booster::shared_ptr< ::cppcms::http::context> cnt(new ::cppcms::http::context(api_));
- api_.reset();
- cnt->run();
- }
- async_accept();
- }
-
- cppcms::service &srv_;
- booster::shared_ptr<connection> api_;
- booster::aio::stream_socket *asio_socket_;
- booster::aio::acceptor acceptor_;
- bool stopped_;
- bool tcp_;
- int sndbuf_,rcvbuf_;
- Factory factory_;
- };
-
-
- } // cgi
- } // impl
- } // cppcms
-
-
- #endif
|