Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WifiClient::write refactoring (second attempt) #2177

Merged
merged 3 commits into from
Jun 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 7 additions & 57 deletions libraries/ESP8266WebServer/src/ESP8266WebServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ void ESP8266WebServer::handleClient() {
_currentStatus = HC_NONE;
return;
}

_currentClient.setTimeout(HTTP_MAX_SEND_WAIT);
_contentLength = CONTENT_LENGTH_NOT_SET;
_handleRequest();

Expand Down Expand Up @@ -241,6 +241,9 @@ void ESP8266WebServer::sendHeader(const String& name, const String& value, bool
}
}

void ESP8266WebServer::setContentLength(size_t contentLength) {
_contentLength = contentLength;
}

void ESP8266WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) {
response = "HTTP/1.1 ";
Expand Down Expand Up @@ -270,7 +273,6 @@ void ESP8266WebServer::send(int code, const char* content_type, const String& co
String header;
_prepareHeader(header, code, content_type, content.length());
sendContent(header);

sendContent(content);
}

Expand Down Expand Up @@ -307,67 +309,15 @@ void ESP8266WebServer::send(int code, const String& content_type, const String&
}

void ESP8266WebServer::sendContent(const String& content) {
const size_t unit_size = HTTP_DOWNLOAD_UNIT_SIZE;
size_t size_to_send = content.length();
const char* send_start = content.c_str();

while (size_to_send) {
size_t will_send = (size_to_send < unit_size) ? size_to_send : unit_size;
size_t sent = _currentClient.write(send_start, will_send);
if (sent == 0) {
break;
}
size_to_send -= sent;
send_start += sent;
}
_currentClient.write(content.c_str(), content.length());
}

void ESP8266WebServer::sendContent_P(PGM_P content) {
char contentUnit[HTTP_DOWNLOAD_UNIT_SIZE + 1];

contentUnit[HTTP_DOWNLOAD_UNIT_SIZE] = '\0';

while (content != NULL) {
size_t contentUnitLen;
PGM_P contentNext;

// due to the memccpy signature, lots of casts are needed
contentNext = (PGM_P)memccpy_P((void*)contentUnit, (PGM_VOID_P)content, 0, HTTP_DOWNLOAD_UNIT_SIZE);

if (contentNext == NULL) {
// no terminator, more data available
content += HTTP_DOWNLOAD_UNIT_SIZE;
contentUnitLen = HTTP_DOWNLOAD_UNIT_SIZE;
}
else {
// reached terminator. Do not send the terminator
contentUnitLen = contentNext - contentUnit - 1;
content = NULL;
}

// write is so overloaded, had to use the cast to get it pick the right one
_currentClient.write((const char*)contentUnit, contentUnitLen);
}
_currentClient.write_P(content, strlen_P(content));
}

void ESP8266WebServer::sendContent_P(PGM_P content, size_t size) {
char contentUnit[HTTP_DOWNLOAD_UNIT_SIZE + 1];
contentUnit[HTTP_DOWNLOAD_UNIT_SIZE] = '\0';
size_t remaining_size = size;

while (content != NULL && remaining_size > 0) {
size_t contentUnitLen = HTTP_DOWNLOAD_UNIT_SIZE;

if (remaining_size < HTTP_DOWNLOAD_UNIT_SIZE) contentUnitLen = remaining_size;
// due to the memcpy signature, lots of casts are needed
memcpy_P((void*)contentUnit, (PGM_VOID_P)content, contentUnitLen);

content += contentUnitLen;
remaining_size -= contentUnitLen;

// write is so overloaded, had to use the cast to get it pick the right one
_currentClient.write((const char*)contentUnit, contentUnitLen);
}
_currentClient.write_P(content, size);
}


Expand Down
5 changes: 3 additions & 2 deletions libraries/ESP8266WebServer/src/ESP8266WebServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ enum HTTPClientStatus { HC_NONE, HC_WAIT_READ, HC_WAIT_CLOSE };
#define HTTP_UPLOAD_BUFLEN 2048
#define HTTP_MAX_DATA_WAIT 1000 //ms to wait for the client to send the request
#define HTTP_MAX_POST_WAIT 1000 //ms to wait for POST data to arrive
#define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed
#define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection

#define CONTENT_LENGTH_UNKNOWN ((size_t) -1)
Expand Down Expand Up @@ -113,7 +114,7 @@ class ESP8266WebServer
void send_P(int code, PGM_P content_type, PGM_P content);
void send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength);

void setContentLength(size_t contentLength) { _contentLength = contentLength; }
void setContentLength(size_t contentLength);
void sendHeader(const String& name, const String& value, bool first = false);
void sendContent(const String& content);
void sendContent_P(PGM_P content);
Expand All @@ -129,7 +130,7 @@ template<typename T> size_t streamFile(T &file, const String& contentType){
sendHeader("Content-Encoding", "gzip");
}
send(200, contentType, "");
return _currentClient.write(file, HTTP_DOWNLOAD_UNIT_SIZE);
return _currentClient.write(file);
}

protected:
Expand Down
35 changes: 15 additions & 20 deletions libraries/ESP8266WiFi/src/WiFiClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,35 +172,30 @@ size_t WiFiClient::write(const uint8_t *buf, size_t size)
{
return 0;
}
return _client->write(buf, size);
}

return _client->write(reinterpret_cast<const char*>(buf), size);
size_t WiFiClient::write(Stream& stream, size_t unused)
{
return WiFiClient::write(stream);
}

size_t WiFiClient::write_P(PGM_P buf, size_t size)
size_t WiFiClient::write(Stream& stream)
{
if (!_client || !size)
if (!_client || !stream.available())
{
return 0;
}
return _client->write(stream);
}

char chunkUnit[WIFICLIENT_MAX_PACKET_SIZE + 1];
chunkUnit[WIFICLIENT_MAX_PACKET_SIZE] = '\0';
size_t remaining_size = size;

while (buf != NULL && remaining_size > 0) {
size_t chunkUnitLen = WIFICLIENT_MAX_PACKET_SIZE;

if (remaining_size < WIFICLIENT_MAX_PACKET_SIZE) chunkUnitLen = remaining_size;
// due to the memcpy signature, lots of casts are needed
memcpy_P((void*)chunkUnit, (PGM_VOID_P)buf, chunkUnitLen);

buf += chunkUnitLen;
remaining_size -= chunkUnitLen;

// write is so overloaded, had to use the cast to get it pick the right one
_client->write((const char*)chunkUnit, chunkUnitLen);
size_t WiFiClient::write_P(PGM_P buf, size_t size)
{
if (!_client || !size)
{
return 0;
}
return size;
return _client->write_P(buf, size);
}

int WiFiClient::available()
Expand Down
48 changes: 4 additions & 44 deletions libraries/ESP8266WiFi/src/WiFiClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ class WiFiClient : public Client, public SList<WiFiClient> {
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
size_t write_P(PGM_P buf, size_t size);
template <typename T>
size_t write(T& source, size_t unitSize);
size_t write(Stream& stream);

// This one is deprecated, use write(Stream& instead)
size_t write(Stream& stream, size_t unitSize) __attribute__ ((deprecated));

virtual int available();
virtual int read();
Expand All @@ -73,28 +75,6 @@ class WiFiClient : public Client, public SList<WiFiClient> {
void setNoDelay(bool nodelay);
static void setLocalPortStart(uint16_t port) { _localPort = port; }

template<typename T> size_t write(T &src){
uint8_t obuf[WIFICLIENT_MAX_PACKET_SIZE];
size_t doneLen = 0;
size_t sentLen;
int i;

while (src.available() > WIFICLIENT_MAX_PACKET_SIZE){
src.read(obuf, WIFICLIENT_MAX_PACKET_SIZE);
sentLen = write(obuf, WIFICLIENT_MAX_PACKET_SIZE);
doneLen = doneLen + sentLen;
if(sentLen != WIFICLIENT_MAX_PACKET_SIZE){
return doneLen;
}
}

uint16_t leftLen = src.available();
src.read(obuf, leftLen);
sentLen = write(obuf, leftLen);
doneLen = doneLen + sentLen;
return doneLen;
}

friend class WiFiServer;

using Print::write;
Expand All @@ -114,24 +94,4 @@ class WiFiClient : public Client, public SList<WiFiClient> {
static uint16_t _localPort;
};


template <typename T>
inline size_t WiFiClient::write(T& source, size_t unitSize) {
std::unique_ptr<uint8_t[]> buffer(new uint8_t[unitSize]);
size_t size_sent = 0;
while(true) {
size_t left = source.available();
if (!left)
break;
size_t will_send = (left < unitSize) ? left : unitSize;
source.read(buffer.get(), will_send);
size_t cb = write(buffer.get(), will_send);
size_sent += cb;
if (cb != will_send) {
break;
}
}
return size_sent;
}

#endif
3 changes: 2 additions & 1 deletion libraries/ESP8266WiFi/src/WiFiClientSecure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,8 @@ extern "C" int ax_port_write(int fd, uint8_t* buffer, size_t count) {
errno = EIO;
return -1;
}
size_t cb = _client->write((const char*) buffer, count);

size_t cb = _client->write(buffer, count);
if (cb != count) {
errno = EAGAIN;
}
Expand Down
Loading