diff --git a/connectivity/netsocket/include/netsocket/NetworkInterface.h b/connectivity/netsocket/include/netsocket/NetworkInterface.h index 25d9f546eb8..86624a2f0a8 100644 --- a/connectivity/netsocket/include/netsocket/NetworkInterface.h +++ b/connectivity/netsocket/include/netsocket/NetworkInterface.h @@ -377,6 +377,7 @@ class NetworkInterface: public DNS { */ virtual void attach(mbed::Callback status_cb); +#if MBED_CONF_NSAPI_ADD_EVENT_LISTENER_RETURN_CHANGE /** Add event listener for interface. * * This API allows multiple callback to be registered for a single interface. @@ -387,8 +388,30 @@ class NetworkInterface: public DNS { * of both leads to undefined behavior. * * @param status_cb The callback for status changes. + * @return NSAPI_ERROR_OK on success + * @return NSAPI_ERROR_NO_MEMORY if the function fails to create a new entry. */ + nsapi_error_t add_event_listener(mbed::Callback status_cb); +#else + /** Add event listener for interface. + * + * This API allows multiple callback to be registered for a single interface. + * When first called, internal list of event handlers are created and registered to + * interface through attach() API. + * + * Application may only use attach() or add_event_listener() interface. Mixing usage + * of both leads to undefined behavior. + * + * @warning This version of the function does not use the `std::nothrow` feature. Subsequently, + * the function may fail to allocate memory and cause a system error. To use the new + * version with the changes, set "nsapi.add-event-listener-return-change": 1 in the + * target overrides section in your mbed_app.json file. + * + * @param status_cb The callback for status changes. + */ + MBED_DEPRECATED_SINCE("mbed-os-6.12", "This function return value will change to nsapi_error_t in the next major release. See documentation for details.") void add_event_listener(mbed::Callback status_cb); +#endif #if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE /** Remove event listener from interface. @@ -501,6 +524,10 @@ class NetworkInterface: public DNS { static NetworkInterface *get_target_default_instance(); #endif //!defined(DOXYGEN_ONLY) +private: + // Unified implementation for different versions of add_event_listener. + nsapi_error_t NetworkInterface::internal_add_event_listener(mbed::Callback status_cb); + public: /** Set default parameters on an interface. * diff --git a/connectivity/netsocket/mbed_lib.json b/connectivity/netsocket/mbed_lib.json index 5d1eccb4a51..d080275ba13 100644 --- a/connectivity/netsocket/mbed_lib.json +++ b/connectivity/netsocket/mbed_lib.json @@ -2,6 +2,10 @@ "name": "nsapi", "config": { "present": 1, + "add-event-listener-return-change": { + "help": "Updates the add_event_listener to return a nsapi_error_t value which can indicate allocation failure. See documents for more details.", + "value": 0 + }, "default-stack": { "help" : "Default stack to be used, valid values: LWIP, NANOSTACK.", "value" : "LWIP" diff --git a/connectivity/netsocket/source/NetworkInterface.cpp b/connectivity/netsocket/source/NetworkInterface.cpp index 3dcd4b33fee..be5c83eb9d2 100644 --- a/connectivity/netsocket/source/NetworkInterface.cpp +++ b/connectivity/netsocket/source/NetworkInterface.cpp @@ -21,6 +21,7 @@ #include "platform/Callback.h" #include "platform/mbed_error.h" #include +#include // Default network-interface state void NetworkInterface::set_as_default() @@ -142,16 +143,50 @@ static void call_all_event_listeners(NetworkInterface *iface, nsapi_event_t even } } -void NetworkInterface::add_event_listener(mbed::Callback status_cb) +nsapi_error_t NetworkInterface::internal_add_event_listener(mbed::Callback status_cb) { iface_eventlist_t *event_list = get_interface_event_list_head(); - iface_eventlist_entry_t *entry = new iface_eventlist_entry_t; +#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE + ns_list_foreach_safe(iface_eventlist_entry_t, entry, event_list) { + if (entry->status_cb == status_cb && entry->iface == this) { + return NSAPI_ERROR_OK; + } + } +#endif + + iface_eventlist_entry_t *entry = new (std::nothrow) iface_eventlist_entry_t; + if (!entry) { + return NSAPI_ERROR_NO_MEMORY; + } + entry->iface = this; entry->status_cb = status_cb; ns_list_add_to_end(event_list, entry); attach(mbed::callback(&call_all_event_listeners, this)); + return NSAPI_ERROR_OK; } +#if MBED_CONF_NSAPI_ADD_EVENT_LISTENER_RETURN_CHANGE +nsapi_error_t NetworkInterface::add_event_listener(mbed::Callback status_cb) +{ + return internal_add_event_listener(status_cb); +} +#else +void NetworkInterface::add_event_listener(mbed::Callback status_cb) +{ + auto error = internal_add_event_listener(status_cb); + switch (error) { + case NSAPI_ERROR_OK: + return; + case NSAPI_ERROR_NO_MEMORY: + MBED_ERROR(error, "Out of memory when adding an event listener"); + break; + default: + MBED_UNREACHABLE; + } +} +#endif // MBED_CONF_NSAPI_ADD_EVENT_LISTENER_RETURN_CHANGE + #if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE void NetworkInterface::remove_event_listener(mbed::Callback status_cb) { @@ -160,7 +195,6 @@ void NetworkInterface::remove_event_listener(mbed::Callbackstatus_cb == status_cb && entry->iface == this) { ns_list_remove(event_list, entry); delete entry; - return; } } } diff --git a/connectivity/netsocket/source/TCPSocket.cpp b/connectivity/netsocket/source/TCPSocket.cpp index 4b72ab09b37..24606f07d78 100644 --- a/connectivity/netsocket/source/TCPSocket.cpp +++ b/connectivity/netsocket/source/TCPSocket.cpp @@ -16,6 +16,7 @@ */ #include "netsocket/TCPSocket.h" +#include #include "Timer.h" #include "mbed_assert.h" @@ -266,7 +267,11 @@ TCPSocket *TCPSocket::accept(nsapi_error_t *error) ret = _stack->socket_accept(_socket, &socket, &address); if (0 == ret) { - connection = new TCPSocket(this, socket, address); + connection = new (std::nothrow) TCPSocket(this, socket, address); + if (!connection) { + ret = NSAPI_ERROR_NO_MEMORY; + break; + } _socket_stats.stats_update_peer(connection, address); _socket_stats.stats_update_socket_state(connection, SOCK_CONNECTED); break; diff --git a/connectivity/netsocket/source/TLSSocketWrapper.cpp b/connectivity/netsocket/source/TLSSocketWrapper.cpp index 2ff807d2f6c..f80f68165a1 100644 --- a/connectivity/netsocket/source/TLSSocketWrapper.cpp +++ b/connectivity/netsocket/source/TLSSocketWrapper.cpp @@ -16,6 +16,7 @@ */ #include "netsocket/TLSSocketWrapper.h" +#include #include "platform/Callback.h" #include "drivers/Timer.h" #include "events/mbed_events.h" @@ -134,7 +135,10 @@ nsapi_error_t TLSSocketWrapper::set_client_cert_key(const void *client_cert, siz #else int ret; - mbedtls_x509_crt *crt = new mbedtls_x509_crt; + mbedtls_x509_crt *crt = new (std::nothrow) mbedtls_x509_crt; + if (!crt) { + return NSAPI_ERROR_NO_MEMORY; + } mbedtls_x509_crt_init(crt); if ((ret = mbedtls_x509_crt_parse(crt, static_cast(client_cert), client_cert_len)) != 0) { @@ -286,7 +290,11 @@ nsapi_error_t TLSSocketWrapper::continue_handshake() #if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(FEA_TRACE_SUPPORT) && !defined(MBEDTLS_X509_REMOVE_INFO) /* Prints the server certificate and verify it. */ const size_t buf_size = 1024; - char *buf = new char[buf_size]; + char *buf = new (std::nothrow) char[buf_size]; + if (!buf) { + print_mbedtls_error("new (std::nothrow) char[buf_size] failed in continue_handshake", NSAPI_ERROR_NO_MEMORY); + return NSAPI_ERROR_NO_MEMORY; + } mbedtls_x509_crt_info(buf, buf_size, "\r ", mbedtls_ssl_get_peer_cert(&_ssl)); tr_debug("Server certificate:\r\n%s\r\n", buf); @@ -427,10 +435,9 @@ void TLSSocketWrapper::print_mbedtls_error(MBED_UNUSED const char *name, MBED_UN { // Avoid pulling in mbedtls_strerror when trace is not enabled #if defined FEA_TRACE_SUPPORT && defined MBEDTLS_ERROR_C - char *buf = new char[128]; + char buf[128]; mbedtls_strerror(err, buf, 128); tr_err("%s() failed: -0x%04x (%d): %s", name, -err, err, buf); - delete[] buf; #else tr_err("%s() failed: -0x%04x (%d)", name, -err, err); #endif @@ -459,7 +466,11 @@ void TLSSocketWrapper::my_debug(void *ctx, int level, const char *file, int line int TLSSocketWrapper::my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { const uint32_t buf_size = 1024; - char *buf = new char[buf_size]; + char *buf = new (std::nothrow) char[buf_size]; + if (!buf) { + return NSAPI_ERROR_NO_MEMORY; + } + (void) data; tr_debug("\nVerifying certificate at depth %d:\n", depth); @@ -569,7 +580,10 @@ mbedtls_ssl_config *TLSSocketWrapper::get_ssl_config() { if (!_ssl_conf) { int ret; - _ssl_conf = new mbedtls_ssl_config; + _ssl_conf = new (std::nothrow) mbedtls_ssl_config; + if (!_ssl_conf) { + return nullptr; + } mbedtls_ssl_config_init(_ssl_conf); _ssl_conf_allocated = true; diff --git a/connectivity/netsocket/source/nsapi_dns.cpp b/connectivity/netsocket/source/nsapi_dns.cpp index 4e250cd5afb..2f6f8b533ff 100644 --- a/connectivity/netsocket/source/nsapi_dns.cpp +++ b/connectivity/netsocket/source/nsapi_dns.cpp @@ -982,7 +982,12 @@ static void nsapi_dns_query_async_create(void *ptr) } if (!query->socket_cb_data) { - query->socket_cb_data = new SOCKET_CB_DATA; + query->socket_cb_data = new (std::nothrow) SOCKET_CB_DATA; + if (!query->socket_cb_data) { + delete socket; + nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL); + return; + } } query->socket_cb_data->call_in_cb = query->call_in_cb; query->socket_cb_data->stack = query->stack; diff --git a/tools/test/travis-ci/doxy-spellchecker/ignore.en.pws b/tools/test/travis-ci/doxy-spellchecker/ignore.en.pws index f8061ae43b0..fbc768bb80d 100644 --- a/tools/test/travis-ci/doxy-spellchecker/ignore.en.pws +++ b/tools/test/travis-ci/doxy-spellchecker/ignore.en.pws @@ -121,3 +121,5 @@ instantiation instantiations KVStore _doxy_ +nothrow +conf