Skip to content

Check for socket handle on each socket call #73

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions ESP8266/ESP8266.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
_packets_end(&_packets),
_connect_error(0),
_fail(false),
_closed(false),
_socket_open(),
_connection_status(NSAPI_STATUS_DISCONNECTED)
{
Expand All @@ -47,6 +48,7 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
_parser.oob("3,CLOSED", callback(this, &ESP8266::_oob_socket3_closed_handler));
_parser.oob("4,CLOSED", callback(this, &ESP8266::_oob_socket4_closed_handler));
_parser.oob("WIFI ", callback(this, &ESP8266::_connection_status_handler));
_parser.oob("UNLINK", callback(this, &ESP8266::_oob_socket_close_error));
}

int ESP8266::get_firmware_version()
Expand Down Expand Up @@ -279,13 +281,15 @@ int ESP8266::scan(WiFiAccessPoint *res, unsigned limit)
return cnt;
}

bool ESP8266::open_udp(int id, const char* addr, int port, int local_port)
nsapi_error_t ESP8266::open_udp(int id, const char* addr, int port, int local_port)
{
static const char *type = "UDP";
bool done = false;

if (id >= SOCKET_COUNT || _socket_open[id]) {
return false;
if (id >= SOCKET_COUNT) {
return NSAPI_ERROR_PARAMETER;
} else if (_socket_open[id]) {
return NSAPI_ERROR_IS_CONNECTED;
}

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

_smutex.unlock();

return done;
return done ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR;
}

bool ESP8266::open_tcp(int id, const char* addr, int port, int keepalive)
Expand Down Expand Up @@ -375,7 +379,7 @@ void ESP8266::_packet_handler()
struct packet *packet = (struct packet*)malloc(
sizeof(struct packet) + amount);
if (!packet) {
debug("Could not allocate memory for RX data\n");
debug("ESP8266: could not allocate memory for RX data\n");
return;
}

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

int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount)
int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout)
{
_smutex.lock();
setTimeout(ESP8266_RECV_TIMEOUT);
setTimeout(timeout);

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

int32_t ESP8266::recv_udp(int id, void *data, uint32_t amount)
int32_t ESP8266::recv_udp(int id, void *data, uint32_t amount, uint32_t timeout)
{
_smutex.lock();
setTimeout(ESP8266_RECV_TIMEOUT);
setTimeout(timeout);

// Poll for inbound packets
while (_parser.process_oob()) {
Expand Down Expand Up @@ -481,8 +485,17 @@ bool ESP8266::close(int id)
//May take a second try if device is busy
for (unsigned i = 0; i < 2; i++) {
_smutex.lock();
if (_parser.send("AT+CIPCLOSE=%d", id) && _parser.recv("OK\n")) {
if (!_socket_open[id]) { // recv(processing OOBs) needs to be done first
if (_parser.send("AT+CIPCLOSE=%d", id)) {
if (!_parser.recv("OK\n")) {
if (_closed) { // UNLINK ERROR
_closed = false;
_socket_open[id] = 0;
_smutex.unlock();
// ESP8266 has a habit that it might close a socket on its own.
//debug("ESP8266: socket %d already closed when calling close\n", id);
return true;
}
} else {
_smutex.unlock();
return true;
}
Expand Down Expand Up @@ -547,6 +560,14 @@ void ESP8266::_connect_error_handler()
}
}

void ESP8266::_oob_socket_close_error()
{
if (_parser.recv("ERROR\n")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the OOB is "UNLINK ERROR", but triggers with "UNLINK", should you be including also the space somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those two words are actually on two separate lines

_closed = true; // Not possible to pinpoint to a certain socket
_parser.abort();
}
}

void ESP8266::_oob_socket0_closed_handler()
{
_socket_open[0] = 0;
Expand Down
8 changes: 5 additions & 3 deletions ESP8266/ESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class ESP8266
* @param local_port UDP socket's local port, zero means any
* @return true only if socket opened successfully
*/
bool open_udp(int id, const char* addr, int port, int local_port = 0);
nsapi_error_t open_udp(int id, const char* addr, int port, int local_port = 0);

/**
* Open a socketed connection
Expand Down Expand Up @@ -185,7 +185,7 @@ class ESP8266
* @param amount number of bytes to be received
* @return the number of bytes received
*/
int32_t recv_udp(int id, void *data, uint32_t amount);
int32_t recv_udp(int id, void *data, uint32_t amount, uint32_t timeout=ESP8266_RECV_TIMEOUT);

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

/**
* Closes a socket
Expand Down Expand Up @@ -290,6 +290,7 @@ class ESP8266
void _oob_socket3_closed_handler();
void _oob_socket4_closed_handler();
void _connection_status_handler();
void _oob_socket_close_error();

char _ip_buffer[16];
char _gateway_buffer[16];
Expand All @@ -298,6 +299,7 @@ class ESP8266

int _connect_error;
bool _fail;
bool _closed;
int _socket_open[SOCKET_COUNT];
nsapi_connection_status_t _connection_status;
Callback<void(nsapi_event_t, intptr_t)> _connection_status_cb;
Expand Down
45 changes: 40 additions & 5 deletions ESP8266Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ int ESP8266Interface::socket_close(void *handle)
{
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
int err = 0;

if (!socket) {
return NSAPI_ERROR_NO_SOCKET;
}

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

if (!socket) {
return NSAPI_ERROR_NO_SOCKET;
}

if (socket->proto == NSAPI_UDP) {
if(address.get_addr().version != NSAPI_UNSPEC) {
return NSAPI_ERROR_UNSUPPORTED;
Expand Down Expand Up @@ -344,10 +352,16 @@ int ESP8266Interface::socket_listen(void *handle, int backlog)
int ESP8266Interface::socket_connect(void *handle, const SocketAddress &addr)
{
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
nsapi_error_t ret;

if (!socket) {
return NSAPI_ERROR_NO_SOCKET;
}

if (socket->proto == NSAPI_UDP) {
if (!_esp.open_udp(socket->id, addr.get_ip_address(), addr.get_port(), _local_ports[socket->id])) {
return NSAPI_ERROR_DEVICE_ERROR;
ret = _esp.open_udp(socket->id, addr.get_ip_address(), addr.get_port(), _local_ports[socket->id]);
if (ret != NSAPI_ERROR_OK) {
return ret;
}
} else {
if (!_esp.open_tcp(socket->id, addr.get_ip_address(), addr.get_port(), socket->keepalive)) {
Expand All @@ -368,6 +382,10 @@ int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
{
nsapi_error_t status;
struct esp8266_socket *socket = (struct esp8266_socket *)handle;

if (!socket) {
return NSAPI_ERROR_NO_SOCKET;
}

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

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

if (!socket) {
return NSAPI_ERROR_NO_SOCKET;
}

int32_t recv;
if (socket->proto == NSAPI_TCP) {
recv = _esp.recv_tcp(socket->id, data, size);
Expand All @@ -395,6 +417,10 @@ int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, con
{
struct esp8266_socket *socket = (struct esp8266_socket *)handle;

if (!socket) {
return NSAPI_ERROR_NO_SOCKET;
}

if((strcmp(addr.get_ip_address(), "0.0.0.0") == 0) || !addr.get_port()) {
return NSAPI_ERROR_DNS_FAILURE;
}
Expand All @@ -420,6 +446,11 @@ int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, con
int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
{
struct esp8266_socket *socket = (struct esp8266_socket *)handle;

if (!socket) {
return NSAPI_ERROR_NO_SOCKET;
}

int ret = socket_recv(socket, data, size);
if (ret >= 0 && addr) {
*addr = socket->addr;
Expand All @@ -430,7 +461,7 @@ int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *d

void ESP8266Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
{
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
_cbs[socket->id].callback = callback;
_cbs[socket->id].data = data;
}
Expand All @@ -440,8 +471,10 @@ nsapi_error_t ESP8266Interface::setsockopt(nsapi_socket_t handle, int level,
{
struct esp8266_socket *socket = (struct esp8266_socket *)handle;

if (!optlen || !socket) {
if (!optlen) {
return NSAPI_ERROR_PARAMETER;
} else if (!socket) {
return NSAPI_ERROR_NO_SOCKET;
}

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

if (!optval || !optlen || !socket) {
if (!optval || !optlen) {
return NSAPI_ERROR_PARAMETER;
} else if (!socket) {
return NSAPI_ERROR_NO_SOCKET;
}

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