Skip to content

Commit d152617

Browse files
committed
Let RxIRQ handle IPD messages. Detect it if the underlying socket changed in recv() call so we don't route back to a closed TCPSocket
1 parent 6a13d12 commit d152617

File tree

3 files changed

+78
-13
lines changed

3 files changed

+78
-13
lines changed

ESP8266/ESP8266.cpp

+66-6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ ESP8266::ESP8266(PinName tx, PinName rx, Callback<void(SignalingAction, int)> si
2222
{
2323
_serial.baud(115200);
2424
_parser.debugOn(debug);
25+
26+
_in_server_mode = false;
27+
_ipd_packet = NULL;
28+
_global_socket_counter = 0;
2529
}
2630

2731
int ESP8266::get_firmware_version()
@@ -211,6 +215,8 @@ bool ESP8266::send(int id, const void *data, uint32_t amount)
211215

212216
void ESP8266::_packet_handler()
213217
{
218+
if (_in_server_mode) return;
219+
214220
int id;
215221
uint32_t amount;
216222

@@ -243,7 +249,10 @@ int32_t ESP8266::recv(int id, void *data, uint32_t amount)
243249
{
244250
bool exit_when_not_found = false;
245251

246-
bool is_incoming_socket = _incoming_socket_status[id];
252+
// see if the underlying socket changed while in the recv() call
253+
// if you don't do this check it might be that a CLOSED,CONNECT happens on the same esp8266 socket id
254+
// and thus we associate the data with the wrong mbed TCPSocket
255+
uint32_t incoming_socket_id = _incoming_socket_status[id];
247256

248257
while (true) {
249258
// check if any packets are ready for us
@@ -281,15 +290,15 @@ int32_t ESP8266::recv(int id, void *data, uint32_t amount)
281290
// We know when it happens (due to monitoring the RX IRQ channel)
282291
// but there's no way of signaling this thread and actually abort the request...
283292

284-
if (is_incoming_socket) {
293+
if (incoming_socket_id > 0) {
285294
int timeout = _parser.getTimeout();
286295
_parser.setTimeout(1000);
287296

288297
if (!_parser.recv("OK")) {
289298
_parser.setTimeout(timeout);
290299

291300
// socket gone
292-
if (!_incoming_socket_status[id]) return NSAPI_ERROR_NO_SOCKET;
301+
if (incoming_socket_id != _incoming_socket_status[id]) return NSAPI_ERROR_NO_SOCKET;
293302

294303
// otherwise, just continue trying to get data...
295304
continue;
@@ -375,18 +384,36 @@ bool ESP8266::bind(const SocketAddress& address)
375384
// attach to the serial
376385
_serial.attach(callback(this, &ESP8266::attach_rx));
377386

387+
_in_server_mode = true;
388+
378389
// and start the actual server
379390
return _parser.send("AT+CIPSERVER=1,%d", address.get_port())
380391
&& _parser.recv("OK");
381392
}
382393

383394
void ESP8266::process_command(char* cmd, size_t size) {
384-
if (size == 9 /* 0,CONNECT */
395+
if (_ipd_packet) {
396+
memcpy(_ipd_packet_data_ptr, cmd, size);
397+
_ipd_packet_data_ptr += size;
398+
399+
_ipd_packet_data_ptr[0] = '\r';
400+
_ipd_packet_data_ptr[1] = '\n';
401+
_ipd_packet_data_ptr += 2;
402+
403+
if (_ipd_packet_data_ptr == ((char*)(_ipd_packet + 1)) + _ipd_packet->len) {
404+
// append to packet list
405+
*_packets_end = _ipd_packet;
406+
_packets_end = &_ipd_packet->next;
407+
408+
_ipd_packet = NULL;
409+
}
410+
}
411+
else if (size == 9 /* 0,CONNECT */
385412
&& (cmd[0] >= '0' && cmd[0] <= '9')
386413
&& (cmd[1] == ',')
387414
&& (strcmp(&cmd[2], "CONNECT") == 0)) {
388415

389-
_incoming_socket_status[cmd[0] - '0'] = true;
416+
_incoming_socket_status[cmd[0] - '0'] = ++_global_socket_counter;
390417

391418
_signalingCallback(ESP8266_SOCKET_CONNECT, cmd[0] - '0');
392419
}
@@ -395,10 +422,43 @@ void ESP8266::process_command(char* cmd, size_t size) {
395422
&& (cmd[1] == ',')
396423
&& (strcmp(&cmd[2], "CLOSED") == 0)) {
397424

398-
_incoming_socket_status[cmd[0] - '0'] = false;
425+
_incoming_socket_status[cmd[0] - '0'] = 0;
399426

400427
_signalingCallback(ESP8266_SOCKET_CLOSE, cmd[0] - '0');
401428
}
429+
else if (cmd[0] == '+' && cmd[1] == 'I' && cmd[2] == 'P' && cmd[3] == 'D') {
430+
int id = cmd[5] - '0';
431+
432+
// parse out the length param...
433+
size_t length_ix = 6;
434+
while (cmd[length_ix] != ':' && length_ix < size) length_ix++;
435+
char* temp_length_buff = (char*)calloc(length_ix - 7 + 1, 1);
436+
if (!temp_length_buff) return;
437+
memcpy(temp_length_buff, cmd + 7, length_ix - 7);
438+
int amount = atoi(temp_length_buff);
439+
440+
// alloc a new packet (and store it in a global var. we'll get the data for this packet straight after this msg)
441+
_ipd_packet = (struct packet*)malloc(
442+
sizeof(struct packet) + amount);
443+
if (!_ipd_packet) {
444+
return;
445+
}
446+
447+
_ipd_packet->id = id;
448+
_ipd_packet->len = amount;
449+
_ipd_packet->next = 0;
450+
451+
_ipd_packet_data_ptr = (char*)(_ipd_packet + 1);
452+
453+
size_t data_len = size - length_ix - 1;
454+
memcpy(_ipd_packet_data_ptr, cmd + length_ix + 1, data_len);
455+
_ipd_packet_data_ptr += data_len;
456+
457+
// re-add the newline \r\n again...
458+
_ipd_packet_data_ptr[0] = '\r';
459+
_ipd_packet_data_ptr[1] = '\n';
460+
_ipd_packet_data_ptr += 2;
461+
}
402462
free(cmd);
403463
}
404464

ESP8266/ESP8266.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,11 @@ class ESP8266
245245
Thread* event_thread;
246246
char* rx_buffer;
247247
size_t rx_ix;
248-
bool _incoming_socket_status[5];
249-
248+
uint32_t _incoming_socket_status[5];
249+
uint32_t _global_socket_counter;
250+
bool _in_server_mode;
251+
struct packet *_ipd_packet;
252+
char* _ipd_packet_data_ptr;
250253
};
251254

252255
#endif

ESP8266Interface.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,6 @@ int ESP8266Interface::socket_accept(void *server, void **socket, SocketAddress *
243243
// _incoming_sockets[ix].socket, _incoming_sockets[ix].socket && _incoming_sockets[ix].socket->connected,
244244
// _incoming_sockets[ix].accepted);
245245
if (_incoming_sockets[ix].socket && _incoming_sockets[ix].socket->connected && !_incoming_sockets[ix].accepted) {
246-
printf("accepting socket %d\n", ix);
247-
248246
*socket = _incoming_sockets[ix].socket;
249247
// addr is not used here I think...
250248
_incoming_sockets[ix].accepted = true;
@@ -262,6 +260,10 @@ int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
262260
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
263261
_esp.setTimeout(ESP8266_SEND_TIMEOUT);
264262

263+
if (!socket->connected) {
264+
return NSAPI_ERROR_NO_SOCKET;
265+
}
266+
265267
if (!_esp.send(socket->id, data, size)) {
266268
return NSAPI_ERROR_DEVICE_ERROR;
267269
}
@@ -336,7 +338,7 @@ void ESP8266Interface::event(int) {
336338

337339
void ESP8266Interface::signal(SignalingAction action, int socket_id) {
338340
if (action == ESP8266_SOCKET_CONNECT) {
339-
printf("ESP8266::SOCKET CONNECT %d\n", socket_id);
341+
// printf("ESP8266::SOCKET CONNECT %d\n", socket_id);
340342
if (_ids[socket_id]) {
341343
// this should not be possible...
342344
// printf("ESP8266_SOCKET_CONNECT for socket that already exists...\n");
@@ -359,7 +361,7 @@ void ESP8266Interface::signal(SignalingAction action, int socket_id) {
359361
_incoming_sockets[socket_id].accepted = false;
360362
}
361363
else if (action == ESP8266_SOCKET_CLOSE) {
362-
printf("ESP8266::SOCKET CLOSE %d\n", socket_id);
364+
// printf("ESP8266::SOCKET CLOSE %d\n", socket_id);
363365

364366
// Q: should we be able to delete the socket here? probably segfaults if held in user code
365367
struct esp8266_socket *socket = _incoming_sockets[socket_id].socket;
@@ -372,6 +374,6 @@ void ESP8266Interface::signal(SignalingAction action, int socket_id) {
372374
_ids[socket_id] = false;
373375
_incoming_sockets[socket_id].accepted = false;
374376
_incoming_sockets[socket_id].socket = NULL;
375-
delete socket;
377+
// delete socket;
376378
}
377379
}

0 commit comments

Comments
 (0)