Cuberite
A lightweight, fast and extensible game server for Minecraft
HTTPServer.cpp
Go to the documentation of this file.
1 
2 // HTTPServer.cpp
3 
4 // Implements the cHTTPServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for processing
5 
6 #include "Globals.h"
7 #include "HTTPServer.h"
8 #include "HTTPMessageParser.h"
9 #include "HTTPServerConnection.h"
10 #include "HTTPFormParser.h"
12 #include "../mbedTLS++/SslConfig.h"
13 
14 
15 
16 
17 
18 // Disable MSVC warnings:
19 #if defined(_MSC_VER)
20  #pragma warning(push)
21  #pragma warning(disable:4355) // 'this' : used in base member initializer list
22 #endif
23 
24 
25 
26 
27 
29 // cHTTPServerListenCallbacks:
30 
33 {
34 public:
36  m_HTTPServer(a_HTTPServer),
37  m_Port(a_Port)
38  {
39  }
40 
41 protected:
44 
47 
48  // cNetwork::cListenCallbacks overrides:
49  virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString & a_RemoteIPAddress, UInt16 a_RemotePort) override
50  {
51  return m_HTTPServer.OnIncomingConnection(a_RemoteIPAddress, a_RemotePort);
52  }
53  virtual void OnAccepted(cTCPLink & a_Link) override {}
54  virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override
55  {
56  LOGWARNING("HTTP server error on port %d: %d (%s)", m_Port, a_ErrorCode, a_ErrorMsg.c_str());
57  }
58 };
59 
60 
61 
62 
63 
65 // cHTTPServer:
66 
68  m_Callbacks(nullptr)
69 {
70 }
71 
72 
73 
74 
75 
77 {
78  Stop();
79 }
80 
81 
82 
83 
84 
86 {
87  // Read the HTTPS cert + key:
88  AString CertFile = cFile::ReadWholeFile("webadmin/httpscert.crt");
89  AString KeyFile = cFile::ReadWholeFile("webadmin/httpskey.pem");
90  if (!CertFile.empty() && !KeyFile.empty())
91  {
92  auto Cert = std::make_shared<cX509Cert>();
93  int res = Cert->Parse(CertFile.data(), CertFile.size());
94  if (res == 0)
95  {
96  auto CertPrivKey = std::make_shared<cCryptoKey>();
97  res = CertPrivKey->ParsePrivate(KeyFile.data(), KeyFile.size(), "");
98  if (res == 0)
99  {
100  // Modifyable locally but otherwise must be const
101  auto Config = cSslConfig::MakeDefaultConfig(false);
102  Config->SetOwnCert(Cert, CertPrivKey);
103  m_SslConfig = std::move(Config);
104  }
105  else
106  {
107  // Reading the private key failed, reset the cert:
108  LOGWARNING("WebServer: Cannot read HTTPS certificate private key: -0x%x", -res);
109  }
110  }
111  else
112  {
113  LOGWARNING("WebServer: Cannot read HTTPS certificate: -0x%x", -res);
114  }
115  }
116 
117  // Notify the admin about the HTTPS / HTTP status
118  if (m_SslConfig == nullptr)
119  {
120  LOGWARNING("WebServer: The server will run in unsecured HTTP mode.");
121  LOGINFO("Put a valid HTTPS certificate in file 'webadmin/httpscert.crt' and its corresponding private key to 'webadmin/httpskey.pem' (without any password) to enable HTTPS support");
122  }
123  else
124  {
125  LOGINFO("WebServer: The server will run in secure HTTPS mode.");
126  }
127  return true;
128 }
129 
130 
131 
132 
133 
134 bool cHTTPServer::Start(cCallbacks & a_Callbacks, const AStringVector & a_Ports)
135 {
136  m_Callbacks = &a_Callbacks;
137 
138  // Open up requested ports:
139  AStringVector ports;
140  for (const auto & port : a_Ports)
141  {
142  UInt16 PortNum;
143  if (!StringToInteger(port, PortNum))
144  {
145  LOGWARNING("WebServer: Invalid port value: \"%s\". Ignoring.", port.c_str());
146  continue;
147  }
148  auto Handle = cNetwork::Listen(PortNum, std::make_shared<cHTTPServerListenCallbacks>(*this, PortNum));
149  if (Handle->IsListening())
150  {
151  m_ServerHandles.push_back(Handle);
152  ports.push_back(port);
153  }
154  } // for port - a_Ports[]
155 
156  // Inform the admin about the ports opened:
157  AString reportPorts;
158  for (const auto & port: ports)
159  {
160  if (!reportPorts.empty())
161  {
162  reportPorts.append(", ");
163  }
164  reportPorts.append(port);
165  }
166  LOGINFO("WebAdmin is running on port(s) %s", reportPorts.c_str());
167 
168  // Report success if at least one port opened successfully:
169  return !m_ServerHandles.empty();
170 }
171 
172 
173 
174 
175 
177 {
178  for (const auto & handle : m_ServerHandles)
179  {
180  handle->Close();
181  }
182  m_ServerHandles.clear();
183 }
184 
185 
186 
187 
188 
190 {
191  UNUSED(a_RemoteIPAddress);
192  UNUSED(a_RemotePort);
193 
194  if (m_SslConfig != nullptr)
195  {
196  return std::make_shared<cSslHTTPServerConnection>(*this, m_SslConfig);
197  }
198  else
199  {
200  return std::make_shared<cHTTPServerConnection>(*this);
201  }
202 }
203 
204 
205 
206 
207 
209 {
210  m_Callbacks->OnRequestBegun(a_Connection, a_Request);
211 }
212 
213 
214 
215 
216 
217 void cHTTPServer::RequestBody(cHTTPServerConnection & a_Connection, cHTTPIncomingRequest & a_Request, const void * a_Data, size_t a_Size)
218 {
219  m_Callbacks->OnRequestBody(a_Connection, a_Request, static_cast<const char *>(a_Data), a_Size);
220 }
221 
222 
223 
224 
225 
227 {
228  m_Callbacks->OnRequestFinished(a_Connection, a_Request);
229 }
230 
231 
232 
233 
unsigned short UInt16
Definition: Globals.h:158
#define UNUSED
Definition: Globals.h:72
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
void LOGINFO(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:61
std::vector< AString > AStringVector
Definition: StringUtils.h:12
std::string AString
Definition: StringUtils.h:11
bool StringToInteger(const AString &a_str, T &a_Num)
Parses any integer type.
Definition: StringUtils.h:143
Provides storage for an incoming HTTP request.
Definition: HTTPMessage.h:90
cHTTPServerListenCallbacks(cHTTPServer &a_HTTPServer, UInt16 a_Port)
Definition: HTTPServer.cpp:35
virtual void OnAccepted(cTCPLink &a_Link) override
Called when the TCP server created with Listen() creates a new link for an incoming connection.
Definition: HTTPServer.cpp:53
UInt16 m_Port
The port for which this instance is responsible.
Definition: HTTPServer.cpp:46
virtual cTCPLink::cCallbacksPtr OnIncomingConnection(const AString &a_RemoteIPAddress, UInt16 a_RemotePort) override
Called when the TCP server created with Listen() receives a new incoming connection.
Definition: HTTPServer.cpp:49
cHTTPServer & m_HTTPServer
The HTTP server instance that we're attached to.
Definition: HTTPServer.cpp:43
virtual void OnError(int a_ErrorCode, const AString &a_ErrorMsg) override
Called when the socket fails to listen on the specified port.
Definition: HTTPServer.cpp:54
cCallbacks * m_Callbacks
The callbacks to call for various events.
Definition: HTTPServer.h:71
bool Initialize(void)
Initializes the server - reads the cert files etc.
Definition: HTTPServer.cpp:85
void NewRequest(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request)
Called by cHTTPServerConnection when it finishes parsing the request header.
Definition: HTTPServer.cpp:208
void RequestBody(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request, const void *a_Data, size_t a_Size)
Called by cHTTPConenction when it receives more data for the request body.
Definition: HTTPServer.cpp:217
cServerHandlePtrs m_ServerHandles
The cNetwork API handle for the listening socket.
Definition: HTTPServer.h:68
cTCPLink::cCallbacksPtr OnIncomingConnection(const AString &a_RemoteIPAddress, UInt16 a_RemotePort)
Called by cHTTPServerListenCallbacks when there's a new incoming connection.
Definition: HTTPServer.cpp:189
void Stop(void)
Stops the server, drops all current connections.
Definition: HTTPServer.cpp:176
cHTTPServer(void)
Definition: HTTPServer.cpp:67
bool Start(cCallbacks &a_Callbacks, const AStringVector &a_Ports)
Starts the server and assigns the callbacks to use for incoming requests.
Definition: HTTPServer.cpp:134
virtual ~cHTTPServer()
Definition: HTTPServer.cpp:76
std::shared_ptr< const cSslConfig > m_SslConfig
Configuration for server ssl connections.
Definition: HTTPServer.h:74
void RequestFinished(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request)
Called by cHTTPServerConnection when it detects that the request has finished (all of its body has be...
Definition: HTTPServer.cpp:226
virtual void OnRequestBody(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request, const char *a_Data, size_t a_Size)=0
Called when another part of request body has arrived.
virtual void OnRequestBegun(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request)=0
Called when a new request arrives over a connection and all its headers have been parsed.
virtual void OnRequestFinished(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request)=0
Called when the request body has been fully received in previous calls to OnRequestBody()
static std::shared_ptr< cSslConfig > MakeDefaultConfig(bool a_IsClient)
Creates a new config with some sensible defaults on top of mbedTLS basic settings.
Definition: SslConfig.cpp:226
static AString ReadWholeFile(const AString &a_FileName)
Returns the entire contents of the specified file as a string.
Definition: File.cpp:573
Interface that provides the methods available on a single TCP connection.
Definition: Network.h:42
std::shared_ptr< cCallbacks > cCallbacksPtr
Definition: Network.h:71
static cServerHandlePtr Listen(UInt16 a_Port, cListenCallbacksPtr a_ListenCallbacks)
Opens up the specified port for incoming connections.
Callbacks used when listening for incoming connections as a server.
Definition: Network.h:254