1
0

Fixed parsing and implemented write nofitication.

The web connection finally works with a browser.
This commit is contained in:
madmaxoft 2013-09-27 20:33:18 +02:00
parent d0b9e81795
commit 0c3fd5e77d
6 changed files with 51 additions and 13 deletions

View File

@ -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;
}

View File

@ -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:

View File

@ -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)

View File

@ -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
*/

View File

@ -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
}

View File

@ -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);