Moved things into new wifi stack submodule

This commit is contained in:
2021-04-05 21:23:22 +02:00
parent 854adc59b7
commit a00a39a8f4
4 changed files with 1 additions and 426 deletions

View File

@ -1,7 +1,5 @@
set(headers
src/asyncudplistener.h
src/espcrc32builder.h
src/espnetworkutils.h
src/esprandom.h
src/lockhelper.h
src/lockingqueue.h
@ -19,9 +17,8 @@ set(headers
)
set(sources
src/asyncudplistener.cpp
src/espchrono_impl.cpp
src/taskutils.cpp
)
idf_component_register(INCLUDE_DIRS src SRCS ${headers} ${sources} REQUIRES freertos esp_system esp_http_client esp_websocket_client lwip cpputils espchrono)
idf_component_register(INCLUDE_DIRS src SRCS ${headers} ${sources} REQUIRES freertos esp_system esp_http_client esp_websocket_client cpputils espchrono)

View File

@ -1,260 +0,0 @@
#include "asyncudplistener.h"
// system includes
#include <cassert>
// esp-idf includes
#include <lwip/priv/tcpip_priv.h>
#include <lwip/prot/ethernet.h>
#include <esp_log.h>
// local utils
#include "taskutils.h"
namespace espcpputils {
namespace {
typedef struct
{
void *arg;
udp_pcb *pcb;
pbuf *pb;
const ip_addr_t *addr;
uint16_t port;
struct netif *netif;
} lwip_event_packet_t;
typedef struct
{
struct tcpip_api_call_data call;
udp_pcb * pcb;
const ip_addr_t *addr;
uint16_t port;
struct pbuf *pb;
struct netif *netif;
err_t err;
} udp_api_call_t;
err_t _udp_bind_api(struct tcpip_api_call_data *api_call_msg)
{
udp_api_call_t *msg = (udp_api_call_t *)api_call_msg;
msg->err = udp_bind(msg->pcb, msg->addr, msg->port);
return msg->err;
}
err_t _udp_bind(struct udp_pcb *pcb, const ip_addr_t *addr, u16_t port)
{
udp_api_call_t msg;
msg.pcb = pcb;
msg.addr = addr;
msg.port = port;
tcpip_api_call(_udp_bind_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
err_t _udp_disconnect_api(struct tcpip_api_call_data *api_call_msg)
{
udp_api_call_t *msg = (udp_api_call_t *)api_call_msg;
msg->err = 0;
udp_disconnect(msg->pcb);
return msg->err;
}
void _udp_disconnect(struct udp_pcb *pcb)
{
udp_api_call_t msg;
msg.pcb = pcb;
tcpip_api_call(_udp_disconnect_api, (struct tcpip_api_call_data*)&msg);
}
void _udp_recv(void *arg, udp_pcb *pcb, pbuf *pb, const ip_addr_t *addr, uint16_t port)
{
while (pb != NULL)
{
pbuf *this_pb = pb;
pb = pb->next;
this_pb->next = NULL;
if (!AsyncUdpListener::_udp_task_post(arg, pcb, this_pb, addr, port, ip_current_input_netif()))
pbuf_free(this_pb);
}
}
} // namespace
UdpPacketWrapper::UdpPacketWrapper(pbuf *pb, const ip_addr_t *raddr, uint16_t rport, struct netif *ntif)
{
_pb = pb;
_if = TCPIP_ADAPTER_IF_MAX;
_data = (uint8_t*)(pb->payload);
_len = pb->len;
_index = 0;
//memcpy(&_remoteIp, raddr, sizeof(ip_addr_t));
_remoteIp.type = raddr->type;
_localIp.type = _remoteIp.type;
eth_hdr* eth = NULL;
const udp_hdr* udphdr = reinterpret_cast<const udp_hdr*>(_data - UDP_HLEN);
_localPort = ntohs(udphdr->dest);
_remotePort = ntohs(udphdr->src);
if (_remoteIp.type == IPADDR_TYPE_V4)
{
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN - SIZEOF_ETH_HDR);
struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP_HLEN);
_localIp.u_addr.ip4.addr = iphdr->dest.addr;
_remoteIp.u_addr.ip4.addr = iphdr->src.addr;
}
else
{
eth = (eth_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN - SIZEOF_ETH_HDR);
struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(pb->payload)) - UDP_HLEN - IP6_HLEN);
std::memcpy(&_localIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16);
std::memcpy(&_remoteIp.u_addr.ip6.addr, (uint8_t *)ip6hdr->src.addr, 16);
}
_remoteMac = mac_t{eth->src.addr};
struct netif *netif{NULL};
void *nif{NULL};
for (int i=0; i<TCPIP_ADAPTER_IF_MAX; i++)
{
tcpip_adapter_get_netif((tcpip_adapter_if_t)i, &nif);
netif = (struct netif *)nif;
if (netif && netif == ntif)
{
_if = (tcpip_adapter_if_t)i;
break;
}
}
}
bool AsyncUdpListener::listen(const ip_addr_t *addr, uint16_t port)
{
if (!_udp_queue.constructed())
{
_udp_queue.construct(UBaseType_t{32}, sizeof(lwip_event_packet_t *));
if (!_udp_queue->handle)
{
_udp_queue.destruct();
ESP_LOGE("AsyncUdpListener", "xQueueCreate failed");
return false;
}
}
if (!_init())
{
ESP_LOGE("AsyncUdpListener", "failed to init");
return false;
}
close();
if (addr)
{
IP_SET_TYPE_VAL(_pcb->local_ip, addr->type);
IP_SET_TYPE_VAL(_pcb->remote_ip, addr->type);
}
if (_udp_bind(_pcb, addr, port) != ERR_OK)
{
ESP_LOGE("AsyncUdpListener", "failed to bind");
return false;
}
_connected = true;
return true;
}
void AsyncUdpListener::poll(TickType_t xTicksToWait)
{
if (!_udp_queue.constructed())
return;
lwip_event_packet_t *e{NULL};
while (_udp_queue->receive(&e, xTicksToWait) == pdTRUE)
{
if (!e->pb)
{
free((void*)(e));
continue;
}
_recv(e->pcb, e->pb, e->addr, e->port, e->netif);
free((void*)(e));
}
}
bool AsyncUdpListener::_udp_task_post(void *arg, udp_pcb *pcb, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif *netif)
{
if (!arg)
return false;
auto &queue = reinterpret_cast<AsyncUdpListener*>(arg)->_udp_queue;
if (!queue.constructed())
return false;
lwip_event_packet_t *e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t));
if (!e)
return false;
e->arg = arg;
e->pcb = pcb;
e->pb = pb;
e->addr = addr;
e->port = port;
e->netif = netif;
if (queue->send(&e, portMAX_DELAY) != pdPASS)
{
free((void*)(e));
return false;
}
return true;
}
bool AsyncUdpListener::_init()
{
if (_pcb)
return true;
_pcb = udp_new();
if (!_pcb)
{
ESP_LOGE("AsyncUdpListener", "udp_new() failed");
return false;
}
udp_recv(_pcb, &_udp_recv, (void *)this);
return true;
}
void AsyncUdpListener::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif *netif)
{
while (pb != NULL)
{
pbuf *this_pb = pb;
pb = pb->next;
this_pb->next = NULL;
if (_handler)
_handler(UdpPacketWrapper{this_pb, addr, port, netif});
pbuf_free(this_pb);
}
}
void AsyncUdpListener::close()
{
if (_pcb)
{
if (_connected)
_udp_disconnect(_pcb);
_connected = false;
}
}
} // namespace espcpputils

View File

@ -1,137 +0,0 @@
#pragma once
// system includes
#include <functional>
#include <cstring>
#include <optional>
#include <array>
// esp-idf includes
#include <lwip/ip_addr.h>
#include <lwip/udp.h>
#include <lwip/pbuf.h>
#include <esp_netif.h>
// local includes
#include "cppmacros.h"
#include "delayedconstruction.h"
#include "espnetworkutils.h"
#include "wrappers/queue.h"
namespace espcpputils {
class UdpPacketWrapper
{
CPP_DISABLE_COPY_MOVE(UdpPacketWrapper)
public:
UdpPacketWrapper(pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif);
const uint8_t *data() const { return _data; }
size_t length() const { return _len; }
bool isBroadcast() const
{
if (_localIp.type == IPADDR_TYPE_V6)
return false;
uint32_t ip = _localIp.u_addr.ip4.addr;
return ip == 0xFFFFFFFF || ip == 0 || (ip & 0xFF000000) == 0xFF000000;
}
bool isMulticast() const { return ip_addr_ismulticast(&(_localIp)); }
bool isIPv6() const { return _localIp.type == IPADDR_TYPE_V6; }
tcpip_adapter_if_t interface() const { return _if; }
std::optional<u32_t> localIP() const
{
if (_localIp.type != IPADDR_TYPE_V4)
return std::nullopt;
return _localIp.u_addr.ip4.addr;
}
std::optional<std::array<u32_t, 4>> localIPv6() const
{
if (_localIp.type != IPADDR_TYPE_V6)
return std::nullopt;
return *reinterpret_cast<const std::array<u32_t, 4>*>(_localIp.u_addr.ip6.addr);
}
uint16_t localPort() const { return _localPort; }
std::optional<u32_t> remoteIP() const
{
if (_remoteIp.type != IPADDR_TYPE_V4)
return std::nullopt;
return _remoteIp.u_addr.ip4.addr;
}
std::optional<std::array<u32_t, 4>> remoteIPv6() const
{
if (_remoteIp.type != IPADDR_TYPE_V6)
return std::nullopt;
return *reinterpret_cast<const std::array<u32_t, 4>*>(_remoteIp.u_addr.ip6.addr);
}
uint16_t remotePort() const { return _remotePort; }
mac_t remoteMac() const { return _remoteMac; }
private:
const pbuf *_pb;
tcpip_adapter_if_t _if;
ip_addr_t _localIp;
uint16_t _localPort;
ip_addr_t _remoteIp;
uint16_t _remotePort;
mac_t _remoteMac;
const uint8_t *_data;
size_t _len;
size_t _index;
};
class AsyncUdpListener
{
CPP_DISABLE_COPY_MOVE(AsyncUdpListener)
public:
AsyncUdpListener() = default;
void onPacket(std::function<void(const UdpPacketWrapper &packet)> cb) { _handler = cb; }
bool listen(const ip_addr_t *addr, uint16_t port);
// bool listen(const IPAddress addr, uint16_t port)
// {
// ip_addr_t laddr;
// laddr.type = IPADDR_TYPE_V4;
// laddr.u_addr.ip4.addr = addr;
// return listen(&laddr, port);
// }
// bool listen(const IPv6Address addr, uint16_t port)
// {
// ip_addr_t laddr;
// laddr.type = IPADDR_TYPE_V6;
// memcpy((uint8_t*)(laddr.u_addr.ip6.addr), (const uint8_t*)addr, 16);
// return listen(&laddr, port);
// }
bool listen(uint16_t port)
{
return listen(IP_ANY_TYPE, port);
}
void poll(TickType_t xTicksToWait = 0);
static bool _udp_task_post(void *arg, udp_pcb *pcb, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif *netif);
private:
bool _init();
void _recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif *netif);
void close();
private:
cpputils::DelayedConstruction<espcpputils::queue> _udp_queue;
udp_pcb *_pcb{};
bool _connected{};
std::function<void(const UdpPacketWrapper &packet)> _handler;
};
} // namespace espcpputils

View File

@ -1,25 +0,0 @@
#pragma once
// system includes
#include <array>
#include <string>
namespace espcpputils {
class mac_t : public std::array<uint8_t, 6>
{
public:
using std::array<uint8_t, 6>::array;
explicit mac_t(const uint8_t *ptr)
{
std::copy(ptr, ptr+6, std::begin(*this));
}
std::string toString() const
{
char macStr[18]{0};
snprintf(macStr, 18, "%02X:%02X:%02X:%02X:%02X:%02X", at(0), at(1), at(2), at(3), at(4), at(5));
return std::string{macStr};
}
};
} // namespace