summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--VC2008/MCServer.vcproj8
-rw-r--r--source/HTTPServer/HTTPConnection.cpp147
-rw-r--r--source/HTTPServer/HTTPConnection.h88
-rw-r--r--source/HTTPServer/HTTPServer.cpp140
-rw-r--r--source/HTTPServer/HTTPServer.h68
5 files changed, 246 insertions, 205 deletions
diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj
index 7aba32b1d..45579a8a7 100644
--- a/VC2008/MCServer.vcproj
+++ b/VC2008/MCServer.vcproj
@@ -2720,6 +2720,14 @@
Name="HTTPServer"
>
<File
+ RelativePath="..\source\HTTPServer\HTTPConnection.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\source\HTTPServer\HTTPConnection.h"
+ >
+ </File>
+ <File
RelativePath="..\source\HTTPServer\HTTPMessage.cpp"
>
</File>
diff --git a/source/HTTPServer/HTTPConnection.cpp b/source/HTTPServer/HTTPConnection.cpp
new file mode 100644
index 000000000..f7318c6ae
--- /dev/null
+++ b/source/HTTPServer/HTTPConnection.cpp
@@ -0,0 +1,147 @@
+
+// HTTPConnection.cpp
+
+// Implements the cHTTPConnection class representing a single persistent connection in the HTTP server.
+
+#include "Globals.h"
+#include "HTTPConnection.h"
+#include "HTTPMessage.h"
+#include "HTTPServer.h"
+
+
+
+
+
+cHTTPConnection::cHTTPConnection(cHTTPServer & a_HTTPServer) :
+ m_HTTPServer(a_HTTPServer),
+ m_State(wcsRecvHeaders),
+ m_CurrentRequest(NULL)
+{
+}
+
+
+
+
+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());
+}
+
+
+
+
+
+void cHTTPConnection::Send(const cHTTPResponse & a_Response)
+{
+ ASSERT(m_State = wcsRecvIdle);
+ a_Response.AppendToData(m_OutgoingData);
+ m_State = wcsSendingResp;
+}
+
+
+
+
+
+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);
+}
+
+
+
+
+
+void cHTTPConnection::FinishResponse(void)
+{
+ ASSERT(m_State == wcsSendingResp);
+ m_OutgoingData.append("0\r\n");
+ m_State = wcsRecvHeaders;
+}
+
+
+
+
+
+void cHTTPConnection::DataReceived(const char * a_Data, int a_Size)
+{
+ switch (m_State)
+ {
+ case wcsRecvHeaders:
+ {
+ ASSERT(m_CurrentRequest == NULL);
+
+ // Start searching 3 chars from the end of the already received data, if available:
+ size_t SearchStart = m_IncomingHeaderData.size();
+ SearchStart = (SearchStart > 3) ? SearchStart - 3 : 0;
+
+ m_IncomingHeaderData.append(a_Data, a_Size);
+
+ // Parse the header, if it is complete:
+ size_t idxEnd = m_IncomingHeaderData.find("\r\n\r\n", SearchStart);
+ if (idxEnd == AString::npos)
+ {
+ return;
+ }
+ m_CurrentRequest = new cHTTPRequest;
+ if (!m_CurrentRequest->ParseHeaders(m_IncomingHeaderData.c_str(), idxEnd + 2))
+ {
+ delete m_CurrentRequest;
+ m_CurrentRequest = NULL;
+ m_State = wcsInvalid;
+ m_HTTPServer.CloseConnection(*this);
+ return;
+ }
+ m_State = wcsRecvBody;
+ m_HTTPServer.NewRequest(*this, *m_CurrentRequest);
+
+ // 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());
+ }
+ break;
+ }
+
+ case wcsRecvBody:
+ {
+ ASSERT(m_CurrentRequest != NULL);
+ // TODO: Receive the body, and the next request (If HTTP/1.1 keepalive)
+ break;
+ }
+
+ default:
+ {
+ // TODO: Should we be receiving data in this state?
+ break;
+ }
+ }
+}
+
+
+
+
+
+void cHTTPConnection::GetOutgoingData(AString & a_Data)
+{
+ std::swap(a_Data, m_OutgoingData);
+}
+
+
+
+
+
+void cHTTPConnection::SocketClosed(void)
+{
+ if (m_CurrentRequest != NULL)
+ {
+ m_HTTPServer.RequestFinished(*this, *m_CurrentRequest);
+ }
+}
+
+
+
+
+
diff --git a/source/HTTPServer/HTTPConnection.h b/source/HTTPServer/HTTPConnection.h
new file mode 100644
index 000000000..e2df5de46
--- /dev/null
+++ b/source/HTTPServer/HTTPConnection.h
@@ -0,0 +1,88 @@
+
+// HTTPConnection.h
+
+// Declares the cHTTPConnection class representing a single persistent connection in the HTTP server.
+
+
+
+
+
+#pragma once
+
+#include "../OSSupport/SocketThreads.h"
+
+
+
+
+
+// fwd:
+class cHTTPServer;
+class cHTTPResponse;
+class cHTTPRequest;
+
+
+
+
+
+class cHTTPConnection :
+ public cSocketThreads::cCallback
+{
+public:
+
+ enum eState
+ {
+ wcsRecvHeaders, ///< Receiving request headers (m_CurrentRequest == NULL)
+ wcsRecvBody, ///< Receiving request body (m_CurrentRequest is valid)
+ wcsRecvIdle, ///< Has received the entire body, waiting to send the response (m_CurrentRequest == NULL)
+ wcsSendingResp, ///< Sending response body (m_CurrentRequest == NULL)
+ wcsInvalid, ///< The request was malformed, the connection is closing
+ } ;
+
+ cHTTPConnection(cHTTPServer & a_HTTPServer);
+
+ /// Sends HTTP status code together with a_Reason (used for HTTP errors)
+ void SendStatusAndReason(int a_StatusCode, const AString & a_Reason);
+
+ /// Sends the headers contained in a_Response
+ void Send(const cHTTPResponse & a_Response);
+
+ /// Sends the data as the response (may be called multiple times)
+ void Send(const void * a_Data, int a_Size);
+
+ /// Sends the data as the response (may be called multiple times)
+ void Send(const AString & a_Data) { Send(a_Data.data(), a_Data.size()); }
+
+ /// Finishes sending current response, gets ready for receiving another request (HTTP 1.1 keepalive)
+ void FinishResponse(void);
+
+protected:
+ typedef std::map<AString, AString> cNameValueMap;
+
+ /// The parent webserver that is to be notified of events on this connection
+ cHTTPServer & m_HTTPServer;
+
+ /// All the incoming data until the entire request header is parsed
+ AString m_IncomingHeaderData;
+
+ /// Status in which the request currently is
+ eState m_State;
+
+ /// Data that is queued for sending, once the socket becomes writable
+ AString m_OutgoingData;
+
+ /// The request being currently received (valid only between having parsed the headers and finishing receiving the body)
+ cHTTPRequest * m_CurrentRequest;
+
+
+ // cSocketThreads::cCallback overrides:
+ virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client
+ virtual void GetOutgoingData(AString & a_Data) override; // Data can be sent to client
+ virtual void SocketClosed (void) override; // The socket has been closed for any reason
+} ;
+
+typedef std::vector<cHTTPConnection *> cHTTPConnections;
+
+
+
+
+
diff --git a/source/HTTPServer/HTTPServer.cpp b/source/HTTPServer/HTTPServer.cpp
index e68032bc2..980cad14f 100644
--- a/source/HTTPServer/HTTPServer.cpp
+++ b/source/HTTPServer/HTTPServer.cpp
@@ -6,6 +6,7 @@
#include "Globals.h"
#include "HTTPServer.h"
#include "HTTPMessage.h"
+#include "HTTPConnection.h"
@@ -21,145 +22,6 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cHTTPConnection:
-
-cHTTPConnection::cHTTPConnection(cHTTPServer & a_HTTPServer) :
- m_HTTPServer(a_HTTPServer),
- m_State(wcsRecvHeaders),
- m_CurrentRequest(NULL)
-{
-}
-
-
-
-
-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());
-}
-
-
-
-
-
-void cHTTPConnection::Send(const cHTTPResponse & a_Response)
-{
- ASSERT(m_State = wcsRecvIdle);
- a_Response.AppendToData(m_OutgoingData);
- m_State = wcsSendingResp;
-}
-
-
-
-
-
-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);
-}
-
-
-
-
-
-void cHTTPConnection::FinishResponse(void)
-{
- ASSERT(m_State == wcsSendingResp);
- m_OutgoingData.append("0\r\n");
- m_State = wcsRecvHeaders;
-}
-
-
-
-
-
-void cHTTPConnection::DataReceived(const char * a_Data, int a_Size)
-{
- switch (m_State)
- {
- case wcsRecvHeaders:
- {
- ASSERT(m_CurrentRequest == NULL);
-
- // Start searching 3 chars from the end of the already received data, if available:
- size_t SearchStart = m_IncomingHeaderData.size();
- SearchStart = (SearchStart > 3) ? SearchStart - 3 : 0;
-
- m_IncomingHeaderData.append(a_Data, a_Size);
-
- // Parse the header, if it is complete:
- size_t idxEnd = m_IncomingHeaderData.find("\r\n\r\n", SearchStart);
- if (idxEnd == AString::npos)
- {
- return;
- }
- m_CurrentRequest = new cHTTPRequest;
- if (!m_CurrentRequest->ParseHeaders(m_IncomingHeaderData.c_str(), idxEnd + 2))
- {
- delete m_CurrentRequest;
- m_CurrentRequest = NULL;
- m_State = wcsInvalid;
- m_HTTPServer.CloseConnection(*this);
- return;
- }
- m_State = wcsRecvBody;
- m_HTTPServer.NewRequest(*this, *m_CurrentRequest);
-
- // 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());
- }
- break;
- }
-
- case wcsRecvBody:
- {
- ASSERT(m_CurrentRequest != NULL);
- // TODO: Receive the body, and the next request (If HTTP/1.1 keepalive)
- break;
- }
-
- default:
- {
- // TODO: Should we be receiving data in this state?
- break;
- }
- }
-}
-
-
-
-
-
-void cHTTPConnection::GetOutgoingData(AString & a_Data)
-{
- std::swap(a_Data, m_OutgoingData);
-}
-
-
-
-
-
-void cHTTPConnection::SocketClosed(void)
-{
- if (m_CurrentRequest != NULL)
- {
- m_HTTPServer.RequestFinished(*this, *m_CurrentRequest);
- }
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cHTTPServer:
-
cHTTPServer::cHTTPServer(void) :
m_ListenThreadIPv4(*this, cSocket::IPv4, "WebServer IPv4"),
m_ListenThreadIPv6(*this, cSocket::IPv6, "WebServer IPv6"),
diff --git a/source/HTTPServer/HTTPServer.h b/source/HTTPServer/HTTPServer.h
index 9287a79e8..fd4782267 100644
--- a/source/HTTPServer/HTTPServer.h
+++ b/source/HTTPServer/HTTPServer.h
@@ -18,80 +18,16 @@
// fwd:
-class cHTTPServer;
class cHTTPMessage;
class cHTTPRequest;
class cHTTPResponse;
+class cHTTPConnection;
+typedef std::vector<cHTTPConnection *> cHTTPConnections;
-class cHTTPConnection :
- public cSocketThreads::cCallback
-{
-public:
-
- enum eState
- {
- wcsRecvHeaders, ///< Receiving request headers (m_CurrentRequest == NULL)
- wcsRecvBody, ///< Receiving request body (m_CurrentRequest is valid)
- wcsRecvIdle, ///< Has received the entire body, waiting to send the response (m_CurrentRequest == NULL)
- wcsSendingResp, ///< Sending response body (m_CurrentRequest == NULL)
- wcsInvalid, ///< The request was malformed, the connection is closing
- } ;
-
- cHTTPConnection(cHTTPServer & a_HTTPServer);
-
- /// Sends HTTP status code together with a_Reason (used for HTTP errors)
- void SendStatusAndReason(int a_StatusCode, const AString & a_Reason);
-
- /// Sends the headers contained in a_Response
- void Send(const cHTTPResponse & a_Response);
-
- /// Sends the data as the response (may be called multiple times)
- void Send(const void * a_Data, int a_Size);
-
- /// Sends the data as the response (may be called multiple times)
- void Send(const AString & a_Data) { Send(a_Data.data(), a_Data.size()); }
-
- /// Finishes sending current response, gets ready for receiving another request (HTTP 1.1 keepalive)
- void FinishResponse(void);
-
-protected:
- typedef std::map<AString, AString> cNameValueMap;
-
- /// The parent webserver that is to be notified of events on this connection
- cHTTPServer & m_HTTPServer;
-
- /// All the incoming data until the entire request header is parsed
- AString m_IncomingHeaderData;
-
- /// Status in which the request currently is
- eState m_State;
-
- /// Data that is queued for sending, once the socket becomes writable
- AString m_OutgoingData;
-
- /// The request being currently received (valid only between having parsed the headers and finishing receiving the body)
- cHTTPRequest * m_CurrentRequest;
-
-
- /// Parses the header in m_IncomingData until the specified end mark
- void ParseHeader(size_t a_IdxEnd);
-
- /// Sends the response status and headers. Transition from wrsRecvBody to wrsSendingResp.
- void SendRespHeaders(void);
-
- // cSocketThreads::cCallback overrides:
- virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client
- virtual void GetOutgoingData(AString & a_Data) override; // Data can be sent to client
- virtual void SocketClosed (void) override; // The socket has been closed for any reason
-} ;
-
-typedef std::vector<cHTTPConnection *> cHTTPConnections;
-
-
class cHTTPServer :