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 write
|
||||||
#undef read
|
#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 {
|
class WiFiClientSocketHandle {
|
||||||
private:
|
private:
|
||||||
int sockfd;
|
int sockfd;
|
||||||
@ -58,6 +170,7 @@ WiFiClient::WiFiClient():_connected(false),next(NULL)
|
|||||||
WiFiClient::WiFiClient(int fd):_connected(true),next(NULL)
|
WiFiClient::WiFiClient(int fd):_connected(true),next(NULL)
|
||||||
{
|
{
|
||||||
clientSocketHandle.reset(new WiFiClientSocketHandle(fd));
|
clientSocketHandle.reset(new WiFiClientSocketHandle(fd));
|
||||||
|
_rxBuffer.reset(new WiFiClientRxBuffer(fd));
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiClient::~WiFiClient()
|
WiFiClient::~WiFiClient()
|
||||||
@ -69,6 +182,7 @@ WiFiClient & WiFiClient::operator=(const WiFiClient &other)
|
|||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
clientSocketHandle = other.clientSocketHandle;
|
clientSocketHandle = other.clientSocketHandle;
|
||||||
|
_rxBuffer = other._rxBuffer;
|
||||||
_connected = other._connected;
|
_connected = other._connected;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -76,6 +190,7 @@ WiFiClient & WiFiClient::operator=(const WiFiClient &other)
|
|||||||
void WiFiClient::stop()
|
void WiFiClient::stop()
|
||||||
{
|
{
|
||||||
clientSocketHandle = NULL;
|
clientSocketHandle = NULL;
|
||||||
|
_rxBuffer = NULL;
|
||||||
_connected = false;
|
_connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +215,7 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
clientSocketHandle.reset(new WiFiClientSocketHandle(sockfd));
|
clientSocketHandle.reset(new WiFiClientSocketHandle(sockfd));
|
||||||
|
_rxBuffer.reset(new WiFiClientRxBuffer(sockfd));
|
||||||
_connected = true;
|
_connected = true;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -260,11 +376,9 @@ size_t WiFiClient::write(Stream &stream)
|
|||||||
|
|
||||||
int WiFiClient::read(uint8_t *buf, size_t size)
|
int WiFiClient::read(uint8_t *buf, size_t size)
|
||||||
{
|
{
|
||||||
if(!available()) {
|
int res = -1;
|
||||||
return -1;
|
res = _rxBuffer->read(buf, size);
|
||||||
}
|
if(_rxBuffer->failed()) {
|
||||||
int res = recv(fd(), buf, size, MSG_DONTWAIT);
|
|
||||||
if(res < 0 && errno != EWOULDBLOCK) {
|
|
||||||
log_e("%d", errno);
|
log_e("%d", errno);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
@ -273,16 +387,12 @@ int WiFiClient::read(uint8_t *buf, size_t size)
|
|||||||
|
|
||||||
int WiFiClient::peek()
|
int WiFiClient::peek()
|
||||||
{
|
{
|
||||||
if(!available()) {
|
int res = _rxBuffer->peek();
|
||||||
return -1;
|
if(_rxBuffer->failed()) {
|
||||||
}
|
|
||||||
uint8_t data = 0;
|
|
||||||
int res = recv(fd(), &data, 1, MSG_PEEK);
|
|
||||||
if(res < 0 && errno != EWOULDBLOCK) {
|
|
||||||
log_e("%d", errno);
|
log_e("%d", errno);
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
return data;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WiFiClient::available()
|
int WiFiClient::available()
|
||||||
@ -290,14 +400,12 @@ int WiFiClient::available()
|
|||||||
if(!_connected) {
|
if(!_connected) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int count;
|
int res = _rxBuffer->available();
|
||||||
int res = lwip_ioctl_r(fd(), FIONREAD, &count);
|
if(_rxBuffer->failed()) {
|
||||||
if(res < 0) {
|
|
||||||
log_e("%d", errno);
|
log_e("%d", errno);
|
||||||
stop();
|
stop();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return count;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Though flushing means to send all pending data,
|
// Though flushing means to send all pending data,
|
||||||
|
@ -28,11 +28,13 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class WiFiClientSocketHandle;
|
class WiFiClientSocketHandle;
|
||||||
|
class WiFiClientRxBuffer;
|
||||||
|
|
||||||
class WiFiClient : public Client
|
class WiFiClient : public Client
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<WiFiClientSocketHandle> clientSocketHandle;
|
std::shared_ptr<WiFiClientSocketHandle> clientSocketHandle;
|
||||||
|
std::shared_ptr<WiFiClientRxBuffer> _rxBuffer;
|
||||||
bool _connected;
|
bool _connected;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Loading…
Reference in New Issue
Block a user