Skip to content

File LwIPRxBuffer.cpp

File List > arduino > libraries > common > WiFiClient > LwIPRxBuffer.cpp

Go to the documentation of this file.

#if LT_HAS_LWIP

#include "LwIPRxBuffer.h"

// disable #defines removing lwip_ prefix
#undef LWIP_COMPAT_SOCKETS
#define LWIP_COMPAT_SOCKETS 0

extern "C" {

#include <lwip/sockets.h>

} // extern "C"

size_t LwIPRxBuffer::r_available() {
    if (_sock < 0) {
        LT_DM(CLIENT, "_sock < 0");
        return 0;
    }
    int count = 0; // must be of same size as in lwip_ioctl()
    int res   = lwip_ioctl(_sock, FIONREAD, &count);
    if (res < 0) {
        LT_DM(CLIENT, "lwip_ioctl()=%d, errno=%d", res, errno);
        _failed = true;
        return 0;
    }
    return count;
}

size_t LwIPRxBuffer::fillBuffer() {
    if (!_buffer) {
        _buffer = (uint8_t *)malloc(_size);
        if (!_buffer) {
            LT_E("buffer alloc failed");
            _failed = true;
            return 0;
        }
    }
    if (_fill && _pos == _fill) {
        _fill = 0;
        _pos  = 0;
    }
    if (!_buffer || _size <= _fill || !r_available()) {
        return 0;
    }
    int res = lwip_recv(_sock, _buffer + _fill, _size - _fill, MSG_DONTWAIT);
    if (res < 0) {
        if (errno != EWOULDBLOCK) {
            LT_ERRNO();
            _failed = true;
        }
        return 0;
    }
    _fill += res;
    return res;
}

LwIPRxBuffer::LwIPRxBuffer(int sock, size_t size)
    : _size(size), _buffer(NULL), _pos(0), _fill(0), _sock(sock), _failed(false) {
    //_buffer = (uint8_t *)malloc(_size);
}

LwIPRxBuffer::~LwIPRxBuffer() {
    free(_buffer);
}

bool LwIPRxBuffer::failed() {
    return _failed;
}

int LwIPRxBuffer::read(uint8_t *dst, size_t len) {
    if (!dst || !len || (_pos == _fill && !fillBuffer())) {
        return _failed ? -1 : 0;
    }
    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 LwIPRxBuffer::peek() {
    if (_pos == _fill && !fillBuffer()) {
        return -1;
    }
    return _buffer[_pos];
}

size_t LwIPRxBuffer::available() {
    return _fill - _pos + r_available();
}

#endif