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