ESP32 HTTPS Server
HTTPConnection.hpp
1 #ifndef SRC_HTTPCONNECTION_HPP_
2 #define SRC_HTTPCONNECTION_HPP_
3 
4 #include <Arduino.h>
5 #include <IPAddress.h>
6 
7 #include <string>
8 #include <mbedtls/base64.h>
9 #include <hwcrypto/sha.h>
10 #include <functional>
11 
12 // Required for sockets
13 #include "lwip/netdb.h"
14 #undef read
15 #include "lwip/sockets.h"
16 
17 #include "HTTPSServerConstants.hpp"
18 #include "ConnectionContext.hpp"
19 
20 #include "HTTPHeaders.hpp"
21 #include "HTTPHeader.hpp"
22 
23 #include "ResourceResolver.hpp"
24 #include "ResolvedResource.hpp"
25 
26 #include "ResourceNode.hpp"
27 #include "HTTPRequest.hpp"
28 #include "HTTPResponse.hpp"
29 
30 #include "WebsocketHandler.hpp"
31 #include "WebsocketNode.hpp"
32 
33 namespace httpsserver {
34 
39 public:
40  HTTPConnection(ResourceResolver * resResolver);
41  virtual ~HTTPConnection();
42 
43  virtual int initialize(int serverSocketID, HTTPHeaders *defaultHeaders);
44  virtual void closeConnection();
45  virtual bool isSecure();
46  virtual IPAddress getClientIP();
47 
48  void loop();
49  bool isClosed();
50  bool isError();
51 
52 protected:
53  friend class HTTPRequest;
54  friend class HTTPResponse;
55  friend class WebsocketInputStreambuf;
56 
57  virtual size_t writeBuffer(byte* buffer, size_t length);
58  virtual size_t readBytesToBuffer(byte* buffer, size_t length);
59  virtual bool canReadData();
60  virtual size_t pendingByteCount();
61 
62  // Timestamp of the last transmission action
63  unsigned long _lastTransmissionTS;
64 
65  // Timestamp of when the shutdown was started
66  unsigned long _shutdownTS;
67 
68  // Internal state machine of the connection:
69  //
70  // O --- > STATE_UNDEFINED -- initialize() --> STATE_INITIAL -- get / http/1.1 --> STATE_REQUEST_FINISHED --.
71  // | | | |
72  // | | | | Host: ...\r\n
73  // STATE_ERROR <- on error-----------------------<---------------------------------------< | Foo: bar\r\n
74  // ^ | | | \r\n
75  // | shutdown .--> STATE_CLOSED | | | \r\n
76  // | fails | | | |
77  // | | close() | | |
78  // STATE_CLOSING <---- STATE_WEBSOCKET <-. | | |
79  // ^ | | | |
80  // `---------- close() ---------- STATE_BODY_FINISHED <-- Body received or GET -- STATE_HEADERS_FINISHED <-ยด
81  //
82  enum {
83  // The order is important, to be able to use state <= STATE_HEADERS_FINISHED etc.
84 
85  // The connection has not been established yet
86  STATE_UNDEFINED,
87  // The connection has just been created
88  STATE_INITIAL,
89  // The request line has been parsed
90  STATE_REQUEST_FINISHED,
91  // The headers have been parsed
92  STATE_HEADERS_FINISHED,
93  // The body has been parsed/the complete request has been processed (GET has body of length 0)
94  STATE_BODY_FINISHED,
95  // The connection is in websocket mode
96  STATE_WEBSOCKET,
97  // The connection is about to close (and waiting for the client to send close notify)
98  STATE_CLOSING,
99  // The connection has been closed
100  STATE_CLOSED,
101  // An error has occured
102  STATE_ERROR
103  } _connectionState;
104 
105  enum {
106  CSTATE_UNDEFINED,
107  CSTATE_ACTIVE,
108  CSTATE_CLOSED
109  } _clientState;
110 
111 private:
112  void raiseError(uint16_t code, std::string reason);
113  void readLine(int lengthLimit);
114 
115  bool isTimeoutExceeded();
116  void refreshTimeout();
117 
118  int updateBuffer();
119  size_t pendingBufferSize();
120 
121  void signalClientClose();
122  void signalRequestError();
123  size_t readBuffer(byte* buffer, size_t length);
124  size_t getCacheSize();
125  bool checkWebsocket();
126 
127  // The receive buffer
128  char _receiveBuffer[HTTPS_CONNECTION_DATA_CHUNK_SIZE];
129 
130  // First index on _receive_buffer that has not been processed yet (anything before may be discarded)
131  int _bufferProcessed;
132  // The index on the receive_buffer that is the first one which is empty at the end.
133  int _bufferUnusedIdx;
134 
135  // Socket address, length etc for the connection
136  struct sockaddr _sockAddr;
137  socklen_t _addrLen;
138  int _socket;
139 
140  // Resource resolver used to resolve resources
141  ResourceResolver * _resResolver;
142 
143  // The parser line. The struct is used to read the next line up to the \r\n in readLine()
144  struct {
145  std::string text = "";
146  bool parsingFinished = false;
147  } _parserLine;
148 
149  // HTTP properties: Method, Request, Headers
150  std::string _httpMethod;
151  std::string _httpResource;
152  HTTPHeaders * _httpHeaders;
153 
154  // Default headers that are applied to every response
155  HTTPHeaders * _defaultHeaders;
156 
157  // Should we use keep alive
158  bool _isKeepAlive;
159 
160  //Websocket connection
161  WebsocketHandler * _wsHandler;
162 
163 };
164 
166 
167 std::string websocketKeyResponseHash(std::string const &key);
168 
169 void validationMiddleware(HTTPRequest * req, HTTPResponse * res, std::function<void()> next);
170 
171 } /* namespace httpsserver */
172 
173 #endif /* SRC_HTTPCONNECTION_HPP_ */
virtual IPAddress getClientIP()
Definition: HTTPConnection.cpp:65
void handleWebsocketHandshake(HTTPRequest *req, HTTPResponse *res)
Definition: HTTPConnection.cpp:652
Represents the request stream for an HTTP request.
Definition: HTTPRequest.hpp:22
Represents the response stream of an HTTP request.
Definition: HTTPResponse.hpp:25
void validationMiddleware(HTTPRequest *req, HTTPResponse *res, std::function< void()> next)
Definition: HTTPConnection.cpp:622
bool isError()
Definition: HTTPConnection.cpp:99
Groups and manages a set of HTTPHeader instances.
Definition: HTTPHeaders.hpp:18
Definition: WebsocketHandler.hpp:34
This class is used internally to resolve a string URL to the corresponding HTTPNode.
Definition: ResourceResolver.hpp:22
Definition: WebsocketInputStreambuf.hpp:21
Internal class to handle the state of a connection.
Definition: ConnectionContext.hpp:18
Represents a single open connection for the plain HTTPServer, without TLS.
Definition: HTTPConnection.hpp:38
bool isClosed()
Definition: HTTPConnection.cpp:92
std::string websocketKeyResponseHash(std::string const &key)
Definition: HTTPConnection.cpp:664
virtual int initialize(int serverSocketID, HTTPHeaders *defaultHeaders)
Definition: HTTPConnection.cpp:33
Definition: ConnectionContext.cpp:3