$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: lists.drrngrvy_at_[hidden]
Date: 2008-02-09 12:18:36
Author: drrngrvy
Date: 2008-02-09 12:18:35 EST (Sat, 09 Feb 2008)
New Revision: 43197
URL: http://svn.boost.org/trac/boost/changeset/43197
Log:
FastCGI environment variables are stored now. The fcgi/hello_world example displays them (will move this to fcgi/echo when things settle a bit).
Text files modified: 
   sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request.hpp                    |    15 ++++-                                   
   sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/shareable_tcp_socket.hpp |     4 +                                       
   sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/protocol_traits.hpp           |     4 +                                       
   sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/error.hpp                            |    31 +++++++++++                             
   sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/client.hpp                      |     9 +++                                     
   sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_service.hpp             |   103 ++++++++++++++++++++++++++++++++++++--- 
   sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/specification.hpp               |     5 +                                       
   sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/main.cpp     |    19 ++++++                                  
   8 files changed, 171 insertions(+), 19 deletions(-)
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request.hpp	(original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/basic_request.hpp	2008-02-09 12:18:35 EST (Sat, 09 Feb 2008)
@@ -111,6 +111,7 @@
                  , const bool parse_post = false)
       : basic_io_object<service_type>(s.io_service())
     {
+      set_protocol_service(s);
       if (load_now) load(parse_post);//this->service.load(this->impl, false, ec);
     }
 
@@ -120,6 +121,7 @@
                  , const bool load_now = false, const bool parse_post = false)
       : basic_io_object<service_type>(s.io_service())
     {
+      set_protocol_service(s);
       if(load_now) load(ec, parse_post);//this->service.load(this->impl, false, ec);
     }
 
@@ -129,6 +131,11 @@
       //  close(http::internal_server_error, 0);
     }
 
+    void set_protocol_service(protocol_service_type& ps)
+    {
+      this->service.set_service(this->impl, ps);
+    }
+
     /// Return `true` if the request is still open (ie. not aborted or closed)
     bool is_open()
     {
@@ -148,8 +155,8 @@
     }
 
     // Error-code semantics
-    boost::system::error_code& load(boost::system::error_code& ec
-                                   , bool parse_stdin = false)
+    boost::system::error_code&
+      load(boost::system::error_code& ec, bool parse_stdin = false)
     {
       return this->service.load(this->impl, parse_stdin, ec);
     }
@@ -241,7 +248,7 @@
     void read_some(const MutableBufferSequence& buf)
     {
       boost::system::error_code ec;
-      this->service.read_some(this->implementation, buf, ec);
+      this->service.read_some(this->impl, buf, ec);
       detail::throw_error(ec);
     }
 
@@ -249,7 +256,7 @@
     boost::system::error_code
       read_some(const MutableBufferSequence& buf, boost::system::error_code& ec)
     {
-      return this->service.read_some(this->implementation, buf, ec);
+      return this->service.read_some(this->impl, buf, ec);
     }
 
     /// Set the output for the request
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/shareable_tcp_socket.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/shareable_tcp_socket.hpp	(original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/connections/shareable_tcp_socket.hpp	2008-02-09 12:18:35 EST (Sat, 09 Feb 2008)
@@ -49,7 +49,10 @@
     //typedef ::cgi::fcgi::client                      client_type;
     typedef //typename
       detail::protocol_traits<fcgi_>::request_type   request_type;
+    typedef 
+      detail::protocol_traits<fcgi_>::request_ptr    request_ptr;
     typedef std::map<boost::uint16_t, request_type*> request_map_type;
+    typedef std::vector<request_ptr>                 request_vector_type;
 
     /** End FastCGI stuff      **/
 
@@ -135,6 +138,7 @@
   public:
     /** FastCGI specific stuff **/
     request_map_type request_map_;
+    request_vector_type requests_;
   };
 
   // probably deletable typedef (leaving it here to keep an open mind)
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/protocol_traits.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/protocol_traits.hpp	(original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/detail/protocol_traits.hpp	2008-02-09 12:18:35 EST (Sat, 09 Feb 2008)
@@ -16,6 +16,7 @@
 #ifndef CGI_REQUEST_TRAITS_HPP_INCLUDED__
 #define CGI_REQUEST_TRAITS_HPP_INCLUDED__
 
+#include <boost/shared_ptr.hpp>
 #include "boost/cgi/tags.hpp"
 #include "boost/cgi/basic_request_fwd.hpp"
 #include "boost/cgi/basic_connection_fwd.hpp"
@@ -137,10 +138,11 @@
       typedef protocol_traits<tags::fcgi>            type;
       typedef fcgi::fcgi_request_impl                impl_type;
       typedef fcgi::fcgi_request_service             request_service_impl;
-      typedef basic_protocol_service<tags::fcgi>     protocol_service_type;
+      typedef basic_protocol_service<fcgi_>          protocol_service_type;
       typedef basic_request<
         request_service_impl, protocol_service_type
       >                                              request_type; 
+      typedef boost::shared_ptr<request_type>        request_ptr;
       //typedef fcgi_request_service
       //        ::implementation_type                  request_impl_type;
       typedef fcgi::fcgi_service_impl                service_impl_type;
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/error.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/error.hpp	(original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/error.hpp	2008-02-09 12:18:35 EST (Sat, 09 Feb 2008)
@@ -27,7 +27,22 @@
 
   /// A packet arrived for a request id that doesn't exist and the packet
   // wasn't a BEGIN_REQUEST record.
-  bad_request_id
+  bad_request_id,
+
+  /// When trying to write a packet, the client::write_some() call didn't
+  // transmit enough data before returning.
+  couldnt_write_complete_packet,
+
+  // Tried to read/write from/to the client associated to a request when it
+  // was closed.
+  client_closed,
+
+  // Self-explanatory (not much a user can do about this though).
+  abort_request_record_recieved_for_invalid_request,
+
+  // For now a user has to recognise this error and construct a request
+  // themselves. This is an ugly hack.
+  multiplexed_request_incoming
 };
 
   namespace detail {
@@ -37,7 +52,19 @@
 {
 public:
   const char* name() const { return "fcgi_error"; }
-  std::string message(int e) const { return "BOOM!!!"; }
+  std::string message(int e) const
+  {
+    switch(e)
+    {
+    case client_closed:
+      return "You are trying to read from or write to a closed client.";
+    case multiplexed_request_incoming:
+      return "A new request is pending on this connection (ie. it is "
+             "multiplexed). This isn't handled for now. **FIXME**";
+    default:
+      return "BOOM!!!";
+    }
+  }
 };
 
   } // namespace detail
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/client.hpp	(original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/client.hpp	2008-02-09 12:18:35 EST (Sat, 09 Feb 2008)
@@ -175,7 +175,14 @@
       out_header_[7] = 0;
 
       bufs.front() = boost::asio::buffer(out_header_);
-      return boost::asio::write(*connection_, bufs, boost::asio::transfer_all(), ec);
+      std::size_t bytes_transferred
+        = boost::asio::write(*connection_, bufs, boost::asio::transfer_all(), ec);
+
+      if (0 != (total_buffer_size + fcgi::spec::header_length::value
+          - bytes_transferred))
+        ec = error::couldnt_write_complete_packet;
+
+      return bytes_transferred;
     }
 
     /// Asynchronously write some data to the client.
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_service.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_service.hpp	(original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/request_service.hpp	2008-02-09 12:18:35 EST (Sat, 09 Feb 2008)
@@ -44,6 +44,9 @@
       typedef std::vector<char>                 buffer_type;
       typedef boost::asio::mutable_buffers_1    mutable_buffers_type;
       typedef client_type::header_buffer_type   header_buffer_type;
+      typedef detail::protocol_traits<
+        protocol_type
+      >::protocol_service_type                  protocol_service_type;
 
       implementation_type()
         : client_()
@@ -55,6 +58,8 @@
       {
       }
 
+      protocol_service_type* service_;
+
       client_type client_;
 
       bool stdin_parsed_;
@@ -138,6 +143,12 @@
     {
     }
 
+    void set_service(implementation_type& impl
+                    , implementation_type::protocol_service_type& ps)
+    {
+      impl.service_ = &ps;
+    }
+
     bool is_open(implementation_type& impl)
     {
       return !impl.all_done_ && impl.client_.is_open();
@@ -302,7 +313,6 @@
       return impl.cookie_vars_;
     }
 
-
     /// Find the environment meta-variable matching name
     std::string env(implementation_type& impl, const std::string& name
                    , boost::system::error_code& ec)
@@ -310,6 +320,10 @@
       return var(impl.env_vars_, name, ec);
     }
 
+    map_type& env(implementation_type& impl)
+    {
+      return impl.env_vars_;
+    }
 
     role_type get_role(implementation_type& impl)
     {
@@ -408,10 +422,14 @@
     /// Read some data from the client.
     template<typename MutableBufferSequence>
     std::size_t
-      read_some(const MutableBufferSequence& buf, boost::system::error_code& ec)
+      read_some(implementation_type& impl, const MutableBufferSequence& buf
+               , boost::system::error_code& ec)
     {
-      //if (impl.client_.status_ == closed_)
-      //  return 0;
+      if (impl.client_.status_ == closed_)
+      {
+        ec = error::client_closed;
+        return 0;
+      }
 
       //if (read_header(ec))
         return -1;
@@ -425,7 +443,9 @@
     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;
@@ -467,10 +487,39 @@
                            , const unsigned char* buf, boost::uint16_t
                            , boost::system::error_code& ec)
     {
-      if (read_header(impl, ec))
-        detail::throw_error(ec);
+      //implementation_type& req
+      //  = impl.client_.request_id_ == 0
+      //    ? impl
+      //    : get_or_make_request(impl);
+          
+      if (impl.client_.request_id_ == 0) // ie. not set
+      {
+        impl.client_.request_id_ = fcgi::spec::get_request_id(impl.header_buf_);
+
+        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_);
+        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<< "Role: " << fcgi::spec::begin_request::get_role(impl.header_buf_) << std::endl;
+        impl.client_.status_ = constructed;
+      }
+      else
+      {
+        std::cerr<< "**FIXME** Role: " 
+          << fcgi::spec::begin_request::get_role(impl.header_buf_) << std::endl;
+        return error::multiplexed_request_incoming;
+      }
 
       //connection_->request_map_[id] = 
       return ec;
@@ -481,6 +530,18 @@
                            , 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_ = 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);
@@ -505,9 +566,8 @@
         
         impl.client_.status_ = params_read;
 
-        // **FIXME**
         std::cerr<< "[hw] Final PARAM record found." << std::endl;
-        return ec;//error::params_all_found;
+        return ec;
       }
 
       while(len)
@@ -550,6 +610,8 @@
 
         std::cerr<< "[hw] name := " << name << std::endl;
         std::cerr<< "[hw] data := " << data << std::endl;
+
+        impl.env_vars_[name] = data;
       }
 
       return ec;
@@ -667,6 +729,29 @@
             , boost::asio::buffer_cast<unsigned char*>(buffer)
             , boost::asio::buffer_size(buffer), ec);
     }
+
+/*
+    implementation_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;
+      implementation_type* ret;
+      
+      try {
+        ret = &requests.at(id - 1);
+        BOOST_ASSERT(req != 0); // should throw
+        return *ret;
+      }catch(...){
+        req = new request_type(impl.service_);
+        if (requests.size() < (id - 1))
+          requests.resize(id);
+        requests.at(id-1) = *req;
+        return *req; // same as *ret
+      }
+    }
+*/
+
   };
 
   //template<>
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/specification.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/specification.hpp	(original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/boost/cgi/fcgi/specification.hpp	2008-02-09 12:18:35 EST (Sat, 09 Feb 2008)
@@ -393,6 +393,11 @@
     struct begin_request
       : boost::mpl::int_<1>
     {
+      struct body
+      {
+        typedef boost::mpl::int_<8> size;
+      };
+
       template<typename Array>
       static spec_detail::role_t
         get_role(Array& a)
Modified: sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/main.cpp	(original)
+++ sandbox/SOC/2007/cgi/branches/acceptor_work/libs/cgi/example/fcgi/hello_world/main.cpp	2008-02-09 12:18:35 EST (Sat, 09 Feb 2008)
@@ -56,13 +56,28 @@
 
   req.load(ec, true);
 
-  string resp("Content-type: text/plain\r\n\r\nHello there, universe!");
-  const char* resp2 = "Content-type: text/plain\r\n\r\nHello there, universe.";
+  string resp("Content-type: text/html\r\n\r\nHello there, universe!<p />");
+  //const char* resp2 = "Content-type: text/plain\r\n\r\nHello there, universe.";
 
   write(req.client(), boost::asio::buffer(resp), boost::asio::transfer_all(), ec);
 
   of<< "[a] Wrote some data: " << ec.message() << endl;
 
+  cgi::map::const_iterator iter = req.env().begin();
+  cgi::map::const_iterator end = req.env().end();
+
+  for (; iter != end; ++iter)
+  {
+    string bit;
+    bit += "<b>" + iter->first + "</b> := <i>" + iter->second + "</i><br />";
+    write(req.client(), boost::asio::buffer(bit), boost::asio::transfer_all(), ec);
+    if (ec)
+    {
+      of<< "Got error writing env: " << ec.message() << endl;
+      break;
+    }
+  }
+
   //req.client().read_some(buf.prepare(64), ec);
   //of<< "[a] Read some data: " << ec.message() << endl;