forked from me-no-dev/AsyncTCP
Merge pull request #66 from matt123p/fix-crash-on-fin-v2
Fix crash on fin attempt 2
This commit is contained in:
@@ -78,7 +78,9 @@ typedef struct {
|
||||
|
||||
static xQueueHandle _async_queue;
|
||||
static TaskHandle_t _async_service_task_handle = NULL;
|
||||
static tcp_pcb * pcb_recently_closed = NULL;
|
||||
const int _number_of_closed_slots = CONFIG_LWIP_MAX_ACTIVE_TCP;
|
||||
static int _closed_index = 0;
|
||||
static int _closed_slots[_number_of_closed_slots];
|
||||
|
||||
static inline bool _init_async_event_queue(){
|
||||
if(!_async_queue){
|
||||
@@ -333,6 +335,7 @@ static int8_t _tcp_accept(void * arg, AsyncClient * client) {
|
||||
typedef struct {
|
||||
struct tcpip_api_call_data call;
|
||||
tcp_pcb * pcb;
|
||||
int8_t closed_slot;
|
||||
int8_t err;
|
||||
union {
|
||||
struct {
|
||||
@@ -357,19 +360,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->pcb != pcb_recently_closed) {
|
||||
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
|
||||
msg->err = tcp_output(msg->pcb);
|
||||
}
|
||||
pcb_recently_closed = NULL;
|
||||
return msg->err;
|
||||
}
|
||||
|
||||
static esp_err_t _tcp_output(tcp_pcb * pcb) {
|
||||
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.closed_slot = closed_slot;
|
||||
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg);
|
||||
return msg.err;
|
||||
}
|
||||
@@ -377,19 +380,19 @@ static esp_err_t _tcp_output(tcp_pcb * pcb) {
|
||||
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->pcb != pcb_recently_closed) {
|
||||
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);
|
||||
}
|
||||
pcb_recently_closed = NULL;
|
||||
return msg->err;
|
||||
}
|
||||
|
||||
static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_t apiflags) {
|
||||
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.closed_slot = closed_slot;
|
||||
msg.write.data = data;
|
||||
msg.write.size = size;
|
||||
msg.write.apiflags = apiflags;
|
||||
@@ -400,20 +403,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->pcb != pcb_recently_closed) {
|
||||
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
|
||||
msg->err = 0;
|
||||
tcp_recved(msg->pcb, msg->received);
|
||||
}
|
||||
pcb_recently_closed = NULL;
|
||||
return msg->err;
|
||||
}
|
||||
|
||||
static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len) {
|
||||
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.closed_slot = closed_slot;
|
||||
msg.received = len;
|
||||
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg);
|
||||
return msg.err;
|
||||
@@ -422,19 +425,19 @@ static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len) {
|
||||
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->pcb != pcb_recently_closed) {
|
||||
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
|
||||
msg->err = tcp_close(msg->pcb);
|
||||
}
|
||||
pcb_recently_closed = NULL;
|
||||
return msg->err;
|
||||
}
|
||||
|
||||
static esp_err_t _tcp_close(tcp_pcb * pcb) {
|
||||
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.closed_slot = closed_slot;
|
||||
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg);
|
||||
return msg.err;
|
||||
}
|
||||
@@ -442,19 +445,19 @@ static esp_err_t _tcp_close(tcp_pcb * pcb) {
|
||||
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->pcb != pcb_recently_closed) {
|
||||
if(msg->closed_slot == -1 || !_closed_slots[msg->closed_slot]) {
|
||||
tcp_abort(msg->pcb);
|
||||
}
|
||||
pcb_recently_closed = NULL;
|
||||
return msg->err;
|
||||
}
|
||||
|
||||
static esp_err_t _tcp_abort(tcp_pcb * pcb) {
|
||||
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.closed_slot = closed_slot;
|
||||
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg);
|
||||
return msg.err;
|
||||
}
|
||||
@@ -465,12 +468,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;
|
||||
@@ -490,6 +494,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);
|
||||
@@ -509,6 +514,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;
|
||||
@@ -546,7 +552,25 @@ AsyncClient::AsyncClient(tcp_pcb* pcb)
|
||||
, next(NULL)
|
||||
{
|
||||
_pcb = pcb;
|
||||
_closed_slot = -1;
|
||||
if(_pcb){
|
||||
_closed_slot = 0;
|
||||
if (_closed_index == 0) {
|
||||
_closed_index = 1;
|
||||
for (int i = 0; i < _number_of_closed_slots; ++ i) {
|
||||
_closed_slots[i] = 1;
|
||||
}
|
||||
} else {
|
||||
int closed_slot_min_index = _closed_slots[0];
|
||||
for (int i = 0; i < _number_of_closed_slots; ++ i) {
|
||||
if (_closed_slots[i] <= closed_slot_min_index && _closed_slots[i] != 0) {
|
||||
closed_slot_min_index = _closed_slots[i];
|
||||
_closed_slot = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
_closed_slots[_closed_slot] = 0;
|
||||
|
||||
_rx_last_packet = millis();
|
||||
tcp_arg(_pcb, this);
|
||||
tcp_recv(_pcb, &_tcp_recv);
|
||||
@@ -572,6 +596,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);
|
||||
@@ -676,7 +701,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;
|
||||
}
|
||||
|
||||
@@ -702,14 +727,14 @@ bool AsyncClient::connect(const char* host, uint16_t port){
|
||||
|
||||
void AsyncClient::close(bool now){
|
||||
if(_pcb){
|
||||
_tcp_recved(_pcb, _rx_ack_len);
|
||||
_tcp_recved(_pcb, _closed_slot, _rx_ack_len);
|
||||
}
|
||||
_close();
|
||||
}
|
||||
|
||||
int8_t AsyncClient::abort(){
|
||||
if(_pcb) {
|
||||
_tcp_abort(_pcb);
|
||||
_tcp_abort(_pcb, _closed_slot );
|
||||
_pcb = NULL;
|
||||
}
|
||||
return ERR_ABRT;
|
||||
@@ -732,7 +757,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);
|
||||
err = _tcp_write(_pcb, _closed_slot, data, will_send, apiflags);
|
||||
if(err != ERR_OK) {
|
||||
return 0;
|
||||
}
|
||||
@@ -741,7 +766,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);
|
||||
err = _tcp_output(_pcb, _closed_slot);
|
||||
if(err == ERR_OK){
|
||||
_pcb_busy = true;
|
||||
_pcb_sent_at = millis();
|
||||
@@ -754,7 +779,7 @@ size_t AsyncClient::ack(size_t len){
|
||||
if(len > _rx_ack_len)
|
||||
len = _rx_ack_len;
|
||||
if(len){
|
||||
_tcp_recved(_pcb, len);
|
||||
_tcp_recved(_pcb, _closed_slot, len);
|
||||
}
|
||||
_rx_ack_len -= len;
|
||||
return len;
|
||||
@@ -764,7 +789,7 @@ void AsyncClient::ackPacket(struct pbuf * pb){
|
||||
if(!pb){
|
||||
return;
|
||||
}
|
||||
_tcp_recved(_pcb, pb->len);
|
||||
_tcp_recved(_pcb, _closed_slot, pb->len);
|
||||
pbuf_free(pb);
|
||||
}
|
||||
|
||||
@@ -783,7 +808,7 @@ int8_t AsyncClient::_close(){
|
||||
tcp_err(_pcb, NULL);
|
||||
tcp_poll(_pcb, NULL, 0);
|
||||
_tcp_clear_events(this);
|
||||
err = _tcp_close(_pcb);
|
||||
err = _tcp_close(_pcb, _closed_slot);
|
||||
if(err != ERR_OK) {
|
||||
err = abort();
|
||||
}
|
||||
@@ -845,7 +870,8 @@ int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) {
|
||||
if(tcp_close(_pcb) != ERR_OK) {
|
||||
tcp_abort(_pcb);
|
||||
}
|
||||
pcb_recently_closed = _pcb;
|
||||
_closed_slots[_closed_slot] = _closed_index;
|
||||
++ _closed_index;
|
||||
_pcb = NULL;
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -886,7 +912,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);
|
||||
_tcp_recved(_pcb, _closed_slot, b->len);
|
||||
}
|
||||
pbuf_free(b);
|
||||
}
|
||||
@@ -1233,7 +1259,7 @@ void AsyncServer::begin(){
|
||||
err = _tcp_bind(_pcb, &local_addr, _port);
|
||||
|
||||
if (err != ERR_OK) {
|
||||
_tcp_close(_pcb);
|
||||
_tcp_close(_pcb, -1);
|
||||
log_e("bind error: %d", err);
|
||||
return;
|
||||
}
|
||||
@@ -1253,7 +1279,7 @@ void AsyncServer::end(){
|
||||
tcp_arg(_pcb, NULL);
|
||||
tcp_accept(_pcb, NULL);
|
||||
if(tcp_close(_pcb) != ERR_OK){
|
||||
_tcp_abort(_pcb);
|
||||
_tcp_abort(_pcb, -1);
|
||||
}
|
||||
_pcb = NULL;
|
||||
}
|
||||
|
@@ -141,6 +141,7 @@ class AsyncClient {
|
||||
|
||||
protected:
|
||||
tcp_pcb* _pcb;
|
||||
int8_t _closed_slot;
|
||||
|
||||
AcConnectHandler _connect_cb;
|
||||
void* _connect_cb_arg;
|
||||
|
Reference in New Issue
Block a user