|
Boost-Commit : |
From: lists.drrngrvy_at_[hidden]
Date: 2008-02-08 09:43:19
Author: drrngrvy
Date: 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
New Revision: 43172
URL: http://svn.boost.org/trac/boost/changeset/43172
Log:
This is a backup commit, it may be less functional than the last revision!
Contents:
* Some work towards SCGI support. This was partly abandoned to work on FastCGI support (which is merely a copy of the scgi directory + modifications).
* FastCGI support has begun to be added. On linux, with apache (mod_fastcgi or mod_fcgid) it can accept multiple connections and read/parse packets. PARAM packets can be parsed correctly, as can STDIN and BEGIN_REQUEST packets. They lack proper handling because I'm not sure if introducing a circular dependency is absolutely necessary - ie. the basic_client<> reads/parses packets but in order to do so must have access to the basic_request<> associated with it (to store variables in). The basic_request<> *has* a basic_client<> so that dependency exists too. There are several ways around it, not sure which is best.
* FastCGI outputting hasn't been addressed yet, will do that after important uni work is done.
* The beginnings of multipart form data handling was added, but only using Boost.Regex. The idea is that 'eventually' this should be a seperate form_parser class that takes a function object for reading more data and a map to store saved data into, so the class is generally useful outside this library. This separation has the advantage of allowing a Boost.Spirit, Boost.Regex and Boost.Xpressive implementation. I'm starting with regex because it won't get done otherwise. It's not finished yet, surprise surprise.
Added:
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/common/
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/common/form_part.hpp (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/error.hpp (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/acceptor.hpp (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/acceptor_service_impl.hpp (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/client.hpp (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request.hpp (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_acceptor_service.hpp (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_service.hpp (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/service.hpp (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/Jamfile.v2 (contents, props changed)
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/main.cpp (contents, props changed)
Removed:
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/util/system/
Text files modified:
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request.hpp | 4
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request_impl.hpp | 4
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request_service.hpp | 4
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_client.hpp | 4
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_connection.hpp | 10
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_protocol_service.hpp | 4
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request.hpp | 133 ++-----
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request_acceptor.hpp | 102 +++++
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/buffer.hpp | 5
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/cgi/request_impl.hpp | 4
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/cgi/request_service.hpp | 4
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/shareable_tcp_socket.hpp | 43 ++
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/stdio.hpp | 35 +
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/cgi_request_impl_base.hpp | 3
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/cgi_service_impl_base.hpp | 686 +++++++++++++++++++++++++++++++++++++--
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/protocol_traits.hpp | 68 ++-
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/throw_error.hpp | 8
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi.hpp | 9
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/specification.hpp | 228 +++++++++++-
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/header.hpp | 50 +-
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/request_service.hpp | 3
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/response.hpp | 249 +++++--------
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/role_type.hpp | 3
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/acceptor_service_impl.hpp | 345 +++++++++++--------
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/request_acceptor_service.hpp | 52 ++
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/request_service.hpp | 12
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/service.hpp | 2
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/status_type.hpp | 3
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/streambuf.hpp | 5
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/tags.hpp | 2
sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/write.hpp | 6
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/Jamfile.v2 | 4
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/building.qbk | 6
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/future_development.qbk | 10
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/introduction.qbk | 57 ++
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/preface.qbk | 12
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/user_guide/async_ops.qbk | 6
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/Jamfile.v2 | 8
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/cookie_game/Jamfile.v2 | 30 -
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/cookie_game/main.cpp | 2
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/echo/Jamfile.v2 | 28
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/echo/main.cpp | 25 +
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/hello_world/Jamfile.v2 | 25
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/CheckCookie.cpp | 7
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Jamfile.v2 | 38 -
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Login.cpp | 47 ++
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Logout.cpp | 8
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/Jamfile.v2 | 25 -
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/scgi/hello_world/Jamfile.v2 | 32 -
sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/scgi/hello_world/main.cpp | 87 ++++
sandbox/SOC/2007/cgi/branches/acceptor_work/project-root.jam | 41 ++
51 files changed, 1833 insertions(+), 755 deletions(-)
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -24,6 +24,10 @@
} // namespace cgi
+//namespace boost { namespace acgi {
+// typedef ::cgi::basic_request< cgi::acgi_request_service, cgi::acgi_service> request;
+//} }
+
#include "boost/cgi/basic_request.hpp"
#endif // CGI_ACGI_REQUEST_HPP_INCLUDED__
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request_impl.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request_impl.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request_impl.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -26,8 +26,8 @@
{
public:
typedef acgi_service protocol_service_type;
- //typedef ::cgi::basic_client<async_stdio_connection, tags::acgi> client_type;
- typedef async_stdio_connection client_type;
+ typedef ::cgi::basic_client<async_stdio_connection, tags::acgi> client_type;
+ //typedef async_stdio_connection client_type;
acgi_request_impl()
: cgi_request_impl_base<async_stdio_connection>()
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request_service.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/acgi/request_service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -46,7 +46,9 @@
}
void construct(implementation_type& impl)
{
- impl.connection() = async_stdio_connection::create(this->io_service());
+ impl.client_.set_connection(
+ implementation_type::connection_type::create(this->io_service())
+ );
}
void destroy(implementation_type& impl)
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_client.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_client.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -83,11 +83,11 @@
/**
* Note: the connection must have been created using the new operator
*/
- bool set_connection(typename connection_type::pointer& conn)
+ bool set_connection(const typename connection_type::pointer& conn)
{
// make sure there isn't already a connection associated with the client
//if (!connection_) return false;
- BOOST_ASSERT(conn != NULL);
+ //BOOST_ASSERT(conn != NULL);
connection_ = conn;
return true;
}
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_connection.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_connection.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_connection.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -9,12 +9,12 @@
#ifndef CGI_BASIC_CONNECTION_HPP_INCLUDED__
#define CGI_BASIC_CONNECTION_HPP_INCLUDED__
-#include <istream>
-#include <ostream>
-#include <boost/asio.hpp>
+//#include <istream>
+//#include <ostream>
+//#include <boost/asio.hpp>
-#include "boost/cgi/tags.hpp"
-#include "boost/cgi/connection_base.hpp"
+//#include "boost/cgi/tags.hpp"
+//#include "boost/cgi/connection_base.hpp"
//#include "connections/async_stdio_connection_impl.hpp"
namespace cgi {
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_protocol_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_protocol_service.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_protocol_service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -132,9 +132,9 @@
/// A strand is used for guaranteeing handlers are dispatched sequentially
//boost::asio::strand strand_;
- /// A std::set of all the requests
+ /// A std::set of all the requests.
set_type request_set_;
- /// A std::queue of the pending requests
+ /// A std::queue of the waiting (ie. not-being-handled) requests.
queue_type request_queue_;
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400))
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -6,6 +6,11 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
////////////////////////////////////////////////////////////////
+//
+// Defines the basic_request<> class; the main entry-point to the
+// library.
+//
+////////////////////////////////////////////////////////////////
#ifndef CGI_BASIC_REQUEST_HPP_INCLUDED__
#define CGI_BASIC_REQUEST_HPP_INCLUDED__
@@ -92,6 +97,7 @@
if (load_now) load(parse_post);//this->service.load(this->impl, true, ec);
}
+ // Won't throw
basic_request(boost::system::error_code& ec
, const bool load_now = true
, const bool parse_post = true)
@@ -100,6 +106,7 @@
if (load_now) load(ec, parse_post);//this->service.load(this->impl, true, ec);
}
+ // Throws
basic_request(protocol_service_type& s, const bool load_now = false
, const bool parse_post = false)
: basic_io_object<service_type>(s.io_service())
@@ -107,6 +114,7 @@
if (load_now) load(parse_post);//this->service.load(this->impl, false, ec);
}
+ // Won't throw
basic_request(protocol_service_type& s
, boost::system::error_code& ec
, const bool load_now = false, const bool parse_post = false)
@@ -117,8 +125,8 @@
~basic_request()
{
- if (is_open())
- close(http::internal_server_error, 0);
+ //if (is_open())
+ // close(http::internal_server_error, 0);
}
/// Return `true` if the request is still open (ie. not aborted or closed)
@@ -127,32 +135,6 @@
return this->service.is_open(this->impl);
}
- /// Set a header
- void set_header(const std::string& name, const std::string& val
- , const std::string& expires)
- {
- this->service.set_header(this->impl, name, val, expires);
- }
-
- /// Set a cookie
- void set_cookie(const std::string& name, const std::string& val
- , const std::string& expires = "")
- {
- this->service.set_cookie(this->impl, name, val, expires);
- }
-
- /// Delete a cookie
- void del_cookie(const std::string& name)
- {
- this->service.del_cookie(this->impl, name);
- }
-
- /// Delete all cookies
- void del_cookies()
- {
- this->service.del_cookies();
- }
-
/// Synchronously read/parse the request meta-data
/**
* Note: 'loading' including reading/parsing STDIN if parse_stdin == true
@@ -218,6 +200,10 @@
this->service.set_status(this->impl, aborted);
}
+ /// Get the client connection associated with the request
+ /**
+ * You use the client for read/write calls. Y
+ */
client_type& client()
{
return this->service.client(this->impl);
@@ -251,52 +237,6 @@
}
*/
-/*
- /// Read some data from the client
- template<typename MutableBufferSequence>
- std::size_t read_some(const MutableBufferSequence& buf)
- {
- boost::system::error_code ec;
- std::size_t s = this->service.read_some(this->impl, buf, ec);
- detail::throw_error(ec);
- return s;
- }
-
- /// Read some data from the client
- template<typename MutableBufferSequence, typename Source>
- std::size_t read_some(const MutableBufferSequence& buf
- , boost::system::error_code& ec)
- {
- return this->service.read_some(this->impl, buf, ec);
- }
-
- /// Write some data to the client
- /**
- * Note: on the first write, the header block is closed (with a blank
- * line).
- *
- template<typename ConstBufferSequence, typename Sink>
- std::size_t write_some(const ConstBufferSequence& buf)
- {
- boost::system::error_code ec;
- std::size_t s = this->service.write_some(this->impl, buf, ec);
- detail::throw_error(ec);
- return s;
- }
-
- /// Write some data to the client
- /**
- * Note: on the first write, the header block is closed (with a blank
- * line).
- *
- template<typename ConstBufferSequence, typename Sink>
- std::size_t write_some(const ConstBufferSequence& buf
- , boost::system::error_code& ec)
- {
- return this->service.write_some(this->impl, buf, ec);
- }
-*/
-
/// Get a `cgi::map&` corresponding to all of the GET variables
map_type& GET()
{
@@ -364,9 +304,12 @@
}
/// Get a `cgi::map&` corresponding to all of the form variables
- map_type& form()
+ map_type& form(bool greedy = true)
{
- return this->service.form(this->impl);
+ boost::system::error_code ec;
+ map_type& data = this->service.form(this->impl, ec, greedy);
+ detail::throw_error(ec);
+ return data;
}
/// Find the form variable matching name
@@ -485,7 +428,7 @@
boost::system::error_code ec;
std::string ret = var(name, ec, greedy);
return this->service.var(this->impl, name, greedy);
- std::string request_method( env_("REQUEST_METHOD") );
+ std::string request_method( env("REQUEST_METHOD") );
std::string tmp;
@@ -516,7 +459,7 @@
return tmp.empty() ? "" : tmp;
}
- // Some helper functions for the basic CGI 1.1 meta-variables
+ // [helper-functions for the basic CGI 1.1 meta-variables.
std::string auth_type()
{ return env("AUTH_TYPE"); }
@@ -567,7 +510,19 @@
std::string server_software()
{ return env("SERVER_SOFTWARE"); }
+ // -- end helper-functions]
+ /// Get the charset from the CONTENT_TYPE header
+ std::string charset()
+ {
+ // Not sure if regex is needlessly heavy-weight here.
+ boost::regex re(";[ ]?charset=([-\\w]+);");
+ boost::smatch match;
+ if (!boost::regex_match(this->content_type(), match, re))
+ return ""; // A default could go here.
+
+ return match[1];
+ }
/// The role that the request is playing
/**
@@ -604,25 +559,10 @@
this->service.set_status(this->impl, status);
}
- /// Get the client connection associated with the request
- /**
- * You use the client for read/write calls. Y
- typename implementation_type::connection_type&
- client()
+ // The boundary marker for multipart forms (this is likely a transient function).
+ std::string boundary_marker()
{
- return this->service.client(this->impl);
- }
-
- /// Set a user cookie
- /**
- * Note: this must be called before you have finished outputting
- * the reply headers or it will just appear as normal data
- *
- * ** Is this actually necessary? **
- */
- void set_cookie(const std::string& name, const std::string& value)
- {
- return this->service.set_cookie(this->impl, name, value);
+ return this->impl.boundary_marker;
}
};
@@ -639,3 +579,4 @@
- The user should supply an abort_handler-derived function if they want
any special handling of aborted requests
*/
+
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request_acceptor.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request_acceptor.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request_acceptor.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -14,6 +14,7 @@
#include <boost/asio/basic_io_object.hpp>
#include <boost/asio/ip/basic_endpoint.hpp>
+#include <boost/asio/ip/tcp.hpp>
#include "boost/cgi/detail/throw_error.hpp"
namespace cgi {
@@ -28,7 +29,16 @@
// typedef impl_type;
typedef RequestAcceptorService service_type;
typedef typename service_type::protocol_type protocol_type;
- typedef unsigned short port_number_type;
+ typedef
+ typename service_type::implementation_type::port_number_type
+ port_number_type;
+ typedef
+ typename service_type::implementation_type::acceptor_service_type
+ next_layer_type;
+ typedef
+ typename service_type::endpoint_type
+ endpoint_type;
+ typedef typename service_type::native_type native_type;
template<typename IoServiceProvider>
explicit basic_request_acceptor(
@@ -45,15 +55,21 @@
: boost::asio::basic_io_object<RequestAcceptorService>(ps.io_service())
{
this->service.set_protocol_service(this->implementation, ps);
+ this->implementation.port_num_ = port_num;
+ this->implementation.endpoint_.port(port_num);
+ //std::cerr<< "___________ protocol := " <<
+ //(this->implementation.endpoint_.protocol() == boost::asio::ip::tcp::v4()) << std::endl;
using boost::asio::ip::tcp;
// This strange-looking conditional checks there's no error at each
// stage of preparation.
boost::system::error_code ec;
- if (this->service.open(this->implementation, tcp::v4(), ec)
- || this->service.bind(this->implementation
- , tcp::endpoint(tcp::v4(), port_num), ec)
- || this->service.listen(this->implementation, ec))
+ //if (//this->service.open(this->implementation, tcp::v4(), ec)
+ //||
+ //this->service.bind(this->implementation
+ // , tcp::endpoint(tcp::v4(), port_num), ec)
+ //|| this->service.listen(this->implementation, ec))
+
{
detail::throw_error(ec);
}
@@ -79,6 +95,19 @@
}
}
+ template<typename IoServiceProvider, typename InternetProtocol>
+ explicit basic_request_acceptor(
+ basic_protocol_service<protocol_type, IoServiceProvider>& ps,
+ const InternetProtocol& ip,
+ const native_type& native_acceptor)
+ : boost::asio::basic_io_object<RequestAcceptorService>(ps.io_service())
+ {
+ this->service.set_protocol_service(this->implementation, ps);
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, ip, native_acceptor, ec);
+ detail::throw_error(ec);
+ }
+
~basic_request_acceptor()
{
}
@@ -91,7 +120,7 @@
/// Open the acceptor
template<typename Protocol>
- void open(Protocol& protocol)
+ void open(const Protocol& protocol)
{
boost::system::error_code ec;
this->service.open(this->implementation, protocol, ec);
@@ -101,11 +130,33 @@
/// Open the acceptor
template<typename Protocol>
boost::system::error_code
- open(Protocol& protocol, boost::system::error_code& ec)
+ open(const Protocol& protocol, boost::system::error_code& ec)
{
return this->service.open(this->implementation, protocol, ec);
}
+ /// Set the acceptor to listen
+ void listen(int backlog = boost::asio::socket_base::max_connections)
+ {
+ boost::system::error_code ec;
+ this->service.listen(this->implementation, backlog, ec);
+ detail::throw_error(ec);
+ }
+
+ /// Set the acceptor to listen
+ boost::system::error_code
+ listen(int backlog, boost::system::error_code& ec)
+ {
+ return this->service.listen(this->implementation, backlog, ec);
+ }
+
+ template<typename Endpoint>
+ boost::system::error_code
+ bind(Endpoint& ep, boost::system::error_code& ec)
+ {
+ return this->service.bind(this->implementation, ep, ec);
+ }
+
/// Cancel all asynchronous operations associated with the acceptor.
boost::system::error_code
cancel()
@@ -128,6 +179,23 @@
return this->service.close(this->implementation, ec);
}
+ template<typename Protocol>
+ void assign(Protocol protocol, const native_type& native_acceptor)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, protocol, native_acceptor, ec);
+ detail::throw_error(ec);
+ }
+
+ template<typename Protocol>
+ boost::system::error_code
+ assign(Protocol protocol, const native_type& native_acceptor
+ , boost::system::error_code& ec)
+ {
+ return this->service.assign(this->implementation, protocol
+ , native_acceptor, ec);
+ }
+
/// Accept one request
template<typename CommonGatewayRequest>
void accept(CommonGatewayRequest& request)
@@ -142,17 +210,37 @@
boost::system::error_code
accept(CommonGatewayRequest& request, boost::system::error_code& ec)
{
+ //std::cerr<< "mine:::: endpoint.port := " << this->implementation.endpoint_.port() << std::endl;
return this->service.accept(this->implementation, request, ec);
}
+ //template<typename CommonGatewayRequest, typename Endpoint>
+ //boost::system::error_code
+
/// Asynchronously accept one request
template<typename CommonGatewayRequest, typename Handler>
void async_accept(CommonGatewayRequest& request, Handler handler)
{
this->service.async_accept(this->implementation, request, handler);
}
+
+ endpoint_type
+ local_endpoint()
+ {
+ boost::system::error_code ec;
+ endpoint_type ep(this->service.local_endpoint(this->implementation, ec));
+ detail::throw_error(ec);
+ return ep;
+ }
+
+ endpoint_type
+ local_endpoint(boost::system::error_code& ec) const
+ {
+ return this->service.local_endpoint(this->implementation, ec);
+ }
};
} // namespace cgi
#endif // CGI_BASIC_REQUEST_ACCEPTOR_HPP_INCLUDED__
+
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/buffer.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/buffer.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/buffer.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -12,9 +12,14 @@
#include <boost/asio/buffer.hpp>
namespace cgi {
+ namespace common {
using boost::asio::buffer;
+ } // namespace common
+
+ using common::buffer;
+
} // namespace cgi
#endif // CGI_HPP_INCLUDED__
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/cgi/request_impl.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/cgi/request_impl.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/cgi/request_impl.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -41,8 +41,8 @@
: public cgi_request_impl_base<stdio_connection>
{
public:
- //typedef ::cgi::basic_client<stdio_connection, tags::cgi> client_type;
- typedef stdio_connection client_type;
+ //typedef stdio_connection client_type;
+ typedef ::cgi::basic_client<stdio_connection, tags::cgi> client_type;
/// Constructor
/**
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/cgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/cgi/request_service.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/cgi/request_service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -45,7 +45,9 @@
void construct(implementation_type& impl)
{
- impl.connection() = implementation_type::connection_type::create();
+ impl.client_.set_connection(
+ implementation_type::connection_type::create()
+ );
}
void destroy(implementation_type& impl)
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/common/form_part.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/common/form_part.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,48 @@
+#include <map>
+#include <vector>
+#include <boost/range.hpp>
+
+namespace cgi {
+ namespace common {
+
+ struct form_part
+ {
+ typedef std::vector<char> buffer_type;
+ typedef buffer_type::iterator iter_t;
+
+ typedef boost::iterator_range<
+ buffer_type::const_iterator
+ > range_type;
+
+ typedef std::pair<iter_t, iter_t> pair_t;
+
+ typedef std::map<
+ std::string, pair_t
+ > meta_data_map_type;
+
+ form_part()
+ {
+ }
+
+ meta_data_map_type meta_data_;
+
+ /// The boundary marker that's needed.
+ // If this is empty, it means the corresponding data has been read.
+ std::string boundary_marker_;
+
+ //range_type buffer_;
+ pair_t buffer_;
+
+ std::string content_type; // must exist
+
+ // Using a simple map while everything is changing. This will not copy the
+ // values when it is properly implemented (it'll hold a pair of iterators
+ // to the data).
+ //std::map<std::string, std::string> meta_data_;
+
+ // Boolean to show if the form part has been completely read/parsed
+ //bool finished_;
+ };
+
+ } // namespace common
+} // namespace cgi
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/shareable_tcp_socket.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/shareable_tcp_socket.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/shareable_tcp_socket.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -9,6 +9,8 @@
#ifndef CGI_CONNECTIONS_SHAREABLE_TCP_SOCKET_HPP_INCLUDED__
#define CGI_CONNECTIONS_SHAREABLE_TCP_SOCKET_HPP_INCLUDED__
+#include <map>
+#include <boost/cstdint.hpp>
#include <boost/shared_ptr.hpp>
#include "boost/cgi/tags.hpp"
@@ -17,8 +19,22 @@
#include "boost/cgi/basic_connection.hpp"
#include "boost/cgi/detail/push_options.hpp"
+//#include "boost/cgi/fcgi/client_fwd.hpp"
+//#include "boost/cgi/fcgi/request_fwd.hpp"
+#include "boost/cgi/detail/protocol_traits.hpp"
+
namespace cgi {
+ /*** 05.02.2008 :
+ * I'm planning on making this class a more FastCGI-specific one since a
+ * rereading of the FastCGI spec (ie. 'Managing request IDs') made me
+ * realise that IDs are connection specific, not just application specific.
+ *
+ * IOW when checking to see if a particular request id exists, rather than
+ * having to check a table in the protocol_service (which may imply explicit
+ * mutex use), we can just check a local array of values. Good good.
+ ***/
+
template<>
class basic_connection<tags::shareable_tcp_socket>
: public connection_base
@@ -27,6 +43,15 @@
typedef boost::shared_ptr<
basic_connection<tags::shareable_tcp_socket> > pointer;
typedef boost::mutex mutex_type;
+ typedef boost::asio::ip::tcp::socket next_layer_type;
+
+ /** FastCGI specific stuff **/
+ //typedef ::cgi::fcgi::client client_type;
+ typedef //typename
+ detail::protocol_traits<fcgi_>::request_type request_type;
+ typedef std::map<boost::uint16_t, request_type*> request_map_type;
+
+ /** End FastCGI stuff **/
// A wrapper to provide condition_type::pointer
struct condition_type : public boost::condition
@@ -51,8 +76,8 @@
static pointer create(io_service& ios)
{
- return static_cast<pointer>(
- new basic_connection<tags::shareable_tcp_socket>(ios));
+ return //static_cast<pointer>(
+ pointer(new basic_connection<tags::shareable_tcp_socket>(ios));
}
template<typename MutableBufferSequence>
@@ -92,14 +117,24 @@
{
sock_.async_write_some(buf, handler);
}
+
+ next_layer_type&
+ next_layer()
+ {
+ return sock_;
+ }
mutex_type& mutex() { return mutex_; }
- condtion_type& condition() { return condition_; }
+ condition_type& condition() { return condition_; }
private:
- boost::asio::ip::tcp::socket sock_;
+ next_layer_type sock_;
mutex_type mutex_;
condition_type condition_;
+
+ public:
+ /** FastCGI specific stuff **/
+ request_map_type request_map_;
};
// probably deletable typedef (leaving it here to keep an open mind)
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/stdio.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/stdio.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/stdio.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -32,17 +32,13 @@
typedef boost::shared_ptr<basic_connection<tags::stdio> > pointer;
basic_connection()
- : in_(std::cin)
- , out_(std::cout)
- , is_open_(true)
+ : is_open_(true)
{
}
template<typename T>
basic_connection(T&)
- : in_(std::cin)
- , out_(std::cout)
- , is_open_(true)
+ : is_open_(true)
{
}
@@ -65,9 +61,26 @@
std::size_t read_some(MutableBufferSequence buf
, boost::system::error_code& ec)
{
- if( buf.data() != in_.rdbuf() )
- return in_.read(buf.begin(), buf.size());
- return buf.size();
+ //if( buf.data() != in_.rdbuf() )
+ // return in_.read(buf.begin(), buf.size());
+ //return buf.size();
+
+ //std::cerr<< "In stdio::read_some()" << std::endl
+ // << "before = {" << std::endl
+ // << std::string(boost::asio::buffer_cast<char *>(buf), boost::asio::buffer_size(buf)) << std::endl
+ // << "}" << std::endl;
+ std::cin.read(boost::asio::buffer_cast<char *>(buf)
+ , boost::asio::buffer_size(buf));
+ if (std::cin.fail() && !std::cin.eof())
+ {
+ ec = boost::system::error_code(654, boost::system::system_category);
+ return 0;
+ }
+ //std::cerr<< "Read data" << std::endl
+ // << "after = {" << std::endl
+ // << std::string(boost::asio::buffer_cast<char *>(buf), boost::asio::buffer_size(buf)) << std::endl
+ // << "}" << std::endl;
+ return std::cin.gcount();
}
template<typename ConstBufferSequence>
@@ -82,14 +95,12 @@
std::string s(boost::asio::buffer_cast<const char*>(*i)
, buf_len);
bytes_transferred += buf_len;
- out_.write(s.c_str(), buf_len);
+ std::cout.write(s.c_str(), buf_len);
}
return bytes_transferred;
}
protected:
- std::istream& in_;
- std::ostream& out_;
bool is_open_;
};
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/cgi_request_impl_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/cgi_request_impl_base.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/cgi_request_impl_base.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -42,7 +42,7 @@
public:
typedef ::cgi::map map_type;
typedef Connection connection_type;
- typedef typename
+ typedef
basic_client<Connection, tags::acgi> client_type;
typedef typename connection_type::pointer conn_ptr;
@@ -82,7 +82,6 @@
status_type request_status_;
conn_ptr connection_;
- client_type client_;
std::string null_str_;
};
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/cgi_service_impl_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/cgi_service_impl_base.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/cgi_service_impl_base.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -7,8 +7,11 @@
#include <cstdlib>
#include <iostream>
#include <boost/assert.hpp>
+#include <boost/regex.hpp>
#include <boost/tokenizer.hpp>
+#include <boost/lexical_cast.hpp>
#include <boost/system/error_code.hpp>
+#include <boost/algorithm/string/find.hpp>
#include "boost/cgi/map.hpp"
#include "boost/cgi/basic_client.hpp"
@@ -16,7 +19,8 @@
#include "boost/cgi/status_type.hpp"
#include "boost/cgi/detail/extract_params.hpp"
#include "boost/cgi/detail/save_environment.hpp"
-//#include "../connections/stdio.hpp"
+#include "boost/cgi/common/form_part.hpp"
+#include "boost/cgi/detail/throw_error.hpp"
namespace cgi {
@@ -33,7 +37,7 @@
class cgi_service_impl_base
{
public:
- typedef RequestImplType implementation_type;
+ //typedef RequestImplType implementation_type;
typedef ::cgi::map map_type;
cgi_service_impl_base()
@@ -45,6 +49,107 @@
{
}
+ struct implementation_type
+ : RequestImplType
+ {
+ typedef boost::asio::const_buffers_1 const_buffers_type;
+ typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
+ typedef typename RequestImplType::client_type client_type;
+ typedef std::vector<char> buffer_type;
+ //typedef std::list<std::string>::iterator marker_list_type;
+
+ implementation_type()
+ : buffer_()
+ , istream_(&buffer_)
+ , pos_()
+ , offset_(0)
+ {
+ }
+
+ client_type client_;
+
+ std::string boundary_marker;
+ std::list<std::string> boundary_markers;
+ //std::vector<char> data_buffer_;
+ // The number of characters left to read (ie. "content_length - bytes_read")
+ std::size_t characters_left_;
+
+ //std::vector<char>::iterator read_pos_;
+ boost::asio::streambuf buffer_;
+ std::istream istream_;
+
+ buffer_type buf_;
+ typename buffer_type::iterator pos_;
+ std::size_t offset_;
+ //boost::sub_match<typename buffer_type::iterator> offset_;
+ std::vector<common::form_part> form_parts_;
+
+ /*
+ mutable_buffers_type prepare(typename buffer_type::iterator& pos, std::size_t size)
+ {
+ std::size_t bufsz( buf_.size() );
+
+ // Reserve more space if it's needed.
+ // (this could be safer, referencing this against CONTENT_LENGTH)
+ if ( (bufsz + size) >= buf_.capacity() )
+ {
+ buf_.resize(bufsz + size);
+ }
+
+ return boost::asio::buffer(&(buf_.begin()), size);
+ // return boost::asio::buffer(&buf_[bufsz], size);
+ }
+ */
+
+ mutable_buffers_type prepare(std::size_t size)
+ {
+
+ std::size_t bufsz( buf_.size() );
+ cerr<< "bufsz = " << bufsz << endl;
+
+ // Reserve more space if it's needed.
+ // (this could be safer, referencing this against CONTENT_LENGTH)
+ //if ( (bufsz + size) >= buf_.capacity() )
+ //{
+ buf_.resize(bufsz + size);
+ //}
+
+ cerr<< "Pre-read buffer (size: " << buf_.size()
+ << "|capacity: " << buf_.capacity() << ") == {" << endl
+ << std::string(buf_.begin(), buf_.end()) << endl
+ // << "-----end buffer-----" << endl
+ // << "-------buffer-------" << endl
+ // << std::string(&buf_[0], &buf_[buf_.size()]) << endl
+ << "}" << endl;
+ ;
+ //return boost::asio::buffer(&(*(buf_.end())), size);
+ // return boost::asio::buffer(&(*(buf_.begin())) + bufsz, size);
+ return boost::asio::buffer(&buf_[bufsz], size);
+ }
+
+ std::string buffer_string()
+ {
+ return std::string(buf_.begin() + offset_, buf_.end());
+ //return std::string(pos_, buf_.size());//buf_.end());
+ }
+ /*
+ // Silently ignore a request to grow the buffer greater than the
+ // content-length allows.
+ // Note: this will break if the contents of the buffer are ever changed
+ // (such as if data is url-decoded and inserted back into the buffer).
+ if (size >= characters_left_)
+ {
+ size = characters_left_;
+ }
+
+ data_buffer_.reserve(bufsz + size);
+ return boost::asio::buffer(data_buffer_.begin() + bufsz
+ , data_buffer_.capacity() - bufsz);
+ }
+ */
+ //boost::acgi::form_entry form_;
+ };
+
/// Return if the request is still open
/**
* For CGI, this always returns true. However, in the case that a
@@ -58,9 +163,9 @@
/// Return the connection associated with the request
typename implementation_type::client_type&
- client(implementation_type& impl)
+ client(implementation_type& impl)
{
- return *impl.connection();
+ return impl.client_;
}
int close(implementation_type& impl, http::status_code& http_s, int status)
@@ -75,11 +180,14 @@
* @param parse_stdin if true then STDIN data is also read/parsed
*/
boost::system::error_code&
- load(implementation_type& impl, bool parse_stdin
- , boost::system::error_code& ec)
+ load(implementation_type& impl, bool parse_stdin
+ , boost::system::error_code& ec)
{
detail::save_environment(impl.env_vars());
- const std::string& request_method = impl.env_vars()["REQUEST_METHOD"];
+ const std::string& cl = var(impl.env_vars(), "CONTENT_LENGTH", ec);
+ impl.characters_left_ = cl.empty() ? 0 : boost::lexical_cast<std::size_t>(cl);
+
+ const std::string& request_method = var(impl.env_vars(), "REQUEST_METHOD", ec);
if (request_method == "GET")
parse_get_vars(impl, ec);
else
@@ -95,37 +203,23 @@
return ec;
}
- template<typename MutableBufferSequence>
- std::size_t read_some(implementation_type& impl
- , const MutableBufferSequence& buf
- , boost::system::error_code& ec)
- {
- std::size_t s = impl.connection()->read_some(buf, ec);
- return s;
- }
-
- template<typename ConstBufferSequence>
- std::size_t write_some(implementation_type& impl
- , const ConstBufferSequence& buf
- , boost::system::error_code& ec)
- {
- return impl.connection()->write_some(buf, ec);
- }
-
- std::string& var(map_type& meta_data, const std::string& name
- , boost::system::error_code& ec)
+ std::string&
+ var(map_type& meta_data, const std::string& name
+ , boost::system::error_code& ec)
{
return meta_data[name];
}
- std::string GET(implementation_type& impl, const std::string& name
- , boost::system::error_code& ec)
+ std::string
+ GET(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec)
{
//BOOST_ASSERT(impl.status() >= loaded);
return var(impl.get_vars(), name, ec);
}
- map_type& GET(implementation_type& impl)
+ map_type&
+ GET(implementation_type& impl)
{
//BOOST_ASSERT(impl.status() >= loaded);
return impl.get_vars();
@@ -143,9 +237,9 @@
-----------------------------------------------
*/
- std::string POST(implementation_type& impl, const std::string& name
- , boost::system::error_code& ec
- , bool greedy = true)
+ std::string
+ POST(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec, bool greedy = true)
{
//BOOST_ASSERT(impl.status() >= loaded);
const std::string& val = var(impl.post_vars(), name, ec);
@@ -157,22 +251,62 @@
return val;
}
- map_type& POST(implementation_type& impl)
+ map_type&
+ POST(implementation_type& impl)
+ {
+ //BOOST_ASSERT(impl.status() >= loaded);
+ return impl.post_vars();
+ }
+
+ // prefer this to the above
+ map_type&
+ POST(implementation_type& impl, boost::system::error_code& ec)
{
//BOOST_ASSERT(impl.status() >= loaded);
return impl.post_vars();
}
+ // TODO: use `greedy`
+ std::string
+ form(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec, bool greedy)
+ {
+ std::string rm(env(impl, "REQUEST_METHOD", ec));
+ //BOOST_ASSERT(!ec && !rm.empty());
+ if (rm == "GET")
+ return GET(impl, name, ec);
+ else
+ if (rm == "POST")
+ return POST(impl, name, ec);
+ else
+ return "***BOOST_CGI_ERROR_INVALID_REQUEST_METHOD***";
+ }
+
+ // TODO: use `greedy`
+ map_type&
+ form(implementation_type& impl, boost::system::error_code& ec
+ , bool greedy)
+ {
+ std::string rm(env(impl, "REQUEST_METHOD", ec));
+ //BOOST_ASSERT(!ec && !rm.empty());
+ if (rm == "GET")
+ return GET(impl);
+ else
+ if (rm == "POST")
+ return POST(impl, ec);
+ }
/// Find the cookie meta-variable matching name
- std::string cookie(implementation_type& impl, const std::string& name
- , boost::system::error_code& ec)
+ std::string
+ cookie(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec)
{
//BOOST_ASSERT(impl.status() >= loaded);
return var(impl.cookie_vars(), name, ec);
}
- map_type& cookie(implementation_type& impl)
+ map_type&
+ cookie(implementation_type& impl)
{
//BOOST_ASSERT(impl.status() >= loaded);
return impl.cookie_vars();
@@ -180,22 +314,25 @@
/// Find the environment meta-variable matching name
- std::string env(implementation_type& impl, const std::string& name
- , boost::system::error_code& ec)
+ std::string
+ env(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec)
{
//BOOST_ASSERT(impl.status() >= loaded);
const char* c = ::getenv(name.c_str());
return c ? c : impl.null_str();
}
- map_type& env(implementation_type& impl)
+ map_type&
+ env(implementation_type& impl)
{
//BOOST_ASSERT(impl.status() >= loaded);
return impl.env_vars();
}
- role_type get_role(implementation_type& impl)
+ role_type
+ get_role(implementation_type& impl)
{
return responder;
}
@@ -208,7 +345,7 @@
protected:
/// Read and parse the cgi GET meta variables
template<typename RequestImpl>
- boost::system::error_code&
+ boost::system::error_code
parse_get_vars(RequestImpl& impl, boost::system::error_code& ec)
{
// Make sure the request is in a pre-loaded state
@@ -228,7 +365,7 @@
/// Read and parse the HTTP_COOKIE meta variable
template<typename RequestImpl>
- boost::system::error_code&
+ boost::system::error_code
parse_cookie_vars(RequestImpl& impl, boost::system::error_code& ec)
{
// Make sure the request is in a pre-loaded state
@@ -248,21 +385,48 @@
/// Read and parse the cgi POST meta variables (greedily)
template<typename RequestImpl>
- boost::system::error_code&
+ boost::system::error_code
parse_post_vars(RequestImpl& impl, boost::system::error_code& ec)
{
// Make sure this function hasn't already been called
//BOOST_ASSERT (!impl.stdin_parsed());
+ std::string content_type (var(impl.env_vars(), "CONTENT_TYPE", ec));
+
+ BOOST_ASSERT(!content_type.empty());
+
+ if (boost::algorithm::ifind_first(content_type,
+ "application/x-www-form-urlencoded"))
+ {
+ detail::throw_error(
+ parse_url_encoded_form(impl, ec)
+ );
+ }
+ else
+ {
+ detail::throw_error(
+ parse_multipart_form(impl, ec)
+ );
+ }
+
+ return ec;
+ }
+
+ boost::system::error_code
+ parse_url_encoded_form(implementation_type& impl
+ , boost::system::error_code& ec)
+ {
std::istream& is(std::cin);
char ch;
std::string name;
std::string str;
map_type& post_map(impl.post_vars());
+ /* What were these lines here for?
const char* a = ::getenv("content_length");
if (a) str = a;
else throw std::runtime_error("no content-length");
+ */
//std::cerr<< "content length = ";
//var(impl.get_vars(), "CONTENT_LENGTH", ec);
@@ -298,15 +462,448 @@
// save the last param (it won't have a trailing &)
if( !name.empty() )
post_map[name] = str;//.empty() ? "" : str;
+
+
+ return ec;
+ }
+
+ /// Parse a multipart form.
+ boost::system::error_code
+ parse_multipart_form(implementation_type& impl, boost::system::error_code& ec)
+ {
+ parse_boundary_marker(impl, ec);
+ //parse_one_form_part(impl, ec);
+ move_to_start_of_first_part(impl, ec);
+ if (ec == boost::asio::error::eof) {
+ cerr<< " -- Parsing done -- " << endl;
+ //return ec.clear();
+ return boost::system::error_code();
+ }
+
+ parse_form_part(impl, ec);
+ // Do this just for now, for debugging
+ parse_url_encoded_form(impl, ec);
+ return ec;
+ }
+ boost::system::error_code
+ parse_form_part(implementation_type& impl, boost::system::error_code& ec)
+ {
+ if (!parse_form_part_meta_data(impl, ec)
+ && !parse_form_part_data(impl, ec))
+ return ec;
return ec;
}
+ boost::system::error_code
+ parse_form_part_data(implementation_type& impl, boost::system::error_code& ec)
+ {
+ std::string regex("^(.*?)" // the data
+ "\\x0D\\x0A" // CR LF
+ "--" "(");
+ //typename implementation_type::form_iterator
+ if (impl.boundary_markers.size() > 1)
+ {
+ std::list<std::string>::iterator i(impl.boundary_markers.begin());
+ regex = regex + "(?:" + *i + ")";
+ ++i;
+ for(; i != impl.boundary_markers.end(); ++i)
+ {
+ regex = regex + "|(?:" + *i + ")";
+ }
+ }
+ else
+ {
+ regex += *impl.boundary_markers.begin();
+ }
+
+ regex += ")[ ]*\\x0D\\x0A";
+ cerr<< "Regex: " << regex << endl;
+ boost::regex re(regex);
+
+ typedef typename
+ implementation_type::buffer_type::iterator
+ buffer_iter;
+
+ boost::match_results<buffer_iter> matches;
+
+ std::size_t offset = impl.offset_;
+ cerr<< "offset = " << offset << endl;
+
+ //int runs = 0;
+ buffer_iter begin(impl.buf_.begin() + offset);
+ buffer_iter end(impl.buf_.end());
+ for(;;)
+ {
+ cerr<< "Starting regex_search" << endl;
+ if (!boost::regex_search(begin, end, matches, re
+ , boost::match_default
+ | boost::match_partial))
+ {
+ cerr<< "Can't match any of this. {" << endl
+ << std::string(begin, end) << endl
+ << "}" << endl;
+ return boost::system::error_code(345, boost::system::system_category);
+ }
+ else
+ {
+ for (unsigned int i = 0; i < matches.size(); ++i)
+ {
+ if (matches[i].length())
+ {
+ cerr<< "[" << i << "] == {" << endl
+ << matches[i] << endl
+ << "}" << endl;
+ }
+ }
+ // cerr<< "matches[0] = {" << endl
+ // << matches[0].str() << endl
+ // << "}" << endl;
+ if (matches[1].matched)
+ {
+ impl.form_parts_.back().buffer_
+ // = boost::range_iterator<;
+ = std::make_pair(matches[1].first, matches[1].second);
+ cerr<< "Saved buffer (size: "
+ << std::distance(matches[1].first, matches[1].second)
+ << ")" << endl;
+ //impl.offset_ +=
+ return ec;
+ }
+ else
+ {
+ cerr<< "Reading more data." << endl;
+ std::size_t bytes_read = impl.client_.read_some(impl.prepare(32), ec);
+ begin = impl.buf_.begin() + offset;
+ end = impl.buf_.end();
+ cerr<< "Buffer (+" << bytes_read << ") == {" << endl
+ << std::string(begin, end) << endl
+ << "}" << endl;
+
+ if (ec)
+ {
+ cerr<< "Error in parse_form_part_data()." << endl;
+ return ec;
+ }
+
+ }
+ }
+
+ }
+
+
+ return ec;
+ }
+
+ boost::system::error_code
+ parse_form_part_meta_data(implementation_type& impl, boost::system::error_code& ec)
+ {
+ boost::regex re(//"(?:.*?)?"
+ "^(?:"//\\x0D\\x0A" // start of the line
+ "(?:" // [IGNORE] the line may be empty, as meta-data is optional
+ "([-\\w]+)" // name
+ ":[ ^]*" // separator
+ "([-\\w]+)" // optional(?) value
+
+ "(?:"
+ ";"
+ "[ \\x0D\\x0A]*" // additional name/value pairs (don't capture)
+ "([-\\w]+)" // name
+ "[ \\x0D\\x0A]*=[ \\x0D\\x0A]*" // separator
+ //"(?"
+ // "(?=\")([^\"]+)\"" // value (delimited; any character)
+ //"|"
+ // "([-\\w]+)" // value (7-bit ASCII only)
+ "(?:\"?([-\\w]+)\"?)"
+ //")"
+ ")*" // mark the extra n/v pairs optional
+ ")*"
+ ")?"
+ //"|(\\x0D\\x0A)"
+ "\\x0D\\x0A"); // followed by the end of the line
+
+ typedef typename
+ implementation_type::buffer_type::iterator
+ buffer_iter;
+
+ boost::match_results<
+ typename
+ implementation_type::buffer_type::iterator
+ > matches;
+
+ //impl.buf_.clear();
+ //typename implementation_type::buffer_type::difference_type
+ std::size_t offset = impl.offset_;//std::difference(impl.buf_.begin(), impl.pos_);
+ cerr.flush();
+ impl.pos_ = impl.buf_.begin();
+ //buffer_iter begin(impl.pos_);
+ int runs = 0;
+ cerr<< "Entering for() loop." << endl;
+ std::size_t bytes_read = 0;
+ for(;;)
+ {
+ buffer_iter begin(impl.buf_.begin() + offset);//impl.pos_);// + offset);//
+ buffer_iter end(impl.buf_.end());
+ if (!boost::regex_search(begin, end, matches, re
+ , boost::match_default | boost::match_partial))
+ {
+ cerr<< "No chance of a match, quitting." << endl;
+ return ec;
+ }
+ cerr<< "matches.str() == {" << endl
+ << matches.str() << endl
+ << "}" << endl;
+ if (matches[0].matched)
+ {
+ //cerr<< "matches[0].length() == " << matches[0].length() << endl;
+ if (0 == matches[1].length())
+ { // empty line: terminate headers
+ cerr<< "Headers terminated." << endl;
+ impl.offset_ = offset + matches[0].length();
+ impl.pos_ = matches[0].second;
+ cerr<< "Current buffer == {" << endl
+ << impl.buffer_string() << endl
+ << "}" << endl;
+ cerr<< "Leaving parse_form_part_meta_data()" << endl;
+ return ec;
+ }
+ // else we have a match for a header line
+ cerr<< "Parsing form part meta-data." << endl;
+ //<< "matches.size() == " << matches.size() << endl;
+ common::form_part part;
+ for (unsigned int i = 1; i < matches.size(); i+=2)
+ {
+ // We need to ignore matches[0] : the complete string
+ // Ignore last match, which is the header terminator
+ /*
+ if (matches[i].length())
+ {
+ cerr<< "[" << i << "] == {" << endl
+ << matches[i] << endl
+ << "}" << endl;
+ }
+ */
+ //if (matches[i].str() == "Content-type
+ part.meta_data_[matches[i]] //= matches[2].str();
+ = std::make_pair(matches[i+1].first, matches[i+1].second);
+ cerr<< "Part := { " << matches[i] << ", " << matches[i+1] << " }" << endl;
+ //= boost::iterator_range<buffer_iter>(matches[3].first, matches[3].second);
+ }
+ impl.form_parts_.push_back(part);
+ //cerr<< "Added meta data to form_part list (size: "
+ // << impl.form_parts_.size() << "| elements: "
+ // << impl.form_parts_.back().meta_data_.size() << ")" << endl;
+
+
+ offset += matches[0].length();
+ impl.pos_ = matches[0].second;
+ //break;
+
+ }else{
+ cerr<< "Not read enough data yet, reading more." << endl;
+ bytes_read = impl.client_.read_some(impl.prepare(32), ec);
+ if (ec)
+ {
+ cerr<< "Error reading data: " << ec.message() << endl;
+ cerr<< "Leaving parse_form_part_meta_data()" << endl;
+ return ec;
+ }
+ cerr<< "Read " << bytes_read << " bytes." << endl;
+ cerr<< "buffer = {" << endl
+ << std::string(impl.buf_.begin(), impl.buf_.end()) << endl
+ << "} or {" << endl;
+ //<< std::string(impl.pos_, ;
+ /*
+ for (unsigned int i = 0; i < matches.size(); ++i)
+ {
+ if (matches[i].length())
+ {
+ cerr<< "[" << i << "] == {" << endl
+ << matches[i] << endl
+ << "}" << endl;
+ }
+ }
+ cerr<< "-------buf------" << endl
+ << std::string(begin, end) << endl
+ << "----------------" << endl;
+ */
+ //offset = impl.buf_.end();
+ if (++runs > 20)
+ break;
+ cerr<< "Waiting buffer (unparsed) == {" << endl << std::flush
+ << impl.buffer_string() << endl
+ << "}" << endl
+ << "offset = " << offset << endl;
+ //if (bytes_read == 0)
+ // break;
+ }
+ }
+
+ //cerr<< "impl.part
+
+ cerr<< "Leaving parse_form_part_meta_data()" << endl;
+ return ec;
+ }
+
+ boost::system::error_code
+ move_to_start_of_first_part(implementation_type& impl, boost::system::error_code& ec)
+ {
+ //cerr<< "Marker = " << impl.boundary_markers.front() << endl
+ // << "blah" << "--" + impl.boundary_markers.front() + ")" << endl;
+ boost::regex re("((?:.*)?" // optional leading characters
+ //"(?:\\x0D\\x0A)|^" // start of line
+ "[\\x0D\\x0A^]*?"
+ "("
+ "--" + impl.boundary_markers.front() + // two dashes and our marker
+ ")"
+ "(--)?" // optional two dashes (not sure if this is allowed)
+ " *\\x0D\\x0A)");
+ // on the first marker.
+
+ typedef typename
+ implementation_type::buffer_type::iterator
+ buffer_iter;
+
+ boost::match_results<
+ typename
+ implementation_type::buffer_type::iterator
+ > matches;
+ //cerr<< "Boundary marker == {" << endl
+ // << impl.boundary_marker << endl
+ // << "}" << endl;
+
+ // get data into our buffer until we reach the first boundary marker.
+ int runs = 0;
+ std::size_t offset = 0;
+// std::size_t bytes_read = impl.client_.read_some(impl.prepare(32), ec);
+// if (ec || (bytes_read == 0))
+// return ec;
+ std::size_t bytes_read = 0;
+ for(;;)
+ {
+ bytes_read = impl.client_.read_some(impl.prepare(32), ec);
+ if (ec || (bytes_read == 0))
+ return ec;
+ buffer_iter begin(impl.buf_.begin());// + offset);
+ buffer_iter end(impl.buf_.end());
+ if (!boost::regex_search(begin, end //impl.buf_.begin(), impl.buf_.end()
+ , matches, re, boost::match_default | boost::match_partial))
+ {
+ // No chance of matching input with expected, so erase it and start again.
+ //std::cerr<< " == buffer = " << std::string(impl.buf_.begin(), impl.buf_.end())
+ // << " == capacity = " << impl.buf_.capacity() << " ======= ";
+ //impl.buf_.clear();
+ cerr<< "No chance of matching." << endl;
+ offset = impl.buf_.size();
+ //std::cerr<< "Buffer cleared." << endl;
+ continue;
+ }
+ else
+ {
+ //std::cerr<< "regex_search == true" << std::endl
+ // << "matches[0] =={{ " << matches[0] << " }}=== " << std::endl
+ // << "matches[1] =={{ " << matches[1] << " }}=== " << std::endl
+ // << "matches[2] =={{ " << matches[2] << " }}=== " << std::endl;
+ if (matches[2].matched){
+ cerr<< "Found boundary marker... OK!!" << endl;
+ //cerr<< "[0] = " << matches[0].str() << endl;
+ //cerr<< "[1] = " << matches[1].str() << endl;
+ //impl.offset_ = matches[1].length();
+ //impl.pos_ = matches[0].second;
+ //cerr<< "setting pos_ to < " << std::string(impl.pos_, impl.pos_ + 5) << "... >" << endl
+ // << "setting offset_ = " << impl.offset_ << endl;
+ // << std::string(matches[1].first, matches[1].second) << endl;
+ //impl.pos_ = matches[1].second;
+ //cerr<< "deleting {" << endl
+ // << std::string(impl.buf_.begin(), matches[0].second) << endl
+ // << "} leaving {" << endl
+ // << std::string(matches[0].second, impl.buf_.end()) << endl
+ // << "}" << endl;
+ //cerr<< "bufsize = " << impl.buf_.size() << endl;
+ //cerr<< "bufsize = " << impl.buf_.size() << endl;
+ cerr<< "buffer now (before erase) == {" << endl
+ << std::string(impl.buf_.begin(), impl.buf_.end()) << endl
+ << "}" << endl;
+ impl.buf_.erase(impl.buf_.begin(), matches[0].second);
+ impl.offset_ = 0;
+ impl.pos_ = impl.buf_.begin();
+ return ec;
+ } else {
+ cerr<< "not read enough data" << std::endl;
+ //std::cerr<< "; bytes_read = " << bytes_read
+ // << "; bufsize = " << impl.buf_.size()
+ // << "; capacity = " << impl.buf_.capacity() << std::flush
+ // << "; data = {{" << std::string(impl.buf_.begin(), impl.buf_.end()) << "}}";
+
+ if (++runs > 10)
+ return ec;
+ continue;
+ }
+ }
+ }
+
+
+ // skip that line and then erase the buffer
+ return ec;
+ }
+
+ boost::system::error_code
+ parse_one_form_part(implementation_type& impl, boost::system::error_code& ec)
+ {
+ // continuously read data while parsing it until one complete form part has
+ // been read.
+ // Note, this may mean recursing into embedded sub-parts if necessary, but
+ // still only the first *complete* part/sub-part would be read.
+ //boost::regex re("\r\n--" + impl.boundary_marker + " +
+
+ for(;;)
+ {
+ //if (impl.client_.read_some(impl.prepare(1024), ec))
+ // return ec;
+ //boost::asio::read_until(impl.client_, impl.buffer_, impl.boundary_marker, ec);
+ break;
+
+
+ }
+
+ return ec;
+ }
+
+ /// Get the boundary marker from the CONTENT_TYPE header.
+ boost::system::error_code
+ parse_boundary_marker(implementation_type& impl, boost::system::error_code& ec)
+ {
+ // get the meta-data appended to the content_type
+ std::string content_type(var(impl.env_vars(), "CONTENT_TYPE", ec));
+ //BOOST_ASSERT(!content_type.empty());
+
+ //boost::algorithm::ifind(var(impl, "CONTENT_TYPE"), "bounday="
+
+ boost::regex re("; ?boundary=\"?([^\"\n\r]+)\"?");
+ boost::smatch match_results;
+ if (!boost::regex_search(content_type, match_results, re))
+ return boost::system::error_code(666, boost::system::system_category);
+
+ impl.boundary_marker = match_results[1].str();
+ // New boundary markers are added to the front of the list.
+ impl.boundary_markers.push_front(match_results[1].str());
+
+ /*
+ cerr<< "full = " << content_type << endl
+ << "full search string = " << match_results[0] << endl
+ << "marker length = " << match_results[1].length() << endl
+ << "marker = " << impl.boundary_marker << endl
+ << "_[2] = " << match_results[2] << endl;
+ */
+
+ return ec;
+ }
+
/// Read and parse a single cgi POST meta variable (greedily)
template<typename RequestImpl>
- boost::system::error_code&
+ boost::system::error_code
parse_one_post_var(RequestImpl& impl, boost::system::error_code& ec)
{
//# error "Not implemented"
@@ -319,3 +916,4 @@
#include "boost/cgi/detail/pop_options.hpp"
#endif // CGI_CGI_SERVICE_IMPL_HPP_INCLUDED__
+
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/protocol_traits.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/protocol_traits.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/protocol_traits.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -25,7 +25,15 @@
namespace cgi {}
namespace acgi {}
- namespace fcgi {}
+ namespace fcgi
+ {
+ class fcgi_request_impl;
+ class fcgi_service_impl;
+ class fcgi_gateway_impl;
+ class fcgi_gateway_service;
+ class fcgi_request_service;
+ class fcgi_acceptor_service;
+ }
namespace scgi
{
class scgi_request_impl;
@@ -81,8 +89,9 @@
typedef cgi_request_impl impl_type;
typedef cgi_request_service request_service_impl;
typedef basic_protocol_service<tags::cgi> protocol_service_type;
- typedef basic_request<request_service_impl, protocol_service_type>
- request_type;
+ typedef basic_request<
+ request_service_impl, protocol_service_type
+ > request_type;
typedef cgi_service_impl service_impl_type;
typedef basic_connection<tags::stdio> connection_type;
// typedef cgi_gateway_impl gateway_impl_type;
@@ -96,8 +105,9 @@
typedef async_cgi_request_impl impl_type;
typedef acgi_request_service request_service_impl;
typedef basic_protocol_service<tags::acgi> protocol_service_type;
- typedef basic_request<request_service_impl, protocol_service_type>
- request_type;
+ typedef basic_request<
+ request_service_impl, protocol_service_type
+ > request_type;
typedef async_cgi_service_impl service_impl_type;
typedef basic_connection<tags::async_stdio> connection_type;
typedef async_cgi_gateway_impl gateway_impl_type;
@@ -112,8 +122,9 @@
typedef acgi_request_impl impl_type;
typedef acgi_request_service request_service_impl;
typedef basic_protocol_service<tags::acgi> protocol_service_type;
- typedef basic_request<request_service_impl, protocol_service_type>
- request_type;
+ typedef basic_request<
+ request_service_impl, protocol_service_type
+ > request_type;
typedef acgi_service_impl service_impl_type;
typedef basic_connection<tags::async_stdio> connection_type;
typedef acgi_gateway_impl gateway_impl_type;
@@ -124,39 +135,52 @@
struct protocol_traits<tags::fcgi>
{
typedef protocol_traits<tags::fcgi> type;
- typedef fcgi_request_impl impl_type;
- typedef fcgi_request_service request_service_impl;
+ typedef fcgi::fcgi_request_impl impl_type;
+ typedef fcgi::fcgi_request_service request_service_impl;
typedef basic_protocol_service<tags::fcgi> protocol_service_type;
- typedef basic_request<request_service_impl, protocol_service_type>
- request_type;
- typedef fcgi_service_impl service_impl_type;
- typedef basic_connection<tags::tcp_socket> connection_type;
- typedef fcgi_gateway_impl gateway_impl_type;
- typedef fcgi_gateway_service gateway_service_type;
+ typedef basic_request<
+ request_service_impl, protocol_service_type
+ > request_type;
+ //typedef fcgi_request_service
+ // ::implementation_type request_impl_type;
+ typedef fcgi::fcgi_service_impl service_impl_type;
+ typedef fcgi::fcgi_acceptor_service acceptor_service_impl;
+ typedef basic_connection<
+ tags::shareable_tcp_socket
+ > connection_type;
+ //typedef fcgi_gateway_impl gateway_impl_type;
+ //typedef fcgi_gateway_service gateway_service_type;
};
template<>
struct protocol_traits<tags::scgi>
{
typedef protocol_traits<tags::scgi> type;
- typedef scgi::scgi_request_impl impl_type;
- typedef scgi::scgi_request_service request_service_impl;
+ typedef scgi::scgi_request_impl impl_type;
+ typedef scgi::scgi_request_service request_service_impl;
typedef basic_protocol_service<tags::scgi> protocol_service_type;
- typedef basic_request<request_service_impl, protocol_service_type>
- request_type;
- typedef scgi::scgi_service_impl service_impl_type;
- typedef scgi::scgi_acceptor_service acceptor_service_impl;
+ typedef basic_request<
+ request_service_impl, protocol_service_type
+ > request_type;
+ typedef scgi::scgi_service_impl service_impl_type;
+ typedef scgi::scgi_acceptor_service acceptor_service_impl;
typedef basic_connection<tags::tcp_socket> connection_type;
//typedef scgi_gateway_impl gateway_impl_type;
//typedef scgi_gateway_service gateway_service_type;
};
template<>
- struct protocol_traits<::cgi::scgi_>
+ struct protocol_traits< ::cgi::scgi_>
: protocol_traits<tags::scgi>
{
};
+ template<>
+ struct protocol_traits< ::cgi::fcgi_>
+ : protocol_traits<tags::fcgi>
+ {
+ };
+
} // namespace detail
} // namespace cgi
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/throw_error.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/throw_error.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/throw_error.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -10,16 +10,16 @@
#define CGI_THROW_ERROR_HPP_INCLUDED__
#include <boost/system/error_code.hpp>
-//#include <boost/system/system_error.hpp>
+#include <boost/system/system_error.hpp>
namespace cgi {
namespace detail {
- void throw_error(boost::system::error_code& ec)
+ void throw_error(const boost::system::error_code& ec)
{
if(ec)
- throw ec;
-// throw boost::system::system_error(ec);
+// throw ec;
+ throw boost::system::system_error(ec);
}
} // namespace detail
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/error.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/error.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,81 @@
+// -- error.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Abstract:
+// ---------
+//
+// The errors for everything are defined in here. ie. FastCGI,
+// CGI and SCGI errors.
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_ERROR_HPP_INCLUDED__
+#define CGI_ERROR_HPP_INCLUDED__
+
+#include <string>
+#include <boost/system/error_code.hpp>
+
+namespace cgi {
+ namespace error {
+
+enum fcgi_errors
+{
+ bad_header_type = 1,
+
+ /// A packet arrived for a request id that doesn't exist and the packet
+ // wasn't a BEGIN_REQUEST record.
+ bad_request_id
+};
+
+ namespace detail {
+
+class fcgi_category
+ : public boost::system::error_category
+{
+public:
+ const char* name() const { return "fcgi_error"; }
+ std::string message(int e) const { return "BOOM!!!"; }
+};
+
+ } // namespace detail
+
+inline const boost::system::error_category& get_fcgi_category()
+{
+ static detail::fcgi_category instance;
+ return instance;
+}
+
+static const boost::system::error_category& fcgi_category
+ = ::cgi::error::get_fcgi_category();
+
+ } // namespace error
+} // namespace cgi
+
+namespace boost {
+ namespace system {
+
+ template<> struct is_error_code_enum< ::cgi::error::fcgi_errors>
+ {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+ };
+
+ } // namespace system
+} // namespace boost
+
+namespace cgi {
+ namespace error {
+
+ inline boost::system::error_code make_error_code(fcgi_errors e)
+ {
+ return boost::system::error_code(
+ static_cast<int>(e), get_fcgi_category());
+ }
+
+ } // namespace error
+} // namespace cgi
+
+#endif // CGI_ERROR_HPP_INCLUDED__
+
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -10,8 +10,15 @@
#define CGI_FCGI_HPP_INCLUDED__
// #include all fcgi-related files only
+#include "boost/cgi/fcgi/service.hpp"
+#include "boost/cgi/fcgi/acceptor.hpp"
+#include "boost/cgi/fcgi/client.hpp"
+#include "boost/cgi/fcgi/request.hpp"
+//#include "boost/cgi/fcgi/request_service.hpp"
+//#include "boost/cgi/fcgi/request_acceptor_service.hpp"
+#include "boost/cgi/detail/common_headers.hpp"
-/// Dump acgi stuff into the boost namespace
+/// Dump fcgi stuff into the boost namespace
namespace boost {
namespace fcgi {
using namespace ::cgi::fcgi;
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/acceptor.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/acceptor.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,24 @@
+// -- fcgi/acceptor.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_FCGI_ACCEPTOR_HPP_INCLUDED__
+#define CGI_FCGI_ACCEPTOR_HPP_INCLUDED__
+
+#include "boost/cgi/basic_request_acceptor.hpp"
+#include "boost/cgi/fcgi/request_acceptor_service.hpp"
+
+namespace cgi {
+ namespace fcgi {
+
+ /// Typedef for common usage (FCGI)
+ typedef basic_request_acceptor<fcgi_request_acceptor_service<> > acceptor;
+
+ } // namespace fcgi
+} // namespace cgi
+
+#endif // CGI_FCGI_ACCEPTOR_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/acceptor_service_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/acceptor_service_impl.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,332 @@
+// -- fcgi/acceptor_service_impl.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_FCGI_ACCEPTOR_SERVICE_IMPL_HPP_INCLUDED__
+#define CGI_FCGI_ACCEPTOR_SERVICE_IMPL_HPP_INCLUDED__
+
+#include "boost/cgi/detail/push_options.hpp"
+
+#include <boost/ref.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/asio.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/system/error_code.hpp>
+
+//#include "is_async.hpp"
+#include "boost/cgi/io_service.hpp"
+#include "boost/cgi/detail/throw_error.hpp"
+#include "boost/cgi/detail/protocol_traits.hpp"
+#include "boost/cgi/basic_protocol_service_fwd.hpp"
+#include "boost/cgi/detail/service_base.hpp"
+//#include "service_selector.hpp"
+#include "boost/cgi/fcgi/request.hpp"
+
+namespace cgi {
+
+ namespace detail {
+
+ /// Helper functions for async_accept operation.
+ template<typename T, /*typename Request, */typename Handler>
+ struct accept_handler
+ {
+ accept_handler(T& t, typename T::implementation_type& impl
+ , typename T::implementation_type::request_type& req
+ , Handler& hnd)
+ : type(t)
+ , implementation(impl)
+ , request(req)
+ , handler(hnd)
+ {}
+
+ void operator()()
+ {
+ type.check_for_waiting_request(implementation, request, handler);
+ }
+
+ T& type;
+ typename T::implementation_type& implementation;
+ typename T::implementation_type::request_type& request;
+ Handler handler;
+ };
+
+ } // namespace detail
+
+ namespace fcgi {
+
+ /// The service_impl class for FCGI basic_request_acceptor<>s
+ /**
+ * Note: this is near enough to being generic. It will hopefully translate
+ * directly to the fcgi_acceptor_service_impl. In other words you would
+ * then have one acceptor_service_impl<>, so you'd use
+ * acceptor_service_impl<scgi> acceptor_service_impl_; // and
+ * acceptor_service_impl<fcgi> acceptor_service_impl_; // etc...
+ *
+ * Note: If the protocol is an asynchronous protocol, which means it requires
+ * access to a boost::asio::io_service instance, then this class becomes a
+ * model of the Service concept (**LINK**) and must only use the constructor
+ * which takes a ProtocolService (**LINK**). If the protocol isn't async then
+ * the class can be used without a ProtocolService.
+ */
+ template<typename Protocol_ = ::cgi::fcgi_>
+ class acceptor_service_impl
+ : public detail::service_base< ::cgi::fcgi::acceptor_service_impl<Protocol_> >
+ {
+ public:
+
+ /// The unique service identifier
+ //static boost::asio::io_service::id id;
+
+ struct implementation_type
+ {
+ typedef Protocol_ protocol_type;
+ typedef basic_protocol_service<protocol_type> protocol_service_type;
+ typedef boost::asio::ip::tcp native_protocol_type;
+ typedef fcgi::request request_type;
+ typedef boost::asio::socket_acceptor_service<
+ native_protocol_type
+ > acceptor_service_type;
+ typedef unsigned short port_number_type;
+ typedef boost::asio::ip::tcp::endpoint endpoint_type;
+ //typedef typename
+ // acceptor_service_type::native_type native_type;
+
+ acceptor_service_type::implementation_type acceptor_;
+ boost::mutex mutex_;
+ std::queue<boost::shared_ptr<request_type> > waiting_requests_;
+ protocol_service_type* service_;
+ port_number_type port_num_;
+ endpoint_type endpoint_;
+ };
+
+ typedef acceptor_service_impl<Protocol_> type;
+ typedef typename
+ type::implementation_type::protocol_type
+ protocol_type;
+ typedef typename
+ type::implementation_type::protocol_service_type
+ protocol_service_type;
+ typedef typename
+ type::implementation_type::acceptor_service_type
+ acceptor_service_type;
+ typedef typename
+ type::implementation_type::native_protocol_type
+ native_protocol_type;
+ typedef typename
+ acceptor_service_type::native_type native_type;
+
+
+ explicit acceptor_service_impl(::cgi::io_service& ios)
+ : detail::service_base< ::cgi::fcgi::acceptor_service_impl<Protocol_> >(ios)
+ , acceptor_service_(boost::asio::use_service<acceptor_service_type>(ios))
+ //, endpoint(boost::asio::ip::tcp::v4())
+ {
+ }
+
+ void set_protocol_service(implementation_type& impl
+ , protocol_service_type& ps)
+ {
+ impl.protocol_service_ = &ps;
+ }
+
+ protocol_service_type&
+ get_protocol_service(implementation_type& impl)
+ {
+ BOOST_ASSERT(impl.service_ != NULL);
+ return *impl.service_;
+ }
+
+ void construct(implementation_type& impl)
+ {
+ acceptor_service_.construct(impl.acceptor_);
+ //impl.acceptor_ptr().reset(impl::acceptor_type(this->io_service()));
+ }
+
+ void destroy(implementation_type& impl)
+ {
+ // close/reject all the waiting requests
+ /***/
+ acceptor_service_.destroy(impl.acceptor_);
+ }
+
+ void shutdown_service()
+ {
+ acceptor_service_.shutdown_service();
+ }
+
+ /// Check if the given implementation is open.
+ bool is_open(implementation_type& impl)
+ {
+ return acceptor_service_.is_open(impl.acceptor_);
+ }
+
+ /// Open a new *socket* acceptor implementation.
+ boost::system::error_code
+ open(implementation_type& impl, const native_protocol_type& protocol
+ , boost::system::error_code& ec)
+ {
+ return acceptor_service_.open(impl.acceptor_, protocol, ec);
+ }
+
+ template<typename Endpoint>
+ boost::system::error_code
+ bind(implementation_type& impl, const Endpoint& endpoint
+ , boost::system::error_code& ec)
+ {
+ acceptor_service_.set_option(impl.acceptor_,
+ boost::asio::socket_base::reuse_address(true), ec);
+ return acceptor_service_.bind(impl.acceptor_, endpoint, ec);
+ }
+
+ /// Assign an existing native acceptor to a *socket* acceptor.
+ boost::system::error_code
+ assign(implementation_type& impl, const native_protocol_type& protocol
+ , const native_type& native_acceptor
+ , boost::system::error_code& ec)
+ {
+ return acceptor_service_.assign(impl.acceptor_, protocol
+ , native_acceptor, ec);
+ }
+
+ boost::system::error_code
+ listen(implementation_type& impl, int backlog, boost::system::error_code& ec)
+ {
+ return acceptor_service_.listen(impl.acceptor_, backlog, ec);
+ }
+
+ /// Accepts one request.
+ template<typename CommonGatewayRequest>
+ boost::system::error_code
+ accept(implementation_type& impl, CommonGatewayRequest& request
+ , boost::system::error_code& ec)
+ {
+ /* THIS BIT IS BROKEN:
+ *-- The noncopyable semantics of a basic_request<> don't allow the
+ assignment. There are a couple of ways around this; the one that
+ seems sensible is to keep the basic_request<>s noncopyable, but
+ allow the actual data be copied. At the moment the actual data is
+ held in a vector<string> headers container and a cgi::streambuf.
+ These two bits should really be factored out into a message type.
+ IOW, the message type will be copyable (but should probably have
+ unique-ownership semantics).
+ --*
+ {
+ boost::mutex::scoped_lock lk(impl.mutex_);
+ if (!impl.waiting_requests_.empty())
+ {
+ request = *(impl.waiting_requests_.front());
+ impl.waiting_requests_.pop();
+ return ec;
+ }
+ }
+ */
+ return acceptor_service_.accept(impl.acceptor_,
+ request.client().connection()->next_layer(), 0, ec);
+ }
+
+ /// Accepts one request.
+ template<typename CommonGatewayRequest, typename Endpoint>
+ boost::system::error_code
+ accept(implementation_type& impl, CommonGatewayRequest& request
+ , Endpoint* endpoint, boost::system::error_code& ec)
+ {
+ /* THIS BIT IS BROKEN:
+ *-- The noncopyable semantics of a basic_request<> don't allow the
+ assignment. There are a couple of ways around this; the one that
+ seems sensible is to keep the basic_request<>s noncopyable, but
+ allow the actual data be copied. At the moment the actual data is
+ held in a vector<string> headers container and a cgi::streambuf.
+ These two bits should really be factored out into a message type.
+ IOW, the message type will be copyable (but should probably have
+ unique-ownership semantics).
+ --*
+ {
+ boost::mutex::scoped_lock lk(impl.mutex_);
+ if (!impl.waiting_requests_.empty())
+ {
+ request = *(impl.waiting_requests_.front());
+ impl.waiting_requests_.pop();
+ return ec;
+ }
+ }
+ */
+ return acceptor_service_.accept(impl.acceptor_,
+ request.client().connection()->next_layer(), endpoint, ec);
+ }
+
+ /// Asynchronously accepts one request.
+ //template<typename CommonGatewayRequest, typename Handler>
+ //void async_accept(implementation_type& impl, CommonGatewayRequest& request
+ template<typename Handler>
+ void async_accept(implementation_type& impl, typename implementation_type::request_type& request
+ , Handler handler)
+ {
+ this->io_service().post(
+ detail::accept_handler<type, Handler>(*this, impl, request, handler)
+ );
+ //boost::system::error_code ec;
+ //handler(ec);
+ //acceptor_service_.async_accept(impl.acceptor_, request.client().connection()->next_layer_type()
+
+/*
+ &acceptor_service_impl<protocol_type>
+ ::typename check_for_waiting_request<
+ CommonGatewayRequest
+ , Handler>,
+ this, boost::ref(impl), boost::ref(request), handler));
+*/
+ }
+
+ /// Close the acceptor (not implemented yet).
+ boost::system::error_code
+ close(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return boost::system::error_code(348, boost::system::system_category);
+ }
+
+ typename implementation_type::endpoint_type
+ local_endpoint(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return acceptor_service_.local_endpoint(impl.acceptor_, ec);
+ }
+
+ public:
+ template<typename CommonGatewayRequest, typename Handler>
+ void check_for_waiting_request(implementation_type& impl
+ , CommonGatewayRequest& request
+ , Handler handler)
+ {
+ /*
+ {
+ boost::mutex::scoped_lock lk(impl.mutex_);
+ if (!impl.waiting_requests_.empty())
+ {
+ request = *(impl.waiting_requests_.front());
+ impl.waiting_requests_.pop();
+ return handler(ec); // this could be `io_service::post`ed again
+ }
+ }
+ */
+ acceptor_service_.async_accept(impl.acceptor_,
+ request.client().connection()->next_layer(), 0, handler);
+ }
+
+ public:
+ /// The underlying socket acceptor service.
+ acceptor_service_type& acceptor_service_;
+ };
+
+ } // namespace fcgi
+} // namespace cgi
+
+#include "boost/cgi/detail/pop_options.hpp"
+
+#endif // CGI_FCGI_ACCEPTOR_SERVICE_IMPL_HPP_INCLUDED__
+
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/client.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/client.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,480 @@
+// -- fcgi/client.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_FCGI_CLIENT_HPP_INCLUDED__
+#define CGI_FCGI_CLIENT_HPP_INCLUDED__
+
+#include <boost/shared_ptr.hpp>
+#include <boost/logic/tribool.hpp>
+#include "boost/cgi/tags.hpp"
+#include "boost/cgi/map.hpp"
+#include "boost/cgi/io_service.hpp"
+#include "boost/cgi/basic_client.hpp"
+#include "boost/cgi/connections/shareable_tcp_socket.hpp"
+#include "boost/cgi/fcgi/specification.hpp"
+#include "boost/cgi/read.hpp"
+#include "boost/cgi/buffer.hpp"
+#include "boost/cgi/error.hpp"
+//#include "boost/cgi/fcgi/request_fwd.hpp"
+#include "boost/cgi/detail/protocol_traits.hpp"
+//#error BOOST_HAS_RVALUE_REFS
+namespace cgi {
+
+ /// A client that uses a TCP socket that owned by it.
+ template<typename Protocol>
+ class basic_client<shareable_tcp_connection, Protocol>
+ {
+ public:
+ typedef ::cgi::io_service io_service_type;
+ typedef ::cgi::map map_type;
+ typedef Protocol protocol_type;
+ typedef shareable_tcp_connection connection_type;
+ //typedef detail::protocol_traits<
+ // fcgi_
+ //>::request_impl_type request_impl_type;
+ //struct connection_type : shareable_tcp_connection
+ //{ typedef boost::shared_ptr<connection_type> pointer; }
+ typedef typename connection_type::pointer connection_ptr;
+ typedef boost::array<
+ unsigned char
+ , fcgi::spec::header_length::value
+ > header_buffer_type;
+ typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
+
+ /// Construct
+ basic_client()
+ : request_id_(-1)
+ , closed_(false)
+ {
+ }
+
+ /// Construct
+ basic_client(io_service_type& ios)
+ : request_id_(-1)
+ , closed_(false)
+ //, io_service_(ios)
+ //, connection_(new connection_type::pointer(ios))
+ {
+ }
+
+ /// Destroy
+ /** Closing the connection as early as possible is good for efficiency */
+ ~basic_client()
+ {
+ if (!keep_connection_ && connection_)
+ connection_->close();
+ }
+
+ /// Construct the client by claiming a request id.
+ /**
+ * Before loading a request, it will usually not have a request id. This
+ * function reads headers (and corresponding bodies if necessary) until
+ * a BEGIN_REQUEST record is found. The calling request then claims and
+ * serves that request.
+ */
+ template<typename RequestImpl>
+ boost::system::error_code
+ construct(RequestImpl& req, boost::system::error_code& ec)
+ {
+ BOOST_ASSERT(connection_->is_open());
+
+ for(;;)
+ {
+ if (read_header(ec))
+ break;
+ int id(fcgi::spec::get_request_id(header_buf_));
+ if (id == fcgi::spec::null_request_id::value)
+ handle_admin_request();
+ else
+ if (fcgi::spec::get_type(header_buf_)
+ == fcgi::spec::begin_request::value)
+ {
+ request_id_ = id;
+ if (read_header(ec))
+ break;
+ req.request_role_ = fcgi::spec::begin_request::get_role(header_buf_);
+ std::cerr<< "[hw] New request role: " << req.request_role_
+ << " (" << fcgi::spec::role_type::to_string(header_buf_) << ")"
+ << std::endl;
+ keep_connection_
+ = fcgi::spec::begin_request::get_flags(header_buf_)
+ & fcgi::spec::keep_connection;
+ break;
+ }else
+ handle_other_request_header();
+ }
+
+ return ec;
+ }
+
+ bool is_open() const
+ {
+ return connection_->is_open();
+ }
+
+ void close()
+ {
+ connection_->close();
+ }
+
+ //io_service_type& io_service() { return io_service_; }
+
+ /// Associate a connection with this client
+ /**
+ * Note: the connection must have been created using the new operator
+ */
+ bool set_connection(connection_type* conn)
+ {
+ // make sure there isn't already a connection associated with the client
+ //if (!connection_) return false;
+ connection_.reset(conn);
+ return true;
+ }
+
+ /// Associate a connection with this client
+ bool set_connection(const connection_type::pointer& conn)
+ {
+ // make sure there isn't already a connection associated with the client
+ //if (!connection_) return false;
+ connection_ = conn;
+ return true;
+ }
+
+ /// Get a shared_ptr of the connection associated with the client.
+ connection_type::pointer&
+ connection() { return connection_; }
+
+ /// Write some data to the client.
+ template<typename ConstBufferSequence>
+ std::size_t
+ write_some(const ConstBufferSequence& buf, boost::system::error_code& ec)
+ {
+ //detail::make_header(out_header_, buf
+ return connection_->write_some(buf, ec);
+ }
+
+ /// Read some data from the client.
+ template<typename MutableBufferSequence>
+ std::size_t
+ read_some(const MutableBufferSequence& buf, boost::system::error_code& ec)
+ {
+ if (closed_)
+ return 0;
+
+ if (read_header(ec))
+ return -1;
+
+ boost::tribool state = parse_header();
+ std::size_t bytes_read;//( connection_->read_some(buf, ec) );
+ return bytes_read;
+ }
+
+ /// Asynchronously write some data to the client.
+ template<typename ConstBufferSequence, typename Handler>
+ void async_write_some(const ConstBufferSequence& buf, Handler handler)
+ {
+ connection_->async_write_some(buf, handler);
+ }
+
+ /// Asynchronously read some data from the client.
+ template<typename MutableBufferSequence, typename Handler>
+ void async_read_some(const MutableBufferSequence& buf, Handler handler)
+ {
+ connection_->async_read_some(buf, handler);
+ }
+
+ boost::system::error_code
+ read_header(boost::system::error_code& ec)
+ {
+ header_buf_ = header_buffer_type();
+ if (8 != read(*connection_, buffer(header_buf_)
+ , boost::asio::transfer_all(), ec) || ec)
+ return ec;
+
+ //if (ec) return ec;
+
+ std::cerr<< std::endl
+ << "[hw] Header details {" << std::endl
+ << " RequestId := " << fcgi::spec::get_request_id(header_buf_) << std::endl
+ << " FastCGI version := " << fcgi::spec::get_version(header_buf_) << std::endl
+ << " Type := " << fcgi::spec::get_type(header_buf_)
+ << " (" << fcgi::spec::request_type::to_string(header_buf_) << ")" << std::endl
+ << " Content-length := " << fcgi::spec::get_content_length(header_buf_) << std::endl
+ << "}" << std::endl;
+
+ return ec;
+ }
+
+ private:
+ friend class fcgi_request_service;
+ boost::uint16_t request_id_;
+ //request_impl_type* current_request_;
+
+ /// A marker to say if the final STDIN (and/or DATA) packets have been
+ // read. Note: having data on the connection doesn't imply it's for
+ // this request; we can save time by knowing when to not even try.
+ bool closed_;
+
+ connection_ptr connection_;
+
+ //fcgi::spec_detail::Header hdr_;
+ /// Buffer used to check the header of each packet.
+ header_buffer_type header_buf_; //in_header_, out_header_;
+
+ bool keep_connection_;
+
+ /*** Various handlers go below here; they might find a
+ * better place to live ***/
+
+ // **FIXME**
+ void handle_admin_request()
+ {
+ std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__
+ << " handle_admin_request()" << std::endl;
+ }
+
+ // **FIXME**
+ void handle_other_request_header()
+ {
+ std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__
+ << " handle_other_request_header()" << std::endl;
+ }
+
+ // **FIXME**
+ boost::system::error_code
+ process_begin_request(boost::uint16_t id, const unsigned char* buf
+ , boost::uint16_t, boost::system::error_code& ec)
+ {
+ if (read_header(ec))
+ detail::throw_error(ec);
+
+ std::cerr<< "Role: " << fcgi::spec::begin_request::get_role(header_buf_) << std::endl;
+ //connection_->request_map_[id] =
+ return ec;
+ }
+
+ boost::system::error_code
+ process_abort_request(boost::uint16_t id, const unsigned char* buf
+ , boost::uint16_t, boost::system::error_code& ec)
+ {
+/*
+ connection_type::request_map_type::iterator i
+ = connection_->find(id);
+
+ if (i == connection_type::request_map_type::iterator())
+ {
+ return bad_request_id;
+ }
+
+ //lookup_request(id).abort();
+*/
+ return ec;
+ }
+
+ boost::system::error_code
+ process_params(boost::uint16_t id, const unsigned char* buf
+ , boost::uint16_t len, boost::system::error_code& ec)
+ {
+ if (0 == len)
+ { // This is the final param record.
+
+ // **FIXME**
+ std::cerr<< "[hw] Final PARAM record found." << std::endl;
+ return ec;
+ }
+
+ while(len)
+ {
+ boost::uint32_t name_len, data_len;
+ std::string name, data;
+ if (*buf >> 7 == 0)
+ {
+ name_len = *(buf++);
+ --len;
+ }
+ else
+ {
+ name_len = ((buf[0] & 0x7F) << 24)
+ + (buf[1] << 16)
+ + (buf[2] << 8)
+ + buf[3];
+ buf += 4;
+ len -= 4;
+ }
+
+ if (*buf >> 7 == 0)
+ {
+ data_len = *(buf++);
+ --len;
+ }
+ else
+ {
+ data_len = ((buf[0] & 0x7F) << 24)
+ + (buf[1] << 16)
+ + (buf[2] << 8)
+ + buf[3];
+ buf += 4;
+ len -= 4;
+ }
+ name.assign(reinterpret_cast<const char*>(buf), name_len);
+ data.assign(reinterpret_cast<const char*>(buf)+name_len, data_len);
+ buf += (name_len + data_len);
+ len -= (name_len + data_len);
+
+ std::cerr<< "[hw] name := " << name << std::endl;
+ std::cerr<< "[hw] data := " << data << std::endl;
+ }
+
+ return ec;
+ }
+
+
+ boost::system::error_code
+ process_stdin(boost::uint16_t id, const unsigned char* buf
+ , boost::uint16_t len, boost::system::error_code& ec)
+ {
+ if (0 == len)
+ {
+ closed_ = true;
+
+ // **FIXME**
+ std::cerr<< "[hw] Final STDIN record found." << std::endl;
+ return ec;
+ }
+
+ // **FIXME**
+ std::cerr<< "[hw] Found some STDIN stuff." << std::endl;
+ return ec;
+ }
+
+ /// Parse the current header
+ boost::tribool parse_header()
+ {
+ BOOST_ASSERT(fcgi::spec::get_version(header_buf_) == 1
+ && "This library is only compatible with FastCGI 1.0");
+
+ using namespace fcgi::spec_detail;
+
+ switch(fcgi::spec::get_type(header_buf_))
+ {
+ case BEGIN_REQUEST:
+ case PARAMS:
+ case STDIN:
+ case DATA:
+ case GET_VALUES:
+ return boost::indeterminate;
+ case ABORT_REQUEST:
+ return false;
+ case UNKNOWN_TYPE:
+ default:
+ return true;
+ }
+ }
+
+ public:
+
+ //template<typename Request>
+ //Request& lookup_request(boost::uint16_t id)
+ //{
+
+
+ // Mammoth typedef corresponding to function signature of process_*
+ // functions.
+ typedef boost::system::error_code
+ ( ::cgi::basic_client<shareable_tcp_connection, fcgi_>::* proc_func_t)
+ (boost::uint16_t, const unsigned char*, boost::uint16_t
+ , boost::system::error_code&);
+
+ static const proc_func_t proc_funcs[];
+
+ template<typename RequestImpl>
+ boost::system::error_code
+ parse_packet(RequestImpl& req, boost::system::error_code& ec)
+ {
+ //current_request_ = &req;
+
+ if (read_header(ec))
+ return ec;
+
+ boost::tribool state = parse_header();
+
+ if (state)
+ { // the header has been handled and all is ok; continue.
+ return ec;
+ }else
+ if (!state)
+ { // The header is confusing; something's wrong. Abort.
+ std::cerr<< "Bad header received (this isn't implemented properly yet"
+ << std::endl;
+ return error::bad_header_type;
+ }
+ // else route (ie. state == boost::indeterminate)
+
+ std::cerr<< "Got to read more stuff now I think." << std::endl;
+ mutable_buffers_type buf
+ = req.prepare(fcgi::spec::get_length(header_buf_));
+
+ if (read_body(buf, ec))
+ return ec;
+
+ parse_body(buf, ec);
+
+ return ec;
+ }
+
+ /// Read the body of the current packet; do nothing with it.
+ template<typename MutableBuffersType>
+ boost::system::error_code
+ read_body(const MutableBuffersType& buffer
+ , boost::system::error_code& ec)
+ {
+ std::size_t bytes_read
+ = read(*connection_, buffer, boost::asio::transfer_all(), ec);
+
+ BOOST_ASSERT(bytes_read == fcgi::spec::get_length(header_buf_)
+ && "Couldn't read all of the record body.");
+ return ec;
+ }
+
+ template<typename MutableBuffersType>
+ boost::system::error_code
+ parse_body(const MutableBuffersType& buffer
+ , boost::system::error_code& ec)
+ {
+ return //ec;/*
+ (this->* proc_funcs[fcgi::spec::get_type(header_buf_)])
+ (fcgi::spec::get_request_id(header_buf_)
+ , boost::asio::buffer_cast<unsigned char*>(buffer)
+ , boost::asio::buffer_size(buffer), ec);
+ //*/
+ }
+ };
+
+//#include "boost/cgi/fcgi/client_fwd.hpp"
+
+namespace fcgi {
+ typedef basic_client<shareable_tcp_connection, ::cgi::fcgi_> client;
+} // namespace fcgi
+
+
+ template<>
+ const fcgi::client::proc_func_t fcgi::client::proc_funcs[] =
+ { 0
+ , &fcgi::client::process_begin_request
+ , &fcgi::client::process_abort_request
+ , 0
+ , &fcgi::client::process_params
+ , &fcgi::client::process_stdin
+ , 0
+ , 0
+ };
+
+}// namespace cgi
+
+#endif // CGI_FCGI_CLIENT_HPP_INCLUDED__
+
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,28 @@
+// -- fcgi/request.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_FCGI_REQUEST_HPP_INCLUDED__
+#define CGI_FCGI_REQUEST_HPP_INCLUDED__
+
+#include "boost/cgi/tags.hpp"
+#include "boost/cgi/basic_request_fwd.hpp"
+//#include "boost/cgi/request_service_fwd.hpp"
+#include "boost/cgi/fcgi/request_service.hpp"
+#include "boost/cgi/fcgi/service.hpp"
+namespace cgi {
+
+ namespace fcgi {
+ // typedef for typical usage (FCGI)
+ typedef basic_request<fcgi_request_service, service> request;
+ } // namespace fcgi
+} // namespace cgi
+
+//#include "boost/cgi/request_service.hpp"
+#include "boost/cgi/basic_request.hpp"
+
+#endif // CGI_FCGI_REQUEST_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_acceptor_service.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_acceptor_service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,164 @@
+// -- fcgi/request_acceptor_service.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_FCGI_REQUEST_ACCEPTOR_SERVICE_HPP_INCLUDED
+#define CGI_FCGI_REQUEST_ACCEPTOR_SERVICE_HPP_INCLUDED
+#include "boost/cgi/detail/push_options.hpp"
+
+#include <boost/utility/enable_if.hpp>
+
+//#include "is_async.hpp"
+#include "boost/cgi/io_service.hpp"
+#include "boost/cgi/detail/throw_error.hpp"
+#include "boost/cgi/detail/protocol_traits.hpp"
+#include "boost/cgi/basic_protocol_service_fwd.hpp"
+#include "boost/cgi/detail/service_base.hpp"
+//#include "service_selector.hpp"
+#include "boost/cgi/fcgi/acceptor_service_impl.hpp"
+
+namespace cgi {
+
+ /// The service class for FCGI basic_request_acceptor<>s
+ /**
+ * Note: If the protocol is an asynchronous protocol, which means it requires
+ * access to a boost::asio::io_service instance, then this class becomes a
+ * model of the Service concept (**LINK**) and must only use the constructor
+ * which takes a ProtocolService (**LINK**). If the protocol isn't async then
+ * the class can be used without a ProtocolService.
+ */
+ template<typename Protocol_ = fcgi_>
+ class fcgi_request_acceptor_service
+ : public detail::service_base<fcgi_request_acceptor_service<Protocol_> >
+ {
+ public:
+ //typedef typename service_impl_type::impl_type impl_type;
+
+ typedef fcgi::acceptor_service_impl<> service_impl_type;
+ typedef service_impl_type::implementation_type implementation_type;
+ typedef typename implementation_type::protocol_type protocol_type;
+ typedef implementation_type::endpoint_type endpoint_type;
+ typedef typename service_impl_type::native_type native_type;
+ //typedef basic_protocol_service<protocol_type> protocol_service_type;
+
+ /// The unique service identifier
+ //static boost::asio::io_service::id id;
+
+ fcgi_request_acceptor_service(::cgi::io_service& ios)
+ : detail::service_base<fcgi_request_acceptor_service<protocol_type> >(ios)
+ , service_impl_(ios)
+ {
+ }
+
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ void shutdown_service()
+ {
+ service_impl_.shutdown_service();
+ }
+
+ bool is_open(implementation_type& impl)
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ void close(implementation_type& impl)
+ {
+ boost::system::error_code ec;
+ service_impl_.close(impl, ec);
+ detail::throw_error(ec);
+ }
+
+ boost::system::error_code
+ close(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ template<typename Protocol>
+ boost::system::error_code
+ open(implementation_type& impl, const Protocol& protocol
+ , boost::system::error_code& ec)
+ {
+ return service_impl_.open(impl, protocol, ec);
+ }
+
+ template<typename Endpoint>
+ boost::system::error_code
+ bind(implementation_type& impl, const Endpoint& endpoint
+ , boost::system::error_code& ec)
+ {
+ return service_impl_.bind(impl, endpoint, ec);
+ }
+
+ boost::system::error_code
+ listen(implementation_type& impl, int backlog, boost::system::error_code& ec)
+ {
+ return service_impl_.listen(impl, backlog, ec);
+ }
+
+ template<typename CommonGatewayRequest>
+ boost::system::error_code
+ accept(implementation_type& impl, CommonGatewayRequest& request
+ , boost::system::error_code& ec)
+ {
+ return service_impl_.accept(impl, request, ec);
+ }
+
+ template<typename CommonGatewayRequest, typename Endpoint>
+ boost::system::error_code
+ accept(implementation_type& impl, CommonGatewayRequest& request
+ , Endpoint* ep, boost::system::error_code& ec)
+ {
+ return service_impl_.accept(impl, request, ep, ec);
+ }
+
+ template<typename CommonGatewayRequest, typename Handler>
+ void async_accept(implementation_type& impl, CommonGatewayRequest& req
+ , Handler handler)
+ {
+ service_impl_.async_accept(impl, req, handler);
+ }
+
+ template<typename T>
+ void set_protocol_service(implementation_type& impl, T& ps)
+ {
+ impl.service_ = &ps;
+ }
+
+ typename implementation_type::endpoint_type
+ local_endpoint(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ template<typename Protocol>
+ boost::system::error_code
+ assign(implementation_type& impl, Protocol protocol
+ , const native_type& native_acceptor, boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, protocol, native_acceptor, ec);
+ }
+
+ public:
+ service_impl_type service_impl_;
+ };
+
+} // namespace cgi
+
+#include "boost/cgi/detail/pop_options.hpp"
+
+#endif // CGI_FCGI_REQUEST_ACCEPTOR_SERVICE_HPP_INCLUDED
+
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_service.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,371 @@
+// -- fcgi/request_service.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_FCGI_REQUEST_SERVICE_HPP_INCLUDED__
+#define CGI_FCGI_REQUEST_SERVICE_HPP_INCLUDED__
+
+#include <boost/system/error_code.hpp>
+
+//#include "boost/cgi/scgi/request_impl.hpp"
+#include "boost/cgi/map.hpp"
+#include "boost/cgi/tags.hpp"
+#include "boost/cgi/read.hpp"
+#include "boost/cgi/role_type.hpp"
+#include "boost/cgi/io_service.hpp"
+#include "boost/cgi/detail/throw_error.hpp"
+#include "boost/cgi/detail/service_base.hpp"
+#include "boost/cgi/detail/extract_params.hpp"
+#include "boost/cgi/fcgi/client.hpp"
+
+namespace cgi {
+ namespace fcgi {
+
+ /// The IoObjectService class for a FCGI basic_request<>s
+ class fcgi_request_service
+ : public detail::service_base<fcgi_request_service>
+ {
+ public:
+ /// The actual implementation date for an FCGI request.
+ struct implementation_type
+ {
+ typedef ::cgi::map map_type;
+ //typedef shareable_tcp_connection connection_type;
+ typedef ::cgi::fcgi_ protocol_type;
+ //typedef basic_client<
+ // connection_type, protocol_type
+ //> client_type;
+ typedef ::cgi::fcgi::client client_type;
+ typedef client_type::connection_type connection_type;
+ typedef std::vector<char> buffer_type;
+ typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
+
+ implementation_type()
+ : client_()
+ , stdin_parsed_(false)
+ , http_status_(http::no_content)
+ , request_status_(unloaded)
+ , request_role_(spec_detail::ANY)
+ , all_done_(false)
+ {
+ }
+
+ client_type client_;
+
+ bool stdin_parsed_;
+ http::status_code http_status_;
+ status_type request_status_;
+ fcgi::spec_detail::role_t request_role_;
+
+ buffer_type buffer_;
+
+ map_type env_vars_;
+ map_type get_vars_;
+ map_type post_vars_;
+ map_type cookie_vars_;
+
+ std::string null_str_;
+ bool all_done_;
+
+ mutable_buffers_type prepare(std::size_t size)
+ {
+ using namespace std;
+ std::size_t bufsz( buffer_.size() );
+ cerr<< "bufsz = " << bufsz << endl;
+
+ // Reserve more space if it's needed.
+ // (this could be safer, referencing this against CONTENT_LENGTH)
+ //if ( (bufsz + size) >= buf_.capacity() )
+ //{
+ buffer_.resize(bufsz + size);
+ //}
+
+ cerr<< "Pre-read buffer (size: " << buffer_.size()
+ << "|capacity: " << buffer_.capacity() << ") == {" << endl
+ << std::string(buffer_.begin(), buffer_.end()) << endl
+ // << "-----end buffer-----" << endl
+ // << "-------buffer-------" << endl
+ // << std::string(&buf_[0], &buf_[buf_.size()]) << endl
+ << "}" << endl;
+ ;
+ //return boost::asio::buffer(&(*(buf_.end())), size);
+ // return boost::asio::buffer(&(*(buf_.begin())) + bufsz, size);
+ return boost::asio::buffer(&buffer_[bufsz], size);
+ }
+ };
+
+ typedef fcgi_request_service type;
+ typedef type::implementation_type::protocol_type protocol_type;
+ typedef type::implementation_type::map_type map_type;
+
+ fcgi_request_service(::cgi::io_service& ios)
+ : detail::service_base<fcgi_request_service>(ios)
+ {
+ }
+
+ ~fcgi_request_service()
+ {
+ }
+
+ void construct(implementation_type& impl)
+ {
+ //std::cerr<< "request_service.hpp:83 Creating connection" << std::endl;
+ impl.client_.set_connection(//new implementation_type::connection_type(this->io_service()));
+ implementation_type::connection_type::create(this->io_service())
+ );
+ //std::cerr<< "conn.is_open() == " << impl.client_.is_open() << std::endl;
+ }
+
+ void destroy(implementation_type& impl)
+ {
+ //if (!impl.all_done_)
+ // detail::abort_impl(impl); // this function isn't implemented yet!
+ //impl.set_state(aborted);
+ }
+
+ void shutdown_service()
+ {
+ }
+
+ bool is_open(implementation_type& impl)
+ {
+ return !impl.all_done_ && impl.client_.is_open();
+ }
+
+ /// Close the request.
+ int close(implementation_type& impl, http::status_code& hsc
+ , int program_status)
+ {
+ impl.all_done_ = true;
+ impl.client_.close();
+ return program_status;
+ }
+
+ /// Load the request to a point where it can be usefully used.
+ /**
+ * FastCGI:
+ * --------
+ *
+ * - Calls client::construct() to claim a request id from the server.
+ * - Reads, parses and handles all packets until the closing `PARAMS`
+ * packet for this request arrives from the server.
+ *
+ */
+ boost::system::error_code&
+ load(implementation_type& impl, bool parse_stdin
+ , boost::system::error_code& ec)
+ {
+ //int header_len( get_length_of_header(impl, ec) );
+ std::cerr<< "Loading request...";
+ BOOST_ASSERT(!ec && "Can't load request due to previous errors.");
+
+ impl.client_.construct(impl, ec);
+
+ while(!ec && impl.request_status_ != loaded)
+ {
+ impl.client_.parse_packet(impl, ec);
+ }
+ // read the header content
+ //::cgi::read(impl.client_, buffer(buf, header_len), ec);
+/*
+ const std::string& request_method = env(impl, "REQUEST_METHOD", ec);
+ if (request_method == "GET")
+ if (parse_get_vars(impl, ec))
+ return ec;
+ else
+ if (request_method == "POST" && parse_stdin)
+ if (parse_post_vars(impl, ec))
+ return ec;
+
+ parse_cookie_vars(impl, ec);
+ */
+ std::cerr<< "done!" << std::endl;
+ return ec;
+ }
+
+ /* These Don't Belong Here.
+ template<typename MutableBufferSequence>
+ std::size_t read_some(implementation_type& impl
+ , const MutableBufferSequence& buf
+ , boost::system::error_code& ec)
+ {
+ std::size_t s = impl.connection()->read_some(buf, ec);
+ return s;
+ }
+
+ template<typename ConstBufferSequence>
+ std::size_t write_some(implementation_type& impl
+ , const ConstBufferSequence& buf
+ , boost::system::error_code& ec)
+ {
+ return impl.connection()->write_some(buf, ec);
+ }
+
+ //template<typename VarType> map_type& var(implementation_type&) const;
+ ********************************************/
+
+ std::string GET(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec)
+ {
+ return var(impl.get_vars_, name, ec);
+ }
+
+ map_type& GET(implementation_type& impl)
+ {
+ return impl.get_vars_;
+ }
+
+ /// Find the post meta-variable matching name
+ /**
+ * @param greedy This determines whether more data can be read to find
+ * the variable. The default is true to cause least surprise in the common
+ * case of having not parsed any of the POST data.
+
+ -----------------------------------------------
+ Should this return a pair of iterators instead?
+ What about url_decoding?
+ -----------------------------------------------
+
+ */
+ std::string POST(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec
+ , bool greedy = true)
+ {
+ const std::string& val = var(impl.post_vars_, name, ec);
+ if (val.empty() && greedy && !ec)
+ {
+
+ }
+
+ return val;
+ }
+
+ map_type& POST(implementation_type& impl)
+ {
+ return impl.post_vars_;
+ }
+
+
+ /// Find the cookie meta-variable matching name
+ std::string cookie(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec)
+ {
+ return var(impl.cookie_vars_, name, ec);
+ }
+
+ map_type& cookie(implementation_type& impl)
+ {
+ return impl.cookie_vars_;
+ }
+
+
+ /// Find the environment meta-variable matching name
+ std::string env(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec)
+ {
+ return var(impl.env_vars_, name, ec);
+ }
+
+
+ role_type get_role(implementation_type& impl)
+ {
+ return responder;
+ }
+
+ implementation_type::client_type&
+ client(implementation_type& impl)
+ {
+ return impl.client_;
+ }
+
+ protected:
+ /// Extract the var value from
+ std::string var(map_type& _data, const std::string& _name
+ , boost::system::error_code& ec)
+ {
+ /* Alt:
+ if ((typename map_type::iterator pos = meta_data.find(name))
+ != meta_data.end())
+ {
+ return *pos;
+ }
+ return std::string();
+ **/
+
+ if( _data.find(_name) != _data.end() )
+ return _data[_name];
+ return "";
+ }
+
+ /// Read and parse the cgi GET meta variables
+ boost::system::error_code&
+ parse_get_vars(implementation_type& impl, boost::system::error_code& ec)
+ {
+ detail::extract_params(env(impl, "QUERY_STRING", ec)
+ , impl.get_vars_
+ , boost::char_separator<char>
+ ("", "=&", boost::keep_empty_tokens)
+ , ec);
+
+ return ec;
+ }
+
+ /// Read and parse the HTTP_COOKIE meta variable
+ template<typename RequestImpl>
+ boost::system::error_code&
+ parse_cookie_vars(implementation_type& impl, boost::system::error_code& ec)
+ {
+ // Make sure this function hasn't already been called
+ //BOOST_ASSERT( impl.cookie_vars_.empty() );
+
+ std::string vars = env(impl, "HTTP_COOKIE", ec);
+ if (vars.empty())
+ return ec;
+
+ detail::extract_params(env(impl, "HTTP_COOKIE", ec)
+ , impl.cookie_vars_
+ , boost::char_separator<char>
+ ("", "=&", boost::keep_empty_tokens)
+ , ec);
+
+ return ec;
+ }
+
+ /// Read and parse the cgi POST meta variables (greedily)
+ template<typename RequestImpl>
+ boost::system::error_code&
+ parse_post_vars(implementation_type& impl, boost::system::error_code& ec)
+ {
+ // Make sure this function hasn't already been called
+ //BOOST_ASSERT( impl.post_vars_.empty() );
+
+ //# error "Not implemented"
+
+ if (impl.stdin_parsed_)
+ {
+ }
+
+ return ec;
+ }
+
+ /// Read and parse a single cgi POST meta variable (greedily)
+ template<typename RequestImpl>
+ boost::system::error_code&
+ parse_one_post_var(implementation_type& impl, boost::system::error_code& ec)
+ {
+ //# error "Not implemented"
+ return ec;
+ }
+
+ private:
+ //cgi::io_service& io_service_;
+ };
+
+ } // namespace fcgi
+} // namespace cgi
+
+#endif // CGI_FCGI_REQUEST_SERVICE_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/service.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,27 @@
+// -- fcgi/service.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+#ifndef CGI_FCGI_SERVICE_HPP_INCLUDED__
+#define CGI_FCGI_SERVICE_HPP_INCLUDED__
+
+#include "boost/cgi/tags.hpp"
+#include "boost/cgi/basic_protocol_service.hpp"
+
+namespace cgi {
+
+ //typedef basic_protocol_service<tags::scgi> scgi_service;
+
+ namespace fcgi {
+
+ // typedef for standard scgi::service (a model of ProtocolService)
+ typedef basic_protocol_service< ::cgi::fcgi_> service;
+
+ }
+} // namespace cgi
+
+#endif // CGI_FCGI_SERVICE_HPP_INCLUDED__
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/specification.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/specification.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/specification.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -9,14 +9,15 @@
#ifndef CGI_FCGI_SPECIFICATION_HPP_INCLUDED__
#define CGI_FCGI_SPECIFICATION_HPP_INCLUDED__
-#include <cinttypes>
+#include <inttypes.h>
+#include <boost/cstdint.hpp>
// NOTE: CamelCase style mimicks the FastCGI specification
// SEE: http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S8
namespace cgi {
namespace fcgi {
- namespace detail {
+ namespace spec_detail {
// Listening socket file number
const short LISTENSOCK_FILENO = 0;
@@ -27,6 +28,7 @@
*/
const short HEADER_LEN = 8;
+#if 1
// Value for version component of Header
const short BOOST_CGI_FASTCGI_VERSION_1 = 1;
@@ -56,7 +58,7 @@
static const unsigned char KEEP_CONN = 1;
// The longest message possible per record
- const std::u_int16_t MAX_MSG_LEN = 65535;
+ const boost::uint16_t MAX_MSG_LEN = 65535;
// Values for role component of BeginRequestBody
enum role_t { RESPONDER = 1
@@ -74,7 +76,7 @@
struct Header
{
- private:
+ //private:
/// The underlying type of a FastCGI header.
/**
* To guarantee the header is laid out exactly as we want, the
@@ -93,46 +95,53 @@
} impl;
public:
- Header() { memset(this->impl, 0, sizeof(*this)); }
+ Header() { memset(static_cast<void*>(&this->impl), 0, sizeof(this->impl)); }
Header(request_t t, int id, int len)
- : impl.version_ (VERSION_NUM)
- , impl.type_ ((unsigned char)t)
- , impl.requestIdB1_ ((unsigned char)(id >> 8) & 0xff)
- , impl.requestIdB0_ ((unsigned char)(id ) & 0xff)
- , impl.contentLengthB1_((unsigned char)(len >> 8) & 0xff)
- , impl.contentLengthB0_((unsigned char)(len ) & 0xff)
- , impl.paddingLength_ ((unsigned char)0)
- , impl.reserved_ (0)
- { }
+ {
+ reset(t, id, len);
+ }
- std::u_int16_t version() const
+ void reset(request_t t, int id, int len)
+ {
+ impl.version_ = (VERSION_NUM);
+ impl.type_ = ((unsigned char)t);
+ impl.requestIdB1_ = ((unsigned char)(id >> 8) & 0xff);
+ impl.requestIdB0_ = ((unsigned char)(id ) & 0xff);
+ impl.contentLengthB1_ = ((unsigned char)(len >> 8) & 0xff);
+ impl.contentLengthB0_ = ((unsigned char)(len ) & 0xff);
+ impl.paddingLength_ = ((unsigned char)0);
+ impl.reserved_ = (0);
+ }
+
+ boost::uint16_t version() const
{
return impl.version_;
}
- std::u_int16_t type() const
+ boost::uint16_t type() const
{
return impl.type_;
}
- std::u_int16_t request_id() const
+ boost::uint16_t request_id() const
{
return impl.requestIdB0_ + (impl.requestIdB1_ << 8);
}
- std::u_int16_t content_length() const
+ boost::uint16_t content_length() const
{
return impl.contentLengthB0_ + (impl.contentLengthB1_ << 8);
}
- std::u_int16_t padding_length() const
+ boost::uint16_t padding_length() const
{
return impl.paddingLength_;
}
+
int body_length() const
{
- return impl.content_length() + impl.padding_length();
+ return content_length() + padding_length();
}
};
@@ -188,15 +197,23 @@
} impl;
public:
- EndRequestBody( std::u_int64_t appStatus
+ EndRequestBody() {}
+
+ EndRequestBody( boost::uint64_t appStatus
, status_t procStatus
)
- : impl.appStatusB3_( (appStatus >> 24) & 0xff )
- , impl.appStatusB2_( (appStatus >> 16) & 0xff )
- , impl.appStatusB1_( (appStatus >> 8) & 0xff )
- , impl.appStatusB0_( (appStatus >> 0) & 0xff )
- , impl.protocolStatus_((unsigned char)procStatus)
{
+ reset(appStatus, procStatus);
+ }
+
+ void reset( boost::uint64_t appStatus, status_t procStatus)
+ {
+ impl.appStatusB3_ = ( (appStatus >> 24) & 0xff );
+ impl.appStatusB2_ = ( (appStatus >> 16) & 0xff );
+ impl.appStatusB1_ = ( (appStatus >> 8) & 0xff );
+ impl.appStatusB0_ = ( (appStatus >> 0) & 0xff );
+ impl.protocolStatus_ = ((unsigned char)procStatus);
+
memset(impl.reserved_, 0, sizeof(impl.reserved_));
}
};
@@ -215,13 +232,13 @@
} impl;
public:
- EndRequestRecord( std::u_int16_t id
- , std::u_int64_t appStatus
+ EndRequestRecord( boost::uint16_t id
+ , boost::uint64_t appStatus
, status_t procStatus
)
- : impl.header_( END_REQUEST, id, sizeof(EndRequestBody) )
- , impl.body_( appStatus, procStatus )
{
+ impl.header_.reset( END_REQUEST, id, sizeof(EndRequestBody) );
+ impl.body_.reset( appStatus, procStatus );
}
};
@@ -239,9 +256,18 @@
} impl;
public:
+ UnknownTypeBody()
+ {
+ }
+
UnknownTypeBody( unsigned char t )
- : impl.type_(t)
{
+ reset(t);
+ }
+
+ void reset(unsigned char t)
+ {
+ impl.type_ = t;
memset(impl.reserved_, 0, sizeof(impl.reserved_));
}
@@ -263,13 +289,147 @@
public:
UnknownTypeRecord( int type )
- : impl.header_( UNKNOWN_TYPE, 0, sizeof(UnknownTypeBody) )
- , impl.body_( (unsigned char)type ) // not sure why this is C-style
{
+ impl.header_.reset( UNKNOWN_TYPE, 0, sizeof(UnknownTypeBody) );
+ impl.body_.reset( (unsigned char)type ); // not sure why this is C-style
}
};
- } // namespace detail
+#endif
+ } // namespace detail
+
+ namespace specification {
+
+#include <boost/mpl/int.hpp>
+ struct header_length
+ : boost::mpl::int_<8>
+ {};
+
+ struct listensock_fileno
+ : boost::mpl::int_<0>
+ {};
+
+ static const unsigned char keep_connection = 1;
+
+ struct null_request_id
+ : boost::mpl::int_<0>
+ {};
+
+ template<typename Array>
+ int get_version(Array& a) { return static_cast<int>(a[0]); }
+
+ template<typename Array>
+ spec_detail::request_t get_type(Array& a)
+ {
+ return static_cast<spec_detail::request_t>(a[1]);
+ }
+
+ template<typename Array>
+ boost::uint16_t get_request_id(Array& a)
+ {
+ return (a[2] << 8) + a[3];
+ }
+
+ template<typename Array>
+ boost::uint16_t get_content_length(Array& a)
+ {
+ return (a[4] << 8) + a[5];
+ }
+
+ template<typename Array>
+ boost::uint16_t get_padding_length(Array& a)
+ {
+ return a[6];
+ }
+
+ template<typename Array>
+ boost::uint16_t get_length(Array& a)
+ {
+ return get_content_length(a) + get_padding_length(a);
+ }
+
+ struct request_type
+ {
+ template<typename Array>
+ static std::string to_string(Array& a)
+ {
+ switch(a[1])
+ {
+ case 0:
+ return "ADMIN_REQUEST";
+ case 1:
+ return "BEGIN_REQUEST";
+ case 2:
+ return "ABORT_REQUEST";
+ case 3:
+ return "END_REQUEST";
+ case 4:
+ return "PARAMS";
+ case 5:
+ return "STDIN";
+ case 6:
+ return "STDOUT";
+ case 7:
+ return "STDERR";
+ case 8:
+ return "DATA";
+ case 9:
+ return "GET_VALUES";
+ case 10:
+ return "GET_VALUES_RESULT";
+ case 11:
+ return "UNKNOWN_TYPE";
+ default:
+ return "***ERROR-INVALID-TYPE***";
+ }
+ }
+ };
+
+ struct begin_request
+ : boost::mpl::int_<1>
+ {
+ template<typename Array>
+ static spec_detail::role_t
+ get_role(Array& a)
+ {
+ return static_cast<spec_detail::role_t>( (a[0] << 8) + a[1] );
+ }
+
+ template<typename Array>
+ static unsigned char
+ get_flags(Array& a)
+ {
+ return a[2];
+ }
+
+ //typedef spec_detail::BEGIN_REQUEST type;
+
+ };
+
+ struct role_type
+ {
+ template<typename Array>
+ static std::string to_string(Array& a)
+ {
+ using namespace spec_detail;
+ switch(begin_request::get_role(a))
+ {
+ case RESPONDER:
+ return "RESPONDER";
+ case AUTHORIZER:
+ return "AUTHORISER";
+ case FILTER:
+ return "FILTER";
+ default:
+ return "ANY";
+ }
+ }
+ };
+ //using namespace ::cgi::fcgi::detail;
+ }
+
+ namespace spec = specification;
+
} // namespace fcgi
}// namespace cgi
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/header.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/header.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/header.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -13,12 +13,12 @@
namespace cgi {
- template<typename StringT = std::string>
- struct basic_header
+ //template<typename StringT = std::string>
+ struct header
{
- typedef StringT string_type;
+ typedef std::string string_type;
- basic_header()
+ header()
: content()
{
}
@@ -26,31 +26,31 @@
/// Templated constructor to allow user-defined types to be converted
//template<typename T>
- //basic_header(T& t)
+ //header(T& t)
// : content(t.to_string())
//{
//}
//template<>
- basic_header(const string_type& _content)
+ header(const string_type& _content)
: content(_content)
{
}
- basic_header(const string_type& name, const string_type& val)
+ header(const string_type& name, const string_type& val)
: content(name + ": " + val)
{
}
- //basic_header(const std::string& name, const std::string& val)
+ //header(const std::string& name, const std::string& val)
// : content(name + ": " + val)
//{
//}
/// Construct an header from a cookie.
template<typename T>
- basic_header(const basic_cookie<T>& ck)
+ header(const basic_cookie<T>& ck)
: content("Set-cookie: " + ck.to_string())
{
}
@@ -60,56 +60,56 @@
/*
template<typename StringT>
- basic_header<StringT>
+ header<StringT>
make_header(const StringT& name, const StringT& val)
{
return basic_header<StringT>(name, val);
- }*/
+ }* /
template<typename T, typename StringT>
T make_header(const StringT& name, const StringT& val)
{
return basic_header<StringT>(name, val);
- }
+ }*/
//{ Some shortcuts, to cut down on typing errors.
template<typename StringT>
- basic_header<StringT>
+ header
content_type(StringT& str)
{
- return basic_header<StringT>("Content-type", str);
+ return header("Content-type", str);
}
template<typename StringT>
- basic_header<StringT>
+ header
content_encoding(StringT& str)
{
- return basic_header<StringT>("Content-encoding", str);
+ return header("Content-encoding", str);
}
/*
template<typename StringT>
- basic_header<StringT>
+ header<StringT>
location(const StringT& url)
{
- return basic_header<StringT>("Location", url);
+ return header<StringT>("Location", url);
}
- basic_header<std::string>
+ header<std::string>
location(const std::string& url)
{
- return basic_header<std::string>("Location", url);
+ return header<std::string>("Location", url);
}*/
- template<typename T>
- T location(const std::string& url)
+ //template<typename T>
+ header location(const std::string& url)
{
- return make_header("Location", url);
+ return header("Location", url);
}
//}
// typedefs for typical usage
- typedef basic_header<std::string> header;
- typedef basic_header<std::wstring> wheader;
+ //typedef basic_header<std::string> header;
+ //typedef basic_header<std::wstring> wheader;
} // namespace cgi
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/request_service.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/request_service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -146,11 +146,14 @@
return service_impl_.cookie(impl, name, ec);
}
+ /*
std::string
header(impl_type& impl, const std::string& name
, boost::system::error_code& ec)
{
+ return "";
}
+*/
private:
service_impl_type& service_impl_;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/response.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/response.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/response.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -18,6 +18,7 @@
#include "boost/cgi/buffer.hpp"
#include "boost/cgi/cookie.hpp"
#include "boost/cgi/header.hpp"
+#include "boost/cgi/write.hpp"
#include "boost/cgi/basic_request_fwd.hpp"
#include "boost/cgi/http/status_code.hpp"
#include "boost/cgi/streambuf.hpp"
@@ -84,12 +85,20 @@
{
}
+ /// Clear the response buffer.
void clear()
{
ostream_.clear();
headers_.clear();
}
+ /// Return the response to the 'just constructed' state.
+ void reset()
+ {
+ clear();
+ headers_terminated_ = false;
+ }
+
// provide this too?
std::size_t write(const char* str, std::size_t len)
{
@@ -105,190 +114,109 @@
template<typename ConstBufferSequence>
std::size_t write(const ConstBufferSequence& buf)
{
- //ostream_.write(buf.data(), buf.size());
- return buf.size();
+ return ostream_.write(buf.begin(), buf.end());
+ //return buf.size();
}
- /// Synchronously flush the data to the supplied request
+ /// Synchronously flush the data to the supplied SyncWriteStream
/**
* This call uses throwing semantics. ie. an exception will be thrown on
* any failure.
* If there is no error, the buffer is cleared.
*/
- template<typename CommonGatewayRequest>
- void flush(CommonGatewayRequest& req)
+ template<typename SyncWriteStream>
+ void flush(SyncWriteStream& sws)
{
- /*
- if (!headers_terminated_)
- {
- ostream_<< "Content-type: text/plain\r\n\r\n";
- headers_terminated_ = true;
- }
- */
- ::cgi::write(req, headers_);
- ::cgi::write(req, rdbuf()->data());
- // the above function will throw on an error
- clear();
+ boost::system::error_code ec;
+ flush(sws, ec);
+ detail::throw_error(ec);
}
-
+
/// Synchronously flush the data via the supplied request
/**
* This call uses error_code semantics. ie. ec is set if an error occurs.
* If there is no error, the buffer is cleared.
*/
- template<typename CommonGatewayRequest>
- boost::system::error_code&
- flush(CommonGatewayRequest& req, boost::system::error_code& ec)
+ template<typename SyncWriteStream>
+ boost::system::error_code
+ flush(SyncWriteStream& sws, boost::system::error_code& ec)
{
if (!headers_terminated_)
{
- ostream_<< "Content-type: text/plain\r\n\r\n";
- headers_terminated_ = true;
+ std::vector<boost::asio::const_buffer> headers;
+ prepare_headers(headers);//, ec);
+ common::write(sws, headers, boost::asio::transfer_all(), ec);
+ if (ec)
+ return ec;
}
- if(!::cgi::write(req, rdbuf()->data(), ec))
- clear();
- return ec;
- }
- // Class for doing post-flush housekeeping (ie. clearing the stream data)
- template<typename Handler>
- class flush_handler
- {
- public:
- flush_handler(response& os, Handler handler)
- : ostream_(os)
- , handler_(handler)
- {
- }
-
- void operator()(boost::system::error_code& ec)
- {
- if(!ec) ostream_.clear();
- handler_(ec);
- }
- private:
- response& ostream_;
- Handler handler_;
- };
+ std::size_t bytes_written = common::write(sws, buffer_->data(), ec);
+ if (!ec)
+ buffer_->consume(bytes_written);
- /// Asynchronously flush the data through the supplied request
- /**
- * If there is no error, the buffer is cleared *after* the write has
- * finished.
- */
- template<typename CommonGatewayRequest, typename Handler>
- void async_flush(CommonGatewayRequest& req, Handler handler)
- {
- /*
- if (!headers_terminated_)
- {
- ostream_<< "Content-type: text/plain\r\n\r\n";
- headers_terminated_ = true;
- }
- */
- ::cgi::async_write(req, rdbuf()->data()
- , flush_handler<Handler>
- (*this, handler, boost::arg<1>()));
+ return ec;
}
-
- /// Synchronously send the reply to the default request
- /**
- * Note: The data in the stream isn't cleared after this call, but the
- * request held in the ostream is removed. ie. send() can't be called
- * twice without an arguement (unless you add another request - something
- * not possible yet).
- */
- //void send()
- //{
- // BOOST_ASSERT(request_ != NULL);
- // send(*request_);
- // request_ = NULL;
- //}
-
- /// Synchronously send the reply to the default request
- /**
- * Note: The data in the stream isn't cleared after this call. If the send
- * is sucessful, the request held in the ostream is removed. ie. send()
- * can't be called twice without an arguement (unless you add another
- * request - something not possible yet).
- */
- //boost::system::error_code& send(boost::system::error_code& ec)
- //{
- // BOOST_ASSERT(request_ != NULL);
- // if(!send(*request_, ec))
- // request_ = NULL;
- // return ec;
- //}
-
-
/// Synchronously send the data via the supplied request.
/**
* This call uses throwing semantics. ie. an exception will be thrown on
* any failure.
* Note: The data in the stream isn't cleared after this call.
*/
- template<typename CommonGatewayRequest>
- void send(CommonGatewayRequest& req)
+ template<typename SyncWriteStream>
+ void send(SyncWriteStream& sws)
{
boost::system::error_code ec;
- send(req, ec);
+ send(sws, ec);
detail::throw_error(ec);
}
- /// Synchronously send the data via the supplied request
+ /// Synchronously send the data via the supplied request.
/**
- * This call uses error_code semantics. ie. ec is set if an error occurs.
- * Note: The data in the stream isn't cleared after this call.
+ * This call will not throw, but will set `ec` such that `ec == true` if
+ * an error occurs. Details of the error are held in the `error_code`
+ * object.
*/
- /*
- template<typename T, typename X, enum Y, typename Z>
- boost::system::error_code&
- send(::cgi::basic_request<T, X, Y, Z>& req, boost::system::error_code& ec)
- {
- send(req.client(), ec);
- //req.set_status(http_status_);
- return ec;
- }
-*/
template<typename SyncWriteStream>
boost::system::error_code&
- send(SyncWriteStream& ws, boost::system::error_code& ec)
+ send(SyncWriteStream& sws, boost::system::error_code& ec)
{
- BOOST_CGI_ADD_DEFAULT_HEADER
-
- // Terminate the headers.
- headers_.push_back("\r\n");
-
- //{ Construct a ConstBufferSequence out of the headers we have.
- std::vector<boost::asio::const_buffer> headers;
- typedef std::vector<std::string>::iterator iter;
- for (iter i(headers_.begin()), e(headers_.end()); i != e; ++i)
+ if (!headers_terminated_)
{
- headers.push_back(::cgi::buffer(*i));
+ //BOOST_FOREACH(headers_.begin(), headers_.end()
+ // , headers.push_back(::cgi::buffer(*_1)));
+ std::vector<boost::asio::const_buffer> headers;
+ prepare_headers(headers);//, ec)
+ if (common::write(sws, headers, boost::asio::transfer_all(), ec))
+ std::cerr<< "Broken." << std::endl;
+ //return ec;
}
- //}
- ::cgi::write(ws, headers
- , boost::asio::transfer_all(), ec);
- headers_terminated_ = true;
- ::cgi::write(ws, rdbuf()->data()
- , boost::asio::transfer_all(), ec);
-
- //BOOST_FOREACH(headers_.begin(), headers_.end()
- // , headers.push_back(::cgi::buffer(*_1)));
+ common::write(sws, buffer_->data(), boost::asio::transfer_all(), ec);
return ec;
}
/// Asynchronously send the data through the supplied request
/**
- * Note: The data in the stream isn't cleared after this call.
+ * Note: This is quite crude at the moment and not as asynchronous as
+ * it could/should be. The data in the stream isn't cleared after
+ * this call.
*/
- template<typename CommonGatewayRequest, typename Handler>
- void async_send(CommonGatewayRequest& req, Handler handler)
+ template<typename AsyncWriteStream, typename Handler>
+ void async_send(AsyncWriteStream& aws, Handler handler)
+ {
+ aws.io_service().post(
+ boost::bind(&response::do_async_send, aws, handler)
+ );
+ }
+
+ template<typename AsyncWriteStream, typename Handler>
+ void do_async_send(AsyncWriteStream& aws, Handler handler)
{
- req.set_status(http_status_);
+
+
+ //req.set_status(http_status_);
/*
if (!headers_terminated_)
{
@@ -296,14 +224,14 @@
headers_terminated_ = true;
}
*/
- ::cgi::async_write(req, rdbuf()->data(), handler);
+ common::async_write(aws, rdbuf()->data(), handler);
}
/// Get the buffer associated with the stream
- ::cgi::streambuf*
+ common::streambuf*
rdbuf()
{
- return static_cast<::cgi::streambuf*>(ostream_.rdbuf());
+ return static_cast<common::streambuf*>(ostream_.rdbuf());
}
/// Set the status code associated with the response.
@@ -319,7 +247,7 @@
return http_status_;
}
- /// Allow more headers to be added (note, avoid using this).
+ /// Allow more headers to be added (WARNING: avoid using this).
void unterminate_headers()
{
headers_terminated_ = false;
@@ -358,9 +286,7 @@
headers_.clear();
headers_terminated_ = false;
}
- //response& operator<< (response& r1, response& r2)
- //{
- // r1.
+
bool headers_terminated() const
{
return headers_terminated_;
@@ -369,24 +295,45 @@
// Vector of all the headers, each followed by a CRLF
std::vector<std::string> headers_;
- boost::shared_ptr<::cgi::streambuf> buffer_; // maybe scoped_ptr?
+ boost::shared_ptr<common::streambuf> buffer_; // maybe scoped_ptr?
ostream_type ostream_;
http::status_code http_status_;
- // True if no more headers are to be appended.
+ // True if no more headers can be appended.
bool headers_terminated_;
- //template<typename T>
- //response& operator<<(const T& t) {
- // ostream_<< t;
- // return *this;
- //}
-
template<typename T>
friend response& operator<<(response& resp, const T& t);
- };
+
+ private:
+
+ // Send the response headers and mark that they've been sent.
+ template<typename ConstBufferSequence>
+ //boost::system::error_code
+ void
+ prepare_headers(ConstBufferSequence& headers)//, boost::system::error_code& ec)
+ {
+ BOOST_CGI_ADD_DEFAULT_HEADER
+
+ // Terminate the headers.
+ if (!headers_terminated_)
+ headers_.push_back("\r\n");
+
+ //{ Construct a ConstBufferSequence out of the headers we have.
+ //std::vector<boost::asio::const_buffer> headers;
+ typedef std::vector<std::string>::iterator iter;
+ for (iter i(headers_.begin()), e(headers_.end()); i != e; ++i)
+ {
+ headers.push_back(common::buffer(*i));
+ }
+ //}
+
+ headers_terminated_ = true;
+ //return ec;
+ }
+ };
/// Generic ostream template
template<typename T>
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/role_type.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/role_type.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/role_type.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -11,7 +11,8 @@
} // namespace role
enum role_type
- { responder
+ { none
+ , responder
, authorizer
, filter
};
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/acceptor_service_impl.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/acceptor_service_impl.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/acceptor_service_impl.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -45,9 +45,9 @@
* which takes a ProtocolService (**LINK**). If the protocol isn't async then
* the class can be used without a ProtocolService.
*/
- template<typename Protocol = ::cgi::scgi_>
+ template<typename Protocol_ = ::cgi::scgi_>
class acceptor_service_impl
- : public detail::service_base<acceptor_service_impl<Protocol> >
+ : public detail::service_base<acceptor_service_impl<Protocol_> >
{
public:
@@ -56,35 +56,47 @@
struct implementation_type
{
- typedef Protocol protocol_type;
+ typedef Protocol_ protocol_type;
typedef basic_protocol_service<protocol_type> protocol_service_type;
typedef boost::asio::ip::tcp native_protocol_type;
typedef scgi::request request_type;
typedef boost::asio::socket_acceptor_service<
- native_protocol_type> acceptor_service_type;
+ native_protocol_type
+ > acceptor_service_type;
+ typedef unsigned short port_number_type;
+ typedef boost::asio::ip::tcp::endpoint endpoint_type;
+ //typedef typename
+ // acceptor_service_type::native_type native_type;
acceptor_service_type::implementation_type acceptor_;
boost::mutex mutex_;
std::queue<boost::shared_ptr<request_type> > waiting_requests_;
protocol_service_type* service_;
+ port_number_type port_num_;
+ endpoint_type endpoint_;
};
- //typedef scgi_request_acceptor_impl implementation_type;
- typedef acceptor_service_impl<Protocol> type;
- typedef typename type::implementation_type::protocol_type
+ typedef acceptor_service_impl<Protocol_> type;
+ typedef typename
+ type::implementation_type::protocol_type
protocol_type;
- typedef typename type::implementation_type::protocol_service_type
+ typedef typename
+ type::implementation_type::protocol_service_type
protocol_service_type;
- typedef typename type::implementation_type::acceptor_service_type
+ typedef typename
+ type::implementation_type::acceptor_service_type
acceptor_service_type;
- typedef typename type::implementation_type::native_protocol_type
+ typedef typename
+ type::implementation_type::native_protocol_type
native_protocol_type;
- typedef typename acceptor_service_type::native_type native_type;
- //typedef typename acceptor_service_type::native_type native_type;
+ typedef typename
+ acceptor_service_type::native_type native_type;
+
explicit acceptor_service_impl(::cgi::io_service& ios)
- : detail::service_base<acceptor_service_impl<Protocol> >(ios)
+ : detail::service_base<acceptor_service_impl<Protocol_> >(ios)
, acceptor_service_(boost::asio::use_service<acceptor_service_type>(ios))
+ //, endpoint(boost::asio::ip::tcp::v4())
{
}
@@ -94,141 +106,184 @@
impl.protocol_service_ = &ps;
}
- protocol_service_type&
- get_protocol_service(implementation_type& impl)
- {
- BOOST_ASSERT(impl.service_ != NULL);
- return *impl.service_;
- }
-
- void construct(implementation_type& impl)
- {
- acceptor_service_.construct(impl.acceptor_);
- //impl.acceptor_ptr().reset(impl::acceptor_type(this->io_service()));
- }
-
- void destroy(implementation_type& impl)
- {
- // close/reject all the waiting requests
- /***/
- acceptor_service_.destroy(impl.acceptor_);
- }
-
- void shutdown_service()
- {
- acceptor_service_.shutdown_service();
- }
-
- /// Check if the given implementation is open.
- bool is_open(implementation_type& impl)
- {
- return acceptor_service_.is_open(impl.acceptor_);
- }
-
- /// Open a new *socket* acceptor implementation.
- boost::system::error_code
- open(implementation_type& impl, const native_protocol_type& protocol
- , boost::system::error_code& ec)
- {
- return acceptor_service_.open(impl.acceptor_, protocol, ec);
- }
-
- template<typename Endpoint>
- boost::system::error_code
- bind(implementation_type& impl, Endpoint& endpoint
- , boost::system::error_code& ec)
- {
- acceptor_service_.set_option(impl.acceptor_,
- boost::asio::socket_base::reuse_address(true), ec);
- return acceptor_service_.bind(impl.acceptor_, endpoint, ec);
- }
-
- /// Assign an existing native acceptor to a *socket* acceptor.
- boost::system::error_code
- assign(implementation_type& impl, const native_protocol_type& protocol
- , const native_type& native_acceptor
- , boost::system::error_code& ec)
- {
- return acceptor_service_.assign(impl.acceptor_, protocol
- , native_acceptor, ec);
- }
-
- boost::system::error_code
- listen(implementation_type& impl, boost::system::error_code& ec)
- {
- return acceptor_service_.listen(impl.acceptor_,
- boost::asio::socket_base::max_connections, ec);
- }
-
- /// Accepts one request.
- template<typename CommonGatewayRequest>
- boost::system::error_code
- accept(implementation_type& impl, CommonGatewayRequest& request
- , boost::system::error_code& ec)
- {
- /* THIS BIT IS BROKEN:
- *-- The noncopyable semantics of a basic_request<> don't allow the
- assignment. There are a couple of ways around this; the one that
- seems sensible is to keep the basic_request<>s noncopyable, but
- allow the actual data be copied. At the moment the actual data is
- held in a vector<string> headers container and a cgi::streambuf.
- These two bits should really be factored out into a message type.
- IOW, the message type will be copyable (but should probably have
- unique-ownership semantics).
- --*
- {
- boost::mutex::scoped_lock lk(impl.mutex_);
- if (!impl.waiting_requests_.empty())
- {
- request = *(impl.waiting_requests_.front());
- impl.waiting_requests_.pop();
- return ec;
- }
- }
- */
- return acceptor_service_.accept(impl.acceptor_,
- request.client().connection()->next_layer(), 0, ec);
- }
-
- /// Asynchronously accepts one request.
- template<typename CommonGatewayRequest, typename Handler>
- void async_accept(implementation_type& impl, CommonGatewayRequest& request
- , Handler handler, boost::system::error_code& ec)
- {
- this->io_service().post(
- boost::bind(
- &acceptor_service_impl<protocol_type>::check_for_waiting_request,
- boost::ref(impl), boost::ref(request), handler, ec));
- }
- private:
- template<typename CommonGatewayRequest, typename Handler>
- void check_for_waiting_request(implementation_type& impl
- , CommonGatewayRequest& request
- , Handler handler)
- {
- /*
- {
- boost::mutex::scoped_lock lk(impl.mutex_);
- if (!impl.waiting_requests_.empty())
- {
- request = *(impl.waiting_requests_.front());
- impl.waiting_requests_.pop();
- return handler(ec); // this could be `io_service::post`ed again
- }
- }
- */
- return accceptor_service_.async_accept(
- request.client().connection()->next_layer(), handler);
- }
-
- private:
- /// The underlying socket acceptor service.
- acceptor_service_type& acceptor_service_;
- };
+ protocol_service_type&
+ get_protocol_service(implementation_type& impl)
+ {
+ BOOST_ASSERT(impl.service_ != NULL);
+ return *impl.service_;
+ }
+
+ void construct(implementation_type& impl)
+ {
+ acceptor_service_.construct(impl.acceptor_);
+ //impl.acceptor_ptr().reset(impl::acceptor_type(this->io_service()));
+ }
+
+ void destroy(implementation_type& impl)
+ {
+ // close/reject all the waiting requests
+ /***/
+ acceptor_service_.destroy(impl.acceptor_);
+ }
+
+ void shutdown_service()
+ {
+ acceptor_service_.shutdown_service();
+ }
+
+ /// Check if the given implementation is open.
+ bool is_open(implementation_type& impl)
+ {
+ return acceptor_service_.is_open(impl.acceptor_);
+ }
+
+ /// Open a new *socket* acceptor implementation.
+ boost::system::error_code
+ open(implementation_type& impl, const native_protocol_type& protocol
+ , boost::system::error_code& ec)
+ {
+ return acceptor_service_.open(impl.acceptor_, protocol, ec);
+ }
+
+ template<typename Endpoint>
+ boost::system::error_code
+ bind(implementation_type& impl, const Endpoint& endpoint
+ , boost::system::error_code& ec)
+ {
+ acceptor_service_.set_option(impl.acceptor_,
+ boost::asio::socket_base::reuse_address(true), ec);
+ return acceptor_service_.bind(impl.acceptor_, endpoint, ec);
+ }
+
+ /// Assign an existing native acceptor to a *socket* acceptor.
+ boost::system::error_code
+ assign(implementation_type& impl, const native_protocol_type& protocol
+ , const native_type& native_acceptor
+ , boost::system::error_code& ec)
+ {
+ return acceptor_service_.assign(impl.acceptor_, protocol
+ , native_acceptor, ec);
+ }
+
+ boost::system::error_code
+ listen(implementation_type& impl, int backlog, boost::system::error_code& ec)
+ {
+ return acceptor_service_.listen(impl.acceptor_, backlog, ec);
+ }
+
+ /// Accepts one request.
+ template<typename CommonGatewayRequest>
+ boost::system::error_code
+ accept(implementation_type& impl, CommonGatewayRequest& request
+ , boost::system::error_code& ec)
+ {
+ /* THIS BIT IS BROKEN:
+ *-- The noncopyable semantics of a basic_request<> don't allow the
+ assignment. There are a couple of ways around this; the one that
+ seems sensible is to keep the basic_request<>s noncopyable, but
+ allow the actual data be copied. At the moment the actual data is
+ held in a vector<string> headers container and a cgi::streambuf.
+ These two bits should really be factored out into a message type.
+ IOW, the message type will be copyable (but should probably have
+ unique-ownership semantics).
+ --*
+ {
+ boost::mutex::scoped_lock lk(impl.mutex_);
+ if (!impl.waiting_requests_.empty())
+ {
+ request = *(impl.waiting_requests_.front());
+ impl.waiting_requests_.pop();
+ return ec;
+ }
+ }
+ */
+ return acceptor_service_.accept(impl.acceptor_,
+ request.client().connection()->next_layer(), 0, ec);
+ }
+
+ /// Accepts one request.
+ template<typename CommonGatewayRequest, typename Endpoint>
+ boost::system::error_code
+ accept(implementation_type& impl, CommonGatewayRequest& request
+ , Endpoint* endpoint, boost::system::error_code& ec)
+ {
+ /* THIS BIT IS BROKEN:
+ *-- The noncopyable semantics of a basic_request<> don't allow the
+ assignment. There are a couple of ways around this; the one that
+ seems sensible is to keep the basic_request<>s noncopyable, but
+ allow the actual data be copied. At the moment the actual data is
+ held in a vector<string> headers container and a cgi::streambuf.
+ These two bits should really be factored out into a message type.
+ IOW, the message type will be copyable (but should probably have
+ unique-ownership semantics).
+ --*
+ {
+ boost::mutex::scoped_lock lk(impl.mutex_);
+ if (!impl.waiting_requests_.empty())
+ {
+ request = *(impl.waiting_requests_.front());
+ impl.waiting_requests_.pop();
+ return ec;
+ }
+ }
+ */
+ return acceptor_service_.accept(impl.acceptor_,
+ request.client().connection()->next_layer(), 0, ec);
+ }
+
+ /// Asynchronously accepts one request.
+ template<typename CommonGatewayRequest, typename Handler>
+ void async_accept(implementation_type& impl, CommonGatewayRequest& request
+ , Handler handler, boost::system::error_code& ec)
+ {
+ this->io_service().post(
+ boost::bind(
+ &acceptor_service_impl<protocol_type>::check_for_waiting_request,
+ boost::ref(impl), boost::ref(request), handler, ec));
+ }
+
+ /// Close the acceptor (not implemented yet).
+ boost::system::error_code
+ close(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return boost::system::error_code(348, boost::system::system_category);
+ }
+ typename implementation_type::endpoint_type
+ local_endpoint(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return acceptor_service_.local_endpoint(impl.acceptor_, ec);
+ }
+ private:
+ template<typename CommonGatewayRequest, typename Handler>
+ void check_for_waiting_request(implementation_type& impl
+ , CommonGatewayRequest& request
+ , Handler handler)
+ {
+ /*
+ {
+ boost::mutex::scoped_lock lk(impl.mutex_);
+ if (!impl.waiting_requests_.empty())
+ {
+ request = *(impl.waiting_requests_.front());
+ impl.waiting_requests_.pop();
+ return handler(ec); // this could be `io_service::post`ed again
+ }
+ }
+ */
+ return this->accceptor_service_.async_accept(
+ request.client().connection()->next_layer(), handler);
+ }
+
+ public:
+ /// The underlying socket acceptor service.
+ acceptor_service_type& acceptor_service_;
+ };
+
} // namespace scgi
} // namespace cgi
-
+
#include "boost/cgi/detail/pop_options.hpp"
#endif // CGI_SCGI_ACCEPTOR_SERVICE_IMPL_HPP_INCLUDED__
+
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/request_acceptor_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/request_acceptor_service.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/request_acceptor_service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -31,9 +31,9 @@
* which takes a ProtocolService (**LINK**). If the protocol isn't async then
* the class can be used without a ProtocolService.
*/
- template<typename Protocol = scgi_>
+ template<typename Protocol_ = scgi_>
class scgi_request_acceptor_service
- : public detail::service_base<scgi_request_acceptor_service<Protocol> >
+ : public detail::service_base<scgi_request_acceptor_service<Protocol_> >
{
public:
//typedef typename service_impl_type::impl_type impl_type;
@@ -41,13 +41,15 @@
typedef scgi::acceptor_service_impl<> service_impl_type;
typedef service_impl_type::implementation_type implementation_type;
typedef typename implementation_type::protocol_type protocol_type;
+ typedef implementation_type::endpoint_type endpoint_type;
+ typedef typename service_impl_type::native_type native_type;
//typedef basic_protocol_service<protocol_type> protocol_service_type;
/// The unique service identifier
//static boost::asio::io_service::id id;
scgi_request_acceptor_service(::cgi::io_service& ios)
- : detail::service_base<scgi_request_acceptor_service<Protocol> >(ios)
+ : detail::service_base<scgi_request_acceptor_service<protocol_type> >(ios)
, service_impl_(ios)
{
}
@@ -74,12 +76,20 @@
void close(implementation_type& impl)
{
- return service_impl_.close(impl);
+ boost::system::error_code ec;
+ service_impl_.close(impl, ec);
+ detail::throw_error(ec);
+ }
+
+ boost::system::error_code
+ close(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
}
template<typename Protocol>
boost::system::error_code
- open(implementation_type& impl, Protocol& protocol
+ open(implementation_type& impl, const Protocol& protocol
, boost::system::error_code& ec)
{
return service_impl_.open(impl, protocol, ec);
@@ -87,16 +97,16 @@
template<typename Endpoint>
boost::system::error_code
- bind(implementation_type& impl, Endpoint& endpoint
+ bind(implementation_type& impl, const Endpoint& endpoint
, boost::system::error_code& ec)
{
return service_impl_.bind(impl, endpoint, ec);
}
boost::system::error_code
- listen(implementation_type& impl, boost::system::error_code& ec)
+ listen(implementation_type& impl, int backlog, boost::system::error_code& ec)
{
- return service_impl_.listen(impl, ec);
+ return service_impl_.listen(impl, backlog, ec);
}
template<typename CommonGatewayRequest>
@@ -107,6 +117,14 @@
return service_impl_.accept(impl, request, ec);
}
+ template<typename CommonGatewayRequest, typename Endpoint>
+ boost::system::error_code
+ accept(implementation_type& impl, CommonGatewayRequest& request
+ , Endpoint* ep, boost::system::error_code& ec)
+ {
+ return service_impl_.accept(impl, request, ep, ec);
+ }
+
template<typename Handler>
void async_accept(implementation_type& impl, Handler handler)
{
@@ -118,7 +136,22 @@
{
impl.service_ = &ps;
}
- private:
+
+ typename implementation_type::endpoint_type
+ local_endpoint(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ template<typename Protocol>
+ boost::system::error_code
+ assign(implementation_type& impl, Protocol protocol
+ , const native_type& native_acceptor, boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, protocol, native_acceptor, ec);
+ }
+
+ public:
service_impl_type service_impl_;
};
@@ -127,3 +160,4 @@
#include "boost/cgi/detail/pop_options.hpp"
#endif // CGI_REQUEST_SERVICE_HPP_INCLUDED
+
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/request_service.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/request_service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -80,11 +80,11 @@
void construct(implementation_type& impl)
{
- std::cerr<< "Creating connection" << std::endl;
+ //std::cerr<< "request_service.hpp:83 Creating connection" << std::endl;
impl.client_.set_connection(//new implementation_type::connection_type(this->io_service()));
implementation_type::connection_type::create(this->io_service())
);
- std::cerr<< "conn.is_open() == " << impl.client_.is_open() << std::endl;
+ //std::cerr<< "conn.is_open() == " << impl.client_.is_open() << std::endl;
}
void destroy(implementation_type& impl)
@@ -157,8 +157,8 @@
//template<typename VarType> map_type& var(implementation_type&) const;
********************************************/
- std::string GET(implementation_type& impl, const std::string& name
- , boost::system::error_code& ec)
+ std::string GET(implementation_type& impl, const std::string& name
+ , boost::system::error_code& ec)
{
return var(impl.get_vars_, name, ec);
}
@@ -271,11 +271,11 @@
// Make sure this function hasn't already been called
//BOOST_ASSERT( impl.cookie_vars_.empty() );
- std::string vars = meta_env(impl, "HTTP_COOKIE", ec);
+ std::string vars = env(impl, "HTTP_COOKIE", ec);
if (vars.empty())
return ec;
- detail::extract_params(meta_env(impl, "HTTP_COOKIE", ec)
+ detail::extract_params(env(impl, "HTTP_COOKIE", ec)
, impl.cookie_vars_
, boost::char_separator<char>
("", "=&", boost::keep_empty_tokens)
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/service.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/scgi/service.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -19,7 +19,7 @@
namespace scgi {
// typedef for standard scgi::service (a model of ProtocolService)
- typedef basic_protocol_service<::cgi::scgi_> service;
+ typedef basic_protocol_service< ::cgi::scgi_> service;
}
} // namespace cgi
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/status_type.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/status_type.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/status_type.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -14,8 +14,9 @@
enum status_type
{ null
, unloaded
+ , activated
, loaded
- , ok
+ , ok = loaded
, aborted
, closed
};
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/streambuf.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/streambuf.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/streambuf.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -12,9 +12,14 @@
#include <boost/asio/streambuf.hpp>
namespace cgi {
+ namespace common {
using boost::asio::streambuf;
+ } // namespace common
+
+ using common::streambuf;
+
} // namespace cgi
#endif // CGI_STREAMBUF_HPP_INCLUDED__
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/tags.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/tags.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/tags.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -17,6 +17,8 @@
/// SCGI (note, this must be removed)
struct scgi_{};
+ /// FastCGI
+ struct fcgi_{};
namespace tags {
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/write.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/write.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/write.hpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -12,10 +12,16 @@
#include <boost/asio/write.hpp>
namespace cgi {
+ namespace common {
using boost::asio::write;
using boost::asio::async_write;
+ } // namespace common
+
+ using common::write;
+ using common::async_write;
+
} // namespace cgi
#endif // CGI_WRITE_HPP_INCLUDED
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/Jamfile.v2 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -3,8 +3,8 @@
# subject to the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-project boost_cgi
- : build-dir ../../../bin.v2
+project cgi.docs
+ #: build-dir ../../../bin.v2
;
import boostbook : boostbook ;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/building.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/building.qbk (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/building.qbk 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -27,7 +27,7 @@
[Boost.Jam - `bjam`]
[No]
[
-Download 'boost-jam' (precomiled versions are highly recommended) and make it accessible by putting it somewhere pointed to by your system's PATH.
+Download 'boost-jam' (precompiled versions are highly recommended) and make it accessible by putting it somewhere pointed to by your system's PATH.
]
]
[
@@ -38,7 +38,7 @@
* Set the environment variable BOOST_ROOT on your system to the download location.
-* Go to the directory BOOST_ROOT and invoke `bjam` (see above). This should finish without any fails.
+* Go to the directory BOOST_ROOT and invoke `bjam --with-system install` (see above). This should finish without any fails.
]
]
[
@@ -52,7 +52,7 @@
[Unit tests]
[Yes]
[
-Tests can be run by going to the libs/cgi/test directory and invoking `bjam` (see above). Boost.CGI aims to be cross-platform, but not all platforms are available for testing. If any tests fail, problems can be reported to [link __reporting_problems__ here].
+Tests can be run by going to the libs/cgi/test directory and invoking `bjam` (see above). Boost.CGI aims to be cross-platform, but not all platforms are available for testing. If any tests fail, problems can be reported to [link __reporting_problems__ here], please.
]
]
[
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/future_development.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/future_development.qbk (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/future_development.qbk 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -27,8 +27,8 @@
[table
[[Protocol][Native error reporting capabilities]]
- [[CGI] [Single error output stream (`std::cout`)]]
- [[SCGI] [A single output stream is shared between requests: Boost.CGI will guarantee thread-safe access to it.]]
+ [[CGI] [Single error output stream (`std::cerr`)]]
+ [[SCGI] [A single output stream (`std::cerr`) is shared between requests: Boost.CGI will guarantee thread-safe access to it.]]
[[FastCGI] [Error stream per request. Inherently thread-safe.]]
]
@@ -38,11 +38,11 @@
[h4 Session handling.]
-Access to persistent session data is a very useful stop-gap to using a complete RDBMS to store/retrieve data. In some cases, such as when an object is supposed to stay in active memory, a RDBMS will not be sufficient, so session management fits in nicely. A templated `basic_session<>` will be provided so various session-storage methods can be used. Boost.Interprocess is an ideal default, while Boost.UUID can be used to generate unique session identifiers.
+Access to persistent session data is a very useful stop-gap to using a complete RDBMS to store/retrieve data. In some cases, such as when an object is supposed to stay in active memory, a RDBMS will not be efficient, so session management fits in nicely. A templated `basic_session<>` will be provided so various session-storage methods can be used. Boost.Interprocess is an ideal default, while Boost.UUID can be used to generate unique session identifiers.
-[h4 Having `meta_*` functions return a `cgi::param` type instead of `std::string`]
+[h4 Having request variable functions return a `cgi::param` type instead of `std::string`]
-An advantage to this approach, for the functions that look up request meta-data, is that multiple values can be easily extracted from the same key, when they exist. Currently, a user must get the complete map of meta-data and use that themselves. [-Since environment meta-data can't be uniformly retrieved as a `cgi::map_type&` (since they are actually process-level environment variables, accessible only through `::getenv()`) this can be awkward.]
+An advantage to this approach, for the functions that look up request data, is that multiple values can be easily extracted from the same key, when they exist. Currently, a user must get the complete map of data and use that themselves.
Another advantage is that a macro can be provided to turn on/off implicit conversion to `std::string`, which is in essence a form of tainting, akin to perl's taint mode.
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/introduction.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/introduction.qbk (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/introduction.qbk 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -11,34 +11,65 @@
#include <boost/cgi/cgi.hpp>
using namespace cgi;
-int main(int, char**)
+int main()
{
request req;
response resp;
resp<< "Hello there, Universe. "
- << "Oh wait, it's just you, " << req.form_("name")
- << ", isn't it?!";
- resp.send(req);
+ << "Oh wait, it's just you, " << req.form("name")
+ << ", isn't it.";
+
+ return_(req, resp, 0); // write the response and 'return 0;'
}
``
-This CGI library reasonably high-level library for web programming. Herein the controller portion of the Model-View-Controller idiom is implemented. The intricacies of dealing with the widely varying specifications of CGI, FastCGI and SCGI are abstracted into three main parts:
+This CGI library is a reasonably high-level library for creating CGI, FastCGI or SCGI programs. Its scope is intentionally limited to the ''controller'' portion of the Model-View-Controller idiom. In other words, XML/HTML templates are not addressed, even if their use is highly recommended (consider having a look at google's cTemplate, or the upcoming ''Karma'' part of Boost.Spirit).
+
+[h4 Concepts]
+
+The library provides abstractions which hide details of the widely varying specifications of CGI, FastCGI and SCGI. These abstractions are briefly:
+
+[table
+[
+ [Concept] [Purpose]
+]
+[
+ [RequestAcceptor]
+ [CGI applications handle one request per process, while both SCGI and FastCGI allow each process to handle many requests, potentially at the same time. A RequestAcceptor makes it easy to ignore these differences and it also allows you to control how fast your process takes on new requests.
+ ]
+]
+[
+ [Request]
+ [Access to all request data is done through a Request object.]
+]
+[
+ [Client]
+ [Each request has an associated Client, which will usually represent a connection to the HTTP server associated with the current request.
+ ]
+]
+[
+ [ProtocolService]
+ [For those of you familiar with Boost.Asio, this is very similar to the `io_service` class (it actually uses one or more of these for its functionality). Its purpose is to provide certain guarantees when you are using asynchronous functions and/or multiple threads. The asynchronous stuff is what underpins this whole library.]
+]
+]
+
+[h4 Protcols]
-* Accepting,
+[:['See __protocol_details__ for more.]]
-* Loading, and
+In a nutshell, CGI is the simple and 'original' way of communicating with web servers. I'll assume you know what it is: one request per process and communication using standard input/output. A nice and simple way of making ['web pages that can change].
-* Handling.
+FastCGI was then developed as a means of allowing much more scalable CGI-like programs to be written. In fact, the FastCGI specification implies maximal efficiency was the main goal of the protocol. Communication with the server now works over sockets or pipes (only TCP sockets are supported for now). Each process and each connection can be used for handling multiple requests. In theory this means you could have a single monolithic process behind your HTTP server handling thousands of concurrent requests.
-Sometimes all a problem calls for is a thin interface to request data and '''I/O''' streams, without any need to be hyper-efficient: in other words, like a short CGI script that you can with [@http://tinyurl.com/2ss4ae perl], [@http://tinyurl.com/39b37l python], [@http://tinyurl.com/3yg4m8 php], etc. To allow this, the library and documentation are split into two parts: 'scripting' and 'everything else'. The code excerpt above is an example of a 'script' which, as you can see, skips the 'accepting' and 'loading' stages.
+SCGI is essentially a simpler version - hence [*S]imple[*CGI] - of FastCGI but is still a significant step up from vanilla CGI: as with FastCGI, each process can handle multiple requests. Use of FastCGI is recommended over SCGI, but unfortunately support for FastCGI is unreliable and buggy with some servers so it may not be a matter of choice.
-If a program's purpose is to serve the wider world, it should be written with scalability in mind. When it comes to heavily used web applications CGI has an inherent limitation: there must be a complete heavyweight process ['for every request].
+[h4 Multiple Requests per Process]
-The __FastCGI__ and __SCGI__ protocols are essentially reworkings of CGI which remove this restriction. They offer other advantages too, the support of which - of widely varying quality and completeness ([-more [link __server_support__ here]]) - comes for most HTTP servers. These protocols add an extra layer to your CGI programs, as you now must manage the request queue.
+So I keep harping on about this, that's because it removes so many limitations of traditional CGI programming. In return for the added complexity, your programs become complete servers, capable of handling arbitrary numbers of requests during each invocation (assuming they don't crash, or leak memory!). This gives you the freedom to keep database connections open between requests, or cache ready-parsed responses, for example. Processing of a client request can even be continued in the case of the client crashing - the `response` can then be stored and given to them when they return - saving precious CPU cycles.
-In return for the added complexity, your programs become complete servers, capable of handling arbitrary numbers of requests during each invocation (assuming they don't crash!). This gives you the freedom to keep database connections open between requests, or cache ready-parsed responses, for example. Processing of a client request can even be continued in the case of the client crashing - the `response` can then be stored and given to them when they return - saving precious CPU cycles.
+You might think dealing with request queues could be a handful but, fortunately, management of the queue (or queues, if you'd prefer) can be largely isolated from the handling of each request. That means that after you have set up a 'server' (ie. something that gathers requests), requests can be handled in much the same way as they would be with a standard CGI program that uses this library.
-It might sound like a handful but, fortunately, management of the request queue can be largely isolated from the handling of each request. That means that after you have set up a 'server' (ie. something that gathers requests), requests can be handled in the same way as they would be with a conventional CGI program.
+Now on to demonstrations...
[endsect]
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/preface.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/preface.qbk (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/preface.qbk 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -13,13 +13,13 @@
[h3 Overview]
-Boost.CGI is a library for writing CGI programs in Standard C++. It can be used to write anything from simple 'admin scripts' to full-fledged, scalable applications. This library rests on top of and should appear familiar to users of Boost.Asio, a cross-platform networking library in boost-style C++. Currently the __cgi__, [-__scgi__ and __fcgi__] protocols are supported, within a framework that should allow code to be reused with as-yet-unwritten protocols without any real modification.
+Boost.CGI is an open-source library for writing CGI programs in Standard C++. The library supports vanilla CGI, SCGI and FastCGI (SCGI/FastCGI don't really work yet) so it can be used to write anything from simple 'admin scripts' to full-fledged, scalable applications. This library rests on top of and should appear familiar to users of Boost.Asio, a cross-platform asynchronous networking library in boost-style C++. One of the main aims of the library is to allow programs to be written for any of the supported protocols without any real modification.
[h3 Motivation]
-C++ isn't the language of choice for many CGI programmers, although it is a powerful one and can be used to produce maintainable and uncompromisingly efficient applications with any feature possible in any other language.
+C++ isn't the language of choice for many CGI programmers, despite being a powerful one that can be used to produce scalable, maintainable and uncompromisingly efficient applications.
-A complete discussion about the benefits of CGI programming in C++ is beyond the scope of this document, but here is a short list:
+A discussion about the benefits of CGI programming in C++ is beyond the scope of this document and I've assumed you're here because you want to try C++ CGI programming, but here is a short list anyway:
* Having a binary application is inherently more secure than scripting languages in the situation where an error causes the application, rather than the output to be returned to the client. See http://www.w3.org/Security/Faq/wwwsf4.html for more.
@@ -29,9 +29,9 @@
* In places where RAD (rapid application development) is of the utmost importance, scripting languages can still be used, for instance by using [link __boost_python__ Boost.Python] - though it could be argued that C++ and RAD are not mutually exclusive.
-* C++ is ['fast]. You can rest assured that the language will never be a bottleneck in your applications.
+* C++ is ['fast]. You can rest assured that the language will never be a bottleneck for your applications.
-* C++ rarely misses out on access to new technologies: for instance, if a new RDBMS came out tomorrow, it would almost certainly ship with a C/C++ API. The same would not be true for most other languages.
+* C++ rarely misses out on access to new technologies: for instance, if a new RDBMS came out tomorrow, it would almost certainly ship with a C/C++ API. The same would not be true for many other languages.
* Web applications can benefit from an enforced modular design.[footnote For an example design choice, see [@http://www.google.co.uk/search?hl=en&rlz=1B3GGGL_enGB234GB235&q=model+view+controller&btnG=Search&meta= Model-View-Controller].] C++'s flexibility with regard to object-oriented design patterns is highly-regarded and well documented.
@@ -42,7 +42,7 @@
[h3 How to use this manual]
[note
-At the moment, the Boost [@http://www.boost.org/more/lib_guide.htm#Guidelines style guidelines] aren't honoured properly or consistently. Please ignore this for now, as the ambiguity is intentional and is simple enough to rectify.
+At the moment, the Boost [@http://www.boost.org/more/lib_guide.htm#Guidelines style guidelines] aren't honoured properly or consistently. Please ignore this for now, as the ambiguity is intentional (['since this [*is not] a Boost library]) and is simple enough to rectify.
]
Start with the introduction, then the tutorial. You can skip the 'scripting' section, as that is a quickstart and the information in it is repeated throughout the rest of the manual. The doxygen header reference is very ugly for now and is going to be heavily reworked and reorganised.
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/user_guide/async_ops.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/user_guide/async_ops.qbk (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/doc/src/user_guide/async_ops.qbk 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -1,6 +1,6 @@
[section:async Asynchronous Operations]
-Asynchronous functionality is inherited from __boost_asio__, which uses __IoService__s to manage I/O operations. Each program that uses an asynchronous __protocol__ requires a single __ProtocolService__ to service all requests in the program. Amongst other things, the ProtocolService uses an underlying IoService to run asynchronous operations.
+Asynchronous functionality is inherited from __boost_asio__, which uses __IoService__s to manage I/O operations. Each program that uses an asynchronous __protocol__ requires a single __ProtocolService__ to service all requests in the program. Amongst other things, the ProtocolService uses one or several underlying IoService(s) to handle asynchronous operations.
The asynchronous operations provided by the library are:
@@ -10,7 +10,7 @@
* Async __loading__ of request meta-data.
-Using asynchronous operations takes a bit of getting used to, but after overcoming the initial Conceptual hurdles, use of the library should be relatively straight-forward.
+Using asynchronous operations takes a bit of getting used to, but after overcoming the initial conceptual hurdles, use of the library should be relatively straight-forward.
@@ -20,4 +20,4 @@
[/ link to the asio IoService concept docs; mention *briefly* what they are for; explain how the protocol services use an IoServiceProvider, linking to relevant examples in the examples section.]
-[endsect]
\ No newline at end of file
+[endsect]
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/Jamfile.v2 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -4,7 +4,15 @@
# (See accompanying file LICENSE_1_0.txt or copy
# at http://www.boost.org/LICENSE_1_0.txt)
+# Install all of the acgi examples
+install acgi
+ : # sources
+ acgi//install
+ :
+ <location>$(cgi-bin)
+ ;
+explicit acgi ;
#install examples
# : # the sources
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/Jamfile.v2 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,21 @@
+# Copyright (c) 2007 Darren Garvey
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy
+# at http://www.boost.org/LICENSE_1_0.txt)
+
+project boost.cgi.examples.acgi ;
+
+# Install all acgi examples to the user-provided variable "cgi-bin"
+install install
+ :
+ hello_world
+ echo
+ cookie_game
+ login
+ :
+ <location>$(cgi-bin)
+ ;
+
+# Only install example if you use `bjam install' or equivalent
+explicit install ;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/cookie_game/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/cookie_game/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/cookie_game/Jamfile.v2 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -5,33 +5,17 @@
# at http://www.boost.org/LICENSE_1_0.txt)
project boost.cgi.examples.acgi.cookie_game
- : build-dir
- $(PROJECT_ROOT)/bin.v2
;
-SOURCES = main ;
+exe acgi : main.cpp ;
-exe acgi
- :
- $(SOURCES).cpp
+# Our install rule (builds binaries and copies them to <location>)
+install install
:
- <include>$(BOOST_ROOT)
- <include>$(PROJECT_ROOT)
- #<library>../../util/system//boost_system
- #<library>libboost_system
- #<define>BOOST_ALL_NO_LIB=1
- #<toolset>gcc:<linkflags>-lpthread
- <define>_CRT_SECURE_NO_WARNINGS
- <define>_SCL_SECURE_NO_WARNINGS
- :
- ;
-
-# uncomment this if you want to test the example with your HTTP server
-install _
- : acgi
- : # this is where the compiled executable is copied to
- # ie. change this to your server's /cgi-bin/
- <location>.
+ acgi
+ :
+ <location>$(cgi-bin)
;
+# Only install example if you use `bjam install' or equivalent
explicit install ;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/cookie_game/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/cookie_game/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/cookie_game/main.cpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -33,7 +33,7 @@
// };
/**
- * The following example has a few simple stages.
+ * The following example has a few stages.
* It is best understood by compiling and testing it, and then looking at
* the source code.
*/
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/echo/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/echo/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/echo/Jamfile.v2 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -1,20 +1,18 @@
+# Copyright (c) 2007 Darren Garvey
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy
+# at http://www.boost.org/LICENSE_1_0.txt)
-project boost.cgi.examples.acgi.echo
- : build-dir
- $(PROJECT_ROOT)/bin.v2
- ;
+exe acgi_echo : main.cpp /boost/thread/ ;
-exe acgi_echo
- : main.cpp
+# Our install rule (builds binaries and copies them to <location>)
+install install
+ : acgi_echo
+ :
:
- <include>$(PROJECT_ROOT)
- <include>$(BOOST_ROOT)
- <define>_CRT_SECURE_NO_WARNINGS
- <define>_SCL_SECURE_NO_WARNINGS
+ <location>$(cgi-bin)
;
-install acgi_echo_install
- : acgi_echo
- : <location>.
- <library>../../../util/system//boost_system
- ;
+# Only install example if you use `bjam install' or equivalent
+explicit install ;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/echo/main.cpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -1,14 +1,31 @@
+// -- main.hpp --
+//
+// Copyright (c) Darren Garvey 2007.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+////////////////////////////////////////////////////////////////
+//
+// This example simply echoes all variables back to the user. ie.
+// the environment and the parsed GET, POST and cookie variables.
+// Note that GET and cookie variables come from the environment
+// variables QUERY_STRING and HTTP_COOKIE respectively.
+//
+
#include <boost/cgi/acgi.hpp>
using namespace std;
using namespace boost::acgi;
+// This function writes the title and map contents to the ostream in an
+// HTML-encoded format (to make them easier on the eye).
template<typename MapT, typename OStreamT>
void show_map_contents(MapT& m, OStreamT& os, const std::string& title)
{
os<< "<h3>" << title << "</h3>";
if (m.empty()) os<< "NONE<br />";
- for (MapT::iterator i = m.begin(); i != m.end(); ++i)
+ for (typename MapT::iterator i = m.begin(); i != m.end(); ++i)
{
os<< "<b>" << i->first << "</b> = <i>" << i->second << "</i><br />";
}
@@ -19,7 +36,7 @@
service s;
request req(s);
- req.load(true);
+ req.load(true); // The 'true' means parse STDIN data too.
response resp;
@@ -28,7 +45,11 @@
show_map_contents(req.POST(), resp, "POST Variables");
show_map_contents(req.cookie(), resp, "Cookie Variables");
+ // Note that this (and any other) HTTP header can go either before or after
+ // the response contents.
resp<< content_type("text/html");
+
+ // Send the response to the client associated with the request.
resp.send(req.client());
return 0;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/hello_world/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/hello_world/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/hello_world/Jamfile.v2 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -1,20 +1,19 @@
+# Copyright (c) 2007 Darren Garvey
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy
+# at http://www.boost.org/LICENSE_1_0.txt)
project boost.cgi.examples.acgi.hello_world
- : build-dir
- $(PROJECT_ROOT)/bin.v2
;
-exe acgi_hello_world
- : main.cpp
- : <name>acgi_hw
- <include>$(PROJECT_ROOT)
- <include>$(BOOST_ROOT)
- <define>_CRT_SECURE_NO_WARNINGS
- <define>_SCL_SECURE_NO_WARNINGS
- ;
+exe acgi_hello_world : main.cpp /boost/regex/ ;
-install acgi_hw_install
+# Our install rule (builds binaries and copies them to <location>)
+install install
: acgi_hello_world
- : <location>.
- <library>../../../util/system//boost_system
+ : <location>$(cgi-bin)
;
+
+# Only install example if you use `bjam install' or equivalent
+explicit install ;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/CheckCookie.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/CheckCookie.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/CheckCookie.cpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -14,7 +14,10 @@
if (!req.cookie("uuid").empty())
{ // The cookie has been set correctly!
- resp<< location(req.form("fwd"));
+ boost::system::error_code ec;
+ std::string fwd(req.form("fwd", ec));
+ resp<< location(fwd);
+ // resp<< location(req.form("fwd"));
}else
{
resp
@@ -36,6 +39,6 @@
resp.send(req.client());
- return req.end(http::ok);
+ return req.close(http::ok);
}
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Jamfile.v2 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -1,32 +1,24 @@
+# Copyright (c) 2007 Darren Garvey
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy
+# at http://www.boost.org/LICENSE_1_0.txt)
-project boost.cgi.examples.acgi.login
- : build-dir
- $(PROJECT_ROOT)/bin.v2
- ;
-
-exe Login
- : Login.cpp
- : <include>$(PROJECT_ROOT)
- <include>$(BOOST_ROOT)
- ;
+project boost.cgi.examples.acgi.login ;
-exe Logout
- : Logout.cpp
- : <include>$(PROJECT_ROOT)
- <include>$(BOOST_ROOT)
- ;
+exe Login : Login.cpp /boost/regex/ ;
+exe Logout : Logout.cpp ;
+exe CheckCookie : CheckCookie.cpp ;
-exe CheckCookie
- : CheckCookie.cpp
- : <include>$(PROJECT_ROOT)
- <include>$(BOOST_ROOT)
- ;
-
-install _
+# Our install rule (builds binaries and copies them to <location>)
+install install
:
Login
Logout
CheckCookie
:
- <location>c:/Apache/Apache2.2/cgi-bin/
+ <location>$(cgi-bin)
;
+
+# Only install example if you use `bjam install' or equivalent
+explicit install ;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Login.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Login.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Login.cpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -4,6 +4,24 @@
#include <boost/lexical_cast.hpp>
using namespace boost::acgi;
+using std::string;
+
+void show_passed_variables(request& req, response& resp)
+{
+ resp<< "<hr />"
+ "<div>"
+ "You provided the following data:"
+ "<p>"
+ "<h3>Form data:</h3>";
+ for (boost::acgi::map::iterator i = req.form().begin();
+ i != req.form().end();
+ ++i)
+ {
+ resp<< "<b>" << i->first << "</b> = <i>" << i->second << "</i>";
+ }
+ resp<< "</p>"
+ "</div>";
+}
int show_default_page(request& req, response& resp)
{
@@ -15,19 +33,22 @@
"</head>"
"<body>"
"<center>"
- "<form action='POST'>"
+ "<form method='POST'>"
"<input type='text' name='name' />"
- "<input type='button' name='cmd' value='login' />"
+ "<input type='hidden' name='cmd' value='login' />"
+ "<input type='submit' value='login' />"
"</form>"
- "</center>"
- "</body>"
+ "</center>";
+ show_passed_variables(req, resp);
+ resp
+ << "</body>"
"</html>";
resp.send(req.client());
return req.close(http::ok);
}
-void show_already_logged_in_page(request& req, response resp)
+int show_already_logged_in_page(request& req, response& resp)
{
resp
<< content_type("text/html")
@@ -40,8 +61,10 @@
"You are already logged in. You should be redirected "
"<a href='"<< req.POST("fwd") <<"'>here</a>"
" in five seconds."
- "</center>"
- "</body>"
+ "</center>";
+ show_passed_variables(req, resp);
+ resp
+ << "</body>"
"</html>";
resp.send(req.client());
@@ -65,8 +88,10 @@
"<input type='text' name='name' value='"<< req.POST("name") <<"' />"
"<input type='button' name='cmd' value='login' />"
"</form>"
- "</center>"
- "</body>"
+ "</center>";
+ show_passed_variables(req, resp);
+ resp
+ << "</body>"
"</html>";
resp.send(req.client());
@@ -78,7 +103,7 @@
using namespace boost;
regex re("\\s*([_a-zA-Z0-9]{5,})\\s*");
- cmatch what;
+ smatch what;
if (!regex_match(name, what, re))
{
@@ -92,7 +117,7 @@
string make_uuid()
{
- return boost::lexical_cast<string>(time());
+ return boost::lexical_cast<string>(time(NULL));
// better, for when Boost.Uuid is finished:
//return boost::uuid::create().to_string();
}
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Logout.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Logout.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/acgi/login/Logout.cpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -12,10 +12,12 @@
response resp;
- resp<< cookie("uuid")
- << location(req.form("fwd"));
+ resp<< cookie("uuid");
+ boost::system::error_code ec;
+ std::string fwd(req.form("fwd", ec));
+ resp<< location(fwd);
resp.send(req.client());
- return req.end(http::ok);
+ return req.close(http::ok);
}
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/Jamfile.v2 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -1,25 +1,14 @@
-project cgi.examples.fcgi.hello_world
- : build-dir
- $(PROJECT_ROOT)/bin.v2
- ;
+project cgi.examples.fcgi.hello_world ;
+
+exe fast_hw : main.cpp ;
-exe fast_hw
+install install
:
- main.cpp
+ fast_hw
:
- <include>$(BOOST_ROOT)
- <include>$(PROJECT_ROOT)
- #<library>../../util/system//boost_system
- #<define>BOOST_ALL_NO_LIB=1
- <define>_CRT_SECURE_NO_WARNINGS
- <define>_SCL_SECURE_NO_WARNINGS
+ <location>$(fcgi-bin)
;
-install fast_hw_install
- : fast_hw
- : #<location>$(BOOST_CGI_BIN_DIR)
- #<location>.
- <location>C:/Apache/Apache2.2/fcgi-bin
- ;
+explicit install ;
Added: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/main.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/main.cpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -0,0 +1,86 @@
+#include <boost/cgi/fcgi.hpp>
+#include <boost/system/system_error.hpp>
+#include <fstream>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/program_options/environment_iterator.hpp>
+
+using namespace cgi::fcgi;
+using namespace std;
+
+#define LOG_FILE "/var/www/log/fcgi_hello_world.txt"
+
+template<typename OStream>
+void accept_handler(OStream& os, const boost::system::error_code ec)
+{
+ os<< "Accepted connection ok!" << endl;
+}
+
+
+int main()
+{
+ std::cerr<< "[hw] Started FCGI daemon (see " LOG_FILE " for more)..." << endl;
+try {
+ ofstream of(LOG_FILE);
+ if (!of) std::cerr<< "Couldn't open file: \"" LOG_FILE "\"." << endl;
+ of<< boost::posix_time::second_clock::local_time() << endl;
+ of<< "Going to start acceptor" << endl;
+ service s;
+ acceptor a(s);
+
+ a.assign(boost::asio::ip::tcp::v4(), 0);
+ of<< "[a] Assigned." << endl;
+ bool give_up = false;
+
+ do {
+
+ of<< "Writing environment variables..." << endl;
+ for(boost::environment_iterator i(environ), e; i != e; ++i)
+ {
+ of<< i->first << ", " << i->second << endl;
+ }
+ of<< "--------------------------------" << endl;
+ request req(s);
+ of<< "Constructed request" << endl;
+ boost::system::error_code ec;
+ a.accept(req, ec);
+
+ of<< "Called accept" << endl;
+ if (ec) { of<< "[hw] accept error: " << ec.message() << endl; return 13; }
+ of<< "request.is_open() := " << req.is_open() << endl;
+ of<< "request.client().is_open() := " << req.client().is_open() << endl;
+ //of<< "next_layer stuff := " << req.client().connection()->next_layer().is_open() << endl;
+ //a.async_accept(s, boost::bind(&accept_handler<std::ofstream>, boost::ref(of), boost::asio::placeholders::error));
+ of<< "Accept had result: " << ec.message() << endl;
+ boost::asio::streambuf buf;
+ of<< "Start log:" << endl;
+
+ req.load(ec, true);
+
+ req.client().read_some(buf.prepare(64), ec);
+ of<< "[a] Read some data: " << ec.message() << endl;
+ //req.load(ec, true);//cgi::parse_all);
+ //if (ec) { of<< "Couldn't load request: " << ec.message() << endl; return 14; }
+ //for (;;)
+ //{
+ // size_t br = req.client().read_some(buf.prepare(64), ec);
+ // of<< "Client wrote " << br << " bytes (max: " << std::numeric_limits<size_t>::max() << ")." << endl
+ // << string(boost::asio::buffer_cast<const char *>(buf.data()),
+ // boost::asio::buffer_size(buf.data())) << endl;
+ // if (ec) { of<< "read error: " << ec.message() << endl; return 5; }
+ //}
+ sleep(4);
+
+ }while(!give_up);
+ s.run();
+ return 0;
+}catch(boost::system::system_error& se){
+ cerr<< "[hw] System error: " << se.what() << endl;
+ return 1313;
+}catch(exception& e){
+ cerr<< "[hw] Exception: " << e.what() << endl;
+ return 666;
+}catch(...){
+ cerr<< "[hw] Uncaught exception!" << endl;
+ return 667;
+}
+}
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/scgi/hello_world/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/scgi/hello_world/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/scgi/hello_world/Jamfile.v2 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -1,24 +1,20 @@
+# Copyright (c) 2007 Darren Garvey
+#
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy
+# at http://www.boost.org/LICENSE_1_0.txt)
-project cgi.examples.hello_world
- : build-dir
- $(PROJECT_ROOT)/bin.v2
- ;
+project cgi.examples.hello_world ;
+
+exe scgi_hw : main.cpp ;
-exe hw
+# Our install rule (builds binaries and copies them to <location>)
+install install
:
- main.cpp
+ scgi_hw
:
- <include>$(BOOST_ROOT)
- <include>$(PROJECT_ROOT)
- #<library>../../util/system//boost_system
- #<define>BOOST_ALL_NO_LIB=1
- <define>_CRT_SECURE_NO_WARNINGS
- <define>_SCL_SECURE_NO_WARNINGS
- ;
-
-install hw_i
- : hw
- : #<location>$(BOOST_CGI_BIN_DIR)
- <location>.
+ <location>$(scgi-bin)
;
+# Only install example if you use `bjam install' or equivalent
+explicit install ;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/scgi/hello_world/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/scgi/hello_world/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/scgi/hello_world/main.cpp 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -1,43 +1,102 @@
#include <boost/cgi/scgi.hpp>
+#include <boost/system/system_error.hpp>
#include <fstream>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/program_options/environment_iterator.hpp>
using namespace cgi::scgi;
using namespace std;
+#define LOG_FILE "/var/www/log/scgi_hello_world.txt"
+//#define LOG_FILE "scgi_hello_world.txt"
+
+template<typename OStream>
+void accept_handler(OStream& os, const boost::system::error_code& ec)
+{
+ os<< "Accepted connection ok!" << endl;
+}
+
+
int main()
{
+ std::cerr<< "[hw] Started SCGI daemon (see " LOG_FILE " for more)..." << endl;
try {
- ofstream of("C:/Logs/scgi_hello_world.txt");
- if (!of) std::cerr<< "broken" << endl;
+ ofstream of(LOG_FILE);
+ if (!of) std::cerr<< "Couldn't open file: \"" LOG_FILE "\"." << endl;
+ of<< boost::posix_time::second_clock::local_time() << endl;
+ of<< "Going to start acceptor" << endl;
service s;
- acceptor a(s, 9472);
+ acceptor a(s, 9499);
+ of<< "Writing environment variables..." << endl;
+ for(boost::environment_iterator i(environ), e; i != e; ++i)
+ {
+ of<< i->first << ", " << i->second << endl;
+ }
+ of<< "--------------------------------" << endl;
request req(s);
+ of<< "Made request" << endl;
boost::system::error_code ec;
- a.accept(req, ec);
- boost::asio::io_service ios;
- using boost::asio::ip::tcp;
- tcp::socket sock(ios);
- if (ec) { of<< "hw accept error: " << ec.message() << endl; return 13; }
+ boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(), 9499);
+ of<< "ep.address := " << ep.address() << endl;
+ //a.open(boost::asio::ip::tcp::v4());
+ //of<< (ec ? "Couldn't open: " + ec.message() : "Opened ok") << endl;
+ //a.listen(boost::asio::socket_base::max_connections, ec);
+ //of<< "[a] Listening: " << ec.message() << endl;
+ //of<< "[a] address: " << a.local_endpoint().address().to_string()
+ // << ":" << a.local_endpoint().port() << endl;
+ a.assign(boost::asio::ip::tcp::v4(), 0, ec);
+ of<< "[a] Assigned: " << ec.message() << endl;
+ //a.bind(, ec);
+ //of<< "[a] Bind outcome: " << ec.message() << endl;
+ while(!a.accept(req, ec))
+ {
+ of<< "Called accept" << endl;
+ //boost::asio::io_service ios;
+ //using boost::asio::ip::tcp;
+ //tcp::socket sock(ios);
+ if (ec) { of<< "[hw] accept error: " << ec.message() << endl; return 13; }
//cout<< "Hello there." << endl;
-
+ //of<< "acceptor.is_open() := " << a.is_open() << endl;
+ of<< "request.is_open() := " << req.is_open() << endl;
+ of<< "request.client().is_open() := " << req.client().is_open() << endl;
+ of<< "next_layer stuff := " << req.client().connection()->next_layer().is_open() << endl;
+
+ //boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 9499);
+ //boost::asio::ip::tcp::acceptor a2(s.io_service(), ep);
+ //a2.open(ep.protocol());
+ //of<< "Opened a2" << endl;
+ //a2.listen(boost::asio::socket_base::max_connections, ec);
+ //of<< "a2 listening: " << ec.message() << endl;
+ //boost::asio::ip::tcp::socket s(s.io_service());
+ //a2.accept(req.client().connection()->next_layer(), ec);
+ //a.async_accept(s, boost::bind(&accept_handler<std::ofstream>, boost::ref(of), boost::asio::placeholders::error));
+ of<< "Accept had result: " << ec.message() << endl;
boost::asio::streambuf buf;
of<< "Start log:" << endl;
+ req.load(ec, true);//cgi::parse_all);
+ if (ec) { of<< "Couldn't load request: " << ec.message() << endl; return 14; }
//for (;;)
- {
+ //{
size_t br = req.client().read_some(buf.prepare(64), ec);
of<< "Client wrote " << br << " bytes." << endl
- << string(buf.data().begin(), buf.data().end()) << endl;
+ ;//<< string(boost::asio::buffer_cast<const char *>(buf.data()),
+ // boost::asio::buffer_size(buf.data())) << endl;
if (ec) { of<< "read error: " << ec.message() << endl; return 5; }
+ //}
+ sleep(4);
}
-
+ of<< "Accept error (shutting down): " << ec.message() << endl;
return 0;
+}catch(boost::system::system_error& se){
+ cerr<< "[hw] System error: " << se.what() << endl;
+ return 1313;
}catch(exception& e){
- cerr<< "hw exception: " << e.what() << endl;
+ cerr<< "[hw] Exception: " << e.what() << endl;
return 666;
}catch(...){
- cerr<< "hw uncaught exception!" << endl;
+ cerr<< "[hw] Uncaught exception!" << endl;
return 667;
}
}
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/project-root.jam
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/project-root.jam (original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/project-root.jam 2008-02-08 09:43:13 EST (Fri, 08 Feb 2008)
@@ -1,7 +1,48 @@
import os ;
+import modules ;
path-constant BOOST_ROOT : [ os.environ BOOST_ROOT ] ;
path-constant BOOST_BUILD_PATH : [ os.environ BOOST_BUILD_PATH ] ;
path-constant PROJECT_ROOT : . ;
path-constant BOOST_CGI_BIN_DIR : c:/Apache/Apache2.2/cgi-bin ;
+
+path-constant top : . ;
+path-constant include-dir : /usr/local/include ;
+path-constant boost-root : [ os.environ BOOST_ROOT ] ;
+path-constant google-root : $(include-dir)/google ;
+
+# These are some helper variables, which will need to be checked against
+# user-supplied variables (ie. using modules.peek, I think)
+#local cgi-bin = [ modules.peek : cgi-bin ] ;
+path-constant cgi-bin : /usr/lib/cgi-bin ;
+path-constant scgi-bin : /usr/lib/scgi-bin ;
+path-constant fcgi-bin : /usr/lib/fcgi-bin ;
+#if (!cgi-bin)
+#{
+# cgi-bin = [ os.environ BOOST_CGI_CGI_BIN ] ;
+#
+# if (!cgi-bin)
+# {
+# cgi-bin = /usr/lib/cgi-bin ;
+# }
+#}
+
+use-project /boost/system/ : $(boost-root)/libs/system/build ;
+use-project /boost/thread/ : $(boost-root)/libs/thread/build ;
+use-project /boost/regex/ : $(boost-root)/libs/regex/build ;
+use-project /google/template/ : $(top)/libs/cgi/util/google/ ;
+use-project /boost/ : $(boost-root) ;
+
+project boost.cgi
+ : build-dir
+ $(top)/bin.v2
+ : requirements
+ <include>$(boost-root)
+ <include>$(top)
+ <library>/boost/system/
+ <library>/boost/thread/
+ #<linkflags>-lctemplate
+ <define>_CRT_SECURE_NO_WARNINGS
+ <define>_SCL_SECURE_NO_WARNINGS
+ ;
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk