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