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 const boost::uint32_t HTTPReader::DEFAULT_READ_TIMEOUT = 10;
00023
00024
00025
00026
00027 void HTTPReader::receive(void)
00028 {
00029 if (m_tcp_conn->getPipelined()) {
00030
00031 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00032 m_tcp_conn->loadReadPosition(m_read_ptr, m_read_end_ptr);
00033 consumeBytes();
00034 } else {
00035
00036 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00037 readBytesWithTimeout();
00038 }
00039 }
00040
00041 void HTTPReader::consumeBytes(const boost::system::error_code& read_error,
00042 std::size_t bytes_read)
00043 {
00044
00045 if (m_timer_ptr) {
00046 m_timer_ptr->cancel();
00047 m_timer_ptr.reset();
00048 }
00049
00050 if (read_error) {
00051
00052 handleReadError(read_error);
00053 return;
00054 }
00055
00056 PION_LOG_DEBUG(m_logger, "Read " << bytes_read << " bytes from HTTP "
00057 << (isParsingRequest() ? "request" : "response"));
00058
00059
00060 setReadBuffer(m_tcp_conn->getReadBuffer().data(), bytes_read);
00061
00062 consumeBytes();
00063 }
00064
00065
00066 void HTTPReader::consumeBytes(void)
00067 {
00068
00069
00070
00071
00072
00073
00074
00075
00076 boost::tribool result = parse(getMessage());
00077
00078 if (gcount() > 0) {
00079
00080 PION_LOG_DEBUG(m_logger, "Parsed " << gcount() << " HTTP bytes");
00081 }
00082
00083 if (result == true) {
00084
00085
00086
00087 if (getMessage().checkKeepAlive()) {
00088 if ( eof() ) {
00089
00090 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_KEEPALIVE);
00091 } else {
00092
00093 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_PIPELINED);
00094
00095
00096
00097
00098 m_tcp_conn->saveReadPosition(m_read_ptr, m_read_end_ptr);
00099
00100 PION_LOG_DEBUG(m_logger, "HTTP pipelined "
00101 << (isParsingRequest() ? "request (" : "response (")
00102 << bytes_available() << " bytes available)");
00103 }
00104 } else {
00105 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00106 }
00107
00108
00109 finishedReading();
00110
00111 } else if (result == false) {
00112
00113
00114 #ifndef NDEBUG
00115
00116 std::string bad_message;
00117 m_read_ptr = m_tcp_conn->getReadBuffer().data();
00118 while (m_read_ptr < m_read_end_ptr && bad_message.size() < 50) {
00119 #ifndef _MSC_VER
00120
00121 if (!isprint(*m_read_ptr) || *m_read_ptr == '\n' || *m_read_ptr=='\r')
00122 bad_message += '.';
00123 else bad_message += *m_read_ptr;
00124 #endif
00125 ++m_read_ptr;
00126 }
00127 PION_LOG_ERROR(m_logger, "Bad " << (isParsingRequest() ? "request" : "response")
00128 << " debug: " << bad_message);
00129 #endif
00130
00131 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00132 getMessage().setIsValid(false);
00133 finishedReading();
00134
00135 } else {
00136
00137 readBytesWithTimeout();
00138 }
00139 }
00140
00141 void HTTPReader::readBytesWithTimeout(void)
00142 {
00143 if (m_read_timeout > 0) {
00144 m_timer_ptr.reset(new TCPTimer(m_tcp_conn));
00145 m_timer_ptr->start(m_read_timeout);
00146 } else if (m_timer_ptr) {
00147 m_timer_ptr.reset();
00148 }
00149 readBytes();
00150 }
00151
00152 void HTTPReader::handleReadError(const boost::system::error_code& read_error)
00153 {
00154
00155 m_tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE);
00156
00157
00158 if (! checkPrematureEOF(getMessage())) {
00159 finishedReading();
00160 return;
00161 }
00162
00163
00164 if (getTotalBytesRead() > 0) {
00165 if (read_error == boost::asio::error::operation_aborted) {
00166
00167
00168 PION_LOG_INFO(m_logger, "HTTP " << (isParsingRequest() ? "request" : "response")
00169 << " parsing aborted (shutting down)");
00170 } else {
00171 PION_LOG_INFO(m_logger, "HTTP " << (isParsingRequest() ? "request" : "response")
00172 << " parsing aborted (" << read_error.message() << ')');
00173 }
00174 }
00175
00176
00177 m_tcp_conn->finish();
00178 }
00179
00180 }
00181 }
00182