diff --git a/features/cellular/framework/AT/AT_CellularStack.cpp b/features/cellular/framework/AT/AT_CellularStack.cpp index 333a88cb84c..ecd59d6498f 100644 --- a/features/cellular/framework/AT/AT_CellularStack.cpp +++ b/features/cellular/framework/AT/AT_CellularStack.cpp @@ -193,15 +193,21 @@ nsapi_error_t AT_CellularStack::socket_bind(nsapi_socket_t handle, const SocketA } if (addr) { - socket->localAddress.set_addr(addr.get_addr()); - } - - if (addr.get_port()) { - socket->localAddress.set_port(addr.get_port()); + return NSAPI_ERROR_UNSUPPORTED; } _at.lock(); + uint16_t port = addr.get_port(); + if (port != socket->localAddress.get_port()) { + if (port && (get_socket_index_by_port(port) == -1)) { + socket->localAddress.set_port(port); + } else { + _at.unlock(); + return NSAPI_ERROR_PARAMETER; + } + } + if (!socket->created) { create_socket_impl(socket); } @@ -335,3 +341,14 @@ void AT_CellularStack::socket_attach(nsapi_socket_t handle, void (*callback)(voi socket->_cb = callback; socket->_data = data; } + +int AT_CellularStack::get_socket_index_by_port(uint16_t port) +{ + int max_socket_count = get_max_socket_count(); + for (int i = 0; i < max_socket_count; i++) { + if (_socket[i]->localAddress.get_port() == port) { + return i; + } + } + return -1; +} diff --git a/features/cellular/framework/AT/AT_CellularStack.h b/features/cellular/framework/AT/AT_CellularStack.h index 2c25da15796..8ce57646653 100644 --- a/features/cellular/framework/AT/AT_CellularStack.h +++ b/features/cellular/framework/AT/AT_CellularStack.h @@ -184,6 +184,8 @@ class AT_CellularStack : public NetworkStack, public AT_CellularBase { private: int find_socket_index(nsapi_socket_t handle); + int get_socket_index_by_port(uint16_t port); + // mutex for write/read to a _socket array, needed when multiple threads may open sockets simultaneously PlatformMutex _socket_mutex; }; diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp index 8d79fa6c745..59ec9487f47 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp @@ -62,6 +62,10 @@ nsapi_error_t QUECTEL_BG96_CellularStack::socket_connect(nsapi_socket_t handle, handle_open_socket_response(modem_connect_id, err); if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) { + if (err == BG96_SOCKET_BIND_FAIL) { + socket->created = false; + return NSAPI_ERROR_PARAMETER; + } _at.cmd_start("AT+QICLOSE="); _at.write_int(modem_connect_id); _at.cmd_stop(); @@ -178,6 +182,10 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc handle_open_socket_response(modem_connect_id, err); if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) { + if (err == BG96_SOCKET_BIND_FAIL) { + socket->created = false; + return NSAPI_ERROR_PARAMETER; + } _at.cmd_start("AT+QICLOSE="); _at.write_int(modem_connect_id); _at.cmd_stop_read_resp(); @@ -206,6 +214,10 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc handle_open_socket_response(modem_connect_id, err); if ((_at.get_last_error() == NSAPI_ERROR_OK) && err) { + if (err == BG96_SOCKET_BIND_FAIL) { + socket->created = false; + return NSAPI_ERROR_PARAMETER; + } _at.cmd_start("AT+QICLOSE="); _at.write_int(modem_connect_id); _at.cmd_stop_read_resp(); @@ -239,6 +251,14 @@ nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *soc nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address, const void *data, nsapi_size_t size) { + if (size > BG96_MAX_SEND_SIZE) { + return NSAPI_ERROR_PARAMETER; + } + + if (!size && socket->proto == NSAPI_UDP) { + return NSAPI_ERROR_UNSUPPORTED; + } + int sent_len = 0; int sent_len_before = 0; int sent_len_after = 0; @@ -296,6 +316,11 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_recvfrom_impl(CellularS _at.cmd_start("AT+QIRD="); _at.write_int(socket->id); + if (socket->proto == NSAPI_TCP) { + // do not read more than max size + size = size > BG96_MAX_RECV_SIZE ? BG96_MAX_RECV_SIZE : size; + _at.write_int(size); + } _at.cmd_stop(); _at.resp_start("+QIRD:"); @@ -303,11 +328,15 @@ nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_recvfrom_impl(CellularS _at.read_string(ip_address, sizeof(ip_address)); port = _at.read_int(); if (recv_len > 0) { + // do not read more than buffer size + recv_len = recv_len > size ? size : recv_len; _at.read_bytes((uint8_t *)buffer, recv_len); } _at.resp_stop(); - if (!recv_len || (_at.get_last_error() != NSAPI_ERROR_OK)) { + // We block only if 0 recv length really means no data. + // If 0 is followed by ip address and port can be an UDP 0 length packet + if (!recv_len && port < 0) { return NSAPI_ERROR_WOULD_BLOCK; } diff --git a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.h b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.h index 1b8e5475305..e8eb670c1c0 100644 --- a/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.h +++ b/features/cellular/framework/targets/QUECTEL/BG96/QUECTEL_BG96_CellularStack.h @@ -25,6 +25,9 @@ namespace mbed { #define BG96_SOCKET_MAX 12 #define BG96_CREATE_SOCKET_TIMEOUT 150000 //150 seconds #define BG96_CLOSE_SOCKET_TIMEOUT 20000 // TCP socket max timeout is >10sec +#define BG96_MAX_RECV_SIZE 1500 +#define BG96_MAX_SEND_SIZE 1460 +#define BG96_SOCKET_BIND_FAIL 556 class QUECTEL_BG96_CellularStack : public AT_CellularStack { public: