Go to the documentation of this file.00001 #include <boost/bind.hpp>
00002 #include <boost/make_shared.hpp>
00003 #include "async_web_server_cpp/http_reply.hpp"
00004
00005 namespace async_web_server_cpp
00006 {
00007
00008 HttpConnection::HttpConnection(boost::asio::io_service &io_service,
00009 HttpServerRequestHandler handler)
00010 : strand_(io_service),
00011 socket_(io_service),
00012 request_handler_(handler),
00013 write_in_progress_(false)
00014 {
00015 }
00016
00017 boost::asio::ip::tcp::socket &HttpConnection::socket()
00018 {
00019 return socket_;
00020 }
00021
00022 void HttpConnection::start()
00023 {
00024 async_read(boost::bind(&HttpConnection::handle_read, shared_from_this(), _1, _2));
00025 }
00026
00027 void HttpConnection::handle_read(const char* begin, const char* end)
00028 {
00029 boost::tribool result;
00030 const char* parse_end;
00031 boost::tie(result, parse_end) = request_parser_.parse(request_, begin, end);
00032
00033 if (result)
00034 {
00035 request_.parse_uri();
00036 try
00037 {
00038 request_handler_(request_, shared_from_this(), parse_end, end);
00039 }
00040 catch (...)
00041 {
00042
00043
00044 }
00045 }
00046 else if (!result)
00047 {
00048 HttpReply::stock_reply(HttpReply::bad_request)(request_, shared_from_this(), begin, end);
00049 }
00050 else
00051 {
00052 async_read(boost::bind(&HttpConnection::handle_read, shared_from_this(), _1, _2));
00053 }
00054 }
00055
00056 void HttpConnection::handle_read_raw(ReadHandler callback,
00057 const boost::system::error_code &e,
00058 std::size_t bytes_transferred)
00059 {
00060 if (!e)
00061 {
00062 callback(buffer_.data(), buffer_.data() + bytes_transferred);
00063 }
00064 else
00065 {
00066 last_error_ = e;
00067 }
00068 }
00069 void HttpConnection::async_read(ReadHandler callback)
00070 {
00071 if (last_error_)
00072 {
00073 boost::throw_exception(boost::system::system_error(last_error_));
00074 }
00075 socket_.async_read_some(boost::asio::buffer(buffer_),
00076 strand_.wrap(boost::bind(&HttpConnection::handle_read_raw, shared_from_this(),
00077 callback,
00078 boost::asio::placeholders::error,
00079 boost::asio::placeholders::bytes_transferred)));
00080 }
00081
00082 void HttpConnection::write_and_clear(std::vector<unsigned char> &data)
00083 {
00084 boost::shared_ptr<std::vector<unsigned char> > buffer(new std::vector<unsigned char>());
00085 buffer->swap(data);
00086 write(boost::asio::buffer(*buffer), buffer);
00087 }
00088
00089 void HttpConnection::write(const std::string &content)
00090 {
00091 boost::shared_ptr<std::string> str(new std::string(content));
00092 write(boost::asio::buffer(*str), str);
00093 }
00094
00095 void HttpConnection::write(const boost::asio::const_buffer &buffer,
00096 ResourcePtr resource)
00097 {
00098 boost::mutex::scoped_lock lock(write_mutex_);
00099 pending_write_buffers_.push_back(buffer);
00100 if (resource)
00101 pending_write_resources_.push_back(resource);
00102 if (!write_in_progress_)
00103 write_pending();
00104 }
00105
00106 void HttpConnection::write(const std::vector<boost::asio::const_buffer> &buffers,
00107 ResourcePtr resource)
00108 {
00109 boost::mutex::scoped_lock lock(write_mutex_);
00110 pending_write_buffers_.insert(pending_write_buffers_.end(), buffers.begin(), buffers.end());
00111 if (resource)
00112 pending_write_resources_.push_back(resource);
00113 if (!write_in_progress_)
00114 write_pending();
00115 }
00116
00117
00118
00119 void HttpConnection::write_pending()
00120 {
00121 if (last_error_)
00122 {
00123 boost::throw_exception(boost::system::system_error(last_error_));
00124 }
00125 write_in_progress_ = true;
00126 boost::asio::async_write(socket_, pending_write_buffers_,
00127 boost::bind(&HttpConnection::handle_write, shared_from_this(),
00128 boost::asio::placeholders::error,
00129 pending_write_resources_));
00130 pending_write_buffers_.clear();
00131 pending_write_resources_.clear();
00132 }
00133
00134 void HttpConnection::handle_write(const boost::system::error_code &e,
00135 std::vector<ResourcePtr> resources)
00136 {
00137 boost::mutex::scoped_lock lock(write_mutex_);
00138 write_in_progress_ = false;
00139 if (!e)
00140 {
00141 if (!pending_write_buffers_.empty())
00142 {
00143 write_pending();
00144 }
00145 }
00146 else
00147 {
00148 last_error_ = e;
00149 }
00150 }
00151
00152 }