Skip to content

Commit a5d31a7

Browse files
authored
deprecate and update Stream::send*(Print -> Stream) (#8874)
* deprecate and update Stream::send(Print -> Stream) in order to benefit from and use output's timeout value
1 parent 01d1c8e commit a5d31a7

File tree

4 files changed

+185
-125
lines changed

4 files changed

+185
-125
lines changed

cores/esp8266/Stream.h

+38-8
Original file line numberDiff line numberDiff line change
@@ -167,25 +167,49 @@ class Stream: public Print {
167167
// When result is 0 or less than requested maxLen, Print::getLastSend()
168168
// contains an error reason.
169169

170+
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
171+
172+
// transfers already buffered / immediately available data (no timeout)
173+
// returns number of transferred bytes
174+
[[deprecated]] size_t sendAvailable (Print* to) { return sendGeneric(to, -1, -1, oneShotMs::alwaysExpired); }
175+
[[deprecated]] size_t sendAvailable (Print& to) { return sendAvailable(&to); }
176+
177+
// transfers data until timeout
178+
// returns number of transferred bytes
179+
[[deprecated]] size_t sendAll (Print* to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, -1, -1, timeoutMs); }
180+
[[deprecated]] size_t sendAll (Print& to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendAll(&to, timeoutMs); }
181+
182+
// transfers data until a char is encountered (the char is swallowed but not transferred) with timeout
183+
// returns number of transferred bytes
184+
[[deprecated]] size_t sendUntil (Print* to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, -1, readUntilChar, timeoutMs); }
185+
[[deprecated]] size_t sendUntil (Print& to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendUntil(&to, readUntilChar, timeoutMs); }
186+
187+
// transfers data until requested size or timeout
188+
// returns number of transferred bytes
189+
[[deprecated]] size_t sendSize (Print* to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, maxLen, -1, timeoutMs); }
190+
[[deprecated]] size_t sendSize (Print& to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendSize(&to, maxLen, timeoutMs); }
191+
192+
#pragma GCC diagnostic pop
193+
170194
// transfers already buffered / immediately available data (no timeout)
171195
// returns number of transferred bytes
172-
size_t sendAvailable (Print* to) { return sendGeneric(to, -1, -1, oneShotMs::alwaysExpired); }
173-
size_t sendAvailable (Print& to) { return sendAvailable(&to); }
196+
size_t sendAvailable (Stream* to) { return sendGeneric(to, -1, -1, oneShotMs::alwaysExpired); }
197+
size_t sendAvailable (Stream& to) { return sendAvailable(&to); }
174198

175199
// transfers data until timeout
176200
// returns number of transferred bytes
177-
size_t sendAll (Print* to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, -1, -1, timeoutMs); }
178-
size_t sendAll (Print& to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendAll(&to, timeoutMs); }
201+
size_t sendAll (Stream* to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, -1, -1, timeoutMs); }
202+
size_t sendAll (Stream& to, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendAll(&to, timeoutMs); }
179203

180204
// transfers data until a char is encountered (the char is swallowed but not transferred) with timeout
181205
// returns number of transferred bytes
182-
size_t sendUntil (Print* to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, -1, readUntilChar, timeoutMs); }
183-
size_t sendUntil (Print& to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendUntil(&to, readUntilChar, timeoutMs); }
206+
size_t sendUntil (Stream* to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, -1, readUntilChar, timeoutMs); }
207+
size_t sendUntil (Stream& to, const int readUntilChar, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendUntil(&to, readUntilChar, timeoutMs); }
184208

185209
// transfers data until requested size or timeout
186210
// returns number of transferred bytes
187-
size_t sendSize (Print* to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, maxLen, -1, timeoutMs); }
188-
size_t sendSize (Print& to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendSize(&to, maxLen, timeoutMs); }
211+
size_t sendSize (Stream* to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendGeneric(to, maxLen, -1, timeoutMs); }
212+
size_t sendSize (Stream& to, const ssize_t maxLen, const oneShotMs::timeType timeoutMs = oneShotMs::neverExpires) { return sendSize(&to, maxLen, timeoutMs); }
189213

190214
// remaining size (-1 by default = unknown)
191215
virtual ssize_t streamRemaining () { return -1; }
@@ -202,11 +226,17 @@ class Stream: public Print {
202226
Report getLastSendReport () const { return _sendReport; }
203227

204228
protected:
229+
[[deprecated]]
205230
size_t sendGeneric (Print* to,
206231
const ssize_t len = -1,
207232
const int readUntilChar = -1,
208233
oneShotMs::timeType timeoutMs = oneShotMs::neverExpires /* neverExpires=>getTimeout() */);
209234

235+
size_t sendGeneric (Stream* to,
236+
const ssize_t len = -1,
237+
const int readUntilChar = -1,
238+
oneShotMs::timeType timeoutMs = oneShotMs::neverExpires /* neverExpires=>getTimeout() */);
239+
210240
size_t SendGenericPeekBuffer(Print* to, const ssize_t len, const int readUntilChar, const oneShotMs::timeType timeoutMs);
211241
size_t SendGenericRegularUntil(Print* to, const ssize_t len, const int readUntilChar, const oneShotMs::timeType timeoutMs);
212242
size_t SendGenericRegular(Print* to, const ssize_t len, const oneShotMs::timeType timeoutMs);

cores/esp8266/StreamSend.cpp

+54-15
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,54 @@
2222
#include <Arduino.h>
2323
#include <StreamDev.h>
2424

25+
size_t Stream::sendGeneric(Stream* to, const ssize_t len, const int readUntilChar,
26+
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
27+
{
28+
// "neverExpires (default, impossible)" is translated to default timeout
29+
esp8266::polledTimeout::oneShotFastMs::timeType inputTimeoutMs
30+
= timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
31+
: timeoutMs;
32+
33+
esp8266::polledTimeout::oneShotFastMs::timeType mainTimeoutMs = std::max(
34+
inputTimeoutMs, (esp8266::polledTimeout::oneShotFastMs::timeType)to->getTimeout());
35+
36+
setReport(Report::Success);
37+
38+
if (len == 0)
39+
{
40+
return 0; // conveniently avoids timeout for no requested data
41+
}
42+
43+
// There are two timeouts:
44+
// - read (network, serial, ...)
45+
// - write (network, serial, ...)
46+
// However
47+
// - getTimeout() is for reading only
48+
// - there is no getOutputTimeout() api
49+
// So we use getTimeout() for both,
50+
// (also when inputCanTimeout() is false)
51+
52+
if (hasPeekBufferAPI())
53+
{
54+
return SendGenericPeekBuffer(to, len, readUntilChar, mainTimeoutMs);
55+
}
56+
57+
if (readUntilChar >= 0)
58+
{
59+
return SendGenericRegularUntil(to, len, readUntilChar, mainTimeoutMs);
60+
}
61+
62+
return SendGenericRegular(to, len, mainTimeoutMs);
63+
}
64+
2565
size_t Stream::sendGeneric(Print* to, const ssize_t len, const int readUntilChar,
2666
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
2767
{
68+
// "neverExpires (default, impossible)" is translated to default timeout
69+
esp8266::polledTimeout::oneShotFastMs::timeType inputTimeoutMs
70+
= timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
71+
: timeoutMs;
72+
2873
setReport(Report::Success);
2974

3075
if (len == 0)
@@ -43,25 +88,23 @@ size_t Stream::sendGeneric(Print* to, const ssize_t len, const int readUntilChar
4388

4489
if (hasPeekBufferAPI())
4590
{
46-
return SendGenericPeekBuffer(to, len, readUntilChar, timeoutMs);
91+
return SendGenericPeekBuffer(to, len, readUntilChar, inputTimeoutMs);
4792
}
4893

4994
if (readUntilChar >= 0)
5095
{
51-
return SendGenericRegularUntil(to, len, readUntilChar, timeoutMs);
96+
return SendGenericRegularUntil(to, len, readUntilChar, inputTimeoutMs);
5297
}
5398

54-
return SendGenericRegular(to, len, timeoutMs);
99+
return SendGenericRegular(to, len, inputTimeoutMs);
55100
}
56101

57102
size_t
58103
Stream::SendGenericPeekBuffer(Print* to, const ssize_t len, const int readUntilChar,
59104
const esp8266::polledTimeout::oneShotFastMs::timeType timeoutMs)
60105
{
61-
// "neverExpires (default, impossible)" is translated to default timeout
62-
esp8266::polledTimeout::oneShotFastMs timedOut(
63-
timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
64-
: timeoutMs);
106+
esp8266::polledTimeout::oneShotFastMs timedOut(timeoutMs);
107+
65108
// len==-1 => maxLen=0 <=> until starvation
66109
const size_t maxLen = std::max((ssize_t)0, len);
67110
size_t written = 0;
@@ -152,10 +195,8 @@ Stream::SendGenericRegularUntil(Print* to, const ssize_t len, const int readUnti
152195
// regular Stream API
153196
// no other choice than reading byte by byte
154197

155-
// "neverExpires (default, impossible)" is translated to default timeout
156-
esp8266::polledTimeout::oneShotFastMs timedOut(
157-
timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
158-
: timeoutMs);
198+
esp8266::polledTimeout::oneShotFastMs timedOut(timeoutMs);
199+
159200
// len==-1 => maxLen=0 <=> until starvation
160201
const size_t maxLen = std::max((ssize_t)0, len);
161202
size_t written = 0;
@@ -231,10 +272,8 @@ size_t Stream::SendGenericRegular(Print* to, const ssize_t len,
231272
// regular Stream API
232273
// use an intermediary buffer
233274

234-
// "neverExpires (default, impossible)" is translated to default timeout
235-
esp8266::polledTimeout::oneShotFastMs timedOut(
236-
timeoutMs >= esp8266::polledTimeout::oneShotFastMs::neverExpires ? getTimeout()
237-
: timeoutMs);
275+
esp8266::polledTimeout::oneShotFastMs timedOut(timeoutMs);
276+
238277
// len==-1 => maxLen=0 <=> until starvation
239278
const size_t maxLen = std::max((ssize_t)0, len);
240279
size_t written = 0;

libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp

+1-100
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static_assert(std::is_move_assignable_v<HTTPClient>, "");
3939
static const char defaultUserAgentPstr[] PROGMEM = "ESP8266HTTPClient";
4040
const String HTTPClient::defaultUserAgent = defaultUserAgentPstr;
4141

42-
static int StreamReportToHttpClientReport (Stream::Report streamSendError)
42+
int HTTPClient::StreamReportToHttpClientReport (Stream::Report streamSendError)
4343
{
4444
switch (streamSendError)
4545
{
@@ -627,105 +627,6 @@ WiFiClient* HTTPClient::getStreamPtr(void)
627627
return nullptr;
628628
}
629629

630-
/**
631-
* write all message body / payload to Stream
632-
* @param stream Stream *
633-
* @return bytes written ( negative values are error codes )
634-
*/
635-
int HTTPClient::writeToStream(Stream * stream)
636-
{
637-
return writeToPrint(stream);
638-
}
639-
640-
/**
641-
* write all message body / payload to Print
642-
* @param print Print *
643-
* @return bytes written ( negative values are error codes )
644-
*/
645-
int HTTPClient::writeToPrint(Print * print)
646-
{
647-
648-
if(!print) {
649-
return returnError(HTTPC_ERROR_NO_STREAM);
650-
}
651-
652-
// Only return error if not connected and no data available, because otherwise ::getString() will return an error instead of an empty
653-
// string when the server returned a http code 204 (no content)
654-
if(!connected() && _transferEncoding != HTTPC_TE_IDENTITY && _size > 0) {
655-
return returnError(HTTPC_ERROR_NOT_CONNECTED);
656-
}
657-
658-
// get length of document (is -1 when Server sends no Content-Length header)
659-
int len = _size;
660-
int ret = 0;
661-
662-
if(_transferEncoding == HTTPC_TE_IDENTITY) {
663-
// len < 0: transfer all of it, with timeout
664-
// len >= 0: max:len, with timeout
665-
ret = _client->sendSize(print, len);
666-
667-
// do we have an error?
668-
if(_client->getLastSendReport() != Stream::Report::Success) {
669-
return returnError(StreamReportToHttpClientReport(_client->getLastSendReport()));
670-
}
671-
} else if(_transferEncoding == HTTPC_TE_CHUNKED) {
672-
int size = 0;
673-
while(1) {
674-
if(!connected()) {
675-
return returnError(HTTPC_ERROR_CONNECTION_LOST);
676-
}
677-
String chunkHeader = _client->readStringUntil('\n');
678-
679-
if(chunkHeader.length() <= 0) {
680-
return returnError(HTTPC_ERROR_READ_TIMEOUT);
681-
}
682-
683-
chunkHeader.trim(); // remove \r
684-
685-
// read size of chunk
686-
len = (uint32_t) strtol((const char *) chunkHeader.c_str(), NULL, 16);
687-
size += len;
688-
DEBUG_HTTPCLIENT("[HTTP-Client] read chunk len: %d\n", len);
689-
690-
// data left?
691-
if(len > 0) {
692-
// read len bytes with timeout
693-
int r = _client->sendSize(print, len);
694-
if (_client->getLastSendReport() != Stream::Report::Success)
695-
// not all data transferred
696-
return returnError(StreamReportToHttpClientReport(_client->getLastSendReport()));
697-
ret += r;
698-
} else {
699-
700-
// if no length Header use global chunk size
701-
if(_size <= 0) {
702-
_size = size;
703-
}
704-
705-
// check if we have write all data out
706-
if(ret != _size) {
707-
return returnError(HTTPC_ERROR_STREAM_WRITE);
708-
}
709-
break;
710-
}
711-
712-
// read trailing \r\n at the end of the chunk
713-
char buf[2];
714-
auto trailing_seq_len = _client->readBytes((uint8_t*)buf, 2);
715-
if (trailing_seq_len != 2 || buf[0] != '\r' || buf[1] != '\n') {
716-
return returnError(HTTPC_ERROR_READ_TIMEOUT);
717-
}
718-
719-
esp_yield();
720-
}
721-
} else {
722-
return returnError(HTTPC_ERROR_ENCODING);
723-
}
724-
725-
disconnect(true);
726-
return ret;
727-
}
728-
729630
/**
730631
* return all payload as String (may need lot of ram or trigger out of memory!)
731632
* @return String

0 commit comments

Comments
 (0)