Fixed parsing and implemented write nofitication.
The web connection finally works with a browser.
This commit is contained in:
parent
d0b9e81795
commit
0c3fd5e77d
@ -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;
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,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:
|
||||
virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user