Implement RX buffer for WiFi client to speed up small reads
This commit is contained in:
parent
b0c6991bcf
commit
9efecc1be0
@ -31,6 +31,118 @@
|
||||
#undef write
|
||||
#undef read
|
||||
|
||||
class WiFiClientRxBuffer {
|
||||
private:
|
||||
size_t _size;
|
||||
uint8_t *_buffer;
|
||||
size_t _pos;
|
||||
size_t _fill;
|
||||
int _fd;
|
||||
bool _failed;
|
||||
|
||||
size_t r_available()
|
||||
{
|
||||
if(_fd < 0){
|
||||
return 0;
|
||||
}
|
||||
int count;
|
||||
int res = lwip_ioctl_r(_fd, FIONREAD, &count);
|
||||
if(res < 0) {
|
||||
_failed = true;
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t fillBuffer()
|
||||
{
|
||||
if(!_buffer){
|
||||
_buffer = (uint8_t *)malloc(_size);
|
||||
}
|
||||
if(_fill && _pos == _fill){
|
||||
_fill = 0;
|
||||
_pos = 0;
|
||||
}
|
||||
if(!_buffer || _size <= _fill || !r_available()) {
|
||||
return 0;
|
||||
}
|
||||
int res = recv(_fd, _buffer + _fill, _size - _fill, MSG_DONTWAIT);
|
||||
if(res < 0 && errno != EWOULDBLOCK) {
|
||||
_failed = true;
|
||||
return 0;
|
||||
}
|
||||
_fill += res;
|
||||
return res;
|
||||
}
|
||||
|
||||
public:
|
||||
WiFiClientRxBuffer(int fd, size_t size=1436)
|
||||
:_size(size)
|
||||
,_buffer(NULL)
|
||||
,_pos(0)
|
||||
,_fill(0)
|
||||
,_fd(fd)
|
||||
,_failed(false)
|
||||
{
|
||||
//_buffer = (uint8_t *)malloc(_size);
|
||||
}
|
||||
|
||||
~WiFiClientRxBuffer()
|
||||
{
|
||||
free(_buffer);
|
||||
}
|
||||
|
||||
bool failed(){
|
||||
return _failed;
|
||||
}
|
||||
|
||||
int read(uint8_t * dst, size_t len){
|
||||
if(!dst || !len || (_pos == _fill && !fillBuffer())){
|
||||
return -1;
|
||||
}
|
||||
size_t a = _fill - _pos;
|
||||
if(len <= a || ((len - a) <= (_size - _fill) && fillBuffer() >= (len - a))){
|
||||
if(len == 1){
|
||||
*dst = _buffer[_pos];
|
||||
} else {
|
||||
memcpy(dst, _buffer + _pos, len);
|
||||
}
|
||||
_pos += len;
|
||||
return len;
|
||||
}
|
||||
size_t left = len;
|
||||
size_t toRead = a;
|
||||
uint8_t * buf = dst;
|
||||
memcpy(buf, _buffer + _pos, toRead);
|
||||
_pos += toRead;
|
||||
left -= toRead;
|
||||
buf += toRead;
|
||||
while(left){
|
||||
if(!fillBuffer()){
|
||||
return len - left;
|
||||
}
|
||||
a = _fill - _pos;
|
||||
toRead = (a > left)?left:a;
|
||||
memcpy(buf, _buffer + _pos, toRead);
|
||||
_pos += toRead;
|
||||
left -= toRead;
|
||||
buf += toRead;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int peek(){
|
||||
if(_pos == _fill && !fillBuffer()){
|
||||
return -1;
|
||||
}
|
||||
return _buffer[_pos];
|
||||
}
|
||||
|
||||
size_t available(){
|
||||
return _fill - _pos + r_available();
|
||||
}
|
||||
};
|
||||
|
||||
class WiFiClientSocketHandle {
|
||||
private:
|
||||
int sockfd;
|
||||
@ -58,6 +170,7 @@ WiFiClient::WiFiClient():_connected(false),next(NULL)
|
||||
WiFiClient::WiFiClient(int fd):_connected(true),next(NULL)
|
||||
{
|
||||
clientSocketHandle.reset(new WiFiClientSocketHandle(fd));
|
||||
_rxBuffer.reset(new WiFiClientRxBuffer(fd));
|
||||
}
|
||||
|
||||
WiFiClient::~WiFiClient()
|
||||
@ -69,6 +182,7 @@ WiFiClient & WiFiClient::operator=(const WiFiClient &other)
|
||||
{
|
||||
stop();
|
||||
clientSocketHandle = other.clientSocketHandle;
|
||||
_rxBuffer = other._rxBuffer;
|
||||
_connected = other._connected;
|
||||
return *this;
|
||||
}
|
||||
@ -76,6 +190,7 @@ WiFiClient & WiFiClient::operator=(const WiFiClient &other)
|
||||
void WiFiClient::stop()
|
||||
{
|
||||
clientSocketHandle = NULL;
|
||||
_rxBuffer = NULL;
|
||||
_connected = false;
|
||||
}
|
||||
|
||||
@ -100,6 +215,7 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
|
||||
return 0;
|
||||
}
|
||||
clientSocketHandle.reset(new WiFiClientSocketHandle(sockfd));
|
||||
_rxBuffer.reset(new WiFiClientRxBuffer(sockfd));
|
||||
_connected = true;
|
||||
return 1;
|
||||
}
|
||||
@ -260,11 +376,9 @@ size_t WiFiClient::write(Stream &stream)
|
||||
|
||||
int WiFiClient::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
if(!available()) {
|
||||
return -1;
|
||||
}
|
||||
int res = recv(fd(), buf, size, MSG_DONTWAIT);
|
||||
if(res < 0 && errno != EWOULDBLOCK) {
|
||||
int res = -1;
|
||||
res = _rxBuffer->read(buf, size);
|
||||
if(_rxBuffer->failed()) {
|
||||
log_e("%d", errno);
|
||||
stop();
|
||||
}
|
||||
@ -273,16 +387,12 @@ int WiFiClient::read(uint8_t *buf, size_t size)
|
||||
|
||||
int WiFiClient::peek()
|
||||
{
|
||||
if(!available()) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t data = 0;
|
||||
int res = recv(fd(), &data, 1, MSG_PEEK);
|
||||
if(res < 0 && errno != EWOULDBLOCK) {
|
||||
int res = _rxBuffer->peek();
|
||||
if(_rxBuffer->failed()) {
|
||||
log_e("%d", errno);
|
||||
stop();
|
||||
}
|
||||
return data;
|
||||
return res;
|
||||
}
|
||||
|
||||
int WiFiClient::available()
|
||||
@ -290,14 +400,12 @@ int WiFiClient::available()
|
||||
if(!_connected) {
|
||||
return 0;
|
||||
}
|
||||
int count;
|
||||
int res = lwip_ioctl_r(fd(), FIONREAD, &count);
|
||||
if(res < 0) {
|
||||
int res = _rxBuffer->available();
|
||||
if(_rxBuffer->failed()) {
|
||||
log_e("%d", errno);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
return res;
|
||||
}
|
||||
|
||||
// Though flushing means to send all pending data,
|
||||
|
@ -28,11 +28,13 @@
|
||||
#include <memory>
|
||||
|
||||
class WiFiClientSocketHandle;
|
||||
class WiFiClientRxBuffer;
|
||||
|
||||
class WiFiClient : public Client
|
||||
{
|
||||
protected:
|
||||
std::shared_ptr<WiFiClientSocketHandle> clientSocketHandle;
|
||||
std::shared_ptr<WiFiClientRxBuffer> _rxBuffer;
|
||||
bool _connected;
|
||||
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user