Skip to content

Commit 19d95f5

Browse files
author
Veijo Pesonen
authored
Check for socket handle on each socket call (#73)
* Adds check for socket handle to socket calls Return NSAPI_ERROR_NO_SOCKET if invalid handle. Don't care about ESP8266 complaining about missing socket when closing.
1 parent 979e9f3 commit 19d95f5

File tree

3 files changed

+77
-19
lines changed

3 files changed

+77
-19
lines changed

ESP8266/ESP8266.cpp

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
2929
_packets_end(&_packets),
3030
_connect_error(0),
3131
_fail(false),
32+
_closed(false),
3233
_socket_open(),
3334
_connection_status(NSAPI_STATUS_DISCONNECTED)
3435
{
@@ -47,6 +48,7 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
4748
_parser.oob("3,CLOSED", callback(this, &ESP8266::_oob_socket3_closed_handler));
4849
_parser.oob("4,CLOSED", callback(this, &ESP8266::_oob_socket4_closed_handler));
4950
_parser.oob("WIFI ", callback(this, &ESP8266::_connection_status_handler));
51+
_parser.oob("UNLINK", callback(this, &ESP8266::_oob_socket_close_error));
5052
}
5153

5254
int ESP8266::get_firmware_version()
@@ -279,13 +281,15 @@ int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
279281
return cnt;
280282
}
281283

282-
bool ESP8266::open_udp(int id, const char* addr, int port, int local_port)
284+
nsapi_error_t ESP8266::open_udp(int id, const char* addr, int port, int local_port)
283285
{
284286
static const char *type = "UDP";
285287
bool done = false;
286288

287-
if (id >= SOCKET_COUNT || _socket_open[id]) {
288-
return false;
289+
if (id >= SOCKET_COUNT) {
290+
return NSAPI_ERROR_PARAMETER;
291+
} else if (_socket_open[id]) {
292+
return NSAPI_ERROR_IS_CONNECTED;
289293
}
290294

291295
_smutex.lock();
@@ -303,7 +307,7 @@ bool ESP8266::open_udp(int id, const char* addr, int port, int local_port)
303307

304308
_smutex.unlock();
305309

306-
return done;
310+
return done ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR;
307311
}
308312

309313
bool ESP8266::open_tcp(int id, const char* addr, int port, int keepalive)
@@ -375,7 +379,7 @@ void ESP8266::_packet_handler()
375379
struct packet *packet = (struct packet*)malloc(
376380
sizeof(struct packet) + amount);
377381
if (!packet) {
378-
debug("Could not allocate memory for RX data\n");
382+
debug("ESP8266: could not allocate memory for RX data\n");
379383
return;
380384
}
381385

@@ -393,10 +397,10 @@ void ESP8266::_packet_handler()
393397
_packets_end = &packet->next;
394398
}
395399

396-
int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount)
400+
int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout)
397401
{
398402
_smutex.lock();
399-
setTimeout(ESP8266_RECV_TIMEOUT);
403+
setTimeout(timeout);
400404

401405
// Poll for inbound packets
402406
while (_parser.process_oob()) {
@@ -441,10 +445,10 @@ int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount)
441445
return NSAPI_ERROR_WOULD_BLOCK;
442446
}
443447

444-
int32_t ESP8266::recv_udp(int id, void *data, uint32_t amount)
448+
int32_t ESP8266::recv_udp(int id, void *data, uint32_t amount, uint32_t timeout)
445449
{
446450
_smutex.lock();
447-
setTimeout(ESP8266_RECV_TIMEOUT);
451+
setTimeout(timeout);
448452

449453
// Poll for inbound packets
450454
while (_parser.process_oob()) {
@@ -481,8 +485,17 @@ bool ESP8266::close(int id)
481485
//May take a second try if device is busy
482486
for (unsigned i = 0; i < 2; i++) {
483487
_smutex.lock();
484-
if (_parser.send("AT+CIPCLOSE=%d", id) && _parser.recv("OK\n")) {
485-
if (!_socket_open[id]) { // recv(processing OOBs) needs to be done first
488+
if (_parser.send("AT+CIPCLOSE=%d", id)) {
489+
if (!_parser.recv("OK\n")) {
490+
if (_closed) { // UNLINK ERROR
491+
_closed = false;
492+
_socket_open[id] = 0;
493+
_smutex.unlock();
494+
// ESP8266 has a habit that it might close a socket on its own.
495+
//debug("ESP8266: socket %d already closed when calling close\n", id);
496+
return true;
497+
}
498+
} else {
486499
_smutex.unlock();
487500
return true;
488501
}
@@ -547,6 +560,14 @@ void ESP8266::_connect_error_handler()
547560
}
548561
}
549562

563+
void ESP8266::_oob_socket_close_error()
564+
{
565+
if (_parser.recv("ERROR\n")) {
566+
_closed = true; // Not possible to pinpoint to a certain socket
567+
_parser.abort();
568+
}
569+
}
570+
550571
void ESP8266::_oob_socket0_closed_handler()
551572
{
552573
_socket_open[0] = 0;

ESP8266/ESP8266.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class ESP8266
152152
* @param local_port UDP socket's local port, zero means any
153153
* @return true only if socket opened successfully
154154
*/
155-
bool open_udp(int id, const char* addr, int port, int local_port = 0);
155+
nsapi_error_t open_udp(int id, const char* addr, int port, int local_port = 0);
156156

157157
/**
158158
* Open a socketed connection
@@ -185,7 +185,7 @@ class ESP8266
185185
* @param amount number of bytes to be received
186186
* @return the number of bytes received
187187
*/
188-
int32_t recv_udp(int id, void *data, uint32_t amount);
188+
int32_t recv_udp(int id, void *data, uint32_t amount, uint32_t timeout=ESP8266_RECV_TIMEOUT);
189189

190190
/**
191191
* Receives stream data from an open TCP socket
@@ -195,7 +195,7 @@ class ESP8266
195195
* @param amount number of bytes to be received
196196
* @return the number of bytes received
197197
*/
198-
int32_t recv_tcp(int id, void *data, uint32_t amount);
198+
int32_t recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout=ESP8266_RECV_TIMEOUT);
199199

200200
/**
201201
* Closes a socket
@@ -290,6 +290,7 @@ class ESP8266
290290
void _oob_socket3_closed_handler();
291291
void _oob_socket4_closed_handler();
292292
void _connection_status_handler();
293+
void _oob_socket_close_error();
293294

294295
char _ip_buffer[16];
295296
char _gateway_buffer[16];
@@ -298,6 +299,7 @@ class ESP8266
298299

299300
int _connect_error;
300301
bool _fail;
302+
bool _closed;
301303
int _socket_open[SOCKET_COUNT];
302304
nsapi_connection_status_t _connection_status;
303305
Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;

ESP8266Interface.cpp

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ int ESP8266Interface::socket_close(void *handle)
301301
{
302302
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
303303
int err = 0;
304+
305+
if (!socket) {
306+
return NSAPI_ERROR_NO_SOCKET;
307+
}
304308

305309
if (socket->connected && !_esp.close(socket->id)) {
306310
err = NSAPI_ERROR_DEVICE_ERROR;
@@ -317,6 +321,10 @@ int ESP8266Interface::socket_bind(void *handle, const SocketAddress &address)
317321
{
318322
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
319323

324+
if (!socket) {
325+
return NSAPI_ERROR_NO_SOCKET;
326+
}
327+
320328
if (socket->proto == NSAPI_UDP) {
321329
if(address.get_addr().version != NSAPI_UNSPEC) {
322330
return NSAPI_ERROR_UNSUPPORTED;
@@ -344,10 +352,16 @@ int ESP8266Interface::socket_listen(void *handle, int backlog)
344352
int ESP8266Interface::socket_connect(void *handle, const SocketAddress &addr)
345353
{
346354
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
355+
nsapi_error_t ret;
356+
357+
if (!socket) {
358+
return NSAPI_ERROR_NO_SOCKET;
359+
}
347360

348361
if (socket->proto == NSAPI_UDP) {
349-
if (!_esp.open_udp(socket->id, addr.get_ip_address(), addr.get_port(), _local_ports[socket->id])) {
350-
return NSAPI_ERROR_DEVICE_ERROR;
362+
ret = _esp.open_udp(socket->id, addr.get_ip_address(), addr.get_port(), _local_ports[socket->id]);
363+
if (ret != NSAPI_ERROR_OK) {
364+
return ret;
351365
}
352366
} else {
353367
if (!_esp.open_tcp(socket->id, addr.get_ip_address(), addr.get_port(), socket->keepalive)) {
@@ -368,6 +382,10 @@ int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
368382
{
369383
nsapi_error_t status;
370384
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
385+
386+
if (!socket) {
387+
return NSAPI_ERROR_NO_SOCKET;
388+
}
371389

372390
status = _esp.send(socket->id, data, size);
373391

@@ -378,6 +396,10 @@ int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size)
378396
{
379397
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
380398

399+
if (!socket) {
400+
return NSAPI_ERROR_NO_SOCKET;
401+
}
402+
381403
int32_t recv;
382404
if (socket->proto == NSAPI_TCP) {
383405
recv = _esp.recv_tcp(socket->id, data, size);
@@ -395,6 +417,10 @@ int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, con
395417
{
396418
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
397419

420+
if (!socket) {
421+
return NSAPI_ERROR_NO_SOCKET;
422+
}
423+
398424
if((strcmp(addr.get_ip_address(), "0.0.0.0") == 0) || !addr.get_port()) {
399425
return NSAPI_ERROR_DNS_FAILURE;
400426
}
@@ -420,6 +446,11 @@ int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, con
420446
int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
421447
{
422448
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
449+
450+
if (!socket) {
451+
return NSAPI_ERROR_NO_SOCKET;
452+
}
453+
423454
int ret = socket_recv(socket, data, size);
424455
if (ret >= 0 && addr) {
425456
*addr = socket->addr;
@@ -430,7 +461,7 @@ int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *d
430461

431462
void ESP8266Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
432463
{
433-
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
464+
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
434465
_cbs[socket->id].callback = callback;
435466
_cbs[socket->id].data = data;
436467
}
@@ -440,8 +471,10 @@ nsapi_error_t ESP8266Interface::setsockopt(nsapi_socket_t handle, int level,
440471
{
441472
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
442473

443-
if (!optlen || !socket) {
474+
if (!optlen) {
444475
return NSAPI_ERROR_PARAMETER;
476+
} else if (!socket) {
477+
return NSAPI_ERROR_NO_SOCKET;
445478
}
446479

447480
if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {
@@ -470,8 +503,10 @@ nsapi_error_t ESP8266Interface::getsockopt(nsapi_socket_t handle, int level, int
470503
{
471504
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
472505

473-
if (!optval || !optlen || !socket) {
506+
if (!optval || !optlen) {
474507
return NSAPI_ERROR_PARAMETER;
508+
} else if (!socket) {
509+
return NSAPI_ERROR_NO_SOCKET;
475510
}
476511

477512
if (level == NSAPI_SOCKET && socket->proto == NSAPI_TCP) {

0 commit comments

Comments
 (0)