From 0c3fd5e77d681c25757efaab6acb305d0b5630c1 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Fri, 27 Sep 2013 20:33:18 +0200 Subject: Fixed parsing and implemented write nofitication. The web connection finally works with a browser. --- source/HTTPServer/HTTPConnection.cpp | 26 ++++++++++++++++++++++++-- source/HTTPServer/HTTPConnection.h | 3 +++ source/HTTPServer/HTTPMessage.cpp | 16 ++++++++++------ source/HTTPServer/HTTPMessage.h | 3 --- source/HTTPServer/HTTPServer.cpp | 11 ++++++++++- source/HTTPServer/HTTPServer.h | 5 ++++- 6 files changed, 51 insertions(+), 13 deletions(-) diff --git a/source/HTTPServer/HTTPConnection.cpp b/source/HTTPServer/HTTPConnection.cpp index f7318c6ae..59fe8f878 100644 --- a/source/HTTPServer/HTTPConnection.cpp +++ b/source/HTTPServer/HTTPConnection.cpp @@ -25,6 +25,7 @@ cHTTPConnection::cHTTPConnection(cHTTPServer & a_HTTPServer) : void cHTTPConnection::SendStatusAndReason(int a_StatusCode, const AString & a_Response) { AppendPrintf(m_OutgoingData, "%d %s\r\n\r\n", a_StatusCode, a_Response.c_str()); + m_HTTPServer.NotifyConnectionWrite(*this); } @@ -36,6 +37,7 @@ void cHTTPConnection::Send(const cHTTPResponse & a_Response) ASSERT(m_State = wcsRecvIdle); a_Response.AppendToData(m_OutgoingData); m_State = wcsSendingResp; + m_HTTPServer.NotifyConnectionWrite(*this); } @@ -47,6 +49,8 @@ void cHTTPConnection::Send(const void * a_Data, int a_Size) ASSERT(m_State == wcsSendingResp); AppendPrintf(m_OutgoingData, "%x\r\n", a_Size); m_OutgoingData.append((const char *)a_Data, a_Size); + m_OutgoingData.append("\r\n"); + m_HTTPServer.NotifyConnectionWrite(*this); } @@ -56,8 +60,9 @@ void cHTTPConnection::Send(const void * a_Data, int a_Size) void cHTTPConnection::FinishResponse(void) { ASSERT(m_State == wcsSendingResp); - m_OutgoingData.append("0\r\n"); + m_OutgoingData.append("0\r\n\r\n"); m_State = wcsRecvHeaders; + m_HTTPServer.NotifyConnectionWrite(*this); } @@ -95,12 +100,19 @@ void cHTTPConnection::DataReceived(const char * a_Data, int a_Size) } m_State = wcsRecvBody; m_HTTPServer.NewRequest(*this, *m_CurrentRequest); + m_CurrentRequestBodyRemaining = m_CurrentRequest->GetContentLength(); // Process the rest of the incoming data into the request body: if (m_IncomingHeaderData.size() > idxEnd + 4) { m_IncomingHeaderData.erase(0, idxEnd + 4); DataReceived(m_IncomingHeaderData.c_str(), m_IncomingHeaderData.size()); + m_IncomingHeaderData.clear(); + } + else + { + m_IncomingHeaderData.clear(); + DataReceived("", 0); // If the request has zero body length, let it be processed right-away } break; } @@ -108,7 +120,17 @@ void cHTTPConnection::DataReceived(const char * a_Data, int a_Size) case wcsRecvBody: { ASSERT(m_CurrentRequest != NULL); - // TODO: Receive the body, and the next request (If HTTP/1.1 keepalive) + if (m_CurrentRequestBodyRemaining > 0) + { + int BytesToConsume = std::min(m_CurrentRequestBodyRemaining, a_Size); + m_HTTPServer.RequestBody(*this, *m_CurrentRequest, a_Data, BytesToConsume); + m_CurrentRequestBodyRemaining -= BytesToConsume; + } + if (m_CurrentRequestBodyRemaining == 0) + { + m_HTTPServer.RequestFinished(*this, *m_CurrentRequest); + m_State = wcsRecvIdle; + } break; } diff --git a/source/HTTPServer/HTTPConnection.h b/source/HTTPServer/HTTPConnection.h index e2df5de46..d8ecdf1d9 100644 --- a/source/HTTPServer/HTTPConnection.h +++ b/source/HTTPServer/HTTPConnection.h @@ -72,6 +72,9 @@ protected: /// The request being currently received (valid only between having parsed the headers and finishing receiving the body) cHTTPRequest * m_CurrentRequest; + + /// Number of bytes that remain to read for the complete body of the message to be received. Valid only in wcsRecvBody + int m_CurrentRequestBodyRemaining; // cSocketThreads::cCallback overrides: diff --git a/source/HTTPServer/HTTPMessage.cpp b/source/HTTPServer/HTTPMessage.cpp index b784cb941..b2e21c712 100644 --- a/source/HTTPServer/HTTPMessage.cpp +++ b/source/HTTPServer/HTTPMessage.cpp @@ -88,7 +88,11 @@ bool cHTTPRequest::ParseHeaders(const char * a_IncomingData, size_t a_IdxEnd) End -= Next; } - return HasReceivedContentLength(); + if (!HasReceivedContentLength()) + { + SetContentLength(0); + } + return true; } @@ -125,12 +129,12 @@ size_t cHTTPRequest::ParseRequestLine(const char * a_Data, size_t a_IdxEnd) { case 0: { - m_Method.assign(a_Data, Last, i - Last - 1); + m_Method.assign(a_Data, Last, i - Last); break; } case 1: { - m_URL.assign(a_Data, Last, i - Last - 1); + m_URL.assign(a_Data, Last, i - Last); break; } default: @@ -145,7 +149,7 @@ size_t cHTTPRequest::ParseRequestLine(const char * a_Data, size_t a_IdxEnd) } case '\n': { - if ((i == 0) || (a_Data[i] != '\r') || (NumSpaces != 2) || (i < Last + 7)) + if ((i == 0) || (a_Data[i - 1] != '\r') || (NumSpaces != 2) || (i < Last + 7)) { // LF too early, without a CR, without two preceeding spaces or too soon after the second space return AString::npos; @@ -155,7 +159,7 @@ size_t cHTTPRequest::ParseRequestLine(const char * a_Data, size_t a_IdxEnd) { return AString::npos; } - return i; + return i + 1; } } // switch (a_Data[i]) } // for i - a_Data[] @@ -263,7 +267,7 @@ cHTTPResponse::cHTTPResponse(void) : void cHTTPResponse::AppendToData(AString & a_DataStream) const { - a_DataStream.append("200 OK\r\nTransfer-Encoding: chunked\r\nContent-Type: "); + a_DataStream.append("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-Type: "); a_DataStream.append(m_ContentType); a_DataStream.append("\r\n"); for (cNameValueMap::const_iterator itr = m_Headers.begin(), end = m_Headers.end(); itr != end; ++itr) diff --git a/source/HTTPServer/HTTPMessage.h b/source/HTTPServer/HTTPMessage.h index a3c4f96d1..fc7b621fe 100644 --- a/source/HTTPServer/HTTPMessage.h +++ b/source/HTTPServer/HTTPMessage.h @@ -78,9 +78,6 @@ protected: /// Full URL of the request AString m_URL; - /// Number of bytes that remain to read for the complete body of the message to be received - int m_BodyRemaining; - /** Parses the RequestLine out of a_Data, up to index a_IdxEnd Returns the index to the next line, or npos if invalid request */ diff --git a/source/HTTPServer/HTTPServer.cpp b/source/HTTPServer/HTTPServer.cpp index 980cad14f..d518df10d 100644 --- a/source/HTTPServer/HTTPServer.cpp +++ b/source/HTTPServer/HTTPServer.cpp @@ -94,6 +94,15 @@ void cHTTPServer::CloseConnection(cHTTPConnection & a_Connection) +void cHTTPServer::NotifyConnectionWrite(cHTTPConnection & a_Connection) +{ + m_SocketThreads.NotifyWrite(&a_Connection); +} + + + + + void cHTTPServer::NewRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) { // TODO @@ -103,7 +112,7 @@ void cHTTPServer::NewRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Re -void cHTTPServer::RequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) +void cHTTPServer::RequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, int a_Size) { // TODO } diff --git a/source/HTTPServer/HTTPServer.h b/source/HTTPServer/HTTPServer.h index fd4782267..2d0acc386 100644 --- a/source/HTTPServer/HTTPServer.h +++ b/source/HTTPServer/HTTPServer.h @@ -55,11 +55,14 @@ protected: /// Called by cHTTPConnection to close the connection (presumably due to an error) void CloseConnection(cHTTPConnection & a_Connection); + /// Called by cHTTPConnection to notify SocketThreads that there's data to be sent for the connection + void NotifyConnectionWrite(cHTTPConnection & a_Connection); + /// Called by cHTTPConnection when it finishes parsing the request header void NewRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request); /// Called by cHTTPConenction when it receives more data for the request body - void RequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request); + void RequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, int a_Size); /// Called by cHTTPConnection when it detects that the request has finished (all of its body has been received) void RequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request); -- cgit v1.2.3