Boost logo

Boost-Commit :

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;
 


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