Skip to content

Commit 9efecc1

Browse files
committed
Implement RX buffer for WiFi client to speed up small reads
1 parent b0c6991 commit 9efecc1

File tree

2 files changed

+127
-17
lines changed

2 files changed

+127
-17
lines changed

libraries/WiFi/src/WiFiClient.cpp

+125-17
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,118 @@
3131
#undef write
3232
#undef read
3333

34+
class WiFiClientRxBuffer {
35+
private:
36+
size_t _size;
37+
uint8_t *_buffer;
38+
size_t _pos;
39+
size_t _fill;
40+
int _fd;
41+
bool _failed;
42+
43+
size_t r_available()
44+
{
45+
if(_fd < 0){
46+
return 0;
47+
}
48+
int count;
49+
int res = lwip_ioctl_r(_fd, FIONREAD, &count);
50+
if(res < 0) {
51+
_failed = true;
52+
return 0;
53+
}
54+
return count;
55+
}
56+
57+
size_t fillBuffer()
58+
{
59+
if(!_buffer){
60+
_buffer = (uint8_t *)malloc(_size);
61+
}
62+
if(_fill && _pos == _fill){
63+
_fill = 0;
64+
_pos = 0;
65+
}
66+
if(!_buffer || _size <= _fill || !r_available()) {
67+
return 0;
68+
}
69+
int res = recv(_fd, _buffer + _fill, _size - _fill, MSG_DONTWAIT);
70+
if(res < 0 && errno != EWOULDBLOCK) {
71+
_failed = true;
72+
return 0;
73+
}
74+
_fill += res;
75+
return res;
76+
}
77+
78+
public:
79+
WiFiClientRxBuffer(int fd, size_t size=1436)
80+
:_size(size)
81+
,_buffer(NULL)
82+
,_pos(0)
83+
,_fill(0)
84+
,_fd(fd)
85+
,_failed(false)
86+
{
87+
//_buffer = (uint8_t *)malloc(_size);
88+
}
89+
90+
~WiFiClientRxBuffer()
91+
{
92+
free(_buffer);
93+
}
94+
95+
bool failed(){
96+
return _failed;
97+
}
98+
99+
int read(uint8_t * dst, size_t len){
100+
if(!dst || !len || (_pos == _fill && !fillBuffer())){
101+
return -1;
102+
}
103+
size_t a = _fill - _pos;
104+
if(len <= a || ((len - a) <= (_size - _fill) && fillBuffer() >= (len - a))){
105+
if(len == 1){
106+
*dst = _buffer[_pos];
107+
} else {
108+
memcpy(dst, _buffer + _pos, len);
109+
}
110+
_pos += len;
111+
return len;
112+
}
113+
size_t left = len;
114+
size_t toRead = a;
115+
uint8_t * buf = dst;
116+
memcpy(buf, _buffer + _pos, toRead);
117+
_pos += toRead;
118+
left -= toRead;
119+
buf += toRead;
120+
while(left){
121+
if(!fillBuffer()){
122+
return len - left;
123+
}
124+
a = _fill - _pos;
125+
toRead = (a > left)?left:a;
126+
memcpy(buf, _buffer + _pos, toRead);
127+
_pos += toRead;
128+
left -= toRead;
129+
buf += toRead;
130+
}
131+
return len;
132+
}
133+
134+
int peek(){
135+
if(_pos == _fill && !fillBuffer()){
136+
return -1;
137+
}
138+
return _buffer[_pos];
139+
}
140+
141+
size_t available(){
142+
return _fill - _pos + r_available();
143+
}
144+
};
145+
34146
class WiFiClientSocketHandle {
35147
private:
36148
int sockfd;
@@ -58,6 +170,7 @@ WiFiClient::WiFiClient():_connected(false),next(NULL)
58170
WiFiClient::WiFiClient(int fd):_connected(true),next(NULL)
59171
{
60172
clientSocketHandle.reset(new WiFiClientSocketHandle(fd));
173+
_rxBuffer.reset(new WiFiClientRxBuffer(fd));
61174
}
62175

63176
WiFiClient::~WiFiClient()
@@ -69,13 +182,15 @@ WiFiClient & WiFiClient::operator=(const WiFiClient &other)
69182
{
70183
stop();
71184
clientSocketHandle = other.clientSocketHandle;
185+
_rxBuffer = other._rxBuffer;
72186
_connected = other._connected;
73187
return *this;
74188
}
75189

76190
void WiFiClient::stop()
77191
{
78192
clientSocketHandle = NULL;
193+
_rxBuffer = NULL;
79194
_connected = false;
80195
}
81196

@@ -100,6 +215,7 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
100215
return 0;
101216
}
102217
clientSocketHandle.reset(new WiFiClientSocketHandle(sockfd));
218+
_rxBuffer.reset(new WiFiClientRxBuffer(sockfd));
103219
_connected = true;
104220
return 1;
105221
}
@@ -260,11 +376,9 @@ size_t WiFiClient::write(Stream &stream)
260376

261377
int WiFiClient::read(uint8_t *buf, size_t size)
262378
{
263-
if(!available()) {
264-
return -1;
265-
}
266-
int res = recv(fd(), buf, size, MSG_DONTWAIT);
267-
if(res < 0 && errno != EWOULDBLOCK) {
379+
int res = -1;
380+
res = _rxBuffer->read(buf, size);
381+
if(_rxBuffer->failed()) {
268382
log_e("%d", errno);
269383
stop();
270384
}
@@ -273,31 +387,25 @@ int WiFiClient::read(uint8_t *buf, size_t size)
273387

274388
int WiFiClient::peek()
275389
{
276-
if(!available()) {
277-
return -1;
278-
}
279-
uint8_t data = 0;
280-
int res = recv(fd(), &data, 1, MSG_PEEK);
281-
if(res < 0 && errno != EWOULDBLOCK) {
390+
int res = _rxBuffer->peek();
391+
if(_rxBuffer->failed()) {
282392
log_e("%d", errno);
283393
stop();
284394
}
285-
return data;
395+
return res;
286396
}
287397

288398
int WiFiClient::available()
289399
{
290400
if(!_connected) {
291401
return 0;
292402
}
293-
int count;
294-
int res = lwip_ioctl_r(fd(), FIONREAD, &count);
295-
if(res < 0) {
403+
int res = _rxBuffer->available();
404+
if(_rxBuffer->failed()) {
296405
log_e("%d", errno);
297406
stop();
298-
return 0;
299407
}
300-
return count;
408+
return res;
301409
}
302410

303411
// Though flushing means to send all pending data,

libraries/WiFi/src/WiFiClient.h

+2
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@
2828
#include <memory>
2929

3030
class WiFiClientSocketHandle;
31+
class WiFiClientRxBuffer;
3132

3233
class WiFiClient : public Client
3334
{
3435
protected:
3536
std::shared_ptr<WiFiClientSocketHandle> clientSocketHandle;
37+
std::shared_ptr<WiFiClientRxBuffer> _rxBuffer;
3638
bool _connected;
3739

3840
public:

0 commit comments

Comments
 (0)