Skip to content

Commit 43b8c56

Browse files
author
Ivan Kostoski
committed
General fixes/improvements
1 parent 1f4ef5e commit 43b8c56

File tree

7 files changed

+94
-25
lines changed

7 files changed

+94
-25
lines changed

src/HTTPConnection.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,13 @@ size_t HTTPConnection::getCacheSize() {
331331
return (_isKeepAlive ? HTTPS_KEEPALIVE_CACHESIZE : 0);
332332
}
333333

334-
void HTTPConnection::loop() {
334+
/**
335+
* Connection main async loop method
336+
*
337+
* Returns true if there is more data to be processed in
338+
* the input buffers
339+
*/
340+
bool HTTPConnection::loop() {
335341
// First, update the buffer
336342
// newByteCount will contain the number of new bytes that have to be processed
337343
updateBuffer();
@@ -379,7 +385,8 @@ void HTTPConnection::loop() {
379385
_connectionState = STATE_REQUEST_FINISHED;
380386
}
381387

382-
break;
388+
if (_connectionState != STATE_REQUEST_FINISHED) break;
389+
383390
case STATE_REQUEST_FINISHED: // Read headers
384391

385392
while (_bufferProcessed < _bufferUnusedIdx && !isClosed()) {
@@ -414,7 +421,8 @@ void HTTPConnection::loop() {
414421
}
415422
}
416423

417-
break;
424+
if (_connectionState != STATE_HEADERS_FINISHED) break;
425+
418426
case STATE_HEADERS_FINISHED: // Handle body
419427
{
420428
HTTPS_LOGD("Resolving resource...");
@@ -520,19 +528,23 @@ void HTTPConnection::loop() {
520528
// we have no chance to do so.
521529
if (!_isKeepAlive) {
522530
// No KeepAlive -> We are done. Transition to next state.
531+
HTTPS_LOGD("No keep-alive");
523532
if (!isClosed()) {
524533
_connectionState = STATE_BODY_FINISHED;
525534
}
526535
} else {
527536
if (res.isResponseBuffered()) {
528-
// If the response could be buffered:
537+
// If the response is buffered:
538+
HTTPS_LOGD("Buffered, set keep-alive");
529539
res.setHeader("Connection", "keep-alive");
530540
res.finalize();
541+
}
542+
if (res.correctContentLength()) {
531543
if (_clientState != CSTATE_CLOSED) {
532544
// Refresh the timeout for the new request
533545
refreshTimeout();
534546
// Reset headers for the new connection
535-
_httpHeaders->clearAll();
547+
if (_httpHeaders) _httpHeaders->clearAll();
536548
// Go back to initial state
537549
_connectionState = STATE_INITIAL;
538550
}
@@ -550,13 +562,16 @@ void HTTPConnection::loop() {
550562
}
551563

552564
}
553-
break;
565+
if (_connectionState != STATE_BODY_FINISHED) break;
566+
554567
case STATE_BODY_FINISHED: // Request is complete
555568
closeConnection();
556569
break;
570+
557571
case STATE_CLOSING: // As long as we are in closing state, we call closeConnection() again and wait for it to finish or timeout
558572
closeConnection();
559573
break;
574+
560575
case STATE_WEBSOCKET: // Do handling of the websocket
561576
refreshTimeout(); // don't timeout websocket connection
562577
if(pendingBufferSize() > 0) {
@@ -575,6 +590,8 @@ void HTTPConnection::loop() {
575590
}
576591
}
577592

593+
// Return true if connection has more data to process
594+
return (!isClosed() && ((_bufferProcessed < _bufferUnusedIdx) || canReadData()));
578595
}
579596

580597

src/HTTPConnection.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class HTTPConnection : private ConnectionContext {
4343
virtual void closeConnection();
4444
virtual bool isSecure();
4545

46-
void loop();
46+
bool loop();
4747
bool isClosed();
4848
bool isError();
4949

src/HTTPRequest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ HTTPRequest::HTTPRequest(
2828
}
2929

3030
HTTPRequest::~HTTPRequest() {
31-
_headers->clearAll();
31+
if (_headers) _headers->clearAll();
3232
}
3333

3434

src/HTTPResponse.cpp

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,14 @@ HTTPResponse::HTTPResponse(ConnectionContext * con):
1313
_statusText = "OK";
1414
_headerWritten = false;
1515
_isError = false;
16+
_setLength = 0;
17+
_sentBytesCount = 0;
1618

1719
_responseCacheSize = con->getCacheSize();
1820
_responseCachePointer = 0;
19-
if (_responseCacheSize > 0) {
20-
HTTPS_LOGD("Creating buffered response, size: %d", _responseCacheSize);
21-
_responseCache = new byte[_responseCacheSize];
22-
} else {
23-
HTTPS_LOGD("Creating non-buffered response");
24-
_responseCache = NULL;
25-
}
21+
_responseCache = NULL;
22+
// Don't create buffer response just yet,
23+
// wait and see if we receive Content-Length ...
2624
}
2725

2826
HTTPResponse::~HTTPResponse() {
@@ -48,8 +46,26 @@ std::string HTTPResponse::getStatusText() {
4846
return _statusText;
4947
}
5048

49+
void HTTPResponse::setContentLength(size_t size) {
50+
if (isHeaderWritten()) {
51+
HTTPS_LOGE("Setting Content-Lenght after headers sent!");
52+
error();
53+
return;
54+
}
55+
if ((_setLength > 0) && (size != _setLength)) {
56+
HTTPS_LOGW("Setting Content-Lenght more than once!");
57+
}
58+
HTTPS_LOGD("Set Content-Lenght: %d", size);
59+
_setLength = size;
60+
}
61+
5162
void HTTPResponse::setHeader(std::string const &name, std::string const &value) {
5263
_headers.set(new HTTPHeader(name, value));
64+
// Watch for "Content-Length" header
65+
if (name.compare("Content-Length") == 0) {
66+
setContentLength(parseUInt(value));
67+
return;
68+
}
5369
}
5470

5571
bool HTTPResponse::isHeaderWritten() {
@@ -60,6 +76,14 @@ bool HTTPResponse::isResponseBuffered() {
6076
return _responseCache != NULL;
6177
}
6278

79+
bool HTTPResponse::correctContentLength() {
80+
if (_setLength > 0) {
81+
if (_sentBytesCount == _setLength) return true;
82+
HTTPS_LOGE("Content-Lenght (%u) and data sent (%u) mismatch!", _setLength, _sentBytesCount);
83+
}
84+
return false;
85+
}
86+
6387
void HTTPResponse::finalize() {
6488
if (isResponseBuffered()) {
6589
drainBuffer();
@@ -77,6 +101,22 @@ void HTTPResponse::printStd(const std::string &str) {
77101
* Writes bytes to the response. May be called several times.
78102
*/
79103
size_t HTTPResponse::write(const uint8_t *buffer, size_t size) {
104+
if (_sentBytesCount < 1) {
105+
if (_setLength > 0) {
106+
HTTPS_LOGD("Streaming response directly, size: %d", _setLength);
107+
} else if (size > 0) {
108+
// Try buffering
109+
if (_responseCacheSize > 0) {
110+
_responseCache = new byte[_responseCacheSize];
111+
HTTPS_LOGD("Content-Length not set. Creating buffered response, size: %d", _responseCacheSize);
112+
} else {
113+
// We'll have to tear down the connection to signal end of data
114+
setHeader("Connection", "close");
115+
HTTPS_LOGD("Content-Length not set. Creating non-buffered response");
116+
}
117+
}
118+
}
119+
_sentBytesCount += size;
80120
if(!isResponseBuffered()) {
81121
printHeader();
82122
}
@@ -87,11 +127,8 @@ size_t HTTPResponse::write(const uint8_t *buffer, size_t size) {
87127
* Writes a single byte to the response.
88128
*/
89129
size_t HTTPResponse::write(uint8_t b) {
90-
if(!isResponseBuffered()) {
91-
printHeader();
92-
}
93130
byte ba[] = {b};
94-
return writeBytesInternal(ba, 1);
131+
return write(ba, 1);
95132
}
96133

97134
/**
@@ -168,8 +205,8 @@ void HTTPResponse::drainBuffer(bool onOverflow) {
168205
HTTPS_LOGD("Draining response buffer");
169206
// Check for 0 as it may be an overflow reaction without any data that has been written earlier
170207
if(_responseCachePointer > 0) {
171-
// FIXME: Return value?
172-
_con->writeBuffer((byte*)_responseCache, _responseCachePointer);
208+
_setLength = _responseCachePointer;
209+
_sentBytesCount = _con->writeBuffer((byte*)_responseCache, _responseCachePointer);
173210
}
174211
delete[] _responseCache;
175212
_responseCache = NULL;

src/HTTPResponse.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ class HTTPResponse : public Print {
4242

4343
void error();
4444

45+
void setContentLength(size_t size);
4546
bool isResponseBuffered();
47+
bool correctContentLength();
4648
void finalize();
4749

4850
ConnectionContext * _con;
@@ -59,6 +61,10 @@ class HTTPResponse : public Print {
5961
bool _headerWritten;
6062
bool _isError;
6163

64+
// Response length
65+
size_t _setLength;
66+
size_t _sentBytesCount;
67+
6268
// Response cache
6369
byte * _responseCache;
6470
size_t _responseCacheSize;

src/HTTPSConnection.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,19 +105,21 @@ void HTTPSConnection::closeConnection() {
105105
}
106106

107107
size_t HTTPSConnection::writeBuffer(byte* buffer, size_t length) {
108-
return SSL_write(_ssl, buffer, length);
108+
if (_ssl != NULL) return SSL_write(_ssl, buffer, length);
109+
return 0;
109110
}
110111

111112
size_t HTTPSConnection::readBytesToBuffer(byte* buffer, size_t length) {
112-
return SSL_read(_ssl, buffer, length);
113+
if (_ssl != NULL) return SSL_read(_ssl, buffer, length);
114+
return 0;
113115
}
114116

115117
size_t HTTPSConnection::pendingByteCount() {
116-
return SSL_pending(_ssl);
118+
return (_ssl != NULL) && SSL_pending(_ssl);
117119
}
118120

119121
bool HTTPSConnection::canReadData() {
120-
return HTTPConnection::canReadData() || (SSL_pending(_ssl) > 0);
122+
return HTTPConnection::canReadData() || ((_ssl != NULL) && (SSL_pending(_ssl) > 0));
121123
}
122124

123125
} /* namespace httpsserver */

src/HTTPSServerConstants.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@
4242
#define HTTPS_LOGD(...) do {} while (0)
4343
#endif
4444

45+
#if HTTPS_LOGLEVEL > 4
46+
#define HTTPS_LOGV(...) HTTPS_LOGTAG("D");Serial.printf(__VA_ARGS__);Serial.println()
47+
#else
48+
#define HTTPS_LOGV(...) {}
49+
#endif
50+
51+
4552
// The following lines define limits of the protocol. Exceeding these limits will lead to a 500 error
4653

4754
// Maximum of header lines that are parsed

0 commit comments

Comments
 (0)