@@ -26,23 +26,28 @@ HTTPConnection::~HTTPConnection() {
26
26
}
27
27
28
28
/* *
29
- * Initializes the connection from a server socket.
29
+ * Initializes the connection
30
+ */
31
+ void HTTPConnection::initialize (int serverSocketID, HTTPHeaders *defaultHeaders) {
32
+ _defaultHeaders = defaultHeaders;
33
+ _serverSocket = serverSocketID;
34
+ }
35
+
36
+ /* *
37
+ * Accepts the connection from a server socket.
30
38
*
31
39
* The call WILL BLOCK if accept(serverSocketID) blocks. So use select() to check for that in advance.
32
40
*/
33
- int HTTPConnection::initialize ( int serverSocketID, HTTPHeaders *defaultHeaders ) {
41
+ int HTTPConnection::initialAccept ( ) {
34
42
if (_connectionState == STATE_UNDEFINED) {
35
- _defaultHeaders = defaultHeaders;
36
- _socket = accept (serverSocketID, (struct sockaddr * )&_sockAddr, &_addrLen);
43
+ _socket = accept (_serverSocket, (struct sockaddr * )&_sockAddr, &_addrLen);
37
44
38
- // Build up SSL Connection context if the socket has been created successfully
39
45
if (_socket >= 0 ) {
40
46
HTTPS_LOGI (" New connection. Socket FID=%d" , _socket);
41
- _connectionState = STATE_INITIAL ;
47
+ _connectionState = STATE_ACCEPTED ;
42
48
_httpHeaders = new HTTPHeaders ();
43
49
refreshTimeout ();
44
50
return _socket;
45
-
46
51
}
47
52
48
53
HTTPS_LOGE (" Could not accept() new connection" );
@@ -58,6 +63,23 @@ int HTTPConnection::initialize(int serverSocketID, HTTPHeaders *defaultHeaders)
58
63
return -1 ;
59
64
}
60
65
66
+ int HTTPConnection::fullyAccept () {
67
+ if (_connectionState == STATE_UNDEFINED) {
68
+ initialAccept ();
69
+ }
70
+ if (_connectionState == STATE_ACCEPTED) {
71
+ _connectionState = STATE_INITIAL;
72
+ return _socket;
73
+ }
74
+ return -1 ;
75
+ }
76
+
77
+ /* *
78
+ * Get connection socket
79
+ */
80
+ int HTTPConnection::getSocket () {
81
+ return _socket;
82
+ }
61
83
62
84
/* *
63
85
* True if the connection is timed out.
@@ -68,6 +90,17 @@ bool HTTPConnection::isTimeoutExceeded() {
68
90
return _lastTransmissionTS + HTTPS_CONNECTION_TIMEOUT < millis ();
69
91
}
70
92
93
+ /* *
94
+ * Return remaining milliseconds until timeout
95
+ *
96
+ * (Should return 0 or negative value if connection is timed-out or closed)
97
+ */
98
+ long int HTTPConnection::remainingMsUntilTimeout () {
99
+ if (isClosed ()) return -1 ;
100
+ unsigned long remain = _lastTransmissionTS + HTTPS_CONNECTION_TIMEOUT - millis ();
101
+ return (long int )remain;
102
+ }
103
+
71
104
/* *
72
105
* Resets the timeout to allow again the full HTTPS_CONNECTION_TIMEOUT milliseconds
73
106
*/
@@ -89,6 +122,14 @@ bool HTTPConnection::isError() {
89
122
return (_connectionState == STATE_ERROR);
90
123
}
91
124
125
+ bool HTTPConnection::isIdle () {
126
+ if (_connectionState == STATE_INITIAL) {
127
+ uint32_t delta = millis () - _lastTransmissionTS;
128
+ return (int32_t )delta > HTTPS_CONNECTION_IDLE_TIMEOUT;
129
+ }
130
+ return false ;
131
+ }
132
+
92
133
bool HTTPConnection::isSecure () {
93
134
return false ;
94
135
}
@@ -129,6 +170,7 @@ void HTTPConnection::closeConnection() {
129
170
if (_wsHandler != nullptr ) {
130
171
HTTPS_LOGD (" Free WS Handler" );
131
172
delete _wsHandler;
173
+ _wsHandler = NULL ;
132
174
}
133
175
}
134
176
@@ -258,20 +300,19 @@ size_t HTTPConnection::readBytesToBuffer(byte* buffer, size_t length) {
258
300
return recv (_socket, buffer, length, MSG_WAITALL | MSG_DONTWAIT);
259
301
}
260
302
261
- void HTTPConnection::serverError ( ) {
303
+ void HTTPConnection::raiseError ( uint16_t code, std::string reason ) {
262
304
_connectionState = STATE_ERROR;
263
-
264
- char staticResponse[] = " HTTP/1.1 500 Internal Server Error\r\n Server: esp32https\r\n Connection:close\r\n Content-Type: text/html\r\n Content-Length:34\r\n\r\n <h1>500 Internal Server Error</h1>" ;
265
- writeBuffer ((byte*)staticResponse, strlen (staticResponse));
266
- closeConnection ();
267
- }
268
-
269
-
270
- void HTTPConnection::clientError () {
271
- _connectionState = STATE_ERROR;
272
-
273
- char staticResponse[] = " HTTP/1.1 400 Bad Request\r\n Server: esp32https\r\n Connection:close\r\n Content-Type: text/html\r\n Content-Length:26\r\n\r\n <h1>400 Bad Request</h1>" ;
274
- writeBuffer ((byte*)staticResponse, strlen (staticResponse));
305
+ std::string sCode = intToString (code);
306
+
307
+ char headers[] = " \r\n Connection: close\r\n Content-Type: text/plain;charset=utf8\r\n\r\n " ;
308
+ writeBuffer ((byte*)" HTTP/1.1 " , 9 );
309
+ writeBuffer ((byte*)sCode .c_str (), sCode .length ());
310
+ writeBuffer ((byte*)" " , 1 );
311
+ writeBuffer ((byte*)(reason.c_str ()), reason.length ());
312
+ writeBuffer ((byte*)headers, strlen (headers));
313
+ writeBuffer ((byte*)sCode .c_str (), sCode .length ());
314
+ writeBuffer ((byte*)" " , 1 );
315
+ writeBuffer ((byte*)(reason.c_str ()), reason.length ());
275
316
closeConnection ();
276
317
}
277
318
@@ -289,7 +330,7 @@ void HTTPConnection::readLine(int lengthLimit) {
289
330
} else {
290
331
// Line has not been terminated by \r\n
291
332
HTTPS_LOGW (" Line without \\ r\\ n (got only \\ r). FID=%d" , _socket);
292
- clientError ( );
333
+ raiseError ( 400 , " Bad Request " );
293
334
return ;
294
335
}
295
336
}
@@ -301,7 +342,7 @@ void HTTPConnection::readLine(int lengthLimit) {
301
342
// Check that the max request string size is not exceeded
302
343
if (_parserLine.text .length () > lengthLimit) {
303
344
HTTPS_LOGW (" Header length exceeded. FID=%d" , _socket);
304
- serverError ( );
345
+ raiseError ( 431 , " Request Header Fields Too Large " );
305
346
return ;
306
347
}
307
348
}
@@ -319,7 +360,7 @@ void HTTPConnection::signalClientClose() {
319
360
*/
320
361
void HTTPConnection::signalRequestError () {
321
362
// TODO: Check that no response has been transmitted yet
322
- serverError ( );
363
+ raiseError ( 400 , " Bad Request " );
323
364
}
324
365
325
366
/* *
@@ -365,7 +406,7 @@ bool HTTPConnection::loop() {
365
406
size_t spaceAfterMethodIdx = _parserLine.text .find (' ' );
366
407
if (spaceAfterMethodIdx == std::string::npos) {
367
408
HTTPS_LOGW (" Missing space after method" );
368
- clientError ( );
409
+ raiseError ( 400 , " Bad Request " );
369
410
break ;
370
411
}
371
412
_httpMethod = _parserLine.text .substr (0 , spaceAfterMethodIdx);
@@ -374,14 +415,14 @@ bool HTTPConnection::loop() {
374
415
size_t spaceAfterResourceIdx = _parserLine.text .find (' ' , spaceAfterMethodIdx + 1 );
375
416
if (spaceAfterResourceIdx == std::string::npos) {
376
417
HTTPS_LOGW (" Missing space after resource" );
377
- clientError ( );
418
+ raiseError ( 400 , " Bad Request " );
378
419
break ;
379
420
}
380
421
_httpResource = _parserLine.text .substr (spaceAfterMethodIdx + 1 , spaceAfterResourceIdx - _httpMethod.length () - 1 );
381
422
382
423
_parserLine.parsingFinished = false ;
383
424
_parserLine.text = " " ;
384
- HTTPS_LOGI (" Request: %s %s (FID=%d)" , _httpMethod.c_str (), _httpResource.c_str (), _socket);
425
+ HTTPS_LOGI (" Request: %s %s (FID=%d, T=%p )" , _httpMethod.c_str (), _httpResource.c_str (), _socket, xTaskGetCurrentTaskHandle () );
385
426
_connectionState = STATE_REQUEST_FINISHED;
386
427
}
387
428
@@ -411,7 +452,7 @@ bool HTTPConnection::loop() {
411
452
HTTPS_LOGD (" Header: %s = %s (FID=%d)" , _parserLine.text .substr (0 , idxColon).c_str (), _parserLine.text .substr (idxColon+2 ).c_str (), _socket);
412
453
} else {
413
454
HTTPS_LOGW (" Malformed request header: %s" , _parserLine.text .c_str ());
414
- clientError ( );
455
+ raiseError ( 400 , " Bad Request " );
415
456
break ;
416
457
}
417
458
}
@@ -558,7 +599,7 @@ bool HTTPConnection::loop() {
558
599
} else {
559
600
// No match (no default route configured, nothing does match)
560
601
HTTPS_LOGW (" Could not find a matching resource" );
561
- serverError ( );
602
+ raiseError ( 404 , " Not Found " );
562
603
}
563
604
564
605
}
@@ -594,7 +635,6 @@ bool HTTPConnection::loop() {
594
635
return (!isClosed () && ((_bufferProcessed < _bufferUnusedIdx) || canReadData ()));
595
636
}
596
637
597
-
598
638
bool HTTPConnection::checkWebsocket () {
599
639
if (_httpMethod == " GET" &&
600
640
!_httpHeaders->getValue (" Host" ).empty () &&
0 commit comments