mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
Initial UDP support
This commit is contained in:
parent
af99a3e388
commit
e5e6dbe222
190
libraries/ESP8266WiFi/src/WiFiUdp.cpp
Normal file
190
libraries/ESP8266WiFi/src/WiFiUdp.cpp
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
WiFiUdp.cpp - Library for Arduino Wifi shield.
|
||||||
|
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LWIP_INTERNAL
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "include/wl_definitions.h"
|
||||||
|
#include "osapi.h"
|
||||||
|
#include "ets_sys.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
#include "ESP8266WiFi.h"
|
||||||
|
#include "WiFiUdp.h"
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/udp.h"
|
||||||
|
#include "lwip/inet.h"
|
||||||
|
#include "include/UdpContext.h"
|
||||||
|
|
||||||
|
/* Constructor */
|
||||||
|
WiFiUDP::WiFiUDP() : _ctx(0) {}
|
||||||
|
|
||||||
|
WiFiUDP::WiFiUDP(const WiFiUDP& other)
|
||||||
|
{
|
||||||
|
_ctx = other._ctx;
|
||||||
|
if (_ctx)
|
||||||
|
_ctx->ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFiUDP& WiFiUDP::operator=(const WiFiUDP& rhs)
|
||||||
|
{
|
||||||
|
_ctx = rhs._ctx;
|
||||||
|
if (_ctx)
|
||||||
|
_ctx->ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFiUDP::~WiFiUDP()
|
||||||
|
{
|
||||||
|
if (_ctx)
|
||||||
|
_ctx->unref();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start WiFiUDP socket, listening at local port */
|
||||||
|
uint8_t WiFiUDP::begin(uint16_t port)
|
||||||
|
{
|
||||||
|
if (_ctx)
|
||||||
|
{
|
||||||
|
_ctx->unref();
|
||||||
|
}
|
||||||
|
_ctx = new UdpContext;
|
||||||
|
ip_addr_t addr;
|
||||||
|
addr.addr = INADDR_ANY;
|
||||||
|
return (_ctx->listen(addr, port)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return number of bytes available in the current packet,
|
||||||
|
will return zero if parsePacket hasn't been called yet */
|
||||||
|
int WiFiUDP::available() {
|
||||||
|
if (!_ctx)
|
||||||
|
return 0;
|
||||||
|
return static_cast<int>(_ctx->getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release any resources being used by this WiFiUDP instance */
|
||||||
|
void WiFiUDP::stop()
|
||||||
|
{
|
||||||
|
if (_ctx)
|
||||||
|
_ctx->disconnect();
|
||||||
|
_ctx->unref();
|
||||||
|
_ctx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WiFiUDP::beginPacket(const char *host, uint16_t port)
|
||||||
|
{
|
||||||
|
IPAddress remote_addr;
|
||||||
|
if (WiFi.hostByName(host, remote_addr))
|
||||||
|
{
|
||||||
|
return beginPacket(remote_addr, port);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port)
|
||||||
|
{
|
||||||
|
ip_addr_t addr;
|
||||||
|
addr.addr = ip;
|
||||||
|
|
||||||
|
if (_ctx)
|
||||||
|
_ctx->unref();
|
||||||
|
_ctx = new UdpContext;
|
||||||
|
return (_ctx->connect(addr, port)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WiFiUDP::endPacket()
|
||||||
|
{
|
||||||
|
if (!_ctx)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_ctx->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t WiFiUDP::write(uint8_t byte)
|
||||||
|
{
|
||||||
|
return write(&byte, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t WiFiUDP::write(const uint8_t *buffer, size_t size)
|
||||||
|
{
|
||||||
|
if (!_ctx)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return _ctx->append(reinterpret_cast<const char*>(buffer), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WiFiUDP::parsePacket()
|
||||||
|
{
|
||||||
|
if (!_ctx)
|
||||||
|
return 0;
|
||||||
|
if (!_ctx->next())
|
||||||
|
return 0;
|
||||||
|
return _ctx->getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WiFiUDP::read()
|
||||||
|
{
|
||||||
|
if (!_ctx)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return _ctx->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
int WiFiUDP::read(unsigned char* buffer, size_t len)
|
||||||
|
{
|
||||||
|
if (!_ctx)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return _ctx->read(reinterpret_cast<char*>(buffer), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WiFiUDP::peek()
|
||||||
|
{
|
||||||
|
if (!_ctx)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return _ctx->peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiFiUDP::flush()
|
||||||
|
{
|
||||||
|
if (_ctx)
|
||||||
|
_ctx->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress WiFiUDP::remoteIP()
|
||||||
|
{
|
||||||
|
uint8_t _remoteIp[4] = {0};
|
||||||
|
uint8_t _remotePort[2] = {0};
|
||||||
|
|
||||||
|
// WiFiDrv::getRemoteData(_sock, _remoteIp, _remotePort);
|
||||||
|
IPAddress ip(_remoteIp);
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t WiFiUDP::remotePort()
|
||||||
|
{
|
||||||
|
uint8_t _remoteIp[4] = {0};
|
||||||
|
uint8_t _remotePort[2] = {0};
|
||||||
|
|
||||||
|
// WiFiDrv::getRemoteData(_sock, _remoteIp, _remotePort);
|
||||||
|
uint16_t port = (_remotePort[0]<<8)+_remotePort[1];
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
@ -1,181 +0,0 @@
|
|||||||
/*
|
|
||||||
WiFiUdp.cpp - Library for Arduino Wifi shield.
|
|
||||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Lesser General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this library; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "utility/debug.h"
|
|
||||||
#include "utility/wifi_spi.h"
|
|
||||||
}
|
|
||||||
#include <string.h>
|
|
||||||
#include "utility/server_drv.h"
|
|
||||||
#include "utility/wifi_drv.h"
|
|
||||||
|
|
||||||
#include "WiFi.h"
|
|
||||||
#include "WiFiUdp.h"
|
|
||||||
#include "WiFiClient.h"
|
|
||||||
#include "WiFiServer.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Constructor */
|
|
||||||
WiFiUDP::WiFiUDP() : _sock(NO_SOCKET_AVAIL) {}
|
|
||||||
|
|
||||||
/* Start WiFiUDP socket, listening at local port PORT */
|
|
||||||
uint8_t WiFiUDP::begin(uint16_t port) {
|
|
||||||
|
|
||||||
uint8_t sock = WiFiClass::getSocket();
|
|
||||||
if (sock != NO_SOCKET_AVAIL)
|
|
||||||
{
|
|
||||||
ServerDrv::startServer(port, sock, UDP_MODE);
|
|
||||||
WiFiClass::_server_port[sock] = port;
|
|
||||||
_sock = sock;
|
|
||||||
_port = port;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return number of bytes available in the current packet,
|
|
||||||
will return zero if parsePacket hasn't been called yet */
|
|
||||||
int WiFiUDP::available() {
|
|
||||||
if (_sock != NO_SOCKET_AVAIL)
|
|
||||||
{
|
|
||||||
return ServerDrv::availData(_sock);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release any resources being used by this WiFiUDP instance */
|
|
||||||
void WiFiUDP::stop()
|
|
||||||
{
|
|
||||||
if (_sock == NO_SOCKET_AVAIL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ServerDrv::stopClient(_sock);
|
|
||||||
|
|
||||||
_sock = NO_SOCKET_AVAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WiFiUDP::beginPacket(const char *host, uint16_t port)
|
|
||||||
{
|
|
||||||
// Look up the host first
|
|
||||||
int ret = 0;
|
|
||||||
IPAddress remote_addr;
|
|
||||||
if (WiFi.hostByName(host, remote_addr))
|
|
||||||
{
|
|
||||||
return beginPacket(remote_addr, port);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port)
|
|
||||||
{
|
|
||||||
if (_sock == NO_SOCKET_AVAIL)
|
|
||||||
_sock = WiFiClass::getSocket();
|
|
||||||
if (_sock != NO_SOCKET_AVAIL)
|
|
||||||
{
|
|
||||||
ServerDrv::startClient(uint32_t(ip), port, _sock, UDP_MODE);
|
|
||||||
WiFiClass::_state[_sock] = _sock;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WiFiUDP::endPacket()
|
|
||||||
{
|
|
||||||
return ServerDrv::sendUdpData(_sock);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t WiFiUDP::write(uint8_t byte)
|
|
||||||
{
|
|
||||||
return write(&byte, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t WiFiUDP::write(const uint8_t *buffer, size_t size)
|
|
||||||
{
|
|
||||||
ServerDrv::insertDataBuf(_sock, buffer, size);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WiFiUDP::parsePacket()
|
|
||||||
{
|
|
||||||
return available();
|
|
||||||
}
|
|
||||||
|
|
||||||
int WiFiUDP::read()
|
|
||||||
{
|
|
||||||
uint8_t b;
|
|
||||||
if (available())
|
|
||||||
{
|
|
||||||
ServerDrv::getData(_sock, &b);
|
|
||||||
return b;
|
|
||||||
}else{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int WiFiUDP::read(unsigned char* buffer, size_t len)
|
|
||||||
{
|
|
||||||
if (available())
|
|
||||||
{
|
|
||||||
uint16_t size = 0;
|
|
||||||
if (!ServerDrv::getDataBuf(_sock, buffer, &size))
|
|
||||||
return -1;
|
|
||||||
// TODO check if the buffer is too smal respect to buffer size
|
|
||||||
return size;
|
|
||||||
}else{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int WiFiUDP::peek()
|
|
||||||
{
|
|
||||||
uint8_t b;
|
|
||||||
if (!available())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ServerDrv::getData(_sock, &b, 1);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WiFiUDP::flush()
|
|
||||||
{
|
|
||||||
while (available())
|
|
||||||
read();
|
|
||||||
}
|
|
||||||
|
|
||||||
IPAddress WiFiUDP::remoteIP()
|
|
||||||
{
|
|
||||||
uint8_t _remoteIp[4] = {0};
|
|
||||||
uint8_t _remotePort[2] = {0};
|
|
||||||
|
|
||||||
WiFiDrv::getRemoteData(_sock, _remoteIp, _remotePort);
|
|
||||||
IPAddress ip(_remoteIp);
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t WiFiUDP::remotePort()
|
|
||||||
{
|
|
||||||
uint8_t _remoteIp[4] = {0};
|
|
||||||
uint8_t _remotePort[2] = {0};
|
|
||||||
|
|
||||||
WiFiDrv::getRemoteData(_sock, _remoteIp, _remotePort);
|
|
||||||
uint16_t port = (_remotePort[0]<<8)+_remotePort[1];
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
@ -17,21 +17,26 @@
|
|||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef wifiudp_h
|
#ifndef WIFIUDP_H
|
||||||
#define wifiudp_h
|
#define WIFIUDP_H
|
||||||
|
|
||||||
#include <Udp.h>
|
#include <Udp.h>
|
||||||
|
|
||||||
#define UDP_TX_PACKET_MAX_SIZE 24
|
#define UDP_TX_PACKET_MAX_SIZE 8192
|
||||||
|
|
||||||
|
class UdpContext;
|
||||||
|
|
||||||
class WiFiUDP : public UDP {
|
class WiFiUDP : public UDP {
|
||||||
private:
|
private:
|
||||||
uint8_t _sock; // socket ID for Wiz5100
|
UdpContext* _ctx;
|
||||||
uint16_t _port; // local port to listen on
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WiFiUDP(); // Constructor
|
WiFiUDP(); // Constructor
|
||||||
virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
WiFiUDP(const WiFiUDP& other);
|
||||||
|
WiFiUDP& operator=(const WiFiUDP& rhs);
|
||||||
|
~WiFiUDP();
|
||||||
|
|
||||||
|
virtual uint8_t begin(uint16_t port); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||||
virtual void stop(); // Finish with the UDP socket
|
virtual void stop(); // Finish with the UDP socket
|
||||||
|
|
||||||
// Sending UDP packets
|
// Sending UDP packets
|
||||||
@ -74,7 +79,7 @@ public:
|
|||||||
// Return the port of the host who sent the current incoming packet
|
// Return the port of the host who sent the current incoming packet
|
||||||
virtual uint16_t remotePort();
|
virtual uint16_t remotePort();
|
||||||
|
|
||||||
friend class WiFiDrv;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif //WIFIUDP_H
|
||||||
|
|
||||||
|
304
libraries/ESP8266WiFi/src/include/UdpContext.h
Normal file
304
libraries/ESP8266WiFi/src/include/UdpContext.h
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
ClientContext.h - TCP connection handling on top of lwIP
|
||||||
|
|
||||||
|
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef UDPCONTEXT_H
|
||||||
|
#define UDPCONTEXT_H
|
||||||
|
|
||||||
|
class UdpContext;
|
||||||
|
|
||||||
|
extern "C" void esp_yield();
|
||||||
|
extern "C" void esp_schedule();
|
||||||
|
|
||||||
|
|
||||||
|
class UdpContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UdpContext()
|
||||||
|
: _pcb(0)
|
||||||
|
, _rx_buf(0)
|
||||||
|
, _first_buf_taken(false)
|
||||||
|
, _rx_buf_offset(0)
|
||||||
|
, _refcnt(0)
|
||||||
|
, _tx_buf_head(0)
|
||||||
|
, _tx_buf_cur(0)
|
||||||
|
, _tx_buf_offset(0)
|
||||||
|
{
|
||||||
|
_pcb = udp_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
~UdpContext()
|
||||||
|
{
|
||||||
|
udp_remove(_pcb);
|
||||||
|
_pcb = 0;
|
||||||
|
if (_tx_buf_head)
|
||||||
|
{
|
||||||
|
pbuf_free(_tx_buf_head);
|
||||||
|
_tx_buf_head = 0;
|
||||||
|
_tx_buf_cur = 0;
|
||||||
|
_tx_buf_offset = 0;
|
||||||
|
}
|
||||||
|
if (_rx_buf)
|
||||||
|
{
|
||||||
|
pbuf_free(_rx_buf);
|
||||||
|
_rx_buf = 0;
|
||||||
|
_rx_buf_offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ref()
|
||||||
|
{
|
||||||
|
++_refcnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unref()
|
||||||
|
{
|
||||||
|
DEBUGV(":ur %d\r\n", _refcnt);
|
||||||
|
if (--_refcnt == 0)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool connect(ip_addr_t addr, uint16_t port)
|
||||||
|
{
|
||||||
|
err_t err = udp_connect(_pcb, &addr, port);
|
||||||
|
return err == ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool listen(ip_addr_t addr, uint16_t port)
|
||||||
|
{
|
||||||
|
udp_recv(_pcb, &_s_recv, (void *) this);
|
||||||
|
err_t err = udp_bind(_pcb, &addr, port);
|
||||||
|
return err == ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void disconnect()
|
||||||
|
{
|
||||||
|
udp_disconnect(_pcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const
|
||||||
|
{
|
||||||
|
if (!_rx_buf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return _rx_buf->len - _rx_buf_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool next()
|
||||||
|
{
|
||||||
|
if (!_rx_buf)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_first_buf_taken)
|
||||||
|
{
|
||||||
|
_first_buf_taken = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto head = _rx_buf;
|
||||||
|
_rx_buf = _rx_buf->next;
|
||||||
|
_rx_buf_offset = 0;
|
||||||
|
|
||||||
|
if (_rx_buf)
|
||||||
|
{
|
||||||
|
pbuf_ref(_rx_buf);
|
||||||
|
}
|
||||||
|
pbuf_free(head);
|
||||||
|
return _rx_buf != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char read()
|
||||||
|
{
|
||||||
|
if (!_rx_buf || _rx_buf->len == _rx_buf_offset)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
char c = reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
|
||||||
|
_consume(1);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t read(char* dst, size_t size)
|
||||||
|
{
|
||||||
|
if (!_rx_buf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size_t max_size = _rx_buf->len - _rx_buf_offset;
|
||||||
|
size = (size < max_size) ? size : max_size;
|
||||||
|
DEBUGV(":rd %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf_offset);
|
||||||
|
|
||||||
|
os_memcpy(dst, reinterpret_cast<char*>(_rx_buf->payload) + _rx_buf_offset, size);
|
||||||
|
_consume(size);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
char peek()
|
||||||
|
{
|
||||||
|
if (!_rx_buf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush()
|
||||||
|
{
|
||||||
|
if (!_rx_buf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_consume(_rx_buf->len - _rx_buf_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t append(const char* data, size_t size)
|
||||||
|
{
|
||||||
|
if (!_tx_buf_head || _tx_buf_head->tot_len < _tx_buf_offset + size)
|
||||||
|
{
|
||||||
|
_reserve(_tx_buf_offset + size);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t left_to_copy = size;
|
||||||
|
while(left_to_copy)
|
||||||
|
{
|
||||||
|
// size already used in current pbuf
|
||||||
|
size_t used_cur = _tx_buf_offset - (_tx_buf_head->tot_len - _tx_buf_cur->tot_len);
|
||||||
|
size_t free_cur = _tx_buf_cur->len - used_cur;
|
||||||
|
if (free_cur == 0)
|
||||||
|
{
|
||||||
|
_tx_buf_cur = _tx_buf_cur->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
size_t will_copy = (left_to_copy < free_cur) ? left_to_copy : free_cur;
|
||||||
|
os_memcpy(reinterpret_cast<char*>(_tx_buf_cur->payload) + used_cur, data, will_copy);
|
||||||
|
_tx_buf_offset += will_copy;
|
||||||
|
left_to_copy -= will_copy;
|
||||||
|
data += will_copy;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void send()
|
||||||
|
{
|
||||||
|
size_t orig_size = _tx_buf_head->tot_len;
|
||||||
|
|
||||||
|
size_t data_size = _tx_buf_offset;
|
||||||
|
size_t size_adjustment = orig_size - data_size;
|
||||||
|
for (pbuf* p = _tx_buf_head; p; p = p->next)
|
||||||
|
{
|
||||||
|
p->tot_len -= size_adjustment;
|
||||||
|
if (!p->next)
|
||||||
|
{
|
||||||
|
p->len = p->tot_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
udp_send(_pcb, _tx_buf_head);
|
||||||
|
|
||||||
|
for (pbuf* p = _tx_buf_head; p; p = p->next)
|
||||||
|
{
|
||||||
|
p->tot_len += size_adjustment;
|
||||||
|
if (!p->next)
|
||||||
|
{
|
||||||
|
p->len = p->tot_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pbuf_free(_tx_buf_head);
|
||||||
|
_tx_buf_head = 0;
|
||||||
|
_tx_buf_cur = 0;
|
||||||
|
_tx_buf_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void _reserve(size_t size)
|
||||||
|
{
|
||||||
|
const size_t pbuf_unit_size = 1024;
|
||||||
|
if (!_tx_buf_head)
|
||||||
|
{
|
||||||
|
_tx_buf_head = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM);
|
||||||
|
_tx_buf_cur = _tx_buf_head;
|
||||||
|
_tx_buf_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cur_size = _tx_buf_head->tot_len;
|
||||||
|
if (size < cur_size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size_t grow_size = size - cur_size;
|
||||||
|
|
||||||
|
while(grow_size)
|
||||||
|
{
|
||||||
|
pbuf* pb = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM);
|
||||||
|
pbuf_cat(_tx_buf_head, pb);
|
||||||
|
if (grow_size < pbuf_unit_size)
|
||||||
|
return;
|
||||||
|
grow_size -= pbuf_unit_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _consume(size_t size)
|
||||||
|
{
|
||||||
|
_rx_buf_offset += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _recv(udp_pcb *upcb, pbuf *pb,
|
||||||
|
ip_addr_t *addr, u16_t port)
|
||||||
|
{
|
||||||
|
if (_rx_buf)
|
||||||
|
{
|
||||||
|
// there is some unread data
|
||||||
|
// chain the new pbuf to the existing one
|
||||||
|
DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len);
|
||||||
|
pbuf_cat(_rx_buf, pb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DEBUGV(":rn %d\r\n", pb->tot_len);
|
||||||
|
_first_buf_taken = false;
|
||||||
|
_rx_buf = pb;
|
||||||
|
_rx_buf_offset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _s_recv(void *arg,
|
||||||
|
udp_pcb *upcb, pbuf *p,
|
||||||
|
ip_addr_t *addr, u16_t port)
|
||||||
|
{
|
||||||
|
reinterpret_cast<UdpContext*>(arg)->_recv(upcb, p, addr, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _refcnt;
|
||||||
|
udp_pcb* _pcb;
|
||||||
|
|
||||||
|
bool _first_buf_taken;
|
||||||
|
pbuf* _rx_buf;
|
||||||
|
size_t _rx_buf_offset;
|
||||||
|
|
||||||
|
pbuf* _tx_buf_head;
|
||||||
|
pbuf* _tx_buf_cur;
|
||||||
|
size_t _tx_buf_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif//CLIENTCONTEXT_H
|
Loading…
x
Reference in New Issue
Block a user