00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <boost/asio.hpp>
00011 #include <boost/logic/tribool.hpp>
00012 #include <pion/net/HTTPReader.hpp>
00013 #include <pion/net/HTTPRequest.hpp>
00014
00015
00016 namespace pion {
00017 namespace net {
00018
00019
00020
00021
00022 void HTTPReader::receive(void)
00023 {
00024 if (m_tcp_conn->getPipelined()) {
00025
00026 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00027 m_tcp_conn->loadReadPosition(m_read_ptr, m_read_end_ptr);
00028 consumeBytes();
00029 } else {
00030
00031 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00032 readBytes();
00033 }
00034 }
00035
00036 void HTTPReader::consumeBytes(const boost::system::error_code& read_error,
00037 std::size_t bytes_read)
00038 {
00039 if (read_error) {
00040
00041 handleReadError(read_error);
00042 return;
00043 }
00044
00045 PION_LOG_DEBUG(m_logger, "Read " << bytes_read << " bytes from HTTP "
00046 << (isParsingRequest() ? "request" : "response"));
00047
00048
00049 setReadBuffer(m_tcp_conn->getReadBuffer().data(), bytes_read);
00050
00051 consumeBytes();
00052 }
00053
00054
00055 void HTTPReader::consumeBytes(void)
00056 {
00057
00058
00059
00060
00061
00062
00063
00064
00065 boost::tribool result = parse(getMessage());
00066
00067 if (gcount() > 0) {
00068
00069 PION_LOG_DEBUG(m_logger, "Parsed " << gcount() << " HTTP bytes");
00070 }
00071
00072 if (result == true) {
00073
00074
00075
00076 if (getMessage().checkKeepAlive()) {
00077 if ( eof() ) {
00078
00079 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_KEEPALIVE);
00080 } else {
00081
00082 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_PIPELINED);
00083
00084
00085
00086
00087 m_tcp_conn->saveReadPosition(m_read_ptr, m_read_end_ptr);
00088
00089 PION_LOG_DEBUG(m_logger, "HTTP pipelined "
00090 << (isParsingRequest() ? "request (" : "response (")
00091 << bytes_available() << " bytes available)");
00092 }
00093 } else {
00094 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00095 }
00096
00097
00098 finishedReading();
00099
00100 } else if (result == false) {
00101
00102
00103 #ifndef NDEBUG
00104
00105 std::string bad_message;
00106 m_read_ptr = m_tcp_conn->getReadBuffer().data();
00107 while (m_read_ptr < m_read_end_ptr && bad_message.size() < 50) {
00108 #ifndef _MSC_VER
00109
00110 if (!isprint(*m_read_ptr) || *m_read_ptr == '\n' || *m_read_ptr=='\r')
00111 bad_message += '.';
00112 else bad_message += *m_read_ptr;
00113 #endif
00114 ++m_read_ptr;
00115 }
00116 PION_LOG_ERROR(m_logger, "Bad " << (isParsingRequest() ? "request" : "response")
00117 << " debug: " << bad_message);
00118 #endif
00119
00120 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00121 getMessage().setIsValid(false);
00122 finishedReading();
00123
00124 } else {
00125
00126
00127 readBytes();
00128 }
00129 }
00130
00131 void HTTPReader::handleReadError(const boost::system::error_code& read_error)
00132 {
00133
00134 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00135
00136
00137 if (! checkPrematureEOF(getMessage())) {
00138 finishedReading();
00139 return;
00140 }
00141
00142
00143 if (getTotalBytesRead() > 0) {
00144 if (read_error == boost::asio::error::operation_aborted) {
00145
00146
00147 PION_LOG_INFO(m_logger, "HTTP " << (isParsingRequest() ? "request" : "response")
00148 << " parsing aborted (shutting down)");
00149 } else {
00150 PION_LOG_INFO(m_logger, "HTTP " << (isParsingRequest() ? "request" : "response")
00151 << " parsing aborted (" << read_error.message() << ')');
00152 }
00153 }
00154
00155
00156 m_tcp_conn->finish();
00157 }
00158
00159 }
00160 }
00161