Boost logo

Boost-Commit :

From: lists.drrngrvy_at_[hidden]
Date: 2008-06-02 18:13:57


Author: drrngrvy
Date: 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
New Revision: 46059
URL: http://svn.boost.org/trac/boost/changeset/46059

Log:
* Added basic_request_acceptor<>::is_cgi() so you can check if you're running with CGI or FastCGI.
* Added example/xcgi with a simple server that handles any request type.
* Bug fixes, etc.

Added:
   sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/ajax_echo/
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/Jamfile.v2 (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/main.cpp (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Jamfile.v2 (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Server.hpp (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/doc.qbk (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/main.cpp (contents, props changed)
   sandbox/SOC/2007/cgi/trunk/libs/cgi/src/
Removed:
   sandbox/SOC/2007/cgi/trunk/boost/cgi/cgi/cgi_service.hpp
   sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/step_one.qbk
Text files modified:
   sandbox/SOC/2007/cgi/trunk/boost/cgi.hpp | 2
   sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi.hpp | 4
   sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request.hpp | 9
   sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_impl.hpp | 16
   sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_service.hpp | 21
   sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/service.hpp | 14
   sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp | 39 +-
   sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request_acceptor.hpp | 11
   sandbox/SOC/2007/cgi/trunk/boost/cgi/common/basic_protocol_service.hpp | 5
   sandbox/SOC/2007/cgi/trunk/boost/cgi/common/cookie.hpp | 4
   sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp | 23
   sandbox/SOC/2007/cgi/trunk/boost/cgi/common/header.hpp | 200 ++++++++-------
   sandbox/SOC/2007/cgi/trunk/boost/cgi/common/response.hpp | 4
   sandbox/SOC/2007/cgi/trunk/boost/cgi/common/source_enums.hpp | 2
   sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/tcp_socket.hpp | 2
   sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp | 12
   sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/common_headers.hpp | 9
   sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/protocol_traits.hpp | 20 +
   sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/url_decode.hpp | 4
   sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/acceptor_service_impl.hpp | 20 +
   sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_acceptor_service.hpp | 14 +
   sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp | 499 ++-------------------------------------
   sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/form_parser.ipp | 50 ++-
   sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/response.ipp | 2
   sandbox/SOC/2007/cgi/trunk/boost/cgi/import/streambuf.hpp | 3
   sandbox/SOC/2007/cgi/trunk/libs/cgi/build/Jamfile.v2 | 35 +-
   sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/cgi.qbk | 2
   sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide.qbk | 2
   sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/tutorial.qbk | 2
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/Jamfile.v2 | 11
   sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/hello_world/main.cpp | 65 ++++
   31 files changed, 392 insertions(+), 714 deletions(-)

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -14,6 +14,6 @@
 #include "boost/cgi/cgi.hpp"
 #include "boost/cgi/acgi.hpp"
 #include "boost/cgi/fcgi.hpp"
-#include "boost/cgi/scgi.hpp"
+//#include "boost/cgi/scgi.hpp"
 
 #endif // CGI_HPP_INCLUDED__

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -19,10 +19,6 @@
 #endif
  namespace acgi {
 
- typedef acgi_request request;
- //typedef acgi_service service;
- //typedef acgi_acceptor acceptor;
- //using namespace ::cgi; // **FIXME** this line must go.
    using namespace ::cgi::common; // import common namespace elements.
 
  } // namespace acgi

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -9,6 +9,7 @@
 #ifndef CGI_ACGI_REQUEST_HPP_INCLUDED__
 #define CGI_ACGI_REQUEST_HPP_INCLUDED__
 
+#include "boost/cgi/detail/protocol_traits.hpp"
 #include "boost/cgi/common/tags.hpp"
 #include "boost/cgi/acgi/service.hpp"
 #include "boost/cgi/acgi/request_impl.hpp"
@@ -16,15 +17,15 @@
 #include "boost/cgi/fwd/basic_request_fwd.hpp"
 
 namespace cgi {
-
- class acgi_request_service;
+ namespace acgi {
 
   typedef
     common::basic_request<
- acgi_request_service, acgi_service
+ acgi::request_service, acgi::service
>
- acgi_request;
+ request;
 
+ } // namespace acgi
 } // namespace cgi
 
 //namespace boost { namespace acgi {

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_impl.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_impl.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_impl.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -18,33 +18,29 @@
 // Make this ProtocolService-independent
 
 namespace cgi {
+ namespace acgi {
 
- // Forward declaration
- class acgi_service_impl;
-
- class acgi_request_impl
+ class request_impl
     : public detail::cgi_request_impl_base<common::async_stdio_connection>
   {
   public:
- typedef acgi_service protocol_service_type;
- typedef common::async_stdio_connection connection_type;
+ typedef ::cgi::acgi::service protocol_service_type;
+ typedef common::async_stdio_connection connection_type;
     typedef
       ::cgi::common::basic_client<
         connection_type, common::tags::acgi
>
     client_type;
 
- acgi_request_impl()
+ request_impl()
       : detail::cgi_request_impl_base<connection_type>()
     {
     }
 
     protocol_service_type* service_;
- protected:
- //acgi_request_impl(); // private default constructor
- friend class acgi_service_impl;
   };
 
+ } // namespace acgi
 } // namespace cgi
 
 #endif // CGI_ASYNC_CGI_REQUEST_IMPL_HPP_INCLUDED__

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_service.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/request_service.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -19,23 +19,19 @@
 #include "boost/cgi/detail/cgi_service_impl_base.hpp"
 
 namespace cgi {
+ namespace acgi {
 
- //template<typename ProtocolService>
- class acgi_request_service
- //: public boost::asio::io_service::service
- : public cgi_service_impl_base<acgi_request_impl>
- , public detail::service_base<acgi_request_service>
+ class request_service
+ : public cgi_service_impl_base<acgi::request_impl>
+ , public detail::service_base<request_service>
   {
   public:
- typedef acgi_request_service type;
+ typedef request_service type;
     typedef common::tags::acgi protocol_type;
- typedef acgi_service protocol_service_type;
+ typedef acgi::service protocol_service_type;
 
- /// The unique service identifier
- // static boost::asio::io_service::id id;
-
- acgi_request_service(common::io_service& ios)
- : detail::service_base<acgi_request_service>(ios)
+ request_service(common::io_service& ios)
+ : detail::service_base<request_service>(ios)
     {
     }
 
@@ -60,6 +56,7 @@
     }
   };
 
+ } // namespace acgi
 } // namespace cgi
 
 #endif // CGI_ASYNC_CGI_SERVICE_IMPL_HPP_INCLUDED__

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/service.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/acgi/service.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -1,4 +1,4 @@
-// -- cgi_service.hpp --
+// -- acgi_service.hpp --
 //
 // Copyright (c) Darren Garvey 2007.
 // Distributed under the Boost Software License, Version 1.0.
@@ -6,8 +6,8 @@
 // http://www.boost.org/LICENSE_1_0.txt)
 //
 ////////////////////////////////////////////////////////////////
-#ifndef CGI_CGI_SERVICE_HPP_INCLUDED__
-#define CGI_CGI_SERVICE_HPP_INCLUDED__
+#ifndef CGI_ACGI_SERVICE_HPP_INCLUDED__
+#define CGI_ACGI_SERVICE_HPP_INCLUDED__
 
 #include "boost/cgi/common/tags.hpp"
 #include "boost/cgi/fwd/basic_protocol_service_fwd.hpp"
@@ -15,11 +15,6 @@
 namespace cgi {
 
   /// typedef for typical usage
- /**
- * Works with both cgi_request and acgi_request.
- */
- typedef common::basic_protocol_service<common::tags::acgi> acgi_service;
-
   namespace acgi {
     typedef common::basic_protocol_service<common::tags::acgi> service;
   }
@@ -46,4 +41,5 @@
 
 #include "boost/cgi/common/basic_protocol_service.hpp"
 
-#endif // CGI_CGI_SERVICE_HPP_INCLUDED__
+#endif // CGI_ACGI_SERVICE_HPP_INCLUDED__
+

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -25,6 +25,7 @@
 #include <boost/asio/basic_io_object.hpp>
 ///////////////////////////////////////////////////////////
 // **FIXME** Half of these are probably useless
+#include "boost/cgi/detail/protocol_traits.hpp"
 #include "boost/cgi/common/map.hpp"
 #include "boost/cgi/common/is_async.hpp"
 #include "boost/cgi/common/role_type.hpp"
@@ -35,7 +36,6 @@
 #include "boost/cgi/fwd/basic_request_fwd.hpp"
 #include "boost/cgi/common/request_service.hpp"
 #include "boost/cgi/import/basic_io_object.hpp"
-#include "boost/cgi/detail/protocol_traits.hpp"
 #include "boost/cgi/detail/basic_sync_io_object.hpp"
 #include "boost/cgi/fwd/basic_protocol_service_fwd.hpp"
 
@@ -44,28 +44,19 @@
 
   /// The basic_request class, primary entry point to the library
   /**
- * Note: This class is supposed to make simple use of the library easy.
- * This comes with some restrictions, such as being noncopyable, and also
- * providing copies of the meta-variables rather than references. This makes
- * sure the internal data is protected.
- * The underlying impl_type classes aren't like this (and as such aren't
- * quite as 'safe' to use) but they may be more suited to certain needs.
+ * Note: By default, synchronous protocols (ie. cgi) auto-load AND parse
+ * STDIN,whereas async protocols don't.
    *
- * Note: By default, synchronous protocols (ie. cgi) auto-load AND parse STDIN,
- * whereas async protocols don't.
+ * Note: The alternative functions which take a boost::system::error_code are
+ * the non-throwing versions. Instead of a boost::system::system_error being
+ * thrown in case of an error, the passed error_code will be set to the value
+ * of the error, s.t. if (error) evaluates to true.`
    *
    * Note: This class isn't thread safe: carrying around a mutex-per-request
    * seems prohibitively expensive. There could be functions which take a mutex
    * as an arguement and lock it. (Async calls could get messy if you need a
- * protected request object)
- *
- * Note: From 10/07/07 this class is going to require a protocol_service be
- * passed to it. This is good for FastCGI/SCGI and asynchronous CGI. A full
- * specialisation of this class for sync CGI can be provided... The reasoning
- * for this is that the added complexity for allowing a non-async CGI request
- * to use the acceptor and this class doesn't seem worth it: it makes the
- * whole library much simpler to do it this way.
- */
+ * protected request object).
+ **/
   template<typename RequestService
           , typename ProtocolService
           , role_type Role
@@ -127,6 +118,7 @@
     }
 
     /// Make a new mutiplexed request from an existing connection.
+ // Throws.
     basic_request(implementation_type& impl)
       : basic_io_object<service_type>(impl.service_->io_service())
     {
@@ -138,6 +130,7 @@
     }
 
     /// Make a new mutiplexed request from an existing connection.
+ // Won't throw.
     basic_request(implementation_type& impl, boost::system::error_code& ec)
       : basic_io_object<service_type>(impl.service_->io_service())
     {
@@ -219,8 +212,11 @@
       //BOOST_ASSERT( request_status_ != status_type::ended );
 
       //this->service.set_status(this->implementation, http_status);
- return this->service.close(this->implementation, http_status
- , program_status);
+ boost::system::error_code ec;
+ this->service.close(this->implementation, http_status,
+ program_status, ec);
+ detail::throw_error(ec);
+ return program_status;
     }
 
     int close(common::http::status_code http_status
@@ -356,6 +352,9 @@
 
     string_type server_software()
     { return env_("SERVER_SOFTWARE"); }
+
+ string_type referer()
+ { return env_("HTTP_REFERER"); }
     // -- end helper-functions]
 
     /// Get the charset from the CONTENT_TYPE header

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request_acceptor.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request_acceptor.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/basic_request_acceptor.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -278,6 +278,17 @@
     {
       return this->service.local_endpoint(this->implementation, ec);
     }
+
+ native_type
+ native()
+ {
+ return this->service.native(this->implementation);
+ }
+
+ bool is_cgi()
+ {
+ return this->service.is_cgi(this->implementation);
+ }
   };
 
  } // namespace common

Deleted: sandbox/SOC/2007/cgi/trunk/boost/cgi/cgi/cgi_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/cgi/cgi_service.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
+++ (empty file)
@@ -1,46 +0,0 @@
-// -- cgi_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_CGI_SERVICE_HPP_INCLUDED__
-#define CGI_CGI_SERVICE_HPP_INCLUDED__
-
-#include "../tags.hpp"
-#include "../connections/stdio.hpp"
-#include "../connections/async_stdio.hpp"
-#include "../gateway_impl/acgi_gateway_impl.hpp"
-#include "../gateway_service/acgi_gateway_service.hpp"
-#include "../basic_protocol_service.hpp"
-
-namespace cgi {
-
- /// typedef for typical usage
- /**
- * Works with both cgi_request and acgi_request.
- */
- typedef basic_protocol_service<tags::acgi> cgi_service;
-
- /// A service 'owned' by a single user-supplied io_service
- //typedef basic_protocol_service<tags::acgi> cgi_sub_service;
-
- /// A service with a pool of io_services underneath
- /*
- template<int IoServiceCount, typename PoolingPolicy = tags::round_robin>
- struct cgi_service_pool
- : public basic_protocol_service<tags::acgi, IoServiceCount, PoolingPolicy>
- {
- cgi_service_pool(int concurrency_hint = 0)
- : basic_protocol_service<tags::acgi, IoServiceCount, PoolingPolicy>
- (concurrency_hint)
- {
- }
- };
- */
-
-} // namespace cgi
-
-#endif // CGI_CGI_SERVICE_HPP_INCLUDED__

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/basic_protocol_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/basic_protocol_service.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/basic_protocol_service.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -104,6 +104,11 @@
       ios_provider_.reset();
     }
 
+ bool is_cgi()
+ {
+ return true;
+ }
+
     /// Return an available io_service from the IoServiceProvider
     /**
      * The order in which the underlying io_services are returned is determined

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/cookie.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/cookie.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/cookie.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -121,7 +121,7 @@
     */
 
     /// Make a string out of the cookie
- string_type to_string()
+ string_type to_string() const
     {
       string_type str(name + "=" + value);
       if (!expires.empty()) str += ("; expires=" + expires);
@@ -138,7 +138,7 @@
 
 
 template<typename OutStream, typename T>
-inline OutStream& operator<< (OutStream& os, cgi::common::basic_cookie<T>& ck)
+inline OutStream& operator<< (OutStream& os, cgi::common::basic_cookie<T> const& ck)
 {
   os<< ck.to_string();
   return os;

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/form_parser.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -33,13 +33,13 @@
   class form_parser
   {
   public:
- //typedef
- // boost::function<
- // std::size_t (
- // const mutable_buffers_type&
- // , boost::system::error_code& )
- // >
- //callback_type;
+ typedef
+ boost::function<
+ std::size_t (
+ const boost::asio::mutable_buffer&
+ , boost::system::error_code& )
+ >
+ callback_type;
 
     typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
     typedef std::vector<char> buffer_type;
@@ -48,6 +48,7 @@
     typedef RequestImplType implementation_type;
 
     form_parser(implementation_type& impl);
+ form_parser(implementation_type& impl, callback_type const& callback);
 
     mutable_buffers_type prepare(std::size_t size)
     {
@@ -97,15 +98,15 @@
     std::list<std::string> boundary_markers;
     std::vector<common::form_part> form_parts_;
 
- //callback_type callback_;
+ const callback_type callback_;
   };
 
  } // namespace detail
 } // namespace cgi
 
-#ifndef BOOST_CGI_BUILD_LIB
-# include "boost/cgi/impl/form_parser.ipp"
-#endif
+//#ifndef BOOST_CGI_BUILD_LIB
+# include "boost/cgi/impl/form_parser.ipp"
+//#endif
 
 #endif // CGI_DETAIL_FORM_PARSER_HPP_INCLUDED__
 

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/header.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/header.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/header.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -15,40 +15,46 @@
 namespace cgi {
  namespace common {
 
- template<typename CharT> class basic_cookie; // **FIXME** (maybe)
+ template<typename CharT> struct basic_header;
 
- // **FIXME** (could include response_fwd.hpp really)...
- template<typename CharT> class basic_response;
-
- template<typename CharT>
- struct basic_header
- {
- typedef CharT char_type;
- typedef typename std::basic_string<CharT> string_type;
+ // typedefs for typical usage
+ typedef basic_header<char> header;
+ typedef basic_header<wchar_t> wheader;
+
+ template<typename CharT> struct basic_cookie; // **FIXME** (could do with removing)
+
+ // **FIXME** (could include response_fwd.hpp really)...
+ template<typename CharT> class basic_response;
+
+ template<typename CharT>
+ struct basic_header
+ {
+ typedef CharT char_type;
+ typedef typename std::basic_string<CharT> string_type;
     
- basic_header()
- : content()
- {
- }
-
- basic_header(const string_type& _content)
- : content(_content)
- {
- }
-
- basic_header(const string_type& name, const string_type& val)
- : content(name + ": " + val)
- {
- }
-
- /// Construct an header from a cookie.
- basic_header(const basic_cookie<char_type>& ck)
- : content("Set-cookie: " + ck.to_string())
- {
- }
+ basic_header()
+ : content()
+ {
+ }
+
+ basic_header(const string_type& _content)
+ : content(_content)
+ {
+ }
+
+ basic_header(const string_type& name, const string_type& val)
+ : content(name + ": " + val)
+ {
+ }
+
+ /// Construct an header from a cookie.
+ basic_header(const basic_cookie<char_type>& ck)
+ : content("Set-cookie: " + ck.to_string())
+ {
+ }
 
- string_type content;
- };
+ string_type content;
+ };
 
 /*
   template<typename StringT>
@@ -65,74 +71,70 @@
   }*/
 
 
- //{ Some shortcuts, to cut down on typing errors.
- template<typename CharT, typename StringT> basic_header<CharT>
- content_type(StringT const& str)
- {
- return basic_header<CharT>("Content-type", str);
- }
-
- template<typename CharT> basic_header<CharT>
- content_type(const CharT* str)
- {
- return basic_header<CharT>("Content-type", str);
- }
-
- template<typename CharT> basic_header<CharT>
- content_encoding(std::basic_string<CharT> const& str)
- {
- return basic_header<CharT>("Content-encoding", str);
- }
-
- template<typename CharT, typename T> basic_header<CharT>
- content_length(const T& t)
- {
- return basic_header<CharT>("Content-length",
- boost::lexical_cast<std::basic_string<CharT> >(t));
- }
-
- template<typename CharT, typename T> basic_header<CharT>
- content_length(T t)
- {
- return basic_header<CharT>("Content-length",
- boost::lexical_cast<std::basic_string<CharT> >(t));
- }
-
- template<typename CharT> basic_header<CharT>
- content_length(std::basic_string<CharT> const& str)
- {
- return basic_header<CharT>("Content-length", str);
- }
-
- template<typename CharT> basic_header<CharT>
- content_length(basic_response<CharT>& resp)
- {
- return basic_header<CharT>("Content-length",
- boost::lexical_cast<std::string>(resp.content_length()));
- }
-
- template<typename CharT> basic_header<CharT>
- location(const CharT* url)
- {
- return basic_header<CharT>("Location", url);
- }
-
- template<typename CharT> basic_header<CharT>
- location(std::basic_string<CharT> const& url)
- {
- return basic_header<CharT>("Location", url);
- }
-
- template<typename CharT, typename U> basic_header<CharT>
- location(U const& url)
- {
- return basic_header<CharT>("Location", url);
- }
- //}
-
- // typedefs for typical usage
- typedef basic_header<char> header;
- typedef basic_header<wchar_t> wheader;
+ //{ Some shortcuts, to cut down on typing errors.
+ template<typename CharT, typename StringT> basic_header<CharT>
+ content_type(StringT const& str)
+ {
+ return basic_header<CharT>("Content-type", str);
+ }
+
+ template<typename CharT> basic_header<CharT>
+ content_type(const CharT* str)
+ {
+ return basic_header<CharT>("Content-type", str);
+ }
+
+ template<typename CharT> basic_header<CharT>
+ content_encoding(std::basic_string<CharT> const& str)
+ {
+ return basic_header<CharT>("Content-encoding", str);
+ }
+
+ template<typename CharT, typename T> basic_header<CharT>
+ content_length(const T& t)
+ {
+ return basic_header<CharT>("Content-length",
+ boost::lexical_cast<std::basic_string<CharT> >(t));
+ }
+
+ template<typename CharT, typename T> basic_header<CharT>
+ content_length(T t)
+ {
+ return basic_header<CharT>("Content-length",
+ boost::lexical_cast<std::basic_string<CharT> >(t));
+ }
+
+ template<typename CharT> basic_header<CharT>
+ content_length(std::basic_string<CharT> const& str)
+ {
+ return basic_header<CharT>("Content-length", str);
+ }
+
+ template<typename CharT> basic_header<CharT>
+ content_length(basic_response<CharT>& resp)
+ {
+ return basic_header<CharT>("Content-length",
+ boost::lexical_cast<std::string>(resp.content_length()));
+ }
+
+ template<typename CharT> basic_header<CharT>
+ location(const CharT* url)
+ {
+ return basic_header<CharT>("Location", url);
+ }
+
+ template<typename CharT> basic_header<CharT>
+ location(std::basic_string<CharT> const& url)
+ {
+ return basic_header<CharT>("Location", url);
+ }
+
+ template<typename CharT, typename U> basic_header<CharT>
+ location(U const& url)
+ {
+ return basic_header<CharT>("Location", url);
+ }
+ //}
 
  } // namespace common
 } // namespace cgi

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/response.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/response.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/response.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -240,8 +240,8 @@
 
 #include "boost/cgi/detail/pop_options.hpp"
 
-#if !defined(BOOST_CGI_BUILD_LIB)
+//#if !defined(BOOST_CGI_BUILD_LIB)
 # include "boost/cgi/impl/response.ipp"
-#endif
+//#endif
 
 #endif // CGI_RESPONSE_HPP_INCLUDED__

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/common/source_enums.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/common/source_enums.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/common/source_enums.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -3,6 +3,8 @@
 #define BOOST_CGI_COMMON_SOURCE_ENUMS_HPP_INCLUDED__
 
 #include <boost/fusion/include/at.hpp>
+///////////////////////////////////////////////////////////
+#include "boost/cgi/common/map.hpp"
 
 namespace cgi {
  namespace common {

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/tcp_socket.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/tcp_socket.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/connections/tcp_socket.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -13,10 +13,10 @@
 #include <boost/asio/ip/tcp.hpp>
 ///////////////////////////////////////////////////////////
 #include "boost/cgi/common/tags.hpp"
-#include "boost/cgi/common/connection_base.hpp"
 #include "boost/cgi/basic_connection.hpp"
 #include "boost/cgi/import/io_service.hpp"
 #include "boost/cgi/detail/push_options.hpp"
+#include "boost/cgi/common/connection_base.hpp"
 
 namespace cgi {
  namespace common {

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/cgi_service_impl_base.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -94,8 +94,9 @@
 
     int request_id(implementation_type& impl) { return 1; }
 
+ // **FIXME** should return error_code
     int close(implementation_type& impl, common::http::status_code& http_s
- , int status)
+ , int status, boost::system::error_code& ec)
     {
       impl.status() = common::closed;
       impl.http_status() = http_s;
@@ -174,6 +175,15 @@
     {
     }
 
+ /// Read some data from the client.
+ template<typename MutableBufferSequence>
+ std::size_t
+ read_some(implementation_type& impl, const MutableBufferSequence& buf
+ , boost::system::error_code& ec)
+ {
+ return impl.client_.read_some(buf,ec);
+ }
+
   protected:
     /// Read and parse the cgi POST meta variables (greedily)
     template<typename RequestImpl>

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/common_headers.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/common_headers.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/common_headers.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -1,4 +1,4 @@
-// -- cgi.hpp --
+// -- common_headers.hpp --
 //
 // Copyright (c) Darren Garvey 2007.
 // Distributed under the Boost Software License, Version 1.0.
@@ -6,8 +6,8 @@
 // http://www.boost.org/LICENSE_1_0.txt)
 //
 ////////////////////////////////////////////////////////////////
-#ifndef CGI_CGI_CGI_HPP_INCLUDED__
-#define CGI_CGI_CGI_HPP_INCLUDED__
+#ifndef CGI_DETAIL_COMMON_HEADERS_HPP_INCLUDED__
+#define CGI_DETAIL_COMMON_HEADERS_HPP_INCLUDED__
 
 // #include all protocol-independent headers only. Protocol-specific
 // headers can just include this after other headers.
@@ -25,4 +25,5 @@
 #include "boost/cgi/http/status_code.hpp"
 #include "boost/cgi/import/io_service.hpp"
 
-#endif // CGI_CGI_CGI_HPP_INCLUDED__
+#endif // CGI_DETAIL_COMMON_HEADERS_HPP_INCLUDED__
+

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/protocol_traits.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/protocol_traits.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/protocol_traits.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -26,7 +26,18 @@
 namespace cgi {
 
   namespace cgi {}
- namespace acgi {}
+ namespace acgi
+ {
+ //class acgi_service;
+ class request_service;
+ class request_impl;
+ typedef common::basic_protocol_service<common::tags::acgi> service;
+ typedef
+ common::basic_request<
+ acgi::request_service, acgi::service
+ >
+ request;
+ }
   namespace fcgi
   {
   class fcgi_request_impl;
@@ -110,7 +121,7 @@
     {
       typedef protocol_traits<tags::async_cgi> type;
       typedef async_cgi_request_impl impl_type;
- typedef acgi_request_service request_service_impl;
+ typedef acgi::request_service request_service_impl;
       typedef common::basic_protocol_service<
                   tags::acgi
> protocol_service_type;
@@ -131,8 +142,8 @@
     // : protocol_traits<tags::async_cgi>
     {
       typedef protocol_traits<tags::acgi> type;
- typedef acgi_request_impl impl_type;
- typedef acgi_request_service request_service_impl;
+ typedef acgi::request_impl impl_type;
+ typedef acgi::request_service request_service_impl;
       typedef common::basic_protocol_service<
                   tags::acgi
> protocol_service_type;
@@ -140,7 +151,6 @@
                   request_service_impl
                 , protocol_service_type
> request_type;
- typedef acgi_service_impl service_impl_type;
       typedef common::basic_connection<
                   tags::async_stdio
> connection_type;

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/url_decode.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/url_decode.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/detail/url_decode.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -32,7 +32,9 @@
  } // namespace detail
 } // namespace cgi
 
-#include "boost/cgi/detail/url_decode.ipp"
+#if !defined( BOOST_CGI_BUILD_LIB )
+# include "boost/cgi/detail/url_decode.ipp"
+#endif
 
 #include "boost/cgi/detail/pop_options.hpp"
 

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/acceptor_service_impl.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/acceptor_service_impl.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/acceptor_service_impl.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -310,6 +310,26 @@
        return acceptor_service_.local_endpoint(impl.acceptor_, ec);
      }
 
+ native_type
+ native(implementation_type& impl)
+ {
+ return acceptor_service_.native(impl.acceptor_);
+ }
+
+ bool
+ is_cgi(implementation_type& impl)
+ {
+ boost::system::error_code ec;
+#if ! defined(BOOST_WINDOWS)
+ socklen_t len
+ = static_cast<socklen_t>(local_endpoint(impl,ec).capacity());
+ int ret = getpeername(native(impl), local_endpoint(impl,ec).data(), &len);
+ return ( ret != 0 && errno == ENOTCONN ) ? false : true;
+#else
+ return false;
+#endif
+ }
+
    public:
      template<typename CommonGatewayRequest, typename Handler>
      void check_for_waiting_request(implementation_type& impl

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_acceptor_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_acceptor_service.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_acceptor_service.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -38,7 +38,8 @@
 
     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
+ 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;
@@ -162,6 +163,17 @@
       return service_impl_.assign(impl, protocol, native_acceptor, ec);
     }
 
+ service_impl_type::native_type
+ native(implementation_type& impl)
+ {
+ return service_impl_.native(impl);
+ }
+
+ bool
+ is_cgi(implementation_type& impl)
+ {
+ return service_impl_.is_cgi(impl);
+ }
   public:
     service_impl_type service_impl_;
   };

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/fcgi/request_service.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -27,36 +27,7 @@
 #include "boost/cgi/common/form_parser.hpp"
 
 namespace cgi {
-
- namespace detail {
-
- template<typename T, typename Handler>
- struct async_load_helper
- {
- async_load_helper(T& t, typename T::implementation_type& impl
- , bool parse_stdin, Handler h)
- : type(t)
- , impl_(impl)
- , parse_stdin_(parse_stdin)
- , handler_(h)
- {
- }
-
- void operator()()
- {
- boost::system::error_code ec;
- type.load(impl_, parse_stdin_, ec);
- handler_(ec);
- }
-
- T& type;
- typename T::implementation_type& impl_;
- bool parse_stdin_;
- Handler handler_;
- };
- }
-
- namespace fcgi {
+ namespace fcgi {
  
   /// The IoObjectService class for a FCGI basic_request<>s
   class fcgi_request_service
@@ -169,44 +140,13 @@
 
     /// Close the request.
     int close(implementation_type& impl, ::cgi::common::http::status_code& hsc
- , int program_status)
- {
- impl.all_done_ = true;
- impl.client_.close(program_status);
- return program_status;
- }
+ , int program_status);
 
     int close(implementation_type& impl, ::cgi::common::http::status_code& hsc
- , int program_status, boost::system::error_code& ec)
- {
- impl.all_done_ = true;
- impl.client_.close(program_status, ec);
- return program_status;
- }
+ , int program_status, boost::system::error_code& ec);
 
- void clear(implementation_type& impl)
- {
- BOOST_ASSERT
- ( impl.request_status_ < common::activated
- && impl.request_status_ > common::ok
- && "Are you trying to clear() a request without closing it?"
- );
-
- impl.buffer_.clear();
- common::get_vars(impl.vars_).clear();
- common::post_vars(impl.vars_).clear();
- common::cookie_vars(impl.vars_).clear();
- common::env_vars(impl.vars_).clear();
- impl.stdin_parsed_ = false;
- impl.http_status_ = common::http::no_content;
- impl.request_status_ = common::null;
- impl.request_role_ = spec_detail::ANY;
- impl.all_done_ = false;
+ void clear(implementation_type& impl);
 
- impl.client_.status_ = common::none_;
- impl.client_.request_id_ = -1;
- }
-
     /// Load the request to a point where it can be usefully used.
     /**
      * FastCGI:
@@ -219,75 +159,11 @@
      */
     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) );
- BOOST_ASSERT(!ec && "Can't load request due to previous errors.");
-
- impl.client_.construct(impl, ec);
- BOOST_ASSERT(impl.client_.connection_->is_open());
-
- for(;;)
- {
- if (read_header(impl, ec))
- break;
- int id(fcgi::spec::get_request_id(impl.header_buf_));
- if (id == fcgi::spec::null_request_id::value)
- handle_admin_request(impl);
- else
- if (fcgi::spec::get_type(impl.header_buf_)
- == fcgi::spec::begin_request::value)
- {
- impl.id_ = id;
- impl.client_.request_id_ = id;
- if (read_header(impl, ec))
- break;
- impl.request_role_ = fcgi::spec::begin_request::get_role(impl.header_buf_);
- //std::cerr<< "[hw] New request role: " << impl.request_role_
- // << " (" << fcgi::spec::role_type::to_string(impl.header_buf_) << ")"
- // << std::endl;
- impl.client_.keep_connection_
- = fcgi::spec::begin_request::get_flags(impl.header_buf_)
- & fcgi::spec::keep_connection;
- //std::cerr<< "keep connection := " << impl.client_.keep_connection_ << std::endl;
- break;
- }else
- handle_other_request_header(impl);
- }
-
- common::client_status completion_condition
- = parse_stdin ? common::stdin_read : common::params_read;
-
- while(!ec
- && impl.client_.status() < completion_condition
- && impl.request_status_ != common::loaded)
- {
- //impl.client_.parse_packet(impl, ec);
- parse_packet(impl, ec);
- }
-
- const std::string& request_method = env_vars(impl.vars_)["REQUEST_METHOD"];
- 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);
-
- return ec;
- }
+ , boost::system::error_code& ec);
 
     // **FIXME**
     template<typename Handler>
- void async_load(implementation_type& impl, bool parse_stdin, Handler handler)
- {
- this->io_service().post(
- detail::async_load_helper<type, Handler>(this, parse_stdin, handler)
- );
- }
+ void async_load(implementation_type& impl, bool parse_stdin, Handler handler);
 
     role_type get_role(implementation_type& impl)
     {
@@ -303,32 +179,12 @@
   protected:
     /// Read and parse the cgi POST meta variables (greedily)
     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"
-/*
- impl.fp_.reset
- (
- new typename implementation_type::form_parser_type
- ( impl )
- );
- impl.fp_->parse(ec);
-*/
-
- return ec;
- }
+ parse_post_vars(implementation_type& impl, boost::system::error_code& 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;
- }
+ parse_one_post_var(implementation_type& impl, boost::system::error_code& ec);
 
   /***************************************************************************/
   public: // Reading stuff goes under here
@@ -338,65 +194,20 @@
     template<typename MutableBufferSequence>
     std::size_t
       read_some(implementation_type& impl, const MutableBufferSequence& buf
- , boost::system::error_code& ec)
- {
- if (impl.client_.status_ == common::closed_)
- {
- ec = error::client_closed;
- return 0;
- }
-
- //if (read_header(ec))
- return -1;
-
- //boost::tribool state = parse_header(impl);
- //std::size_t bytes_read;//( connection_->read_some(buf, ec) );
- //return bytes_read;
- }
-
+ , boost::system::error_code& ec);
+
     /// Read a single header, buf do nothing with it.
     boost::system::error_code
- read_header(implementation_type& impl, boost::system::error_code& ec)
- {
- // clear the header first (might be unneccesary).
- impl.header_buf_ = implementation_type::header_buffer_type();
-
- if (8 != read(*impl.client_.connection_, buffer(impl.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(impl.header_buf_) << std::endl
- << " FastCGI version := " << fcgi::spec::get_version(impl.header_buf_) << std::endl
- << " Type := " << fcgi::spec::get_type(impl.header_buf_)
- << " (" << fcgi::spec::request_type::to_string(impl.header_buf_) << ")" << std::endl
- << " Content-length := " << fcgi::spec::get_content_length(impl.header_buf_) << std::endl
- << "}" << std::endl;
- */
-
- return ec;
- }
+ read_header(implementation_type& impl, boost::system::error_code& ec);
 
     /*** Various handlers go below here; they might find a
      * better place to live ***/
 
     // **FIXME**
- void handle_admin_request(implementation_type& impl)
- {
- //std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__
- // << " handle_admin_request()" << std::endl;
- }
+ void handle_admin_request(implementation_type& impl);
 
     // **FIXME**
- void handle_other_request_header(implementation_type& impl)
- {
- //std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__
- // << " handle_other_request_header()" << std::endl;
- }
+ void handle_other_request_header(implementation_type& impl);
 
     // **FIXME**
     boost::system::error_code
@@ -407,140 +218,21 @@
     boost::system::error_code
       process_abort_request(implementation_type& impl, boost::uint16_t id
                            , const unsigned char* buf, boost::uint16_t
- , boost::system::error_code& ec)
- {
- if (id == fcgi::spec::get_request_id(impl.header_buf_))
- {
- impl.request_status_ = common::aborted;
- return ec;
- }
- try {
- //std::cerr<< "**FIXME** request aborted (id = " << id
- // << ") but request not notified." << std::endl;
- //impl.client_.connection_->requests_.at(id - 1)->abort();
- }catch(...){
- ec = error::abort_request_record_recieved_for_invalid_request;
- }
-/*
- 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& ec);
 
     boost::system::error_code
       process_params(implementation_type& impl, 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.
-
- impl.client_.status_ = common::params_read;
-
- //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;
-
- // **FIXME**
- env_vars(impl.vars_)[name.c_str()] = data;
- }
-
- return ec;
- }
-
+ , boost::system::error_code& ec);
 
     boost::system::error_code
       process_stdin(implementation_type& impl, boost::uint16_t id
                    , const unsigned char* buf, boost::uint16_t len
- , boost::system::error_code& ec)
- {
- if (0 == len)
- {
- impl.client_.status_ = common::stdin_read;
-
- // **FIXME**
- //std::cerr<< "[hw] Final STDIN record found." << std::endl;
- return ec;
- }
-
- // **FIXME**
- //std::cerr<< "[hw] Found some STDIN stuff." << std::endl;
- return ec;
- }
+ , boost::system::error_code& ec);
 
     /// Parse the current header
- boost::tribool parse_header(implementation_type& impl)
- {
- BOOST_ASSERT(fcgi::spec::get_version(impl.header_buf_) == 1
- && "This library is only compatible with FastCGI 1.0");
+ boost::tribool parse_header(implementation_type& impl);
 
- using namespace fcgi::spec_detail;
-
- switch(fcgi::spec::get_type(impl.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;
- }
- }
-
     // Mammoth typedef corresponding to function signature of process_*
     // functions.
     typedef boost::system::error_code
@@ -551,175 +243,34 @@
     static const proc_func_t proc_funcs[];
   
     boost::system::error_code
- parse_packet(implementation_type& impl, boost::system::error_code& ec)
- {
- //current_request_ = &req;
-
- if (this->read_header(impl, ec))
- return ec;
-
- boost::tribool state = this->parse_header(impl);
-
- 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.
- return error::bad_header_type;
- }
- // else route (ie. state == boost::indeterminate)
-
- implementation_type::mutable_buffers_type buf
- = impl.prepare(fcgi::spec::get_length(impl.header_buf_));
-
- if (this->read_body(impl, buf, ec))
- return ec;
-
- this->parse_body(impl, buf, ec);
-
- return ec;
- }
-
+ parse_packet(implementation_type& impl, boost::system::error_code& ec);
+
     /// Read the body of the current packet; do nothing with it.
     template<typename MutableBuffersType>
     boost::system::error_code
       read_body(implementation_type& impl, const MutableBuffersType& buffer
- , boost::system::error_code& ec)
- {
- std::size_t bytes_read
- = read(*impl.client_.connection_, buffer, boost::asio::transfer_all(), ec);
-
- BOOST_ASSERT(bytes_read == fcgi::spec::get_length(impl.header_buf_)
- && "Couldn't read all of the record body.");
- return ec;
- }
+ , boost::system::error_code& ec);
 
     template<typename MutableBuffersType>
     boost::system::error_code
       parse_body(implementation_type& impl, const MutableBuffersType& buffer
- , boost::system::error_code& ec)
- {
- return
- (this->* proc_funcs[fcgi::spec::get_type(impl.header_buf_)])
- (impl, fcgi::spec::get_request_id(impl.header_buf_)
- , boost::asio::buffer_cast<unsigned char*>(buffer)
- , boost::asio::buffer_size(buffer), ec);
- }
-
+ , boost::system::error_code& ec);
 
     boost::system::error_code
       begin_request_helper(implementation_type& impl
                           , implementation_type::header_buffer_type& header
- , boost::system::error_code& ec)
- {
- impl.client_.request_id_ = fcgi::spec::get_request_id(header);
-
- BOOST_STATIC_ASSERT((
- fcgi::spec::begin_request::body::size::value
- == fcgi::spec::header_length::value));
-
- // A begin request body is as long as a header, so we can optimise:
- if (read_header(impl, ec))
- return ec;
-
- impl.request_role_
- = fcgi::spec::begin_request::get_role(impl.header_buf_);
- // **FIXME** (rm impl.request_role_)
- impl.client_.role_ = impl.request_role_;
- impl.client_.keep_connection_
- = fcgi::spec::begin_request::get_flags(impl.header_buf_)
- & fcgi::spec::keep_connection;
- impl.client_.status_ = common::constructed;
-
- return ec;
- }
+ , boost::system::error_code& ec);
   };
 
- //template<>
- const fcgi_request_service::proc_func_t fcgi_request_service::proc_funcs[] =
- { 0
- , &fcgi_request_service::process_begin_request
- , &fcgi_request_service::process_abort_request
- , 0
- , &fcgi_request_service::process_params
- , &fcgi_request_service::process_stdin
- , 0
- , 0
- };
-
  } // namespace fcgi
 } // namespace cgi
 
 #include "boost/cgi/fcgi/request.hpp"
 #include "boost/cgi/basic_request.hpp"
 
-namespace cgi {
- namespace fcgi {
-
- namespace fdetail {
- typedef fcgi_request_service service_type;
- typedef service_type::implementation_type impl_type;
- typedef impl_type::request_type request_type;
- } // namespace detail
-
-/*
- fdetail::request_type&
- get_or_make_request(fdetail::impl_type& impl, boost::uint16_t id)
- {
- fdetail::impl_type::client_type::connection_type::request_vector_type&
- requests = impl.client_.connection_->requests_;
-
- if (!requests.at(id-1))
- {
- if (requests.size() < (id-1))
- requests.resize(id);
- requests.at(id-1) = fdetail::request_type::create(*impl.service_);
- }
-
- return *requests.at(id-1);
- }
-*/
-
- boost::system::error_code
- fdetail::service_type::process_begin_request
- (
- fdetail::impl_type& impl, boost::uint16_t id, const unsigned char* buf
- , boost::uint16_t, boost::system::error_code& ec
- )
- {
- if (impl.client_.request_id_ == 0) // ie. hasn't been set yet.
- {
- begin_request_helper(impl, impl.header_buf_, ec);
- }
- else
- {
- //std::cerr<< "**FIXME** Role: "
- // << fcgi::spec::begin_request::get_role(impl.header_buf_) << std::endl;
-
- fdetail::impl_type::client_type::connection_type&
- conn = *impl.client_.connection_;
-
- if (conn.get_slot(id, ec))
- { // error
- return ec;
- }
-
- // **FIXME** THIS LEAKS MEMORY!!!!!!!
- //requests.at(id-1)
- request_type* new_request = new request_type(impl, ec);
-
- conn.add_request(id, new_request, true, ec);
-
- return ec;//error::multiplexed_request_incoming;
- }
-
- return ec;
- }
-
-
- } // namespace fcgi
-} // namespace cgi
+#if !defined( BOOST_CGI_BUILD_LIB )
+# include "boost/cgi/impl/fcgi_request_service.ipp"
+#endif
 
 #endif // CGI_FCGI_REQUEST_SERVICE_HPP_INCLUDED__
 

Added: sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/fcgi_request_service.ipp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -0,0 +1,663 @@
+// -- fcgi/request_service.ipp --
+//
+// 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_IPP_INCLUDED__
+#define CGI_FCGI_REQUEST_SERVICE_IPP_INCLUDED__
+
+#include <boost/fusion/support.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/mem_fn.hpp>
+////////////////////////////////////////////////////////////////
+#include "boost/cgi/common/map.hpp"
+#include "boost/cgi/common/tags.hpp"
+#include "boost/cgi/fcgi/client.hpp"
+#include "boost/cgi/import/read.hpp"
+#include "boost/cgi/http/status_code.hpp"
+#include "boost/cgi/common/role_type.hpp"
+#include "boost/cgi/import/io_service.hpp"
+#include "boost/cgi/detail/throw_error.hpp"
+#include "boost/cgi/common/source_enums.hpp"
+#include "boost/cgi/common/request_base.hpp"
+#include "boost/cgi/detail/service_base.hpp"
+#include "boost/cgi/common/form_parser.hpp"
+#include "boost/cgi/fcgi/request_service.hpp"
+
+namespace cgi {
+
+ namespace detail {
+
+ template<typename T, typename Handler>
+ struct async_load_helper
+ {
+ async_load_helper(T& t, typename T::implementation_type& impl
+ , bool parse_stdin, Handler h)
+ : type(t)
+ , impl_(impl)
+ , parse_stdin_(parse_stdin)
+ , handler_(h)
+ {
+ }
+
+ void operator()()
+ {
+ boost::system::error_code ec;
+ type.load(impl_, parse_stdin_, ec);
+ handler_(ec);
+ }
+
+ T& type;
+ typename T::implementation_type& impl_;
+ bool parse_stdin_;
+ Handler handler_;
+ };
+
+ } // namespace detail
+
+ namespace fcgi {
+
+ /// Close the request.
+ BOOST_CGI_INLINE int
+ fcgi_request_service::close(
+ implementation_type& impl, ::cgi::common::http::status_code& hsc
+ , int program_status)
+ {
+ impl.all_done_ = true;
+ impl.client_.close(program_status);
+ return program_status;
+ }
+
+ BOOST_CGI_INLINE int
+ fcgi_request_service::close(
+ implementation_type& impl, ::cgi::common::http::status_code& hsc
+ , int program_status, boost::system::error_code& ec)
+ {
+ impl.all_done_ = true;
+ impl.client_.close(program_status, ec);
+ return program_status;
+ }
+
+ BOOST_CGI_INLINE void
+ fcgi_request_service::clear(implementation_type& impl)
+ {
+ BOOST_ASSERT
+ ( impl.request_status_ < common::activated
+ && impl.request_status_ > common::ok
+ && "Are you trying to clear() a request without closing it?"
+ );
+
+ impl.buffer_.clear();
+ common::get_vars(impl.vars_).clear();
+ common::post_vars(impl.vars_).clear();
+ common::cookie_vars(impl.vars_).clear();
+ common::env_vars(impl.vars_).clear();
+ impl.stdin_parsed_ = false;
+ impl.http_status_ = common::http::no_content;
+ impl.request_status_ = common::null;
+ impl.request_role_ = spec_detail::ANY;
+ impl.all_done_ = false;
+
+ impl.client_.status_ = common::none_;
+ impl.client_.request_id_ = -1;
+ }
+
+ /// 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_CGI_INLINE boost::system::error_code&
+ fcgi_request_service::load(
+ implementation_type& impl, bool parse_stdin
+ , boost::system::error_code& ec)
+ {
+ //int header_len( get_length_of_header(impl, ec) );
+ BOOST_ASSERT(!ec && "Can't load request due to previous errors.");
+
+ impl.client_.construct(impl, ec);
+ BOOST_ASSERT(impl.client_.connection_->is_open());
+
+ for(;;)
+ {
+ if (read_header(impl, ec))
+ break;
+ int id(fcgi::spec::get_request_id(impl.header_buf_));
+ if (id == fcgi::spec::null_request_id::value)
+ handle_admin_request(impl);
+ else
+ if (fcgi::spec::get_type(impl.header_buf_)
+ == fcgi::spec::begin_request::value)
+ {
+ impl.id_ = id;
+ impl.client_.request_id_ = id;
+ if (read_header(impl, ec))
+ break;
+ impl.request_role_ = fcgi::spec::begin_request::get_role(impl.header_buf_);
+ //std::cerr<< "[hw] New request role: " << impl.request_role_
+ // << " (" << fcgi::spec::role_type::to_string(impl.header_buf_) << ")"
+ // << std::endl;
+ impl.client_.keep_connection_
+ = fcgi::spec::begin_request::get_flags(impl.header_buf_)
+ & fcgi::spec::keep_connection;
+ //std::cerr<< "keep connection := " << impl.client_.keep_connection_ << std::endl;
+ break;
+ }else
+ handle_other_request_header(impl);
+ }
+
+ common::client_status completion_condition
+ = parse_stdin ? common::stdin_read : common::params_read;
+
+ while(!ec
+ && impl.client_.status() < completion_condition
+ && impl.request_status_ != common::loaded)
+ {
+ //impl.client_.parse_packet(impl, ec);
+ parse_packet(impl, ec);
+ }
+
+ const std::string& request_method = env_vars(impl.vars_)["REQUEST_METHOD"];
+ 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);
+
+ return ec;
+ }
+
+ // **FIXME**
+ template<typename Handler> BOOST_CGI_INLINE
+ void fcgi_request_service::async_load(
+ implementation_type& impl, bool parse_stdin, Handler handler)
+ {
+ this->io_service().post(
+ detail::async_load_helper<type, Handler>(this, parse_stdin, handler)
+ );
+ }
+
+ /// Read and parse the cgi POST meta variables (greedily)
+ BOOST_CGI_INLINE boost::system::error_code&
+ fcgi_request_service::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"
+ // **FIXME** should use form_parser, when it's ready.
+ // Only works with url-encoded forms (ie. not with multipart forms)
+ std::string name;
+ std::string str;
+
+ char ch;
+ char ch1;
+ while( impl.client_.bytes_left_ )
+ {
+ ch = getchar();
+ --impl.client_.bytes_left_;
+
+ switch(ch)
+ {
+ case '%': // unencode a hex character sequence
+ if (impl.client_.bytes_left_ >= 2)
+ {
+ ch = getchar();
+ ch1 = getchar();
+ if (std::isxdigit(ch) && std::isxdigit(ch1))
+ {
+ str.append(1, detail::hex_to_char(ch, ch1));
+ }
+ else // we don't have a hex sequence
+ {
+ str.append(1, '%').append(1, ch).append(1, ch1);
+ }
+ impl.client_.bytes_left_ -= 2;
+ }
+ else // There aren't enough characters to make a hex sequence
+ {
+ str.append(1, '%');
+ --impl.client_.bytes_left_;
+ }
+ break;
+ case '+':
+ str.append(1, ' ');
+ break;
+ case ' ': // skip spaces
+ break;
+ case '=': // the name is complete, now get the corresponding value
+ name.swap(str);
+ break;
+ case '&': // we now have the name/value pair, so save it
+ // **FIXME** have to have .c_str() ?
+ ::cgi::common::post_vars(impl.vars_)[name.c_str()] = str;
+ str.clear();
+ name.clear();
+ break;
+ default:
+ str.append(1, ch);
+ }
+ }
+ // save the last param (it won't have a trailing &)
+ if( !name.empty() )
+ // **FIXME** have to have .c_str() ?
+ ::cgi::common::post_vars(impl.vars_)[name.c_str()] = str;
+
+ /*
+ impl.fp_.reset
+ (
+ new implementation_type::form_parser_type
+ ( impl, boost::mem_fn(&fcgi_request_service::read_some<boost::asio::mutable_buffer>) )
+ );
+ impl.fp_->parse(ec);
+ */
+
+ return ec;
+ }
+
+ /// Read and parse a single cgi POST meta variable (greedily)
+ template<typename RequestImpl> BOOST_CGI_INLINE
+ boost::system::error_code&
+ fcgi_request_service::parse_one_post_var(
+ implementation_type& impl, boost::system::error_code& ec)
+ {
+ //# error "Not implemented"
+ return ec;
+ }
+
+ // **FIXME**
+ /// Read some data from the client.
+ template<typename MutableBufferSequence>
+ BOOST_CGI_INLINE std::size_t
+ fcgi_request_service::read_some(
+ implementation_type& impl, const MutableBufferSequence& buf
+ , boost::system::error_code& ec)
+ {
+ if (impl.client_.status_ == common::closed_)
+ {
+ ec = error::client_closed;
+ return 0;
+ }
+
+ //if (read_header(ec))
+ return -1;
+
+ //boost::tribool state = parse_header(impl);
+ //std::size_t bytes_read;//( connection_->read_some(buf, ec) );
+ //return bytes_read;
+ }
+
+ /// Read a single header, buf do nothing with it.
+ BOOST_CGI_INLINE boost::system::error_code
+ fcgi_request_service::read_header(
+ implementation_type& impl
+ , boost::system::error_code& ec)
+ {
+ // clear the header first (might be unneccesary).
+ impl.header_buf_ = implementation_type::header_buffer_type();
+
+ if (8 != read(*impl.client_.connection_, buffer(impl.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(impl.header_buf_) << std::endl
+ << " FastCGI version := " << fcgi::spec::get_version(impl.header_buf_) << std::endl
+ << " Type := " << fcgi::spec::get_type(impl.header_buf_)
+ << " (" << fcgi::spec::request_type::to_string(impl.header_buf_) << ")" << std::endl
+ << " Content-length := " << fcgi::spec::get_content_length(impl.header_buf_) << std::endl
+ << "}" << std::endl;
+ */
+
+ return ec;
+ }
+
+ /*** Various handlers go below here; they might find a
+ * better place to live ***/
+
+ // **FIXME**
+ BOOST_CGI_INLINE void
+ fcgi_request_service::handle_admin_request(implementation_type& impl)
+ {
+ //std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__
+ // << " handle_admin_request()" << std::endl;
+ }
+
+ // **FIXME**
+ BOOST_CGI_INLINE void
+ fcgi_request_service::handle_other_request_header(implementation_type& impl)
+ {
+ //std::cerr<< std::endl << "**FIXME** " << __FILE__ << ":" << __LINE__
+ // << " handle_other_request_header()" << std::endl;
+ }
+
+ BOOST_CGI_INLINE boost::system::error_code
+ fcgi_request_service::process_abort_request(
+ implementation_type& impl, boost::uint16_t id
+ , const unsigned char* buf, boost::uint16_t
+ , boost::system::error_code& ec)
+ {
+ if (id == fcgi::spec::get_request_id(impl.header_buf_))
+ {
+ impl.request_status_ = common::aborted;
+ return ec;
+ }
+ try {
+ //std::cerr<< "**FIXME** request aborted (id = " << id
+ // << ") but request not notified." << std::endl;
+ //impl.client_.connection_->requests_.at(id - 1)->abort();
+ }catch(...){
+ ec = error::abort_request_record_recieved_for_invalid_request;
+ }
+/*
+ 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_CGI_INLINE boost::system::error_code
+ fcgi_request_service::process_params(
+ implementation_type& impl, 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.
+
+ impl.client_.status_ = common::params_read;
+
+ //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;
+
+ // **FIXME**
+ env_vars(impl.vars_)[name.c_str()] = data;
+ }
+
+ return ec;
+ }
+
+
+ BOOST_CGI_INLINE boost::system::error_code
+ fcgi_request_service::process_stdin(
+ implementation_type& impl, boost::uint16_t id
+ , const unsigned char* buf, boost::uint16_t len
+ , boost::system::error_code& ec)
+ {
+ if (0 == len)
+ {
+ impl.client_.status_ = common::stdin_read;
+
+ // **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_CGI_INLINE boost::tribool
+ fcgi_request_service::parse_header(implementation_type& impl)
+ {
+ BOOST_ASSERT(fcgi::spec::get_version(impl.header_buf_) == 1
+ && "This library is only compatible with FastCGI 1.0");
+
+ using namespace fcgi::spec_detail;
+
+ switch(fcgi::spec::get_type(impl.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;
+ }
+ }
+
+ BOOST_CGI_INLINE boost::system::error_code
+ fcgi_request_service::parse_packet(
+ implementation_type& impl, boost::system::error_code& ec)
+ {
+ //current_request_ = &req;
+
+ if (this->read_header(impl, ec))
+ return ec;
+
+ boost::tribool state = this->parse_header(impl);
+
+ 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.
+ return error::bad_header_type;
+ }
+ // else route (ie. state == boost::indeterminate)
+
+ implementation_type::mutable_buffers_type buf
+ = impl.prepare(fcgi::spec::get_length(impl.header_buf_));
+
+ if (this->read_body(impl, buf, ec))
+ return ec;
+
+ this->parse_body(impl, buf, ec);
+
+ return ec;
+ }
+
+ /// Read the body of the current packet; do nothing with it.
+ template<typename MutableBuffersType> BOOST_CGI_INLINE
+ boost::system::error_code
+ fcgi_request_service::read_body(
+ implementation_type& impl, const MutableBuffersType& buffer
+ , boost::system::error_code& ec)
+ {
+ std::size_t bytes_read
+ = read(*impl.client_.connection_, buffer, boost::asio::transfer_all(), ec);
+
+ BOOST_ASSERT(bytes_read == fcgi::spec::get_length(impl.header_buf_)
+ && "Couldn't read all of the record body.");
+ return ec;
+ }
+
+ template<typename MutableBuffersType> BOOST_CGI_INLINE
+ boost::system::error_code
+ fcgi_request_service::parse_body(
+ implementation_type& impl, const MutableBuffersType& buffer
+ , boost::system::error_code& ec)
+ {
+ return
+ (this->* proc_funcs[fcgi::spec::get_type(impl.header_buf_)])
+ (impl, fcgi::spec::get_request_id(impl.header_buf_)
+ , boost::asio::buffer_cast<unsigned char*>(buffer)
+ , boost::asio::buffer_size(buffer), ec);
+ }
+
+
+ BOOST_CGI_INLINE boost::system::error_code
+ fcgi_request_service::begin_request_helper(
+ implementation_type& impl
+ , implementation_type::header_buffer_type& header
+ , boost::system::error_code& ec)
+ {
+ impl.client_.request_id_ = fcgi::spec::get_request_id(header);
+
+ BOOST_STATIC_ASSERT((
+ fcgi::spec::begin_request::body::size::value
+ == fcgi::spec::header_length::value));
+
+ // A begin request body is as long as a header, so we can optimise:
+ if (read_header(impl, ec))
+ return ec;
+
+ impl.request_role_
+ = fcgi::spec::begin_request::get_role(impl.header_buf_);
+ // **FIXME** (rm impl.request_role_)
+ impl.client_.role_ = impl.request_role_;
+ impl.client_.keep_connection_
+ = fcgi::spec::begin_request::get_flags(impl.header_buf_)
+ & fcgi::spec::keep_connection;
+ impl.client_.status_ = common::constructed;
+
+ return ec;
+ }
+
+ //template<>
+ const fcgi_request_service::proc_func_t fcgi_request_service::proc_funcs[] =
+ { 0
+ , &fcgi_request_service::process_begin_request
+ , &fcgi_request_service::process_abort_request
+ , 0
+ , &fcgi_request_service::process_params
+ , &fcgi_request_service::process_stdin
+ , 0
+ , 0
+ };
+
+ } // namespace fcgi
+} // namespace cgi
+
+#include "boost/cgi/fcgi/request.hpp"
+#include "boost/cgi/basic_request.hpp"
+
+namespace cgi {
+ namespace fcgi {
+
+/*
+ fdetail::request_type&
+ get_or_make_request(implementation_type& impl, boost::uint16_t id)
+ {
+ implementation_type::client_type::connection_type::request_vector_type&
+ requests = impl.client_.connection_->requests_;
+
+ if (!requests.at(id-1))
+ {
+ if (requests.size() < (id-1))
+ requests.resize(id);
+ requests.at(id-1) = fdetail::request_type::create(*impl.service_);
+ }
+
+ return *requests.at(id-1);
+ }
+*/
+
+ BOOST_CGI_INLINE boost::system::error_code
+ fcgi_request_service::process_begin_request(
+ implementation_type& impl, boost::uint16_t id
+ , const unsigned char* buf, boost::uint16_t
+ , boost::system::error_code& ec)
+ {
+ if (impl.client_.request_id_ == 0) // ie. hasn't been set yet.
+ {
+ begin_request_helper(impl, impl.header_buf_, ec);
+ }
+ else
+ {
+ //std::cerr<< "**FIXME** Role: "
+ // << fcgi::spec::begin_request::get_role(impl.header_buf_) << std::endl;
+
+ implementation_type::client_type::connection_type&
+ conn = *impl.client_.connection_;
+
+ if (conn.get_slot(id, ec))
+ { // error
+ return ec;
+ }
+
+ // **FIXME** THIS LEAKS MEMORY!!!!!!!
+ //requests.at(id-1)
+ request_type* new_request = new request_type(impl, ec);
+
+ conn.add_request(id, new_request, true, ec);
+
+ return ec;//error::multiplexed_request_incoming;
+ }
+
+ return ec;
+ }
+
+
+ } // namespace fcgi
+} // namespace cgi
+
+#endif // CGI_FCGI_REQUEST_SERVICE_IPP_INCLUDED__
+

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/form_parser.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/form_parser.ipp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/form_parser.ipp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -17,19 +17,32 @@
 namespace cgi {
  namespace detail {
 
- template<typename T>
- form_parser<T>::form_parser
- (
- implementation_type& impl
+ template<typename T> BOOST_CGI_INLINE
+ form_parser<T>::form_parser (
+ implementation_type& impl
     )
       : impl_(impl)
       , bytes_left_(impl.client_.bytes_left_)
       //, stdin_data_read_(impl.stdin_data_read_)
       , offset_(0)
+ , callback_(NULL)
     {
     }
 
- template<typename T>
+ template<typename T> BOOST_CGI_INLINE
+ form_parser<T>::form_parser (
+ implementation_type& impl
+ , callback_type const& callback
+ )
+ : impl_(impl)
+ , bytes_left_(impl.client_.bytes_left_)
+ //, stdin_data_read_(impl.stdin_data_read_)
+ , offset_(0)
+ , callback_(callback)
+ {
+ }
+
+ template<typename T> BOOST_CGI_INLINE
     boost::system::error_code
       form_parser<T>::parse(boost::system::error_code& ec)
     {
@@ -54,7 +67,7 @@
       return ec;
     }
 
- template<typename T>
+ template<typename T> BOOST_CGI_INLINE
     boost::system::error_code
       form_parser<T>::parse_url_encoded_form(boost::system::error_code& ec)
     {
@@ -118,7 +131,7 @@
     }
 
     /// Parse a multipart form.
- template<typename T>
+ template<typename T> BOOST_CGI_INLINE
     boost::system::error_code
       form_parser<T>::parse_multipart_form(boost::system::error_code& ec)
     {
@@ -139,7 +152,7 @@
     }
 
 
- template<typename T>
+ template<typename T> BOOST_CGI_INLINE
     boost::system::error_code
       form_parser<T>::parse_form_part(boost::system::error_code& ec)
     {
@@ -150,7 +163,7 @@
       return ec;
     }
 
- template<typename T>
+ template<typename T> BOOST_CGI_INLINE
     boost::system::error_code
       form_parser<T>::parse_form_part_data(boost::system::error_code& ec)
     {
@@ -216,7 +229,9 @@
           }
           else
           {
- std::size_t bytes_read = impl_.client_.read_some(prepare(64), ec);
+ std::size_t bytes_read
+ = //callback_(prepare(64), ec);
+ impl_.client_.read_some(prepare(64), ec);
 
             if (bytes_read == 0 && impl_.client_.bytes_left_ == 0) // **FIXME**
             {
@@ -236,7 +251,7 @@
       return ec;
     }
 
- template<typename T>
+ template<typename T> BOOST_CGI_INLINE
     boost::system::error_code
       form_parser<T>::parse_form_part_meta_data(boost::system::error_code& ec)
     {
@@ -342,7 +357,9 @@
          }
 
         }else{
- bytes_read = impl_.client_.read_some(prepare(64), ec);
+ bytes_read
+ = //callback_(prepare(64), ec);
+ impl_.client_.read_some(prepare(64), ec);
           if (ec)
             return ec;
           if (++runs > 40)
@@ -356,7 +373,7 @@
       return ec;
     }
 
- template<typename T>
+ template<typename T> BOOST_CGI_INLINE
     boost::system::error_code
       form_parser<T>::move_to_start_of_first_part(boost::system::error_code& ec)
     {
@@ -381,7 +398,10 @@
       std::size_t bytes_read = 0;
       for(;;)
       {
- bytes_read = impl_.client_.read_some(prepare(32), ec);
+ bytes_read
+ = //callback_(prepare(32), ec);
+ impl_.client_.read_some(prepare(32), ec);
+
         if (ec || (bytes_read == 0))
           return ec;
         buffer_iter begin(impl_.buffer_.begin());// + offset);
@@ -413,7 +433,7 @@
       return ec;
     }
 
- template<typename T>
+ template<typename T> BOOST_CGI_INLINE
     boost::system::error_code
       form_parser<T>::parse_boundary_marker(boost::system::error_code& ec)
     {

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/response.ipp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/response.ipp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/impl/response.ipp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -402,7 +402,7 @@
    */
   template<typename T> BOOST_CGI_INLINE
   cgi::common::basic_response<T>&
- operator<< (cgi::common::basic_response<T>& resp
+ operator<< (cgi::common::basic_response<T> const& resp
                , cgi::common::basic_cookie<T> ck)
   {
     BOOST_ASSERT(!resp.headers_terminated());

Modified: sandbox/SOC/2007/cgi/trunk/boost/cgi/import/streambuf.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/boost/cgi/import/streambuf.hpp (original)
+++ sandbox/SOC/2007/cgi/trunk/boost/cgi/import/streambuf.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -17,9 +17,6 @@
   using boost::asio::streambuf;
 
  } // namespace common
-
- using common::streambuf;
-
 } // namespace cgi
 
 #endif // CGI_STREAMBUF_HPP_INCLUDED__

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/build/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/build/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/build/Jamfile.v2 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -1,6 +1,12 @@
 
-# These are some helper variables, which will need to be checked against
-# user-supplied variables (ie. using modules.peek, I think)
+import modules ;
+
+local DEFINES ;
+
+if [ MATCH "^(--build-cgi)" : [ modules.peek : ARGV ] ]
+{ # compile library
+ DEFINES = <define>BOOST_CGI_BUILD_LIB ;
+}
 
 project boost/cgi
   : build-dir
@@ -13,6 +19,7 @@
       <library>/boost/regex/
       <define>_CRT_SECURE_NO_WARNINGS
       <define>_SCL_SECURE_NO_WARNINGS
+ $(DEFINES)
   : usage-requirements
       <include>$(top)
       <include>$(boost-root)
@@ -20,32 +27,24 @@
       <library>/boost/system/
       <library>/boost/regex/
       <linkflags>-pthread
+ $(DEFINES)
   ;
 
-
-import modules ;
-
-# make BB recognise .ipp files as .cpp files.
-import type ;
-type.register IPP : ipp : CPP ;
-
-path-constant impl : $(top)/boost/cgi/impl ;
-
-SOURCES =
- $(impl)/form_parser.ipp
- $(impl)/response.ipp
- ;
-
-
 if [ MATCH "^(--build-cgi)" : [ modules.peek : ARGV ] ]
 { # compile library
   ECHO "Building CGI library" ;
 
+ # make BB recognise .ipp files as .cpp files.
+ import type ;
+ type.register IPP : ipp : CPP ;
+
+ SOURCES = $(top)/libs/cgi/src/library_sources.cpp ;
+
   lib boost_cgi
     :
       $(SOURCES)
     :
- <define>BOOST_CGI_BUILD_LIBRARY
+ <define>BOOST_CGI_BUILD_LIB
     ;
 }
 else

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/cgi.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/cgi.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/cgi.qbk 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -113,6 +113,8 @@
 
 [/xinclude ../cgi_dox.xml]
 
+[include:examples examples.qbk]
+
 [include:reference reference.qbk]
 
 [include:future future_development.qbk]

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide.qbk 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -19,8 +19,6 @@
 
 [/include:tutorial user_guide/tutorial.qbk]
 
-[include:examples ../../example/doc.qbk]
-
 [include user_guide/tutorial/tutorial.qbk]
 
 [/endsect]

Deleted: sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/step_one.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/step_one.qbk 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
+++ (empty file)
@@ -1,79 +0,0 @@
-
-[section "Hello, World."]
-
-Let's start at the beginning, with the eponymous "Hello world" example:
-
-``
-#include <boost/cgi.hpp>
-using namespace boost::cgi;
-
-int main()
-{
- service s;
- request req(s);
- response resp;
-
- resp<< content_type("text/plain")
- << "Hello, world.";
-
- resp.send(req.client());
-
- return 0;
-}
-``
-
-That should be mostly self-explanatory, here is what is happening:
-
-``
-#include <boost/cgi.hpp>
-using namespace boost::cgi;
-``
-
-The boost/cgi.hpp header includes the headers for CGI, SCGI and FastCGI. If you only want the CGI stuff you can `#include <boost/cgi/cgi.hpp>`, or similarly for the other protocols (scgi.hpp or fcgi.hpp).
-
-``
-service s;
-request req(s);
-``
-
-The use of the `service` class here might seem cumbersome, but its value should become more apparent later on when we try and scale our program.
-
-[note
- Still think it's ugly; I'm trying to think of the best way to remove the need for it without losing the protocol-independence of parts of the library.
-]
-
-``
-response resp;
-``
-
-You aren't required to use the `response` class with this library, but it's highly recommended. [-There is a rationale for the `response` class in the design notes] [/**FIXME**/]. A `response` is independent of protocol and any request you choose to use it with - that makes it easy to reuse.
-
-``
-resp<< content_type("text/plain")
- << "Hello, world.";
-``
-
-You can stream data to a `response` just like you can with `std::cout`. In addition, you can stream things like `content_type("text/html")` and `cookie("whatever", "value")` (more on this later).
-
-`content_type` is one of the ['header factories] provided by the library. In other words it is a function which returns a `header` object, so instead of streaming `content_type("text/plain")` to a `response` you can stream `header("Content-type", "text/plain")`. Both are equivalent, but the former is cleaner and less error prone.
-
-The `response` class understands `header`s and keeps them separate from the rest of the response. This allows you to add headers at any point, so long as you haven't flushed/sent the response already. For instance, you could add a custom header "Running-time", stating the time it took to handle the request, just before you send the response.
-
-``
-resp.send(req.client());
-
-return 0;
-``
-
-As already mentioned, the `response` class buffers your data, so you must send it when it is ready. It is sent to the `client` associated with a request - ie. req.client() - but you don't need to know anything else about the Client concept for now. The library also provides a convenient macro to clean up the above:
-
-``
-return_(resp, req, 0); // 'returns 0' from main.
-``
-
-[tip
- A CGI request is effectively closed when the application exits, but since FastCGI and SCGI can handle multiple requests per process you must explicitly close each one. The `return_()` macro does this properly.
-]
-
-[endsect] [/ hello_world]
-

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/tutorial.qbk
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/tutorial.qbk (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/doc/src/user_guide/tutorial/tutorial.qbk 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -1,7 +1,7 @@
 
 [section Tutorial]
 
-[include step_one.qbk]
+[include hello_world.qbk]
 
 [section:what_next The next step]
 

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/Jamfile.v2 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -17,8 +17,10 @@
 build-project acgi ;
 # Build all of the fcgi examples
 build-project fcgi ;
+# Build all of the xcgi examples
+build-project xcgi ;
 
-alias all_examples : cgi acgi fcgi ;
+alias all_examples : cgi acgi fcgi xcgi ;
 
 install cgi-install
  : # sources
@@ -41,7 +43,12 @@
     <location>$(fcgi-bin)
   ;
 
-alias install : cgi//install acgi//install fcgi//install ;
+install xcgi-install
+ :
+ xcgi//install
+ ;
+
+alias install : cgi//install acgi//install fcgi//install xcgi//install ;
 
 explicit cgi-install ;
 explicit acgi-install ;

Modified: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/hello_world/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/hello_world/main.cpp (original)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/fcgi/hello_world/main.cpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -12,33 +12,76 @@
 // The simplest FastCGI program, outputs only "Hello there, universe."
 //
 
+#include <iomanip>
+#include <fstream>
 #include <boost/cgi/fcgi.hpp>
+#include <boost/cgi.hpp>
+#include <boost/asio.hpp>
+#include <sys/socket.h>
 
 using namespace std;
 using namespace boost::fcgi;
 
-int main()
+template<typename Request, typename Response>
+int handle_request(Request& req, Response& resp)
 {
-try
+ // This is a minimal response. The content_type(...) may go before or after
+ // the response text.
+ resp<< content_type("text/plain")
+ << "Hello there, universe.";
+
+ return_(resp, req, 0);
+}
+
+/// Handle a vanilla CGI request
+int handle_request()
 {
- service s; // This becomes useful with async operations.
- acceptor a(s); // This is used to accept requests from the server.
- request req(s); // Our request.
+ boost::cgi::request req;
+ response resp;
+ return handle_request(req,resp);
+}
+
+/// Handle a FastCGI request
+template<typename Acceptor>
+int handle_request(Acceptor& a)
+{
+ request req(a.protocol_service()); // Our request.
 
+ int ret = 0;
   for (;;) // Handle requests until something goes wrong
            // (an exception will be thrown).
   {
     a.accept(req);
     response resp; // A response object to make our lives easier.
+ ret = handle_request(req, resp);
+ }
 
- // This is a minimal response. The content_type(...) may go before or after
- // the response text.
- resp<< content_type("text/plain")
- << "Hello there, universe.";
+ return ret;
+}
 
- resp.send(req.client()); // Send the response.
- req.close(resp.status()); // Close the request (we can reuse this object now).
+int main()
+{
+try
+{
+ service s; // This becomes useful with async operations.
+ acceptor a(s);
+ ofstream file("/var/www/log/is_cgi.log", std::ios::app);
+
+ if (a.is_cgi())
+ {
+ file<< "Is CGI" << endl;
+ file.flush();
+ handle_request();
   }
+ else
+ {
+ file<< "Is FastCGI (probably)";
+ file.flush();
+ handle_request(a);
+ }
+
+ file.flush();
+
   return 0;
 }
 catch(boost::system::system_error& err)

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/Jamfile.v2 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -0,0 +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/example/xcgi/basic ;
+
+exe xcgi_basic : main.cpp /boost/regex/ ;
+
+# Our install rule (builds binaries and copies them to <location>)
+install install_cgi : xcgi_basic : <location>$(cgi-bin) ;
+install install_fcgi : xcgi_basic : <location>$(fcgi-bin) ;
+
+# Only install example if you use `bjam install' or equivalent
+explicit install_cgi ;
+explicit install_fcgi ;
+alias install : install_cgi install_fcgi ;
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/doc.qbk 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -0,0 +1,11 @@
+
+[section Hello world]
+
+[import main.cpp]
+
+[acgi_hello_world]
+
+See the [@../../example/acgi/hello_world/main.cpp full source listing].
+
+[endsect][/ hello_world]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/main.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/basic/main.cpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -0,0 +1,88 @@
+// -- 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)
+//
+////////////////////////////////////////////////////////////////
+//
+//[xcgi_basic
+//
+// A completely stripped-down, protocol-independent program, outputs only
+// "Hello there, universe."
+//
+// example/xcgi/basic$ `bjam install`
+//
+// will install the example to your cgi-bin and fcgi-bin. Look
+// [link ../../doc.qbk here] for more information, including how to set these.
+//
+
+#include <boost/cgi.hpp>
+#include <boost/cgi/fcgi.hpp>
+
+using namespace std;
+using namespace boost::fcgi;
+
+template<typename Request, typename Response>
+int handle_request(Request& req, Response& resp)
+{
+ // This is a minimal response. The content_type(...) may go before or after
+ // the response text.
+ resp<< content_type("text/plain")
+ << "Hello there, universe.";
+
+ return_(resp, req, 0);
+}
+
+/// Handle a vanilla CGI request
+int handle_request()
+{
+ boost::cgi::request req;
+ response resp;
+ return handle_request(req,resp);
+}
+
+/// Handle a FastCGI request
+template<typename Acceptor>
+int handle_request(Acceptor& a)
+{
+ request req(a.protocol_service()); // Our request.
+
+ int ret = 0;
+ for (;;) // Handle requests until something goes wrong
+ // (an exception will be thrown).
+ {
+ a.accept(req);
+ response resp; // A response object to make our lives easier.
+ ret = handle_request(req, resp);
+ }
+
+ return ret;
+}
+
+int main()
+{
+try
+{
+ service s; // This becomes useful with async operations.
+ acceptor a(s);
+
+ return a.is_cgi() ?
+ handle_request() // Start it as a CGI request.
+ : handle_request(a); // Start it as a FastCGI request.
+}
+catch(boost::system::system_error& err)
+{
+ std::cerr<< "System error " << err.code() << ": "
+ << err.what() << std::endl;
+ return 1;
+}
+catch(...)
+{
+ std::cerr<< "Unknown error!" << std::endl;
+ return 2;
+}
+}
+//]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Jamfile.v2 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -0,0 +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/example/xcgi/server1 ;
+
+exe xcgi_server1 : main.cpp /boost/regex/ ;
+
+# Our install rule (builds binaries and copies them to <location>)
+install install_cgi : xcgi_server1 : <location>$(cgi-bin) ;
+install install_fcgi : xcgi_server1 : <location>$(fcgi-bin) ;
+
+# Only install example if you use `bjam install' or equivalent
+explicit install_cgi ;
+explicit install_fcgi ;
+alias install : install_cgi install_fcgi ;
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Server.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/Server.hpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -0,0 +1,56 @@
+#ifndef BOOST_CGI_EXAMPLES_XCGI_SERVER2_SERVER_HPP_INCLUDED_
+#define BOOST_CGI_EXAMPLES_XCGI_SERVER2_SERVER_HPP_INCLUDED_
+
+#include <boost/cgi/fcgi.hpp>
+#include <boost/cgi/acgi.hpp>
+
+class Server
+{
+public:
+ Server()
+ : service_()
+ , acceptor_(service_)
+ {
+ }
+
+ template<typename Handler>
+ int run(Handler handler = Handler())
+ {
+ return acceptor_.is_cgi() ?
+ handle_cgi_request(handler)
+ : handle_fcgi_requests(handler);
+ }
+
+ template<typename Handler>
+ int handle_cgi_request(Handler handler)
+ {
+ // **FIXME**
+ // Uses acgi - would be better if boost::cgi::request was asynchronous.
+ boost::acgi::service srv;
+ boost::acgi::request req(srv);
+ boost::acgi::response resp;
+ return handler(req, resp);
+ }
+
+ template<typename Handler>
+ int handle_fcgi_requests(Handler handler)
+ {
+ boost::fcgi::request req(acceptor_.protocol_service());
+
+ int ret = 0;
+ for (;;) // Handle requests until something goes wrong
+ // (an exception will be thrown).
+ {
+ acceptor_.accept(req);
+ boost::fcgi::response resp;
+ ret = handler(req, resp);
+ }
+ return ret;
+ }
+private:
+ boost::fcgi::service service_;
+ boost::fcgi::acceptor acceptor_;
+};
+
+#endif // BOOST_CGI_EXAMPLES_XCGI_SERVER2_SERVER_HPP_INCLUDED_
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/doc.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/doc.qbk 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -0,0 +1,11 @@
+
+[section Hello world]
+
+[import main.cpp]
+
+[acgi_hello_world]
+
+See the [@../../example/acgi/hello_world/main.cpp full source listing].
+
+[endsect][/ hello_world]
+

Added: sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/main.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/trunk/libs/cgi/example/xcgi/server1/main.cpp 2008-06-02 18:13:53 EDT (Mon, 02 Jun 2008)
@@ -0,0 +1,69 @@
+// -- 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)
+//
+////////////////////////////////////////////////////////////////
+//
+//[xcgi_server2
+//
+// A protocol-independent program, outputs only
+//
+// "Hello there, universe."
+//
+// This one is similar to the xcgi/basic example and equally simple, but here
+// the protocol-dependent bits done by `Server` class (see "Server.hpp").
+//
+// example/xcgi/basic$ `bjam install`
+//
+// will install the example to your cgi-bin and fcgi-bin. Look
+// [link ../../doc.qbk here] for more information, including how to set these.
+//
+
+#include <boost/cgi/fcgi.hpp>
+#include <boost/cgi.hpp>
+#include "Server.hpp"
+
+using namespace std;
+using namespace boost::cgi::common;
+
+// Our request handler
+struct request_handler
+{
+ // Handle any request type.
+ template<typename Request, typename Response>
+ int operator()(Request& req, Response& resp)
+ {
+ // This is a minimal response. The content_type(...) may go before or after
+ // the response text.
+ resp<< content_type("text/plain")
+ << "Hello there, universe.";
+
+ return_(resp, req, 0);
+ }
+};
+
+int main()
+{
+try
+{
+ Server server;
+ return server.run(request_handler());
+ //return server.run<request_handler>(); // Equivalent to the line above.
+}
+catch(boost::system::system_error& err)
+{
+ std::cerr<< "System error " << err.code() << ": "
+ << err.what() << std::endl;
+ return 1;
+}
+catch(...)
+{
+ std::cerr<< "Unknown error!" << std::endl;
+ return 2;
+}
+}
+//]
+


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