Updated AsyncTCP library - had bad DNS handling if name not resolvable (null pointer dereference)

This commit is contained in:
Ray Jones 2019-10-28 17:32:16 +11:00
parent b1cee63ec3
commit 96b3cecdb0
13 changed files with 149 additions and 64 deletions

View File

@ -1,17 +1,26 @@
sudo: false
language: python
python:
- "2.7"
os:
- linux
dist:
- xenial
git:
depth: false
script:
- bash $TRAVIS_BUILD_DIR/travis/build.sh
stages:
- build
jobs:
include:
- name: "Arduino Build"
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
stage: build
script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh
- name: "PlatformIO Build"
if: tag IS blank AND (type = pull_request OR (type = push AND branch = master))
stage: build
script: bash $TRAVIS_BUILD_DIR/.github/scripts/on-push.sh 1 1
notifications:
email:
@ -22,4 +31,4 @@ notifications:
- https://webhooks.gitter.im/e/60e65d0c78ea0a920347
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always
on_start: false # default: false

View File

@ -1,5 +1,7 @@
# AsyncTCP
Async TCP Library for ESP32 Arduino
# AsyncTCP
[![Build Status](https://travis-ci.org/me-no-dev/AsyncTCP.svg?branch=master)](https://travis-ci.org/me-no-dev/AsyncTCP) ![](https://github.com/me-no-dev/AsyncTCP/workflows/Async%20TCP%20CI/badge.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/2f7e4d1df8b446d192cbfec6dc174d2d)](https://www.codacy.com/manual/me-no-dev/AsyncTCP?utm_source=github.com&utm_medium=referral&utm_content=me-no-dev/AsyncTCP&utm_campaign=Badge_Grade)
### Async TCP Library for ESP32 Arduino
[![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

View File

@ -12,7 +12,7 @@
"type": "git",
"url": "https://github.com/me-no-dev/AsyncTCP.git"
},
"version": "1.1.0",
"version": "1.1.1",
"license": "LGPL-3.0",
"frameworks": "arduino",
"platforms": "espressif32",

View File

@ -1,5 +1,5 @@
name=AsyncTCP
version=1.1.0
version=1.1.1
author=Me-No-Dev
maintainer=Me-No-Dev
sentence=Async TCP Library for ESP32

View File

@ -36,7 +36,7 @@ extern "C"{
* */
typedef enum {
LWIP_TCP_SENT, LWIP_TCP_RECV, LWIP_TCP_FIN, LWIP_TCP_ERROR, LWIP_TCP_POLL, LWIP_TCP_CLEAR, LWIP_TCP_ACCEPT, LWIP_TCP_CONNECTED, LWIP_TCP_DNS
LWIP_TCP_SENT, LWIP_TCP_RECV, LWIP_TCP_FIN, LWIP_TCP_ERROR, LWIP_TCP_POLL, LWIP_TCP_CLEAR, LWIP_TCP_ACCEPT, LWIP_TCP_CONNECTED, LWIP_TCP_DNS
} lwip_event_t;
typedef struct {
@ -79,6 +79,20 @@ typedef struct {
static xQueueHandle _async_queue;
static TaskHandle_t _async_service_task_handle = NULL;
SemaphoreHandle_t _slots_lock;
const int _number_of_closed_slots = CONFIG_LWIP_MAX_ACTIVE_TCP;
static uint32_t _closed_slots[_number_of_closed_slots];
static uint32_t _closed_index = []() {
_slots_lock = xSemaphoreCreateBinary();
xSemaphoreGive(_slots_lock);
for (int i = 0; i < _number_of_closed_slots; ++ i) {
_closed_slots[i] = 1;
}
return 1;
}();
static inline bool _init_async_event_queue(){
if(!_async_queue){
_async_queue = xQueueCreate(32, sizeof(lwip_event_packet_t *));
@ -138,7 +152,10 @@ static bool _remove_events_with_arg(void * arg){
}
static void _handle_async_event(lwip_event_packet_t * e){
if(e->event == LWIP_TCP_CLEAR){
if(e->arg == NULL){
// do nothing when arg is NULL
//ets_printf("event arg == NULL: 0x%08x\n", e->recv.pcb);
} else if(e->event == LWIP_TCP_CLEAR){
_remove_events_with_arg(e->arg);
} else if(e->event == LWIP_TCP_RECV){
//ets_printf("-R: 0x%08x\n", e->recv.pcb);
@ -297,10 +314,15 @@ static void _tcp_error(void * arg, int8_t err) {
static void _tcp_dns_found(const char * name, struct ip_addr * ipaddr, void * arg) {
lwip_event_packet_t * e = (lwip_event_packet_t *)malloc(sizeof(lwip_event_packet_t));
//ets_printf("+DNS: name=%s ipaddr=0x%08x arg=%x\n", name, ipaddr, arg);
e->event = LWIP_TCP_DNS;
e->arg = arg;
e->dns.name = name;
memcpy(&e->dns.addr, ipaddr, sizeof(struct ip_addr));
if (ipaddr) {
memcpy(&e->dns.addr, ipaddr, sizeof(struct ip_addr));
} else {
memset(&e->dns.addr, 0, sizeof(e->dns.addr));
}
if (!_send_async_event(&e)) {
free((void*)(e));
}
@ -327,7 +349,7 @@ static int8_t _tcp_accept(void * arg, AsyncClient * client) {
typedef struct {
struct tcpip_api_call_data call;
tcp_pcb * pcb;
AsyncClient * client;
int8_t closed_slot;
int8_t err;
union {
struct {
@ -352,19 +374,19 @@ typedef struct {
static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(msg->client && msg->client->pcb() == msg->pcb){
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
msg->err = tcp_output(msg->pcb);
}
return msg->err;
}
static esp_err_t _tcp_output(tcp_pcb * pcb, AsyncClient * client) {
static esp_err_t _tcp_output(tcp_pcb * pcb, int8_t closed_slot) {
if(!pcb){
return ERR_CONN;
}
tcp_api_call_t msg;
msg.pcb = pcb;
msg.client = client;
msg.closed_slot = closed_slot;
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
@ -372,19 +394,19 @@ static esp_err_t _tcp_output(tcp_pcb * pcb, AsyncClient * client) {
static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(msg->client && msg->client->pcb() == msg->pcb){
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags);
}
return msg->err;
}
static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_t apiflags, AsyncClient * client) {
static esp_err_t _tcp_write(tcp_pcb * pcb, int8_t closed_slot, const char* data, size_t size, uint8_t apiflags) {
if(!pcb){
return ERR_CONN;
}
tcp_api_call_t msg;
msg.pcb = pcb;
msg.client = client;
msg.closed_slot = closed_slot;
msg.write.data = data;
msg.write.size = size;
msg.write.apiflags = apiflags;
@ -395,20 +417,20 @@ static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_
static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(msg->client && msg->client->pcb() == msg->pcb){
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
msg->err = 0;
tcp_recved(msg->pcb, msg->received);
}
return msg->err;
}
static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len, AsyncClient * client) {
static esp_err_t _tcp_recved(tcp_pcb * pcb, int8_t closed_slot, size_t len) {
if(!pcb){
return ERR_CONN;
}
tcp_api_call_t msg;
msg.pcb = pcb;
msg.client = client;
msg.closed_slot = closed_slot;
msg.received = len;
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
@ -417,19 +439,19 @@ static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len, AsyncClient * client) {
static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(!msg->client || msg->client->pcb() == msg->pcb){
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
msg->err = tcp_close(msg->pcb);
}
return msg->err;
}
static esp_err_t _tcp_close(tcp_pcb * pcb, AsyncClient * client) {
static esp_err_t _tcp_close(tcp_pcb * pcb, int8_t closed_slot) {
if(!pcb){
return ERR_CONN;
}
tcp_api_call_t msg;
msg.pcb = pcb;
msg.client = client;
msg.closed_slot = closed_slot;
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
@ -437,19 +459,19 @@ static esp_err_t _tcp_close(tcp_pcb * pcb, AsyncClient * client) {
static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
msg->err = ERR_CONN;
if(!msg->client || msg->client->pcb() == msg->pcb){
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
tcp_abort(msg->pcb);
}
return msg->err;
}
static esp_err_t _tcp_abort(tcp_pcb * pcb, AsyncClient * client) {
static esp_err_t _tcp_abort(tcp_pcb * pcb, int8_t closed_slot) {
if(!pcb){
return ERR_CONN;
}
tcp_api_call_t msg;
msg.pcb = pcb;
msg.client = client;
msg.closed_slot = closed_slot;
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg);
return msg.err;
}
@ -460,12 +482,13 @@ static err_t _tcp_connect_api(struct tcpip_api_call_data *api_call_msg){
return msg->err;
}
static esp_err_t _tcp_connect(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port, tcp_connected_fn cb) {
static esp_err_t _tcp_connect(tcp_pcb * pcb, int8_t closed_slot, ip_addr_t * addr, uint16_t port, tcp_connected_fn cb) {
if(!pcb){
return ESP_FAIL;
}
tcp_api_call_t msg;
msg.pcb = pcb;
msg.closed_slot = closed_slot;
msg.connect.addr = addr;
msg.connect.port = port;
msg.connect.cb = cb;
@ -485,6 +508,7 @@ static esp_err_t _tcp_bind(tcp_pcb * pcb, ip_addr_t * addr, uint16_t port) {
}
tcp_api_call_t msg;
msg.pcb = pcb;
msg.closed_slot = -1;
msg.bind.addr = addr;
msg.bind.port = port;
tcpip_api_call(_tcp_bind_api, (struct tcpip_api_call_data*)&msg);
@ -504,6 +528,7 @@ static tcp_pcb * _tcp_listen_with_backlog(tcp_pcb * pcb, uint8_t backlog) {
}
tcp_api_call_t msg;
msg.pcb = pcb;
msg.closed_slot = -1;
msg.backlog = backlog?backlog:0xFF;
tcpip_api_call(_tcp_listen_api, (struct tcpip_api_call_data*)&msg);
return msg.pcb;
@ -541,7 +566,9 @@ AsyncClient::AsyncClient(tcp_pcb* pcb)
, next(NULL)
{
_pcb = pcb;
_closed_slot = -1;
if(_pcb){
_allocate_closed_slot();
_rx_last_packet = millis();
tcp_arg(_pcb, this);
tcp_recv(_pcb, &_tcp_recv);
@ -555,6 +582,7 @@ AsyncClient::~AsyncClient(){
if(_pcb) {
_close();
}
_free_closed_slot();
}
/*
@ -567,6 +595,7 @@ AsyncClient& AsyncClient::operator=(const AsyncClient& other){
}
_pcb = other._pcb;
_closed_slot = other._closed_slot;
if (_pcb) {
_rx_last_packet = millis();
tcp_arg(_pcb, this);
@ -671,7 +700,7 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){
tcp_sent(pcb, &_tcp_sent);
tcp_poll(pcb, &_tcp_poll, 1);
//_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected);
_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_tcp_connected);
_tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected);
return true;
}
@ -679,7 +708,6 @@ bool AsyncClient::connect(const char* host, uint16_t port){
ip_addr_t addr;
if(!_start_async_task()){
Serial.println("failed to start task");
log_e("failed to start task");
return false;
}
@ -697,14 +725,14 @@ bool AsyncClient::connect(const char* host, uint16_t port){
void AsyncClient::close(bool now){
if(_pcb){
_tcp_recved(_pcb, _rx_ack_len, this);
_tcp_recved(_pcb, _closed_slot, _rx_ack_len);
}
_close();
}
int8_t AsyncClient::abort(){
if(_pcb) {
_tcp_abort(_pcb, this);
_tcp_abort(_pcb, _closed_slot );
_pcb = NULL;
}
return ERR_ABRT;
@ -727,7 +755,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) {
}
size_t will_send = (room < size) ? room : size;
int8_t err = ERR_OK;
err = _tcp_write(_pcb, data, will_send, apiflags, this);
err = _tcp_write(_pcb, _closed_slot, data, will_send, apiflags);
if(err != ERR_OK) {
return 0;
}
@ -736,7 +764,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) {
bool AsyncClient::send(){
int8_t err = ERR_OK;
err = _tcp_output(_pcb, this);
err = _tcp_output(_pcb, _closed_slot);
if(err == ERR_OK){
_pcb_busy = true;
_pcb_sent_at = millis();
@ -749,7 +777,7 @@ size_t AsyncClient::ack(size_t len){
if(len > _rx_ack_len)
len = _rx_ack_len;
if(len){
_tcp_recved(_pcb, len, this);
_tcp_recved(_pcb, _closed_slot, len);
}
_rx_ack_len -= len;
return len;
@ -759,7 +787,7 @@ void AsyncClient::ackPacket(struct pbuf * pb){
if(!pb){
return;
}
_tcp_recved(_pcb, pb->len, this);
_tcp_recved(_pcb, _closed_slot, pb->len);
pbuf_free(pb);
}
@ -778,7 +806,7 @@ int8_t AsyncClient::_close(){
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
_tcp_clear_events(this);
err = _tcp_close(_pcb, this);
err = _tcp_close(_pcb, _closed_slot);
if(err != ERR_OK) {
err = abort();
}
@ -790,6 +818,29 @@ int8_t AsyncClient::_close(){
return err;
}
void AsyncClient::_allocate_closed_slot(){
xSemaphoreTake(_slots_lock, portMAX_DELAY);
uint32_t closed_slot_min_index = 0;
for (int i = 0; i < _number_of_closed_slots; ++ i) {
if ((_closed_slot == -1 || _closed_slots[i] <= closed_slot_min_index) && _closed_slots[i] != 0) {
closed_slot_min_index = _closed_slots[i];
_closed_slot = i;
}
}
if (_closed_slot != -1) {
_closed_slots[_closed_slot] = 0;
}
xSemaphoreGive(_slots_lock);
}
void AsyncClient::_free_closed_slot(){
if (_closed_slot != -1) {
_closed_slots[_closed_slot] = _closed_index;
_closed_slot = -1;
++ _closed_index;
}
}
/*
* Private Callbacks
* */
@ -812,10 +863,12 @@ int8_t AsyncClient::_connected(void* pcb, int8_t err){
void AsyncClient::_error(int8_t err) {
if(_pcb){
tcp_arg(_pcb, NULL);
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
if(_pcb->state == LISTEN) {
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
}
_pcb = NULL;
}
if(_error_cb) {
@ -833,13 +886,16 @@ int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) {
return ERR_OK;
}
tcp_arg(_pcb, NULL);
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
if(_pcb->state == LISTEN) {
tcp_sent(_pcb, NULL);
tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL);
tcp_poll(_pcb, NULL, 0);
}
if(tcp_close(_pcb) != ERR_OK) {
tcp_abort(_pcb);
}
_free_closed_slot();
_pcb = NULL;
return ERR_OK;
}
@ -880,7 +936,7 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) {
if(!_ack_pcb) {
_rx_ack_len += b->len;
} else if(_pcb) {
_tcp_recved(_pcb, b->len, this);
_tcp_recved(_pcb, _closed_slot, b->len);
}
pbuf_free(b);
}
@ -922,7 +978,7 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){
}
void AsyncClient::_dns_found(struct ip_addr *ipaddr){
if(ipaddr){
if(ipaddr && ipaddr->u_addr.ip4.addr){
connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port);
} else {
if(_error_cb) {
@ -1227,7 +1283,7 @@ void AsyncServer::begin(){
err = _tcp_bind(_pcb, &local_addr, _port);
if (err != ERR_OK) {
_tcp_close(_pcb, NULL);
_tcp_close(_pcb, -1);
log_e("bind error: %d", err);
return;
}
@ -1246,7 +1302,9 @@ void AsyncServer::end(){
if(_pcb){
tcp_arg(_pcb, NULL);
tcp_accept(_pcb, NULL);
_tcp_abort(_pcb, NULL);
if(tcp_close(_pcb) != ERR_OK){
_tcp_abort(_pcb, -1);
}
_pcb = NULL;
}
}

View File

@ -141,6 +141,7 @@ class AsyncClient {
protected:
tcp_pcb* _pcb;
int8_t _closed_slot;
AcConnectHandler _connect_cb;
void* _connect_cb_arg;
@ -169,6 +170,8 @@ class AsyncClient {
uint16_t _connect_port;
int8_t _close();
void _free_closed_slot();
void _allocate_closed_slot();
int8_t _connected(void* pcb, int8_t err);
void _error(int8_t err);
int8_t _poll(tcp_pcb* pcb);

View File

@ -28,4 +28,4 @@ build_flags =
-Wl,--wrap,millis
debug_tool = esp-prog
;upload_protocol = esp-prog
debug_init_break = tbreak setup
debug_init_break =

View File

@ -454,7 +454,7 @@ void setup() {
setupGPIO();
#endif
#if USE_SW_WATCHDOG == 1
#if USE_SW_WATCHDOG == 1 && USE_JTAG == 0
// create a watchdog timer
watchdogTimer = timerBegin(0, 80, true); //timer 0, divisor 80
timerAlarmWrite(watchdogTimer, 15000000, false); //set time in uS must be fed within this time or reboot
@ -607,7 +607,7 @@ void loop()
case CommStates::Idle:
#if USE_SW_WATCHDOG == 1
#if USE_SW_WATCHDOG == 1 && USE_JTAG == 0
feedWatchdog(); //reset timer (feed watchdog)
#endif

View File

@ -399,9 +399,10 @@ CGPIOout1::begin(int pin, CGPIOout1::Modes mode)
}
void
CGPIOout1::setMode(Modes mode)
{
_Mode = mode;
CGPIOout1::setMode(CGPIOout1::Modes mode)
{
if(mode >= Disabled && mode <= User)
_Mode = mode;
_prevState = -1;
ledcDetachPin(_pin); // ensure PWM detached from IO line
};
@ -604,7 +605,8 @@ CGPIOout2::begin(int pin, Modes mode)
void
CGPIOout2::setMode(CGPIOout2::Modes mode)
{
_Mode = mode;
if(mode >= Disabled && mode <= User)
_Mode = mode;
if(_pin)
ledcDetachPin(_pin); // ensure PWM detached from IO line
};
@ -651,6 +653,7 @@ CGPIOout2::getState()
CGPIOalg::CGPIOalg()
{
_expMean = 0;
_Mode = Disabled;
}
void

View File

@ -196,6 +196,16 @@ struct sGPIO {
bool outState[2];
bool inState[2];
int algVal;
sGPIO() {
outState[0] = outState[1] = false;
inState[0] = inState[1] = false;
algVal = 0;
out1Mode = CGPIOout1::Disabled;
out2Mode = CGPIOout2::Disabled;
in1Mode = CGPIOin1::Disabled;
in2Mode = CGPIOin2::Disabled;
algMode = CGPIOalg::Disabled;
};
CGPIOout1::Modes out1Mode;
CGPIOout2::Modes out2Mode;
CGPIOin1::Modes in1Mode;

View File

@ -190,7 +190,7 @@ bool mqttInit()
{
#ifdef USE_RTOS_MQTTTIMER
if(mqttReconnectTimer==NULL)
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(20000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
#else
mqttReconnect = 0;
#endif

View File

@ -766,7 +766,7 @@ void onUploadProgression()
// handle file fragments of form upload
else if (upload.status == UPLOAD_FILE_WRITE) {
#if USE_SW_WATCHDOG == 1
#if USE_SW_WATCHDOG == 1 && USE_JTAG == 0
feedWatchdog(); // we get stuck here for a while, don't let the watchdog bite!
#endif
int sts = BrowserUpload.fragment(upload);

View File

@ -67,7 +67,7 @@ void initOTA(){
DebugPort.println("Start updating " + type);
DebugPort.handle(); // keep telnet spy alive
ShowOTAScreen();
#if USE_SW_WATCHDOG == 1
#if USE_SW_WATCHDOG == 1 && USE_JTAG == 0
feedWatchdog(); // we get stuck here for a while, don't let the watchdog bite!
#endif
})