@@ -26,23 +26,28 @@ HTTPConnection::~HTTPConnection() {
2626}
2727
2828/* *
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.
3038 *
3139 * The call WILL BLOCK if accept(serverSocketID) blocks. So use select() to check for that in advance.
3240 */
33- int HTTPConnection::initialize ( int serverSocketID, HTTPHeaders *defaultHeaders ) {
41+ int HTTPConnection::initialAccept ( ) {
3442 if (_connectionState == STATE_UNDEFINED) {
35- _defaultHeaders = defaultHeaders;
36- _socket = accept (serverSocketID, (struct sockaddr * )&_sockAddr, &_addrLen);
43+ _socket = accept (_serverSocket, (struct sockaddr * )&_sockAddr, &_addrLen);
3744
38- // Build up SSL Connection context if the socket has been created successfully
3945 if (_socket >= 0 ) {
4046 HTTPS_LOGI (" New connection. Socket FID=%d" , _socket);
41- _connectionState = STATE_INITIAL ;
47+ _connectionState = STATE_ACCEPTED ;
4248 _httpHeaders = new HTTPHeaders ();
4349 refreshTimeout ();
4450 return _socket;
45-
4651 }
4752
4853 HTTPS_LOGE (" Could not accept() new connection" );
@@ -58,6 +63,23 @@ int HTTPConnection::initialize(int serverSocketID, HTTPHeaders *defaultHeaders)
5863 return -1 ;
5964}
6065
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+ }
6183
6284/* *
6385 * True if the connection is timed out.
@@ -68,6 +90,17 @@ bool HTTPConnection::isTimeoutExceeded() {
6890 return _lastTransmissionTS + HTTPS_CONNECTION_TIMEOUT < millis ();
6991}
7092
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+
71104/* *
72105 * Resets the timeout to allow again the full HTTPS_CONNECTION_TIMEOUT milliseconds
73106 */
@@ -89,6 +122,14 @@ bool HTTPConnection::isError() {
89122 return (_connectionState == STATE_ERROR);
90123}
91124
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+
92133bool HTTPConnection::isSecure () {
93134 return false ;
94135}
@@ -129,6 +170,7 @@ void HTTPConnection::closeConnection() {
129170 if (_wsHandler != nullptr ) {
130171 HTTPS_LOGD (" Free WS Handler" );
131172 delete _wsHandler;
173+ _wsHandler = NULL ;
132174 }
133175}
134176
@@ -258,20 +300,19 @@ size_t HTTPConnection::readBytesToBuffer(byte* buffer, size_t length) {
258300 return recv (_socket, buffer, length, MSG_WAITALL | MSG_DONTWAIT);
259301}
260302
261- void HTTPConnection::serverError ( ) {
303+ void HTTPConnection::raiseError ( uint16_t code, std::string reason ) {
262304 _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 ());
275316 closeConnection ();
276317}
277318
@@ -289,7 +330,7 @@ void HTTPConnection::readLine(int lengthLimit) {
289330 } else {
290331 // Line has not been terminated by \r\n
291332 HTTPS_LOGW (" Line without \\ r\\ n (got only \\ r). FID=%d" , _socket);
292- clientError ( );
333+ raiseError ( 400 , " Bad Request " );
293334 return ;
294335 }
295336 }
@@ -301,7 +342,7 @@ void HTTPConnection::readLine(int lengthLimit) {
301342 // Check that the max request string size is not exceeded
302343 if (_parserLine.text .length () > lengthLimit) {
303344 HTTPS_LOGW (" Header length exceeded. FID=%d" , _socket);
304- serverError ( );
345+ raiseError ( 431 , " Request Header Fields Too Large " );
305346 return ;
306347 }
307348 }
@@ -319,7 +360,7 @@ void HTTPConnection::signalClientClose() {
319360 */
320361void HTTPConnection::signalRequestError () {
321362 // TODO: Check that no response has been transmitted yet
322- serverError ( );
363+ raiseError ( 400 , " Bad Request " );
323364}
324365
325366/* *
@@ -365,7 +406,7 @@ bool HTTPConnection::loop() {
365406 size_t spaceAfterMethodIdx = _parserLine.text .find (' ' );
366407 if (spaceAfterMethodIdx == std::string::npos) {
367408 HTTPS_LOGW (" Missing space after method" );
368- clientError ( );
409+ raiseError ( 400 , " Bad Request " );
369410 break ;
370411 }
371412 _httpMethod = _parserLine.text .substr (0 , spaceAfterMethodIdx);
@@ -374,14 +415,14 @@ bool HTTPConnection::loop() {
374415 size_t spaceAfterResourceIdx = _parserLine.text .find (' ' , spaceAfterMethodIdx + 1 );
375416 if (spaceAfterResourceIdx == std::string::npos) {
376417 HTTPS_LOGW (" Missing space after resource" );
377- clientError ( );
418+ raiseError ( 400 , " Bad Request " );
378419 break ;
379420 }
380421 _httpResource = _parserLine.text .substr (spaceAfterMethodIdx + 1 , spaceAfterResourceIdx - _httpMethod.length () - 1 );
381422
382423 _parserLine.parsingFinished = false ;
383424 _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 () );
385426 _connectionState = STATE_REQUEST_FINISHED;
386427 }
387428
@@ -411,7 +452,7 @@ bool HTTPConnection::loop() {
411452 HTTPS_LOGD (" Header: %s = %s (FID=%d)" , _parserLine.text .substr (0 , idxColon).c_str (), _parserLine.text .substr (idxColon+2 ).c_str (), _socket);
412453 } else {
413454 HTTPS_LOGW (" Malformed request header: %s" , _parserLine.text .c_str ());
414- clientError ( );
455+ raiseError ( 400 , " Bad Request " );
415456 break ;
416457 }
417458 }
@@ -558,7 +599,7 @@ bool HTTPConnection::loop() {
558599 } else {
559600 // No match (no default route configured, nothing does match)
560601 HTTPS_LOGW (" Could not find a matching resource" );
561- serverError ( );
602+ raiseError ( 404 , " Not Found " );
562603 }
563604
564605 }
@@ -594,7 +635,6 @@ bool HTTPConnection::loop() {
594635 return (!isClosed () && ((_bufferProcessed < _bufferUnusedIdx) || canReadData ()));
595636}
596637
597-
598638bool HTTPConnection::checkWebsocket () {
599639 if (_httpMethod == " GET" &&
600640 !_httpHeaders->getValue (" Host" ).empty () &&
0 commit comments