|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r56365 - in sandbox/SOC/2007/cgi/branches/pickmeup: boost/cgi/common boost/cgi/fcgi libs/cgi/build/msvc/9.0/Boost.CGI libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_file_browser libs/cgi/example/fcgi/echo libs/cgi/example/fcgi/file_browser
From: lists.drrngrvy_at_[hidden]
Date: 2009-09-23 08:29:57
Author: drrngrvy
Date: 2009-09-23 08:29:56 EDT (Wed, 23 Sep 2009)
New Revision: 56365
URL: http://svn.boost.org/trac/boost/changeset/56365
Log:
Bug fixes for FastCGI. Tested on Windows XP with MSVC9.0. Binary reads / writes seem stable now with large files, if a bit slow.
Binary files modified:
sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.ncb
sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.suo
Text files modified:
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/header.hpp | 11 ++---
sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp | 49 ++++++++++++++++----------
sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_file_browser/fcgi_file_browser.vcproj | 6 ++-
sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/echo/main.cpp | 29 +++++----------
sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/file_browser/main.cpp | 73 +++++++++++++++++++++++++--------------
5 files changed, 94 insertions(+), 74 deletions(-)
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/header.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/header.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/common/header.hpp 2009-09-23 08:29:56 EDT (Wed, 23 Sep 2009)
@@ -52,6 +52,10 @@
: content("Set-cookie: " + ck.to_string())
{
}
+
+ operator string_type () {
+ return content + "\r\n";
+ }
string_type content;
};
@@ -115,13 +119,6 @@
return basic_header<CharT>("Content-encoding", str);
}
- template<typename CharT, typename T> basic_header<CharT>
- content_length(const T& t)
- {
- return basic_header<CharT>("Content-length",
- boost::lexical_cast<std::basic_string<CharT> >(t));
- }
-
template<typename CharT> basic_header<CharT>
content_length(const CharT * t)
{
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/boost/cgi/fcgi/client.hpp 2009-09-23 08:29:56 EDT (Wed, 23 Sep 2009)
@@ -124,26 +124,36 @@
boost::system::error_code
close(boost::uint64_t app_status, boost::system::error_code& ec)
{
- if (status_ == closed_) return ec;
-
- outbuf_.clear();
- header_.reset(spec_detail::END_REQUEST, request_id_, 8);
- // Write an EndRequest packet to the server.
-
- //BOOST_ASSERT(role_ == fcgi::spec_detail::RESPONDER
- // && "Only supports Responder role for now (**FIXME**)");
-
- fcgi::spec::end_request_body body(
- app_status, fcgi::spec_detail::REQUEST_COMPLETE);
+ // We can safely ignore this next bit when the connection
+ // is already closed. This might happen when the client aborts
+ // the connection.
+ if (!ec && status_ != closed_ && connection_->is_open())
+ {
+ outbuf_.clear();
+ header_.reset(spec_detail::END_REQUEST, request_id_, 8);
- outbuf_.push_back(header_.data());
- outbuf_.push_back(body.data());
+ // Write an EndRequest packet to the server.
+ fcgi::spec::end_request_body body(
+ app_status, fcgi::spec_detail::REQUEST_COMPLETE);
- write(*connection_, outbuf_, boost::asio::transfer_all(), ec);
+ outbuf_.push_back(header_.data());
+ outbuf_.push_back(body.data());
- if (!ec && !keep_connection_)
- connection_->close();
+ write(*connection_, outbuf_, boost::asio::transfer_all(), ec);
+ if (!ec && !keep_connection_)
+ {
+ connection_->close();
+ }
+ }
+
+ if (ec && !keep_connection_)
+ {
+ // If there was an error writing to the client, we can ignore it
+ // unless the `keep_connection_` flag is set.
+ // The client has likely aborted the request if we reach here.
+ ec = boost::system::error_code();
+ }
return ec;
}
@@ -188,8 +198,6 @@
{
boost::asio::const_buffer buffer(*iter);
std::size_t new_buf_size( boost::asio::buffer_size(*iter) );
- std::cerr<< "-" << new_buf_size << "-";
- // Only write a maximum of 65535 bytes.
if (total_buffer_size + new_buf_size
> static_cast<std::size_t>(fcgi::spec::max_packet_size::value))
{
@@ -200,8 +208,10 @@
{
total_buffer_size
= std::min<std::size_t>(new_buf_size,65500);
+ /*
std::cerr<< "Oversized buffer: " << total_buffer_size
<< " / " << new_buf_size << " bytes sent\n";
+ */
outbuf_.push_back(
boost::asio::buffer(*iter, total_buffer_size));
break;
@@ -221,13 +231,14 @@
= boost::asio::write(*connection_, outbuf_
, boost::asio::transfer_all(), ec);
+ /*
std::cerr<< "Transferred " << bytes_transferred
<< " / " << total_buffer_size << " bytes (running total: "
<< total_sent_bytes_ << "; "
<< total_sent_packets_ << " packets).\n";
if (ec)
std::cerr<< "Error " << ec << ": " << ec.message() << '\n';
-
+ */
total_sent_bytes_ += bytes_transferred;
total_sent_packets_ += 1;
// Now remove the protocol overhead from the caller, who
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.ncb
==============================================================================
Binary files. No diff available.
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/Boost.CGI.suo
==============================================================================
Binary files. No diff available.
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_file_browser/fcgi_file_browser.vcproj
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_file_browser/fcgi_file_browser.vcproj (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/build/msvc/9.0/Boost.CGI/fcgi_file_browser/fcgi_file_browser.vcproj 2009-09-23 08:29:56 EDT (Wed, 23 Sep 2009)
@@ -114,11 +114,13 @@
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="2"
+ Optimization="3"
EnableIntrinsicFunctions="true"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
+ DisableLanguageExtensions="false"
+ RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
@@ -135,7 +137,7 @@
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
- GenerateDebugInformation="true"
+ GenerateDebugInformation="false"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/echo/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/echo/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/echo/main.cpp 2009-09-23 08:29:56 EDT (Wed, 23 Sep 2009)
@@ -150,18 +150,9 @@
resp<< "Response content-length == "
<< resp.content_length(); // the content-length (returns std::size_t)
- // This function finishes up:
- return commit(req, resp, 0);
- //
- // It is equivalent to the below, where the third argument is represented by
- // `program_status`:
- //
- // resp.send(req.client());
- // req.close(resp.status(), program_status);
- // return program_status;
- //
- // Note: in this case `program_status == 0`.
- //
+ // This function finishes up. The optional third argument
+ // is the program status (default: 0).
+ return commit(req, resp);
}
int main()
@@ -197,7 +188,7 @@
for (;;)
{
a.accept(req);
- //cerr<< "Accepted" << endl;
+ cerr<< "Accepted new request.\n";
ret = handle_request(req);
if (ret)
break;
@@ -214,15 +205,15 @@
}catch(boost::system::system_error const& se){
// This is the type of error thrown by the library.
- //cerr<< "[fcgi] System error: " << se.what() << endl;
- return 1313;
+ cerr<< "[fcgi] System error: " << se.what() << endl;
+ return -1;
}catch(std::exception const& e){
// Catch any other exceptions
- //cerr<< "[fcgi] Exception: " << e.what() << endl;
- return 666;
+ cerr<< "[fcgi] Exception: " << e.what() << endl;
+ return -2;
}catch(...){
- //cerr<< "[fcgi] Uncaught exception!" << endl;
- return 667;
+ cerr<< "[fcgi] Uncaught exception!" << endl;
+ return -3;
}
}
//]
Modified: sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/file_browser/main.cpp
==============================================================================
--- sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/file_browser/main.cpp (original)
+++ sandbox/SOC/2007/cgi/branches/pickmeup/libs/cgi/example/fcgi/file_browser/main.cpp 2009-09-23 08:29:56 EDT (Wed, 23 Sep 2009)
@@ -97,6 +97,9 @@
if (filetype == "ogg")
return "audio/ogg";
else
+ if (filetype == "flac")
+ return "audio/flac";
+ else
if (filetype == "mp3")
return "audio/mpeg";
else
@@ -145,7 +148,9 @@
}
template<typename Response, typename Client>
-void show_file(Response& resp, Client& client, fs::path const& file)
+boost::system::error_code& show_file(
+ Response& resp, Client& client, fs::path const& file
+ , boost::system::error_code& ec)
{
if (!fs::exists(file))
resp<< content_type("text/plain")
@@ -154,7 +159,7 @@
{
boost::uintmax_t size (fs::file_size(file));
cerr<< "size: " << size << endl;
- if (size > 200000000L) // Files must be < 200MB
+ if (size > 750000000L) // Files must be < 750MB (this is arbitrary).
resp<< "File too large.";
else
{
@@ -162,42 +167,52 @@
std::string mime_type (get_mime_type(file));
if (!mime_type.empty())
{
+ // Write unbuffered (ie. not using a response). This makes sense
+ // for large files, which would take up too much memory to
+ // buffer.
+ // First, some debugging to the console.
cerr<< "MIME-type: " << mime_type << '\n';
cerr<< "File size: " << size << '\n';
- std::string ctype (content_type(mime_type).content + "\r\n\r\n");
- write(client, boost::asio::buffer(clen));
- write(client, boost::asio::buffer(ctype));
/// Open the file and read it as binary data.
ifstream ifs (file.string().c_str(), std::ios::binary);
if (ifs.is_open())
{
- resp<< content_type(mime_type);
- //resp.flush(client);
- boost::uintmax_t bufsize = 1000;
+ // Write out the response headers.
+ std::string ctype (content_type(mime_type));
+ std::string clen (content_length<char>(size));
+ clen += "\r\n";
+ write(client, boost::asio::buffer(ctype));
+ write(client, boost::asio::buffer(clen));
+ // Read then write up to 1MB at a time.
+ boost::uintmax_t bufsize = 1000000;
boost::uintmax_t read_bytes;
- char buf[1000];
+ char buf[1000000];
ifs.seekg(0, std::ios::beg);
- while (!ifs.eof() && size > 0)
+ while (!ifs.eof() && size > 0 && !ec)
{
ifs.read(buf, size < bufsize ? size : bufsize);
read_bytes = ifs.gcount();
size -= read_bytes;
- cerr<< "Read " << read_bytes << " bytes from the file.\n";
- //if (resp.content_length() + read_bytes >= 65000)
- // resp.flush(client);
- //resp.write(buf, read_bytes);
- write(client, boost::asio::buffer(buf, read_bytes));
- //resp.flush(client);
+ //cerr<< "Read " << read_bytes << " bytes from the file.\n";
+ // Write unbuffered (ie. not using a response).
+ write(client, boost::asio::buffer(buf, read_bytes)
+ , boost::asio::transfer_all(), ec);
}
- //resp.send(client);
- //cerr<< "Content-length: " << resp.content_length() << '\n';
+ }
+ else
+ {
+ resp<< content_type("text/plain")
+ << "File cannot be opened. Please try again later.";
}
}
else
+ {
resp<< content_type("text/plain")
<< "File type not allowed.";
+ }
}
}
+ return ec;
}
template<typename Response>
@@ -229,12 +244,10 @@
}
else
{
- // display filename only.
+ // Display only the filename.
resp<< "<li class=\"file\"><a href=\"?file="
<< iter->string() << "\">" << iter->path().filename()
<< "</a>";
- //if (fs::is_regular_file(iter->status()))
- // resp<< " [" << fs::file_size(iter->path()) << " bytes]";
resp<< "</li>\n";
}
}
@@ -265,9 +278,15 @@
if (req.get.count("file"))
{
- show_file(resp, req.client(), req.get["file"]);
- req.close(resp.status(), 0);
- return 0; //commit(req, resp);
+ boost::system::error_code ec;
+ show_file(resp, req.client(), req.get["file"], ec);
+ if (ec)
+ {
+ cerr<< "Writing file finished unexpectedly!\n"
+ " Error " << ec << ": " << ec.message() << '\n';
+ // Carry on processing other requests.
+ return req.close(http::request_timeout, -1, ec);
+ }
}
else
if (req.get.count("dir"))
@@ -292,7 +311,7 @@
resp<< content_type("text/plain")
<< "No path specified.\n";
- //resp<< header("FastCGI-client", "fcgi_file_browser");
+ resp<< header("FastCGI-client", "fcgi_file_browser");
return commit(req, resp);
}
@@ -307,7 +326,7 @@
// Accept requests on port 8001. You should configure your HTTP
// server to try to connect on this port.
- acceptor a(s, 8001);
+ acceptor a(s, 8001);
int ret(0);
for (;;)
@@ -317,7 +336,7 @@
for (;;)
{
a.accept(req);
- if (0 != handle_request(req))
+ if (handle_request(req))
break;
req.clear();
}
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