http_connection.cpp
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       // error constructing request
00043       // just kill the connection as the handler may have already started writing stuff out
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 // Must be called while holding write lock
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 }


async_web_server_cpp
Author(s): Mitchell Wills
autogenerated on Fri Mar 4 2016 11:30:14