|
Boost-Commit : |
From: drrngrvy_at_[hidden]
Date: 2007-07-05 15:51:35
Author: drrngrvy
Date: 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
New Revision: 7366
URL: http://svn.boost.org/trac/boost/changeset/7366
Log:
@?¯0)4j¤0210p¿öø¦_¦ø40.81y81û68?7YpZ480984?0îÃÃ654654 1A4Ãâ¢?9861?21
Added:
sandbox/SOC/2007/cgi/Jamfile.v2
sandbox/SOC/2007/cgi/boost/cgi/basic_connection.hpp
sandbox/SOC/2007/cgi/boost/cgi/basic_protocol_service.hpp
sandbox/SOC/2007/cgi/boost/cgi/basic_request_acceptor.hpp
sandbox/SOC/2007/cgi/boost/cgi/cgi.hpp
sandbox/SOC/2007/cgi/boost/cgi/cgi_request_service.hpp
sandbox/SOC/2007/cgi/boost/cgi/connection_base.hpp
sandbox/SOC/2007/cgi/boost/cgi/detail/protocol_traits.hpp
sandbox/SOC/2007/cgi/boost/cgi/detail/request_traits.hpp
sandbox/SOC/2007/cgi/boost/cgi/fcgi/
sandbox/SOC/2007/cgi/boost/cgi/fcgi.hpp
sandbox/SOC/2007/cgi/boost/cgi/fcgi/specification.hpp
sandbox/SOC/2007/cgi/boost/cgi/gateway_service.hpp
sandbox/SOC/2007/cgi/boost/cgi/http/
sandbox/SOC/2007/cgi/boost/cgi/http/status_code.hpp
sandbox/SOC/2007/cgi/boost/cgi/reply.hpp
sandbox/SOC/2007/cgi/boost/cgi/request_acceptor_service.hpp
sandbox/SOC/2007/cgi/boost/cgi/request_impl/
sandbox/SOC/2007/cgi/boost/cgi/request_impl/cgi_request_impl.hpp
sandbox/SOC/2007/cgi/boost/cgi/request_impl/fcgi_request_impl.hpp
sandbox/SOC/2007/cgi/boost/cgi/request_impl/request_impl.hpp
sandbox/SOC/2007/cgi/boost/cgi/request_impl/request_service_impl.hpp
sandbox/SOC/2007/cgi/boost/cgi/request_impl/scgi_request_impl.hpp
sandbox/SOC/2007/cgi/boost/cgi/request_service.hpp
sandbox/SOC/2007/cgi/boost/cgi/role_type.hpp
sandbox/SOC/2007/cgi/boost/cgi/scgi.hpp
sandbox/SOC/2007/cgi/libs/cgi/build/Jamfile.v2
sandbox/SOC/2007/cgi/libs/cgi/doc/Jamfile.v2
sandbox/SOC/2007/cgi/libs/cgi/doc/cgi.qbk
sandbox/SOC/2007/cgi/libs/cgi/doc/program_flow.txt
sandbox/SOC/2007/cgi/libs/cgi/test/Jamfile.v2
sandbox/SOC/2007/cgi/project-root.jam
Added: sandbox/SOC/2007/cgi/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/Jamfile.v2 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,470 @@
+# Copyright Vladimir Prus 2002-2006.
+# Copyright Dave Abrahams 2005-2006.
+# Copyright Rene Rivera 2005-2006.
+# Copyright Douglas Gregor 2005.
+#
+# 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)
+
+# Usage:
+#
+# bjam [options] [install|stage]
+#
+# Builds and installs Boost.
+#
+# Targets and Related Options:
+#
+# install Install headers and compiled library files to the
+# ======= configured locations (below).
+#
+# --prefix=<PREFIX> Install architecture independent files here.
+# Default; C:\Boost on Win32
+# Default; /usr/local on Unix. Linux, etc.
+#
+# --exec-prefix=<EPREFIX> Install architecture dependent files here.
+# Default; <PREFIX>
+#
+# --libdir=<DIR> Install library files here.
+# Default; <EPREFIX>/lib
+#
+# --includedir=<HDRDIR> Install header files here.
+# Default; <PREFIX>/include
+#
+# stage Build and install only compiled library files
+# ===== to the stage directory.
+#
+# --stagedir=<STAGEDIR> Install library files here
+# Default; ./stage
+#
+# Other Options:
+#
+# --builddir=DIR Build in this location instead of building
+# within the distribution tree. Recommended!
+#
+# --toolset=toolset Indicates the toolset to build with.
+#
+# --show-libraries Displays the list of Boost libraries that require
+# build and installation steps, then exit.
+#
+# --layout=<layout> Determines whether to choose library names
+# and header locations such that multiple
+# versions of Boost or multiple compilers can
+# be used on the same system.
+#
+# versioned (default) - Names of boost
+# binaries include the Boost version
+# number and the name and version of the
+# compiler. Boost headers are installed
+# in a subdirectory of <HDRDIR> whose
+# name contains the Boost version
+# number.
+#
+# system - Binaries names do not include
+# the Boost version number or the name
+# and version number of the compiler.
+# Boost headers are installed directly
+# into <HDRDIR>. This option is
+# intended for system integrators who
+# are building distribution packages.
+#
+# --buildid=ID Adds the specified ID to the name of built
+# libraries. The default is to not add anything.
+#
+# --help This message.
+#
+# --with-<library> Build and install the specified <library>
+# If this option is used, only libraries
+# specified using this option will be built.
+#
+# --without-<library> Do not build, stage, or install the specified
+# <library>. By default, all libraries are built.
+
+# TODO:
+# - handle boost version
+# - handle python options such as pydebug
+
+import modules ;
+import set ;
+import stage ;
+import package ;
+import path ;
+import common ;
+import os ;
+import regex ;
+import errors ;
+import "class" : new ;
+import common ;
+import sequence ;
+
+constant BOOST_VERSION : 1.35.0 ;
+
+local version-tag = [ MATCH "^([^.]+)[.]([^.]+)[.]([^.]+)" : $(BOOST_VERSION) ] ;
+if $(version-tag[3]) = 0
+{
+ version-tag = $(version-tag[1-2]) ;
+}
+
+constant BOOST_VERSION_TAG : $(version-tag:J="_") ;
+
+local default-build ;
+if $(__file__:D) = ""
+{
+ default-build =
+ debug release
+ <threading>single <threading>multi
+ <link>shared <link>static
+ ;
+
+ if [ os.name ] = NT
+ {
+ default-build += <runtime-link>shared <runtime-link>static ;
+ }
+}
+else
+{
+ default-build =
+ debug
+ ;
+}
+
+
+rule handle-static-runtime ( properties * )
+{
+ # This property combination is dangerous.
+ # Ideally, we'd add constraint to default build,
+ # so that user can build with property combination
+ # by hand. But we don't have any 'constraint' mechanism
+ # for default-build, so disable such builds in requirements.
+
+ # For CW, static runtime is needed so that
+ # std::locale works.
+ if <link>shared in $(properties)
+ && <runtime-link>static in $(properties)
+ && ! ( <toolset>cw in $(properties) )
+ {
+ return <build>no ;
+ }
+}
+
+
+project boost
+ : requirements <include>.
+ # disable auto-linking for all targets here,
+ # primarily because it caused troubles with V2
+ <define>BOOST_ALL_NO_LIB=1
+ # Used to encode variant in target name. See the
+ # 'tag' rule below.
+ <tag>@$(__name__).tag
+ <conditional>@handle-static-runtime
+
+ : usage-requirements <include>.
+ : build-dir bin.v2
+ : default-build $(default-build)
+ ;
+
+# Setup convenient aliases for all libraries.
+
+all-libraries =
+ [ MATCH .*libs/(.*)/build/.* : [ glob libs/*/build/Jamfile.v2 ] [ glob libs/*/build/Jamfile ] ]
+ ;
+
+all-libraries = [ sequence.unique $(all-libraries) ] ;
+
+# First, the complicated libraries: where the target name in
+# Jamfile is different from directory name.
+alias prg_exec_monitor : libs/test/build//boost_prg_exec_monitor ;
+alias test_exec_monitor : libs/test/build//boost_test_exec_monitor ;
+alias unit_test_framework : libs/test/build//boost_unit_test_framework ;
+alias bgl-vis : libs/graps/build//bgl-vis ;
+alias serialization : libs/serialization/build//boost_serialization ;
+alias wserialization : libs/serialization/build//boost_wserialization ;
+
+explicit prg_exec_monitor test_exec_monitor unit_test_framework
+ bgl-vis serialization wserialization ;
+
+for local l in $(all-libraries)
+{
+ if ! $(l) in test graph serialization
+ {
+ alias $(l) : libs/$(l)/build//boost_$(l) ;
+ explicit $(l) ;
+ }
+}
+
+alias headers : : : : <include>. ;
+
+
+# Decides which libraries are to be installed by looking at --with-<library>
+# --without-<library> arguments. Returns the list of directories under "libs"
+# which must be built at installed.
+rule libraries-to-install ( existing-libraries * )
+{
+ local argv = [ modules.peek : ARGV ] ;
+ local with-parameter = [ MATCH --with-(.*) : $(argv) ] ;
+ local without-parameter = [ MATCH --without-(.*) : $(argv) ] ;
+
+ # Do some checks
+ if $(with-parameter) && $(without-parameter)
+ {
+ ECHO "error: both --with-<library> and --without-<library> specified" ;
+ EXIT ;
+ }
+
+ local wrong = [ set.difference $(with-parameter) : $(existing-libraries) ] ;
+ if $(wrong)
+ {
+ ECHO "error: wrong library name '$(wrong[1])' in the --with-<library> option." ;
+ EXIT ;
+ }
+ local wrong = [ set.difference $(without-parameter) : $(existing-libraries) ] ;
+ if $(wrong)
+ {
+ ECHO "error: wrong library name '$(wrong[1])' in the --without-<library> option." ;
+ EXIT ;
+ }
+
+ if $(with-parameter)
+ {
+ return [ set.intersection $(existing-libraries) : $(with-parameter) ] ;
+ }
+ else
+ {
+ return [ set.difference $(existing-libraries) : $(without-parameter) ] ;
+ }
+}
+
+# what kind of layout are we doing?
+layout = [ MATCH "^--layout=(.*)" : [ modules.peek : ARGV ] ] ;
+layout ?= versioned ;
+layout-$(layout) = true ;
+
+# possible stage only location
+local stage-locate = [ MATCH "^--stagedir=(.*)" : [ modules.peek : ARGV ] ] ;
+stage-locate ?= stage ;
+
+path-constant BOOST_STAGE_LOCATE : $(stage-locate) ;
+
+
+# location of python
+local python-root = [ MATCH "^--with-python-root=(.*)" : [ modules.peek : ARGV ] ] ;
+PYTHON_ROOT ?= $(python-root) ;
+
+# Select the libraries to install.
+libraries = [ libraries-to-install $(all-libraries) ] ;
+
+if --show-libraries in [ modules.peek : ARGV ]
+{
+ ECHO "The following libraries require building:" ;
+ for local l in $(libraries)
+ {
+ ECHO " - $(l)" ;
+ }
+ EXIT ;
+}
+
+# Custom build ID.
+local build-id = [ MATCH "^--buildid=(.*)" : [ modules.peek : ARGV ] ] ;
+if $(build-id)
+{
+ constant BUILD_ID : [ regex.replace $(build-id) "[*\\/:.\"\' ]" "_" ] ;
+}
+
+# This rule is called by Boost.Build to determine the name of
+# target. We use it to encode build variant, compiler name and
+# boost version in the target name
+rule tag ( name : type ? : property-set )
+{
+ if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
+ {
+ if $(layout) = versioned
+ {
+ local result = [ common.format-name
+ <base> <toolset> <threading> <runtime> -$(BOOST_VERSION_TAG)
+ -$(BUILD_ID)
+ : $(name) : $(type) : $(property-set) ] ;
+
+ # Optionally add version suffix.
+ # On NT, library with version suffix won't be recognized
+ # by linkers. On CYGWIN, we get strage duplicate symbol
+ # errors when library is generated with version suffix.
+ # On OSX, version suffix is not needed -- the linker expets
+ # libFoo.1.2.3.dylib format.
+ # AIX linkers don't accept version suffixes either.
+ if $(type) = SHARED_LIB &&
+ ! ( [ $(property-set).get <target-os> ] in windows cygwin darwin aix )
+ {
+ result = $(result).$(BOOST_VERSION) ;
+ }
+
+ return $(result) ;
+ }
+ else
+ {
+ return [ common.format-name
+ <base> <threading> <runtime> -$(BUILD_ID)
+ : $(name) : $(type) : $(property-set) ] ;
+ }
+ }
+}
+
+# Install to system location.
+
+local install-requirements =
+ <install-source-root>boost
+ ;
+if $(layout-versioned)
+{
+ install-requirements += <install-header-subdir>boost-$(BOOST_VERSION_TAG)/boost ;
+}
+else
+{
+ install-requirements += <install-header-subdir>boost ;
+}
+if [ modules.peek : NT ]
+{
+ install-requirements += <install-default-prefix>C:/Boost ;
+}
+else if [ modules.peek : UNIX ]
+{
+ install-requirements += <install-default-prefix>/usr/local ;
+}
+
+local headers =
+ [ path.glob-tree boost : *.hpp *.ipp *.h *.inc : CVS ]
+ [ path.glob-tree boost/compatibility/cpp_c_headers : c* : CVS ]
+ ;
+
+
+# Complete install
+package.install install-proper
+ : $(install-requirements) <install-no-version-symlinks>on
+ :
+ : libs/$(libraries)/build
+ : $(headers)
+ ;
+explicit install-proper ;
+
+# Install just library.
+install stage-proper
+ : libs/$(libraries)/build
+ : <location>$(stage-locate)/lib
+ <install-dependencies>on <install-type>LIB
+ <install-no-version-symlinks>on
+ ;
+explicit stage-proper ;
+
+
+if $(layout-versioned)
+ && ( [ modules.peek : NT ] || [ modules.peek : UNIX ] )
+{
+ rule make-unversioned-links ( project name ? : property-set : sources * )
+ {
+ local result ;
+ local filtered ;
+ local pattern ;
+ local nt = [ modules.peek : NT ] ;
+
+ # Collect the libraries that have the version number in 'filtered'.
+ for local s in $(sources)
+ {
+ local m ;
+ if $(nt)
+ {
+ m = [ MATCH "(.*[.]lib)" : [ $(s).name ] ] ;
+ }
+ else
+ {
+ m = [ MATCH "(.*[.]so[.0-9]+)" "(.*[.]a)" : [ $(s).name ] ] ;
+ }
+ if $(m)
+ {
+ filtered += $(s) ;
+ }
+ }
+
+ # Create hardlinks without version.
+ for local s in $(filtered)
+ {
+ local name = [ $(s).name ] ;
+ local ea = [ $(s).action ] ;
+ local ep = [ $(ea).properties ] ;
+ local a = [
+ new non-scanning-action $(s) : common.hard-link : $(ep) ] ;
+
+ local noversion-file ;
+ if $(nt)
+ {
+ noversion-file = [ MATCH "(.*)-[0-9_]+([.]lib)" : $(name) ] ;
+ }
+ else
+ {
+ noversion-file =
+ [ MATCH "(.*)-[0-9_]+([.]so)[.0-9]*" : $(name) ]
+ [ MATCH "(.*)-[0-9_]+([.]a)" : $(name) ] ;
+ }
+
+ local new-name =
+ $(noversion-file[1])$(noversion-file[2]) ;
+ result += [ new file-target $(new-name) exact : [ $(s).type ] : $(project)
+ : $(a) ] ;
+
+ }
+ return $(result) ;
+ }
+
+ generate stage-unversioned : stage-proper :
+ <generating-rule>@make-unversioned-links ;
+ explicit stage-unversioned ;
+
+ generate install-unversioned : install-proper :
+ <generating-rule>@make-unversioned-links ;
+ explicit install-unversioned ;
+}
+else
+{
+ # Create do-nothing aliases
+ alias stage-unversioned ;
+ alias install-unversioned ;
+}
+
+alias install : install-proper install-unversioned ;
+alias stage : stage-proper stage-unversioned ;
+explicit install ;
+explicit stage ;
+
+
+# Just build the libraries, don't install them anywhere.
+# This is what happens with just "bjam --v2".
+alias build_all : libs/$(libraries)/build ;
+
+# This rule should be called from libraries' Jamfiles and will
+# create two targets, "install" and "stage", that will install
+# or stage that library. The --prefix option is respected, by
+# --with and --without options, naturally, are ignored.
+#
+# - libraries -- list of library targets to install.
+rule boost-install ( libraries * )
+{
+ package.install install
+ : <dependency>/boost//install-headers $(install-requirements)
+ : # No binaries
+ : $(libraries)
+ : # No headers, it's handled by the dependency
+ ;
+
+ install stage : $(libraries) : <location>$(BOOST_STAGE_LOCATE) ;
+
+ local c = [ project.current ] ;
+ local project-module = [ $(c).project-module ] ;
+ module $(project-module)
+ {
+ explicit stage ;
+ }
+}
+
+# Make project ids of all libraries known.
+for local l in $(libraries)
+{
+ use-project /boost/$(l) : libs/$(l)/build ;
+}
Added: sandbox/SOC/2007/cgi/boost/cgi/basic_connection.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/basic_connection.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,166 @@
+// -- basic_connection.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_BASIC_CONNECTION_HPP_INCLUDED__
+#define CGI_BASIC_CONNECTION_HPP_INCLUDED__
+
+#include <istream>
+#include <ostream>
+#include <boost/asio.hpp>
+#include "connection_base.hpp"
+
+namespace cgi {
+
+ template<typename ProtocolService, typename ConnectionType>
+ class basic_connection
+ : connection_base
+ //, connection_wrapper<ConnectionType>
+ {
+ public:
+ typedef connection_impl<ProtocolService::protocol_type> impl_type;
+
+ private:
+ impl_type* impl_;
+ };
+
+ template<typename ProtocolService>
+ class basic_connection<tags::stdio>
+ : public connection_base
+ {
+ public:
+ typedef ProtocolService protocol_service_type;
+
+ basic_connection(protocol_service_type& ps)
+ : in_(std::cin)
+ , out_(std::cout)
+ {
+ }
+
+ template<typename MutableBufferSequence>
+ std::size_t read(MutableBufferSequence buf, boost::system::error_code& ec)
+ {
+ if( buf.data() != in_.rdbuf() )
+ return in_.read(buf.data(), buf.size());
+ return buf.size();
+ }
+
+ template<typename MutableBufferSequence, typename Handler>
+ void async_read(MutableBufferSequence buf, Handler handler)
+ {
+ handler(boost::system_error(), read(buf));
+ }
+
+ template<typename ConstBufferSequence>
+ std::size_t write(ConstBufferSequence& buf)
+ {
+ return out_.write(buf.data(), buf.size());
+ }
+
+ template<typename ConstBufferSequence, typename Handler>
+ void async_write(ConstBufferSequence& buf, Handler handler)
+ {
+ out_.write(buf.data(), buf.size());
+ protocol_service_.post(handler);
+ }
+
+ private:
+ protocol_service_type& protocol_service_;
+ std::istream& in_;
+ std::ostream& out_;
+ };
+
+ template<typename ProtocolService>
+ class basic_connection<tags::stdio_async>
+ : public connection_base
+ {
+ public:
+ typedef ProtocolService protocol_service_type;
+
+ basic_connection(protocol_service_type& ps)
+ : protocol_service_(ps)
+ , in_(std::cin)
+ , out_(std::cout)
+ {
+ }
+
+ template<typename MutableBufferSequence>
+ std::size_t read(MutableBufferSequence buf)
+ {
+ if( buf.data() != in_.rdbuf() )
+ return in_.read(buf.data(), buf.size());
+ return buf.size();
+ }
+
+ template<typename MutableBufferSequence, typename Handler>
+ void async_read(MutableBufferSequence buf, Handler handler)
+ {
+ std::size_t bytes_read;
+ if( buf.data() != in_.rdbuf() )
+ bytes_read = in_.read(buf.data(), buf.size());
+ else
+ bytes_read = buf.size();
+
+ protocol_service_.post(boost::bind(&Handler
+ , handler
+ , boost::system::system_error()
+ , bytes_read ));
+ }
+
+ template<typename ConstBufferSequence>
+ std::size_t write(ConstBufferSequence& buf)
+ {
+ return out_.write(buf.data(), buf.size());
+ }
+
+ template<typename ConstBufferSequence, typename Handler>
+ void async_write(ConstBufferSequence& buf, Handler handler)
+ {
+ out_.write(buf.data(), buf.size());
+ protocol_service_.post(handler);
+ }
+
+ private:
+ protocol_service_type& protocol_service_;
+ std::istream& in_;
+ std::ostream& out_;
+ };
+
+
+
+ template<typename ProtocolService>
+ class basic_connection<ProtocolService, tags::tcp_socket>
+ : public connection_base
+ {
+ public:
+ typedef ProtocolService protocol_service_type;
+
+ basic_connection(protocol_service_type& ps)
+ : protocol_service_(ps)
+ , sock_(ps.io_service())
+ {
+ }
+
+ template<typename ConstBufferSequence, typename Handler>
+ void async_write(ConstBufferSequence& buf, Handler handler)
+ {
+ }
+
+ private:
+ protocol_service_type protocol_service_;
+ boost::asio::ip::tcp::socket sock_;
+ };
+
+
+ typedef basic_connection<tags::stdio> stdio_connection;
+ typedef basic_connection<tags::tcp> tcp_connection;
+ //typedef basic_connection<tags::pipe> pipe_connection; // not implemented
+
+
+} // namespace cgi
+
+#endif // CGI_BASIC_CONNECTION_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/basic_protocol_service.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/basic_protocol_service.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,109 @@
+// -- basic_protocol_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_BASIC_PROTOCOL_SERVICE_HPP_INCLUDED__
+#define CGI_BASIC_PROTOCOL_SERVICE_HPP_INCLUDED__
+
+#include <set>
+#include <boost/asio/io_service.hpp>
+
+#include "basic_gateway.hpp"
+#include "connection.hpp"
+
+namespace cgi {
+
+ /// Basic Protocol Service
+ /**
+ * Holds the request queue and the connection queue.
+ * It is also a wrapper around asio::io_service
+ */
+ template<typename Protocol, typename TypeTraits = type_traits<Protocol> >
+ class basic_protocol_service
+ {
+ public:
+ typedef basic_gateway<Protocol> gateway_type;
+ typedef basic_acceptor<Protocol> acceptor_type;
+ typedef basic_request<Protocol> request_type;
+
+
+ basic_protocol_service()
+ : io_service_()
+ , mutex_()
+ , gateway_(this)
+ {
+ }
+
+ ~basic_protocol_service()
+ {
+ gateway_.stop_all();
+ }
+
+ void run()
+ {
+ io_service_.run();
+ }
+
+ void stop()
+ {
+ gateway_.stop_all();
+ io_service_.stop();
+ }
+
+ boost::asio::io_service& io_service()
+ {
+ return io_service_;
+ }
+
+ template<typename Handler>
+ void post(Handler handler)
+ {
+ io_service_.post(handler);
+ }
+
+ template<typename Handler>
+ void dispatch(Handler handler)
+ {
+ io_service_.dispatch(handler);
+ }
+
+ /*
+ void add_request(request_ptr new_request)
+ {
+ boost::thread::mutex::scoped_lock lk(mutex_);
+ requests_.push_back(new_request);
+ }
+
+ bool del_request(request_ptr request)
+ {
+ boost::thread::mutex::scoped_lock lk(mutex_);
+ if( !requests_.find(request) == requests_.end() )
+ return false;
+ **/
+
+ private:
+ boost::asio::io_service io_service_;
+ boost::thread::mutex mutex_;
+ boost::thread::condition condition_;
+
+ /// A strand is used for guaranteeing handlers are dispatched sequentially
+ boost::asio::strand strand_;
+
+ std::set<request_type::pointer> request_set_;
+ std::queue<request_type::pointer> request_queue_;
+ //std::set<connection_ptr> connections_;
+ gateway_type gateway_;
+
+ friend class gateway_type;
+ friend class gateway_service<protocol_type>;
+ friend class acceptor_type;
+ friend class request_type;
+ };
+
+} // namespace cgi
+
+#endif // CGI_BASIC_PROTOCOL_SERVICE_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/basic_request_acceptor.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/basic_request_acceptor.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,87 @@
+// -- basic_request_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_BASIC_REQUEST_ACCEPTOR_HPP_INCLUDED__
+#define CGI_BASIC_REQUEST_ACCEPTOR_HPP_INCLUDED__
+
+#include <boost/system.hpp>
+
+namespace cgi {
+
+ template<typename Protocol>
+ class basic_request_acceptor
+ : private boost::noncopyable
+ {
+ public:
+ // typedef impl_type;
+ typedef Protocol protocol_type;
+
+ explicit basic_request_acceptor(basic_protocol_service<Protocol>& pserv)
+ : service_(pserv)
+ {
+ }
+
+ ~basic_request_acceptor()
+ {
+ service_.cancel();
+ }
+
+ template<typename CGI_Request>
+ void accept(CGI_Request& request)
+ {
+ boost::system::error_code ec;
+ service_.accept(request, ec);
+ boost::throw_error(ec);
+ }
+
+ template<typename CGI_Request> boost::system::error_code&
+ accept(CGI_Request& request, boost::system::error_code& ec)
+ {
+ return service_.accept(request, ec);
+ }
+
+ template<typename CGI_Request, typename Handler>
+ void async_accept(CGI_Request& request, Handler handler)
+ {
+ service_.async_accept(request, handler);
+ }
+
+ private:
+ request_acceptor_service<protocol_type> service_;
+ };
+
+
+
+ /*
+ /// Specialisation for the CGI protocol
+ template<>
+ class basic_acceptor<protocol::cgi>
+ : private boost::noncopyable
+ {
+ public:
+ /// Accept a connection
+ /*
+ * For CGI, the connection is just a std::cin/cout wrapper, so is always
+ * connected
+
+ void accept() { }
+
+ /// Asynchronously accept a connection
+ /*
+ * Ask the service to asynchronously accept a connection. When one is accepted
+ * the handler is invoked (in a thread calling basic_service<>::run() ?).
+
+ template<typename Handler>
+ void async_accept(Handler handler)
+ {
+ handler();
+ }
+ */
+} // namespace cgi
+
+#endif // CGI_BASIC_REQUEST_ACCEPTOR_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/cgi.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/cgi.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,14 @@
+// -- cgi.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_HPP_INCLUDED__
+#define CGI_CGI_HPP_INCLUDED__
+
+// #include all cgi-related headers only
+
+#endif // CGI_CGI_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/cgi_request_service.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/cgi_request_service.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,19 @@
+#ifndef CGI_CGI_REQUEST_SERVICE_HPP_INCLUDED
+#define CGI_CGI_REQUEST_SERVICE_HPP_INCLUDED
+
+namespace cgi {
+
+template<>
+class basic_request_service<protocol::cgi>
+{
+ basic_request_service()
+ : in_buf_(std::cin.rdbuf())
+ , out_buf_(std::cout.rdbuf())
+ {
+ }
+
+};
+
+} // namespace cgi
+
+#endif // CGI_CGI_REQUEST_SERVICE_HPP_INCLUDED
Added: sandbox/SOC/2007/cgi/boost/cgi/connection_base.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/connection_base.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,37 @@
+// -- connection_base.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_CONNECTION_BASE_HPP_INCLUDED__
+#define CGI_CONNECTION_BASE_HPP_INCLUDED__
+
+namespace cgi {
+
+ /// Abstract Base Class for all connection types
+ class connection_base
+ {
+ public:
+ virtual ~connection_base() {}
+
+ // read functions
+ template<typename MutableBufferSequence>
+ virtual std::size_t read(MutableBufferSequence) = 0;
+
+ template<typename MutableBufferSequence, typename Handler>
+ virtual void async_read(MutableBufferSequence, Handler) = 0;
+
+ // write functions
+ template<typename ConstBufferSequence>
+ virtual std::size_t write(ConstBufferSequence) = 0;
+
+ template<typename ConstBufferSequence, typename Handler>
+ virtual void async_write(ConstBufferSequence, Handler) = 0;
+ };
+
+} // namespace cgi
+
+#endif // CGI_CONNECTION_BASE_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/detail/protocol_traits.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/detail/protocol_traits.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,19 @@
+#ifndef CGI_PROTOCOL_TRAITS_HPP_INCLUDED__
+#define CGI_PROTOCOL_TRAITS_HPP_INCLUDED__
+
+namespace cgi { namespace detail {
+
+ template<typename Protocol>
+ struct protocol_traits
+ {
+ typedef Protocol protocol_type;
+ typedef basic_request<Protocol> request_type;
+ typedef gateway<Protocol> gateway_type;
+ typedef basic_service<Protocol> service_type;
+ typedef service_options<Protocol> service_options; // just an idea
+ };
+
+} // namespace detail
+} // namespace cgi
+
+#endif // CGI_PROTOCOL_TRAITS_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/detail/request_traits.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/detail/request_traits.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,52 @@
+#ifndef CGI_REQUEST_TRAITS_HPP_INCLUDED__
+#define CGI_REQUEST_TRAITS_HPP_INCLUDED__
+
+#include "request_type.hpp"
+
+namespace cgi {
+ namespace detail {
+
+ template<typename Protocol, typename RequestType = request_type::responder>
+ struct request_traits
+ {
+/*
+ typedef Protocol protocol_type;
+ typedef basic_request<Protocol> request_type;
+ typedef gateway<Protocol> gateway_type;
+ typedef basic_service<Protocol> service_type;
+ typedef service_options<Protocol> service_options; // just an idea
+**/
+ };
+
+ template<>
+ struct request_traits<protocol::cgi>
+ {
+ typedef cgi_request_impl impl_type;
+ typedef request_service<protocol::cgi> service_type;
+ };
+
+ template<>
+ struct request_traits<protocol::async_cgi>
+ {
+ typedef cgi_async_request_impl impl_type;
+ typedef request_service<protocol::async_cgi> service_type;
+ };
+
+ template<>
+ struct request_traits<protocol::fcgi>
+ {
+ typedef fcgi_request_impl impl_type;
+ typedef request_service<protocol::fcgi> service_type;
+ };
+
+ template<>
+ struct request_traits<protocol::scgi>
+ {
+ typedef scgi_request_impl impl_type;
+ typedef request_service<protocol::scgi> service_type;
+ };
+
+ } // namespace detail
+} // namespace cgi
+
+#endif // CGI_REQUEST_TRAITS_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/fcgi.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/fcgi.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,14 @@
+// -- fcgi.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_HPP_INCLUDED__
+#define CGI_FCGI_HPP_INCLUDED__
+
+// #include all fcgi-related files only
+
+#endif // CGI_FCGI_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/fcgi/specification.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/fcgi/specification.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,218 @@
+// -- fcgi/specification.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_SPECIFICATION_HPP_INCLUDED__
+#define CGI_FCGI_SPECIFICATION_HPP_INCLUDED__
+
+#include <cinttypes>
+
+// NOTE: CamelCase style mimicks the FastCGI specification
+// SEE: http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S8
+
+namespace cgi {
+ namespace fcgi {
+ namespace detail {
+
+ // Listening socket file number
+ const short LISTENSOCK_FILENO = 0;
+
+ /**
+ * Number of bytes in a Header. Future versions of the protocol
+ * will not reduce this number
+ */
+ const short HEADER_LEN = 8;
+
+ // Value for version component of Header
+ const short VERSION_1 = 1;
+
+ // current version
+ const unsigned char VERSION_NUM = (unsigned char)VERSION_1;
+
+ // Values for the type component of Header
+ enum request_t { BEGIN_REQUEST = 1
+ , ABORT_REQUEST = 2
+ , END_REQUEST = 3
+ , PARAMS = 4
+ , STDIN = 5
+ , STDOUT = 6
+ , STDERR = 7
+ , DATA = 8
+ , GET_VALUES = 9
+ , GET_VALUES_RESULT = 10
+ , UNKNOWN_TYPE = 11
+ , MAXTYPE = UNKNOWN_TYPE
+ };
+
+ // a null request id is a management record
+ static const unsigned char NULL_REQUEST_ID = 0;
+
+ // Mask for flags component of BeginRequestBody
+ static const unsigned char KEEP_CONN = 1;
+
+ // The longest message possible per record
+ const std::u_int16_t MAX_MSG_LEN = 65535;
+
+ // Values for role component of BeginRequestBody
+ enum role_t { RESPONDER = 1
+ , AUTHORIZER = 2
+ , FILTER = 3
+ , ANY
+ };
+
+ // Values for protocolStatus component of EndRequestBody
+ enum status_t { REQUEST_COMPLETE = 0
+ , CANT_MPX_CONN = 1
+ , OVERLOADED = 2
+ , UNKNOWN_ROLE = 3
+ };
+
+ struct Header
+ {
+ private:
+ unsigned char version_;
+ unsigned char type_;
+ unsigned char requestIdB1_;
+ unsigned char requestIdB0_;
+ unsigned char contentLengthB1_;
+ unsigned char contentLengthB0_;
+ unsigned char paddingLength_;
+ unsigned char reserved_;
+ public:
+ Header() { memset(this, 0, sizeof(*this)); }
+
+ Header(request_t t, int id, int len)
+ : version_ (VERSION_NUM)
+ , type_ ((unsigned char)t)
+ , requestIdB1_ ((unsigned char)(id >> 8) & 0xff)
+ , requestIdB0_ ((unsigned char)(id ) & 0xff)
+ , contentLengthB1_((unsigned char)(len >> 8) & 0xff)
+ , contentLengthB0_((unsigned char)(len ) & 0xff)
+ , paddingLength_ ((unsigned char)0)
+ , reserved_ (0)
+ { }
+
+ std::u_int16_t version() const
+ {
+ return version_;
+ }
+
+ std::u_int16_t type() const
+ {
+ return type_;
+ }
+
+ std::u_int16_t request_id() const
+ {
+ return requestIdB0_ + (requestIdB1_ << 8);
+ }
+
+ std::u_int16_t content_length() const
+ {
+ return contentLengthB0_ + (contentLengthB1_ << 8);
+ }
+
+ std::u_int16_t padding_length() const
+ {
+ return paddingLength_;
+ }
+ int body_length() const
+ {
+ return content_length() + padding_length();
+ }
+ };
+
+ struct BeginRequestBody
+ {
+ unsigned char roleB1_;
+ unsigned char roleB0_;
+ unsigned char flags_;
+ unsigned char reserved_[5];
+
+ int role() const
+ {
+ return (roleB1_ << 8 ) + roleB0_;
+ }
+
+ unsigned char flags() const
+ {
+ return flags_;
+ }
+ };
+
+ struct BeginRequestRecord
+ {
+ Header header_;
+ BeginRequestBody body_;
+ };
+
+ struct EndRequestBody
+ {
+ unsigned char appStatusB3_;
+ unsigned char appStatusB2_;
+ unsigned char appStatusB1_;
+ unsigned char appStatusB0_;
+ unsigned char protocolStatus_;
+ unsigned char reserved_[3];
+
+ EndRequestBody( std::u_int64_t appStatus
+ , status_t procStatus
+ )
+ : appStatusB3_( (appStatus >> 24) & 0xff )
+ , appStatusB2_( (appStatus >> 16) & 0xff )
+ , appStatusB1_( (appStatus >> 8) & 0xff )
+ , appStatusB0_( (appStatus >> 0) & 0xff )
+ , protocolStatus_((unsigned char)procStatus)
+ {
+ memset(reserved_, 0, sizeof(reserved_));
+ }
+ };
+
+ struct EndRequestRecord
+ {
+ Header header_;
+ EndRequestBody body_;
+
+ EndRequestRecord( std::u_int16_t id
+ , std::u_int64_t appStatus
+ , status_t procStatus
+ )
+ : header_( END_REQUEST, id, sizeof(EndRequestBody) )
+ , body_( appStatus, procStatus )
+ {
+ }
+ };
+
+ struct UnknownTypeBody
+ {
+ unsigned char type_;
+ unsigned char reserved_[7];
+
+ UnknownTypeBody( unsigned char t )
+ : type_(t)
+ {
+ memset(reserved_, 0, sizeof(reserved_));
+ }
+ };
+
+ struct UnknownTypeRecord
+ {
+ Header header_;
+ UnknownTypeBody body_;
+
+ UnknownTypeRecord( int type )
+ : header_( UNKNOWN_TYPE, 0, sizeof(UnknownTypeBody) )
+ , body_( (unsigned char)type )
+ {
+ }
+ };
+
+ } // namespace detail
+ } // namespace fcgi
+}// namespace cgi
+
+#endif // CGI_FCGI_SPECIFICATION_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/gateway_service.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/gateway_service.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,114 @@
+// -- gateway_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_GATEWAY_SERVICE_HPP_INCLUDED__
+#define CGI_GATEWAY_SERVICE_HPP_INCLUDED__
+
+namespace cgi {
+
+
+ template<typename Protocol
+ , typename ProtocolService = basic_protocol_service<Protocol> >
+ class gateway_service
+ {
+ public:
+ typedef Protocol protocol_type;
+ typedef ProtocolService io_service_type;
+ typedef boost::shared_ptr<connection_base> conn_ptr;
+
+
+ gateway_service(io_service_type& ios)
+ : io_service_(ios)
+ {
+ }
+
+
+ boost::system::error_code&
+ accept_impl(conn_ptr conn, boost::system::error_code& ec)
+ {
+ boost::asio::acceptor(
+ }
+
+ boost::system::error_code&
+ accept(conn_ptr conn, boost::system::error_code& ec)
+ {
+ conn = create_connection();
+
+ if( accept_impl(conn, ec) )
+ {
+ io_service_.connections_.insert(conn);
+ return ec;
+ }
+
+ // else change the current connection type held by the service, and try again
+ // (when implemented by asio & server front-ends)
+ // for now just set an error and return
+ ec = boost::system::system_error(666);
+ return ec;
+ }
+
+ template<typename Handler>
+ class accept_handler
+ {
+ public:
+ accept_handler(Handler handler)
+ : handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec)
+ {
+ handler_(ec);
+ }
+
+ private:
+ Handler handler_;
+ };
+
+ template<typename Handler>
+ void async_accept(Handler handler)
+ {
+ }
+
+ private:
+
+ /// Create a connection of the correct type
+ /**
+ * For now this only creates one type of connection (either a tcp socket for FCGI,
+ * or a cin/cout wrapper for vanilla CGI).
+ *
+ * It will be necessary once asio has the capabilities, to allow for different
+ * connection types here. This should be relatively simple assuming conn_ptr is
+ * a shared_ptr of a connection_base and all connection types inherit from this.
+ */
+ conn_ptr create_connection()
+ {
+ return new tcp_connection(io_service_);
+ }
+
+ io_service_type& io_service_;
+ };
+
+
+ template<> boost::system::error_code&
+ gateway_service<protocol::cgi>::accept( gateway_service<protocol::cgi>::conn_ptr conn
+ , boost::system::error_code& ec
+ )
+ {
+ conn = create_connection();
+ }
+
+ template<> boost::shared_ptr<connection_base>
+ gateway_service<protocol::cgi>::create_connection()
+ {
+ return new stdio_connection(gateway_);
+ }
+
+} // namespace cgi
+
+#endif // CGI_GATEWAY_SERVICE_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/http/status_code.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/http/status_code.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,78 @@
+// -- http/status_code.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_HTTP_STATUS_CODES_HPP__
+#define CGI_HTTP_STATUS_CODES_HPP__
+
+namespace cgi {
+ namespace http {
+
+ enum status_code
+ {
+ /// Success codes
+ ok = 200,
+ created
+ accepted,
+ non_authorative_information,
+ no_content,
+ reset_content,
+ partial_content,
+ multi_status,
+
+ /// Redirect codes
+ multiple_choices = 300,
+ moved_permanently,
+ found,
+ see_other,
+ not_modified,
+ use_proxy,
+ switch_proxy,
+ temporary_redirect,
+
+ /// Domain error codes
+ bad_request = 400,
+ unauthorized,
+ payment_required,
+ forbidden,
+ not_found,
+ method_not_allowed,
+ not_acceptable,
+ proxy_authentication_required,
+ request_timeout,
+ conflict,
+ gone,
+ length_required,
+ precondition_failed,
+ request_entity_too_large,
+ request_uri_too_long,
+ unsupported_media_type,
+ request_range_not_satisfiable,
+ expectation_failed,
+ unprocessable_entity = 422,
+ locked,
+ failed_dependency,
+ unordered_collection,
+ upgrade_required,
+ retry_with = 449,
+
+ /// Internal error codes
+ internal_server_error = 500,
+ not_implemented,
+ bad_gateway,
+ service_unavailable,
+ gateway_timeout,
+ http_version_not_supported,
+ insufficient_storage,
+ bandwidth_limit_exceeded = 509
+ };
+
+ } // namespace http
+} // namespace cgi
+
+#endif // CGI_HTTP_STATUS_CODES_HPP__
+
Added: sandbox/SOC/2007/cgi/boost/cgi/reply.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/reply.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,178 @@
+// -- reply.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_REPLY_HPP_INCLUDED__
+#define CGI_REPLY_HPP_INCLUDED__
+
+#include <ostream>
+
+#include "detail/buffer_ops.hpp"
+
+namespace cgi {
+
+ class reply
+ {
+ public:
+ /// Default constructor
+ /**
+ * Creates a shared pointer of a buffer to use internally.
+ */
+ explicit reply()
+ : ostream_(detail::make_buffer())
+ {
+ }
+
+ /// Construct with a particular buffer
+ /**
+ * Takes the buffer and uses it internally, does nothing with it on
+ * destruction.
+ */
+ reply(std::streambuf* buf)
+ : ostream_(buf)
+ {
+ }
+
+ /// Construct, taking a buffer from an external source
+ /**
+ * Takes a buffer from T (can be a model of ProtocolService or CGI_Request)
+ * to use internally.
+ */
+ template<typename T>
+ reply(T& t)
+ : ostream_(t.make_buffer())
+ {
+ }
+
+ ~reply()
+ {
+ }
+
+ std::size_t write(
+
+ template<typename MutableBufferSequence>
+ std::size_t write(MutableBufferSequence& buf)
+ {
+ return ostream_.write(buf.data(), buf.size());
+ }
+
+
+ /// Synchronously flush the reply via the supplied request
+ /**
+ * This call uses throwing semantics. ie. an exception will be thrown on
+ * any failure.
+ */
+ template<typename CGI_Request>
+ void flush(CGI_Request& req)
+ {
+ req.write(ostream_.rdbuf());
+ }
+
+ /// Synchronously flush the reply via the supplied request
+ /**
+ * This call uses error_code semantics. ie. ec is set if an error occurs.
+ */
+ template<typename CGI_Request>
+ boost::system::error_code& flush(CGI_Request& req
+ , boost::system::error_code& ec)
+ {
+ return req.write(ostream_.rdbuf(), ec);
+ }
+
+ /// Asynchronously flush the reply through the supplied request
+ template<typename CGI_Request, typename Handler>
+ void async_flush(CGI_Request& req, Handler handler)
+ {
+ req.async_write(ostream_.rdbuf(), handler));
+ }
+
+ /// Synchronously send the reply via the supplied request
+ /**
+ * This call uses throwing semantics. ie. an exception will be thrown on
+ * any failure.
+ */
+ template<typename CGI_Request>
+ void send(CGI_Request& req)
+ {
+ req.write(ostream_.rdbuf());
+ req.end(
+ }
+
+ /// Synchronously send the reply via the supplied request
+ /**
+ * This call uses error_code semantics. ie. ec is set if an error occurs.
+ */
+ template<typename CGI_Request>
+ boost::system::error_code& send(CGI_Request& req
+ , boost::system::error_code& ec)
+ {
+ req.write(ostream_.rdbuf(), ec);
+ req.end(status_
+ }
+
+ template<typename CGI_Request, typename Handler>
+ class send_handler
+ {
+ public:
+ send_handler(CGI_Request& req, int status, Handler handler)
+ : request_(req)
+ , status_(status)
+ , handler_(handler)
+ {
+ }
+
+ void operator()(boost::system::error_code ec)
+ {
+ if( !ec )
+ {
+ request_.close(
+
+ }
+ private:
+ CGI_Request& request_;
+ int status_;
+ Handler handler_;
+ };
+
+ /// Asynchronously send the reply through the supplied request
+ template<typename CGI_Request, typename Handler>
+ void async_send(CGI_Request& req, Handler handler)
+ {
+ req.async_write(ostream_.rdbuf()
+ , send_handler<CGI_Request
+ , Handler>(req, status_, handler));
+ }
+
+ /// Operator<< overload for basic outputting ability
+ template<typename T>
+ reply& operator<<(reply& rep, const T& t)
+ {
+ ostream_<< t;
+ return rep;
+ }
+
+ std::streambuf* rdbuf() const { return ostream_.rdbuf(); }
+
+ void status(int num)
+ {
+ status_ = num;
+ //data_.set_status(num);
+ }
+
+ int status() const { return status_; }//data_.get_status(); }
+
+ private:
+ int status_;
+ std::ostream ostream_;
+
+ //template<typename T>
+ //friend reply& operator<<(reply&, const T&);
+ };
+
+} // namespace cgi
+
+#endif // CGI_REPLY_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/request_acceptor_service.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/request_acceptor_service.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,69 @@
+// -- 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_REQUEST_ACCEPTOR_SERVICE_HPP_INCLUDED
+#define CGI_REQUEST_ACCEPTOR_SERVICE_HPP_INCLUDED
+
+namespace cgi {
+
+ template<typename Protocol>
+ class request_acceptor_service
+ {
+ public:
+ typedef Protocol protocol_type;
+
+ request_acceptor_service(basic_protocol_service<protocol_type>& pserv)
+ : pservice_(pserv)
+ {
+ }
+
+ /// Accept a request
+ /**
+ * Check if there is a waiting request in the queue. If not, accept a
+ * connection, and associate it with the request.
+ */
+ template<typename CGI_Request> boost::system::error_code&
+ accept(CGI_Request& request, boost::system::error_code& ec)
+ {
+ boost::thread::mutex::scoped_lock lk(io_service_.mutex_);
+ if( !io_service_.request_queue_.empty() )
+ {
+ request = pservice_.request_queue_.front();
+ pservice_.request_queue_.pop();
+
+ return ec;
+ }
+ lk.unlock();
+ pservice_.gateway_.accept(&request.connection(), ec);
+
+ return ec;
+ }
+
+ /// Asynchronously accept a request
+ template<typename RequestService, typename Handler>
+ void async_accept( basic_request<RequestService>& request, Handler handler )
+ {
+ boost::thread::mutex::scoped_lock lk(io_service_.mutex_);
+ if( !io_service_.request_queue_.empty() )
+ {
+ request = pservice_.request_queue_.front();
+ pservice_.request_queue_.pop();
+
+ return ec;
+ }
+ lk.unlock();
+ pservice_.gateway_.async_accept(&request.connection(), handler);
+ }
+
+ private:
+ basic_protocol_service<protocol_type>& pservice_;
+ };
+
+} // namespace cgi
+
+#endif // CGI_REQUEST_ACCEPTOR_SERVICE_HPP_INCLUDED
Added: sandbox/SOC/2007/cgi/boost/cgi/request_impl/cgi_request_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/request_impl/cgi_request_impl.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,157 @@
+// -- cgi_request_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_CGI_REQUEST_IMPL_HPP_INCLUDED__
+#define CGI_CGI_REQUEST_IMPL_HPP_INCLUDED__
+
+#include <map>
+#include <boost/noncopyable.hpp>
+
+namespace cgi {
+ namespace detail {
+ typename std::map<std::string,std::string> map_type;
+ } // namespace detail
+
+
+ /// Implementation for a standard CGI request
+ /**
+ * Note: This isn't noncopyable since there's no real reason it can't be
+ * copied around. Since basic_request is noncopyable, basic copying will be
+ * restricted but if someone really wants to copy the data, then they can.
+ */
+ class cgi_request_impl
+ {
+ public:
+ /// Constructor
+ /**
+ * Since this request type is synchronous, there is no need for an
+ * io_service, so the passed ProtocolService is just ignored.
+ */
+ template<typename ProtocolService>
+ cgi_request_impl(ProtocolService& pserv)
+ {
+ load(false);
+ }
+
+ /// Synchronously read/parse the request meta-data
+ /**
+ * @param parse_stdin if true then STDIN data is also read/parsed
+ */
+ bool load(bool parse_stdin)
+ {
+ }
+
+ /// Asynchronously read/parse the request meta-data
+ /**
+ * @param parse_stdin if true then STDIN data is also read/parsed
+ */
+ template<typename Handler>
+ void async_load(bool parse_stdin, Handler handler)
+ {
+ load(parse_stdin);
+ handler();
+ }
+
+ template<typename ConnectionPtr, typename MutableBufferSequence>
+ std::size_t read(ConnectionPtr conn, MutableBufferSequence buf)
+ {
+ return conn.read(buf);
+ }
+
+ template<typename ConnectionPtr, typename MutableBufferSequence
+ , typename Handler>
+ void async_read(ConnectionPtr conn, MutableBufferSequence buf
+ , Handler handler)
+ {
+ conn.async_read(buf, handler);
+ }
+
+ template<typename ConnectionPtr, typename ConstBufferSequence>
+ std::size_t write(ConnectionPtr conn, ConstBufferSequence buf)
+ {
+ return conn.write(buf);
+ }
+
+ template<typename ConnectionPtr, typename ConstBufferSequence
+ , typename Handler>
+ void async_write(ConnectionPtr conn, ConstBufferSequence buf
+ , Handler handler)
+ {
+ conn.async_write(buf, handler);
+ }
+
+ template<typename VarType> map_type& var() const;
+
+ template<typename VarType>
+ const std::string& var(const std::string& name) const
+ {
+ map_type& meta_data = var<VarType>();
+ if((map_type::iterator pos = meta_data.find(name))
+ != meta_data.end())
+ {
+ return *pos;
+ }
+ return std::string();
+
+ /* Alt:
+ if( meta_data.find(name) != meta_data.end() )
+ return meta_data[name];
+ return std::string();
+ **/
+ }
+
+ void* strand() const { return NULL; }
+ role_type role() const { return role_type::responder; }
+
+ private: // functions
+
+
+ private: // variables
+ //map_type env_map_;
+ map_type http_map_;
+ map_type cookie_map_;
+ map_type get_map_;
+ map_type post_map_;
+ };
+
+ template<> inline const std::string&
+ cgi_request_impl::var<tags::ENV>(const std::string& name)
+ {
+ return ::getenv(name);
+ }
+
+ /// Get a request map of all the environment meta-variables (slow)
+ /**
+ * -- NOT IMPLEMENTED FOR NOW --
+ *
+ * In the case of a CGI request, the environment meta-data is usually stored
+ * in the process environment, which means there is no direct access to all
+ * of them as a map_type&. In other words, this function call will have to
+ * load all of the variables into memory and then return the map
+ */
+ //template<> inline cgi_request_impl::map_type&
+ //cgi_request_impl::var<tags::ENV>()
+ //{
+ // throw std::logic_error("Can't get all environment vars as a map_type&");
+ //}
+
+ template<> inline cgi_request_impl::map_type&
+ cgi_request_impl::var<tags::HTTP>() { return http_map_; }
+
+ template<> inline cgi_request_impl::map_type&
+ cgi_request_impl::var<tags::COOKIE>() { return cookie_map_; }
+
+ template<> inline cgi_request_impl::map_type&
+ cgi_request_impl::var<tags::GET>() { return get_map_; }
+
+ template<> inline cgi_request_impl::map_type&
+ cgi_request_impl::var<tags::POST>() { return post_map_; }
+
+} // namespace cgi
+
+#endif // CGI_CGI_REQUEST_IMPL_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/request_impl/fcgi_request_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/request_impl/fcgi_request_impl.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,44 @@
+// -- fcgi_request_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_REQUEST_IMPL_HPP_INCLUDED__
+#define CGI_FCGI_REQUEST_IMPL_HPP_INCLUDED__
+
+namespace cgi {
+
+ /// Implementation for a FastCGI Responder request
+ class fcgi_responder_request_impl
+ {
+ fcgi_request() {} // private default constructor
+ public:
+ fcgi_request(protocol_service_type& pserv)
+ : protocol_service_(pserv)
+ {
+ }
+
+ bool load(bool parse_stdin)
+ {
+ }
+
+ template<typename Handler>
+ void async_load(bool parse_stdin, Handler handler)
+ {
+ }
+
+ /// The role of the request; in this case a responder
+ static role_type& role() { return role_type::responder; }
+ private:
+ protocol_service_type& protocol_service_;
+
+ /// Finished reading from stdin buffer (ie. POST data)
+ bool stdin_read_;
+ };
+
+} // namespace cgi
+
+#endif // CGI_FCGI_REQUEST_IMPL_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/request_impl/request_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/request_impl/request_impl.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,61 @@
+#ifndef CGI_REQUEST_IMPL_HPP_INCLUDED__
+#define CGI_REQUEST_IMPL_HPP_INCLUDED__
+
+namespace cgi {
+
+ template<typename Protocol, typename RequestType = request_type::responder>
+ class request_impl
+ {
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+ // FastCGI traits
+ template<>
+ class request_impl<protocol::fcgi>
+ {
+ public:
+ typedef fcgi_responder_request_impl type;
+ };
+
+ template<>
+ class request_impl<protocol::fcgi, request_type::filter>
+ {
+ public:
+ typedef fcgi_filter_request_impl type;
+ };
+
+ template<>
+ class request_impl<protocol::fcgi, request_type::authorizer>
+ {
+ public:
+ typedef fcgi_authorizer_request_impl type;
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+ // CGI traits
+ template<>
+ class request_impl<protocol::cgi>
+ {
+ public:
+ typedef cgi_request_impl type;
+ };
+
+ template<>
+ class request_impl<protocol::async_cgi>
+ {
+ public:
+ typedef cgi_async_request_impl type;
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+ // SCGI traits
+ template<>
+ class request_impl<protocol::scgi>
+ {
+ public:
+ typedef scgi_request_impl type;
+ };
+
+} // namespace cgi
+
+#endif // CGI_REQUEST_IMPL_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/request_impl/request_service_impl.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/request_impl/request_service_impl.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,48 @@
+#ifndef CGI_REQUEST_SERVICE_IMPL_HPP_INCLUDED__
+#define CGI_REQUEST_SERVICE_IMPL_HPP_INCLUDED__
+
+namespace cgi {
+
+ template<typename Protocol>
+ class request_service_impl
+ {
+ typedef request_service_impl type;
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+ // FastCGI traits
+ template<>
+ class request_service_impl<protocol::fcgi>
+ {
+ public:
+ typedef fcgi_request_service_impl type;
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+ // CGI traits
+ template<>
+ class request_service_impl<protocol::cgi, false>
+ {
+ public:
+ typedef cgi_request_service_impl type;
+ };
+
+ //template<>
+ //class request_service_impl<protocol::cgi, request_type::responder, true>
+ //{
+ //public:
+ // typedef cgi_arequest_service_impl type;
+ //};
+
+ /////////////////////////////////////////////////////////////////////////////
+ // SCGI traits
+ //template<>
+ //class request_service_impl<protocol::scgi>
+ //{
+ //public:
+ // typedef scgi_request_service_impl type;
+ //};
+
+} // namespace cgi
+
+#endif // CGI_REQUEST_SERVICE_IMPL_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/request_impl/scgi_request_impl.hpp
==============================================================================
Added: sandbox/SOC/2007/cgi/boost/cgi/request_service.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/request_service.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,82 @@
+// -- 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_REQUEST_SERVICE_HPP_INCLUDED
+#define CGI_REQUEST_SERVICE_HPP_INCLUDED
+
+namespace cgi {
+
+ template<typename Protocol>
+ class request_service
+ : public boost::asio::io_service::service
+ {
+ public:
+ typedef Protocol protocol_type;
+ typedef basic_protocol_service<Protocol> protocol_service_type;
+ typedef basic_request<Protocol> request_type;
+ //typedef request_impl<Protocol>
+
+
+ request_service(io_service_type& ios)
+ : boost::asio::io_service::service(ios.io_service())
+ , io_service_(ios)
+ {
+ }
+
+ void shutdown_service()
+ {
+ }
+
+ //void construct
+
+ bool load()
+ {
+ }
+
+ template<typename ProtocolService, typename Handler>
+ class load_handler
+ {
+ public:
+ load_handler(ProtocolService& ps, Handler handler)
+ : service_(ps)
+ , handler_(handler)
+ {
+ }
+
+ void operator()(boost::system::error_code& ec)
+ {
+ if( ec )
+ handler(ec);
+
+
+ //service_.dispatch(handler_(ec));
+ }
+
+ private:
+ ProtocolService& service_;
+ Handler handler_;
+ };
+
+ template<typename Handler>
+ void async_load(Handler handler)
+ {
+ }
+ private:
+ io_service_type& io_service_;
+ };
+
+ template<>
+ class request_service<protocol::cgi>
+ {
+ public:
+
+ };
+
+} // namespace cgi
+
+#endif // CGI_REQUEST_SERVICE_HPP_INCLUDED
Added: sandbox/SOC/2007/cgi/boost/cgi/role_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/role_type.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,27 @@
+// -- role_type.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_ROLE_TYPE_HPP_INCLUDED__
+#define CGI_ROLE_TYPE_HPP_INCLUDED__
+
+namespace cgi {
+
+ /// The 'role' of the request
+ /**
+ * See the section on 'role types' in the Design notes for more information.
+ * @code responder @endcode is by far the most common type.
+ */
+ enum role_type { responder
+ , authorizer
+ , filter
+ , undefined = responder // CGI programs default to responder
+ };
+
+} // namespace cgi
+
+#endif // CGI_ROLE_TYPE_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/boost/cgi/scgi.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/boost/cgi/scgi.hpp 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,14 @@
+// -- scgi.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_SCGI_HPP_INCLUDED__
+#define CGI_SCGI_HPP_INCLUDED__
+
+// #include all scgi-related headers only
+
+#endif // CGI_SCGI_HPP_INCLUDED__
Added: sandbox/SOC/2007/cgi/libs/cgi/build/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/libs/cgi/build/Jamfile.v2 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,10 @@
+
+project cgi
+ : requirements
+ <include>$(BOOST_ROOT)
+ : usage-requirements
+ <include>$(BOOST_ROOT)
+ #source-location = ../src
+ ;
+
+#SOURCES
Added: sandbox/SOC/2007/cgi/libs/cgi/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/Jamfile.v2 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,46 @@
+# Copyright (c) Darren Garvey 2007.
+# Use, modification, and distribution are
+# 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 cgi/doc ;
+
+import boostbook : boostbook ;
+import quickbook ;
+import doxygen ;
+
+# compile the doxygen sources here
+doxygen cgi_dox
+ :
+# [ glob-tree ../../../boost/cgi/*.hpp : .svn ]
+# [ glob-tree ../../../boost/libs/cgi/src/*.cpp : .svn ]
+ [ glob ../../../boost/cgi/*.hpp ]
+ [ glob ../../../boost/cgi/detail/*.hpp ]
+ [ glob ../../../boost/libs/cgi/src/*.cpp ]
+ [ glob ../../../boost/libs/cgi/src/detail/*.cpp ]
+ :
+ <doxygen:param>HIDE_UNDOC_MEMBERS=YES
+ <doxygen:param>EXTRACT_PRIVATE=NO
+ <doxygen:param>EXTRACT_ALL=NO
+ ;
+
+xml cgi_xml : cgi.qbk ;
+
+boostbook standalone
+ :
+ cgi_xml
+ cgi_dox
+ :
+ <xsl:param>boost.root=/usr/local/src/boost
+ <xsl:param>boost.libraries=/usr/local/src/boost/libs/libraries.htm
+ <xsl:param>boost.images=http://boost.org/images
+ <xsl:param>toc.max.depth=10
+ <xsl:param>toc.section.depth=10
+ <xsl:param>chunk.section.depth=10
+ ;
+
+install html
+ :
+ /boost//doc/html/boostbook.css
+ /bin/doc/$(toolset)/debug/cgi_xml.xml
+ ;
Added: sandbox/SOC/2007/cgi/libs/cgi/doc/cgi.qbk
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/cgi.qbk 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,365 @@
+[article CGI
+ [quickbook 1.5]
+ [version 0.01]
+ [id cgi]
+ [dirname the_document_dir]
+ [copyright 2007 Darren Garvey]
+ [purpose Thoughts about CGI implementation]
+ [authors [Garvey, Darren]]
+]
+
+[section Introduction]
+
+This library is an aid to writing portable CGI/FastCGI/SCGI programs. etc...
+
+[endsect]
+
+[section Design Notes]
+
+[section Concepts]
+
+[section Gateway]
+
+The purpose of the Gateway is to accept a connection and return it. For any particular protocol, there can be multiple types of valid connection (eg. FastCGI connections can be "any reliable full-duplex connection") so the Gateway simplifies the act of iterating through the different allowed (and supported) connection types and notifying the caller when one is established.
+
+[endsect]
+
+[endsect]
+
+[endsect]
+
+
+
+
+
+
+
+
+[section Old Stuff]
+
+[note There are many technicalities to the different protocols that aren't discussed in the SoC proposal, or even this document. Examples of these include issues about automatic parsing of CGI POST variables, security issues with external FastCGI 'servers' and different FastCGI process types (ie. Responder, Authorizer and Filter). Queries about issues like these can be brought up either through the boost mailing list or via personal email ( lists.drrngrvy '''[ @ ] gmail [ . ]''' com ).]
+
+[section Links]
+
+These links relate to the Summer of Code proposal.
+
+[section References]
+
+'''[CGI]''' - version 1.1 - [@http://www.ietf.org/rfc/rfc3875] [br]
+(version 1.2 (draft '''[outdated/irrelevant?]''') - [@http://cgi-spec.golux.com/cgi-120-00a.html])
+
+'''[FCGI]''' - [@http://www.fastcgi.com/devkit/doc/fcgi-spec.html]
+
+'''[SCGI]''' - [@http://python.ca/scgi/protocol.txt]
+
+[endsect]
+
+[section Further Discussion]
+
+http://www.fastcgi.com - Links to documents about FastCGI, explaining rationale and performance benefits.
+
+http://cryp.to/libfastcgi - The only known FastCGI implementation specifically for C++. It is currently lacking IO facilities (+ a minor bug).
+
+[endsect]
+
+[endsect]
+
+[section Code Examples]
+
+These examples are just thoughts based on what I have already coded. They are likely to change based on input from boost mailing lists and further research, but not due to technical considerations.
+Note: `#include`s are expunged from the code below.
+
+[section Basic CGI Example]
+
+``
+int main(int, char**)
+{
+ cgi::request req;
+ req.status(200); // This would output "Status: 200 OK\r\n" for an nph file; a NOP otherwise
+ req.header("Content-type: text/html");
+ req<< "Hello world";
+ return 0;
+}
+``
+[endsect]
+[section Simple FastCGI Example]
+
+Below are two alternatives to handle multiple requests sequentially within the same program. The function `cgi::request::accept()` is inspired by the FastCGI reference implementation, although alternatives might be `reset()` or `renew()`
+``
+int main(int, char**)
+{
+ cgi::fcgi_service service;
+
+ cgi::request req(&service);
+ do {
+ req.header("Content-type: text/plain");
+ req<< "Hello world";
+ } while( req.reset() );
+
+ return 0;
+}
+``
+An alternative to this, fitting closer to the FastCGI reference implementation might be the following:
+(NB.this approach would change the code slightly in the FastCGI example [link cgi.code_examples.realistic_fastcgi_example below])
+``
+int main(int, char**)
+{
+ cgi::fcgi_service service; // equivalent to cgi::basic_cgi_service<cgi::fcgi> service;
+
+ cgi::request req(&service, false); // false => don't load a request yet
+ while( req.accept() )
+ {
+ req.status(204); // would output "204 No Content\r\n" for SCGI
+ // "Status: 204 No Content\r\n" for FastCGI
+ // and would be a NOP for stdCGI
+ req.header("Content-type: text/plain");
+ req<< "Hello world";
+ }
+}
+``
+
+[endsect]
+[section Realistic FastCGI Example]
+
+The following is an example of a CGI program that exploits the benefits of handling many requests per program. This setup allows alot of flexibility in how responsive a process should be to incoming requests.
+``
+void sub_main( cgi::reqest& req )
+{
+ do {
+ req.header("Content-type: text/plain");
+ req<< "Hello, world";
+ } while( req.renew() );
+}
+
+class event_handler : public cgi::event_handler
+{
+ boost::thread_group work_threads_;
+ boost::mutex mutex_;
+ int available_threads_;
+public:
+ typedef boost::mutex::scoped_lock scoped_lock;
+
+ event_handler( int max_threads )
+ : available_threads_(max_threads)
+ { }
+
+ virtual ~event_handler()
+ {
+ work_threads_.join_all();
+ }
+
+ virtual void operator() ( cgi::event_type event, cgi::request* req, )
+ {
+ scoped_lock lk(&mutex_);
+ if( event == cgi::event_type::new_request && available_threads_ )
+ {
+ --available_threads_;
+ work_threads_.create_thread( boost::bind( &sub_main
+ , boost::ref(*req)
+ )
+ );
+ }
+ if( event == cgi::event_type::request_not_renewed ) // just a thought
+ /* this event_type would be sent when a request is closed without
+ being renewed. If this example was extended and the loop in
+ sub_main could be broken, that would imply destruction of a
+ thread */
+ ++available_threads_;
+ }
+};
+
+int main(int, char**)
+{
+ event_handler listener(50);
+ cgi::fcgi_service service( listener );
+ return 0;
+}
+``
+
+The above shows how my FastCGI implementation currently uses an external event handler. Personally, I'd prefer to have an internal scheduler, which could make `main()` above become something like:
+
+``
+int main(int, char**)
+{
+ // ideally this would just be 'cgi::options' with no code generation for
+ // options that don't work with that particular flavour of service
+ // is this possible? worthwhile?
+ cgi::fcgi_options opt;
+ // up to 50 threads are spawned to handle new requests, assuming a thread
+ // isn't waiting for a new one
+ opt.set_option(cgi::max_threads, 50);
+ // if the max threads are in use and the queue size reaches this limit,
+ // start rejecting incoming requests by returning FCGI_OVERLOADED to the
+ // server
+ opt.set_option(cgi::max_queue_size, 30);
+ cgi::fcgi_service service( &sub_main, opt );
+ return 0;
+}
+``
+
+This would remove the need for the nasty-looking event handler, make the simplest "hello world" case more practicable and possibly make the code more portable by removing the need for applications to detect if threads are available. The reason I've kept the external event handler for now is that I'm still not sure that there are no cases where the added insight into the workings of the `fcgi_service` is needed. I'm not sure if it's still necessary though, and I like the cleaner, internal-handler approach better. (Thoughts, please?)
+
+What I'm wondering now:
+
+* Is the first approach better, or can the second approach (ie. dynamic options) plus an incremental check (from `main`) as to the status of the `fcgi_service` offer more flexibility?
+ * Essentially this boils down to: can every fringe case be handled with an option setting?
+* Rather than hard-coding the spawn/serve/reject rules in the second approach, would using an internal handler - which could be replaced by a user-defined handler - add significant/any overhead? Hmmm.
+
+[endsect]
+
+[section Simple SCGI example]
+
+The following is essentially the same as above, but using the SCGI protcol.
+``
+int main(int, char**)
+{
+ cgi::scgi_service service; // the only line changed
+
+ cgi::request req(&service);
+ while( req.accept() )
+ {
+ req.status(206); // would output "206 Partial Content\r\n"
+ req.header("Content-type: text/plain");
+ std::cout(&req.rdbuf()); // this has to work too
+ std::cout<< "Hello world";
+ }
+}
+``
+[endsect]
+
+[endsect]
+
+[section Discussion]
+
+[section The `cgi::request` object]
+
+To clarify some of the discussion in the proposal, the referenced `request` object will likely be a 'bridge' object (correct nomenclature?) and could take the following form:
+
+``
+template<typename CGI_Service>
+class request : boost:noncopyable
+{
+ service_type* service_;
+ request_type* request_impl_;
+ bool std_cgi_;
+public:
+ typedef basic_cgi_service<CGI_Service> service_type;
+ typedef basic_cgi_request<CGI_Service> request_type;
+
+ request( service_type* service = NULL
+ , bool load_now = true )
+ : service_(service)
+ , std_cgi_(false)
+ {
+ if( !service )
+ {// default to standard CGI
+ std_cgi_ = true;
+ service_ = new basic_cgi_service<cgi>;
+ }
+ if( load_now )
+ request_impl_ = service_.yield_one(); // get a request from the request queue
+ }
+
+ ~request()
+ {
+ service_.end_request(request_impl_); // housekeeping
+ if( std_cgi_ ) delete service_;
+ }
+
+ int accept()
+ {
+ if( std_cgi_ ) return 0;
+ return service_.yield_one()
+
+ // ...
+};
+``
+[endsect]
+
+[section C++'s use as a CGI language]
+
+Some thoughts:
+
+* C++ is designed to aid large-scale developments, which modern web-based applications are a prime example of;
+* C++0x will likely bring with it facilities (such as regular expressions and threads) which make the language well suited to this domain;
+* An emerging trend (I use the term loosely) as web applications and language-binding technologies mature, is for components to be first developed using an RAD language like Python and later when the code settles for it to be ported to C++. Access to a scalable C++ CGI library would aid and encourage this development style;
+* Given how widely practised and understood CGI programming is, with all the home-grown CGI libraries around, C++ should really have a robust CGI library with a standard API.
+
+[endsect]
+
+
+
+[section Justification for seperation of `cgi::service` and `cgi::request`]
+
+It is actually possible to create a library capable of dealing with CGI, FastCGI and SCGI protocols with the simple 'hello world' example below. The logic for doing so [link cgi.discussion.logic follows this section].
+``
+int main(int, char**)
+{
+ cgi::request q;
+ q.header("Content-type: text/plain");
+ q<< "Hello world";
+ return 0;
+}
+``
+This approach is poor C++ style for several reasons:
+
+* First - and most importantly - the assumption made to differentiate between FastCGI and SCGI is not guaranteed to always remain valid. In that case, the `service` and `request` objects would have to be separated, breaking any code using the library.
+* Second, it is guaranteed to provide suboptimal performance by clarifying program function at run-time when it could very simply be achieved at compile-time.
+* Thirdly, the syntax implies a closer tying of request and protocol service than an implementation is likely to provide: in reality, protocols will provide control mechanisms to the program which bear no relation to the processing request. Programmers should be able to distinguish between the two targets rather than making ambiguous-looking calls on a `request` object when it in fact bears no relation to that request.
+* Finally, separation provides flexibility. A `cgi::basic_cgi_service<>` object has to provide no more than a guarantee to interpret functions into a `cgi::basic_cgi_request<>` format - which will hopefully be very unrestrictive - in order to be useable. As an hypothetical example, a program using this library could potentially be a standalone HTTP server, as long as the '`http_service`' (eg. a `typedef` of `cgi::basic_cgi_service<cgi::http>`) handled everything, except for CGI requests, which it loads into an `http_request` and adds to the request queue. (I like this idea, although it's far beyond the scope of the proposal)
+
+A more subtle point is that some systems allow CGI variables to be sent via the command line. Since this is uncommon practice, the example above should work in the vast majority of cases. Since I consider taking over `main()` a no-go, this fringe case can easily be handled by a `cgi::service` whose constructor takes the program command line arguements.
+
+All but the first point are also justification for not just proposing a FastCGI-only library.
+
+[endsect]
+
+[section:logic Differentiating Between CGI, SCGI and FastCGI Automatically]
+
+Below is a brief explanation how the differences between these protocols could ['currently] be exploited to provide a library that can automagically guess which protocol it's being called with.
+
+Note: This is essentially a 'trick', which works on the basis of several (high-probability) assumptions. It's something I shrugged off for good reason before even attempting to implement it. It is here as a curiosity, so skip it if you're pressed for time.
+
+``
+// Guarantee: FCGI_LISTENSOCK_FILENO equals STDIN_FILENO
+if ( ! (getpeername(FCGI_LISTENSOCK_FILENO) == -1 && errno == ENOTCONN ) )
+ // we have a standard CGI object; end of guessing
+``
+
+# SCGI always reports the message length followed by a colon before the packet starts. This message length does not include the stdin characters.
+# Then CGI environment variables are passed through the socket (these add to the message length) with the format `NAME<00>VALUE<00>` where `<00>` is the NULL character.
+# A guarantee of SCGI is that variable `CONTENT_LENGTH` is set even if it is zero. There must also be a variable `SCGI` with a value of 1. That makes the shortest message length 24 - from `CONTENT_LENGTH<00>0<00>SCGI<00>1<00>`.
+This means that the first two characters sent to the program must be either "24" or numerically larger ("25", "26", etc.).
+# With FastCGI the first character is the version number, which is currently 1. The second character would have to be either 1 (`FCGI_BEGIN_REQUEST`) or 9 (`FCGI_GET_VALUES` - used by the server to query the program about its multiplexing capabilities: currently this isn't used by either apache, lighttpd or Zeus)
+# [*Now the theory starts getting speculative]
+# The SCGI protocol states that the server ['should] pass the standard CGI variables through the socket, this would push the message length (ie. the first two+ characters) well over 24.
+# The FastCGI 1.0 specification has been around for over a decade. The assumption here is that the number isn't likely to increment at a fast pace (probable, but crude)
+# Even if FastCGI 2.0 came out, the only possible failing scenario is if the server queries with FCGI_GET_VALUES: the SCGI equivalent arises with the minimum message described above with an environment variable whose name<00>value<00> combined length is 5, called via the POST method (ie. QUERY_STRING will probably not be set). This is unlikely (but possible) since REQUEST_METHOD is always likely to be set as either GET or POST, adding at least 19 to the message length value.
+
+Thus, this hypothetical all-inclusive library would probably function until the implementation of a FastCGI 4 - compatible server. Considering FastCGI 1.0 is still very poorly supported by servers, this is not exactly a 'jaws senario'. The guessing penalty would even become insignificant if the program ran for long enough. Heh, in the end, this just isn't C++, is it? Besides, a service capable of doing this could easily be implemented using the proposed framework.
+
+[endsect]
+
+[section To Do]
+
+* Signal handling (see [@http://www.fastcgi.com/docs/faq.html#Signals] for FastCGI-specific information; inquire about SCGI)
+* Change outputting for `cgi::fcgi_service` to use Boost.Iostreams (probably a `filtering_streambuf` so it can be added to a chain - in case a user wants to format output, for instance)
+* ...
+
+[endsect]
+
+[section Moving fcgi::service::event_handler into an internal one]
+
+Possible signals for the `event_handler` (and what they're likely to be used for), assuming efficiency wasn't an issue:
+
+* New request
+ * Taken by existing thread
+ * Not taken by existing thread (ie. spawn a new thread to handle it)
+* Request not renewed (aka. thread not reused/thread closed naturally)
+* Request aborted (FastCGI-specific, I think)
+
+[endsect]
+
+[endsect]
+
+[endsect]
Added: sandbox/SOC/2007/cgi/libs/cgi/doc/program_flow.txt
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/libs/cgi/doc/program_flow.txt 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,47 @@
+service
+-> makes:
+ an io_service object, or takes a reference from the user
+ a gateway
+ a request queue (std::queue, empty)
+ a container for request_parsers (std::set, empty)
+ a dispatcher
+
+gateway
+-> constructed with the max number of connections allowed
+-> makes:
+ an acceptor
+ a container for connections (std::set, empty)
+-> asynchronously accepts a connection
+-> verifies the connection is good: if not, then try another allowed type
+-> notifies the service when a connection is created
+
+service
+-> makes:
+ a request_parser
+
+request_parser
+-> constructed with the connection and the service
+-> makes:
+ a pointer to the request currently being served
+ a relevant header object (uninitialized)
+ a note of the current state of the parser
+-> requests the connection read into a supplied buffer supplied by the
+ request_parser
+
+connection
+-> constructed with the request_parser
+-> does an async_read into the buffer supplied by the parser_
+-> notify the parser_ when the read is complete: call parser_.parse()
+
+request_parser
+-> parse the supplied data
+-> if it's a header, interpret it, handle it if necessary and then continue
+-> the return value of parse():
+ true => all ok, stop reading for now
+ false => error: stop reading, close connection
+ indeterminite => all ok, read some more
+-> eventually, the request will be ready for being handled
+ it's added to the request queue
+-> read the next header only, in case it relates to another request
+
+
Added: sandbox/SOC/2007/cgi/libs/cgi/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/libs/cgi/test/Jamfile.v2 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,7 @@
+
+import testing ;
+
+test-suite "cgi"
+ : # [ run test_1.cpp ]
+ ;
+
Added: sandbox/SOC/2007/cgi/project-root.jam
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/project-root.jam 2007-07-05 15:51:32 EDT (Thu, 05 Jul 2007)
@@ -0,0 +1,4 @@
+import os ;
+
+path-constant BOOST_ROOT : [ os.environ BOOST_ROOT ] ;
+path-constant BOOST_BUILD_PATH : [ os.environ BOOST_BUILD_PATH ] ;
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