From 886cddba495937a8073577c1f4e51a7a692f28d9 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Tue, 21 May 2024 07:48:52 +0000 Subject: [PATCH 1/4] ports: fix TCP client disconnect notifications --- api/cloud/oc_cloud.c | 14 +------- api/oc_client_api.c | 24 ++++++++++---- api/oc_session_events.c | 2 +- api/plgd/plgd_time.c | 2 +- apps/client_multithread_linux.c | 2 +- messaging/coap/engine.c | 2 +- messaging/coap/signal.c | 3 +- port/android/ipadapter.c | 10 +++++- port/android/tcpadapter.c | 24 +++++++------- port/android/tcpadapter.h | 3 +- port/esp32/adapter/src/ipadapter.c | 10 +++++- port/esp32/adapter/src/tcpadapter.c | 24 +++++++------- port/esp32/adapter/src/tcpadapter.h | 3 +- port/linux/ipadapter.c | 14 ++++++-- port/linux/tcpsession.c | 27 ++++++++++------ port/linux/tcpsession.h | 2 +- port/oc_connectivity.h | 7 ++-- port/oc_connectivity_internal.h | 11 +++++++ port/windows/ipadapter.c | 12 +++++-- port/windows/tcpadapter.c | 15 ++++++--- port/windows/tcpadapter.h | 2 +- security/oc_tls.c | 45 +++++++++++++------------- security/oc_tls_internal.h | 3 +- security/unittest/acltest.cpp | 12 +++---- security/unittest/rolestest.cpp | 2 +- security/unittest/tlstest.cpp | 4 +-- swig/swig_interfaces/oc_connectivity.i | 1 + 27 files changed, 174 insertions(+), 106 deletions(-) diff --git a/api/cloud/oc_cloud.c b/api/cloud/oc_cloud.c index 7db7f44c04..2831ee5f0d 100644 --- a/api/cloud/oc_cloud.c +++ b/api/cloud/oc_cloud.c @@ -132,19 +132,7 @@ void oc_cloud_close_endpoint(const oc_endpoint_t *ep) { OC_CLOUD_DBG("oc_cloud_close_endpoint"); -#ifdef OC_SECURITY - const oc_tls_peer_t *peer = oc_tls_get_peer(ep); - if (peer != NULL) { - OC_CLOUD_DBG("oc_cloud_close_endpoint: oc_tls_close_connection"); - oc_tls_close_connection(ep); - } else -#endif /* OC_SECURITY */ - { -#ifdef OC_TCP - OC_CLOUD_DBG("oc_cloud_close_endpoint: oc_connectivity_end_session"); - oc_connectivity_end_session(ep); -#endif /* OC_TCP */ - } + oc_close_session(ep); } void diff --git a/api/oc_client_api.c b/api/oc_client_api.c index c01aceae71..fbfe120532 100644 --- a/api/oc_client_api.c +++ b/api/oc_client_api.c @@ -18,6 +18,18 @@ #include "oc_config.h" +#include "oc_api.h" +#include "oc_endpoint.h" + +#ifdef OC_TCP +#include "api/oc_session_events_internal.h" +#include "port/oc_connectivity_internal.h" +#endif /* OC_TCP */ + +#ifdef OC_SECURITY +#include "security/oc_tls_internal.h" +#endif /* OC_SECURITY */ + #ifdef OC_CLIENT #include "api/client/oc_client_cb_internal.h" @@ -38,10 +50,6 @@ #include "messaging/coap/signal_internal.h" #endif /* OC_TCP */ -#ifdef OC_SECURITY -#include "security/oc_tls_internal.h" -#endif /* OC_SECURITY */ - #include typedef struct oc_dispatch_context_t @@ -948,6 +956,8 @@ oc_do_ip_discovery_at_endpoint(const char *rt, oc_discovery_handler_t handler, return status; } +#endif /* OC_CLIENT */ + void oc_close_session(const oc_endpoint_t *endpoint) { @@ -957,9 +967,9 @@ oc_close_session(const oc_endpoint_t *endpoint) #endif /* OC_SECURITY */ } else if (endpoint->flags & TCP) { #ifdef OC_TCP - oc_connectivity_end_session(endpoint); + if (oc_connectivity_end_session_v1(endpoint, false)) { + oc_handle_session(endpoint, OC_SESSION_DISCONNECTED); + } #endif /* OC_TCP */ } } - -#endif /* OC_CLIENT */ diff --git a/api/oc_session_events.c b/api/oc_session_events.c index 66420f013b..4d19107e20 100644 --- a/api/oc_session_events.c +++ b/api/oc_session_events.c @@ -332,7 +332,7 @@ handle_session_disconnected(const oc_endpoint_t *endpoint) (void)endpoint; #ifdef OC_SECURITY if ((endpoint->flags & SECURED) != 0 && (endpoint->flags & TCP) != 0) { - oc_tls_remove_peer(endpoint); + oc_tls_remove_peer(endpoint, false); } #endif /* OC_SECURITY */ #ifdef OC_SERVER diff --git a/api/plgd/plgd_time.c b/api/plgd/plgd_time.c index bf26bb8010..1188764e69 100644 --- a/api/plgd/plgd_time.c +++ b/api/plgd/plgd_time.c @@ -922,7 +922,7 @@ plgd_time_fetch(plgd_time_fetch_config_t fetch, unsigned *flags) OC_ERR("failed to send fetch plgd-time request to endpoint"); #if defined(OC_SECURITY) && defined(OC_PKI) if (add_insecure_peer) { - oc_tls_remove_peer(fetch.endpoint); + oc_tls_remove_peer(fetch.endpoint, true); } #endif /* OC_SECURITY && OC_PKI */ oc_memb_free(&g_fetch_params_s, fetch_params); diff --git a/apps/client_multithread_linux.c b/apps/client_multithread_linux.c index b558b111db..57eab2def2 100644 --- a/apps/client_multithread_linux.c +++ b/apps/client_multithread_linux.c @@ -107,7 +107,7 @@ pong_received_handler(oc_client_response_t *data) ping_count++; if (ping_count > PING_RETRY_COUNT) { OC_PRINTF("retry over. close connection.\n"); - oc_connectivity_end_session(data->endpoint); + oc_close_session(data->endpoint); } else { ping_timeout <<= 1; OC_PRINTF("PING send again.[retry: %zd, time: %u]\n", ping_count, diff --git a/messaging/coap/engine.c b/messaging/coap/engine.c index aa0352097c..9fe51449dc 100644 --- a/messaging/coap/engine.c +++ b/messaging/coap/engine.c @@ -1100,7 +1100,7 @@ coap_process_invalid_inbound_message(const coap_packet_t *packet, #endif /* OC_SECURITY */ #ifdef OC_TCP if ((msg->endpoint.flags & TCP) != 0) { - oc_connectivity_end_session(&msg->endpoint); + oc_close_session(&msg->endpoint); return; } #endif /* OC_TCP */ diff --git a/messaging/coap/signal.c b/messaging/coap/signal.c index 7995b7550f..0212fad3f7 100644 --- a/messaging/coap/signal.c +++ b/messaging/coap/signal.c @@ -21,6 +21,7 @@ #include "log_internal.h" #include "signal_internal.h" #include "coap_internal.h" +#include "oc_api.h" #include "transactions_internal.h" #include @@ -223,7 +224,7 @@ coap_signal_handle_message(const coap_packet_t *packet, if (packet->code == RELEASE_7_04) { // alternative address // hold off - oc_connectivity_end_session(endpoint); + oc_close_session(endpoint); return COAP_SIGNAL_DONE; } diff --git a/port/android/ipadapter.c b/port/android/ipadapter.c index dc228895c4..e7d43bfd4c 100644 --- a/port/android/ipadapter.c +++ b/port/android/ipadapter.c @@ -1629,13 +1629,21 @@ oc_connectivity_shutdown(size_t device) #ifdef OC_TCP void oc_connectivity_end_session(const oc_endpoint_t *endpoint) +{ + oc_connectivity_end_session_v1(endpoint, true); +} + +bool +oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, + bool notify_session_end) { if (endpoint->flags & TCP) { ip_context_t *dev = get_ip_context_for_device(endpoint->device); if (dev) { - oc_tcp_end_session(dev, endpoint); + return oc_tcp_end_session(dev, endpoint, notify_session_end); } } + return false; } #endif /* OC_TCP */ diff --git a/port/android/tcpadapter.c b/port/android/tcpadapter.c index b811f560ff..97ae5a5092 100644 --- a/port/android/tcpadapter.c +++ b/port/android/tcpadapter.c @@ -189,11 +189,11 @@ oc_tcp_add_socks_to_fd_set(ip_context_t *dev) } static void -free_tcp_session(tcp_session_t *session) +free_tcp_session(tcp_session_t *session, bool notify_session_end) { oc_list_remove(session_list, session); - if (!oc_session_events_disconnect_is_ongoing()) { + if (!oc_session_events_disconnect_is_ongoing() && notify_session_end) { oc_session_end_event(&session->endpoint); } @@ -401,13 +401,13 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) if (count < 0) { OC_ERR("recv error! %d", errno); - free_tcp_session(session); + free_tcp_session(session, true); ret_with_code(ADAPTER_STATUS_ERROR); } else if (count == 0) { OC_DBG("peer closed TCP session\n"); - free_tcp_session(session); + free_tcp_session(session, true); ret_with_code(ADAPTER_STATUS_NONE); } @@ -428,7 +428,7 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) oc_tcp_get_total_length_from_message_header(message); if (length_from_header < 0) { OC_ERR("invalid message size in header"); - free_tcp_session(session); + free_tcp_session(session, true); ret_with_code(ADAPTER_STATUS_ERROR); } @@ -438,7 +438,7 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) OC_ERR( "total receive length(%zu) is bigger than message buffer size(%zu)", total_length, oc_message_buffer_size(message)); - free_tcp_session(session); + free_tcp_session(session, true); ret_with_code(ADAPTER_STATUS_ERROR); } OC_DBG("tcp packet total length : %zu bytes.", total_length); @@ -448,7 +448,7 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) } while (total_length > message->length); if (!oc_tcp_is_valid_message(message)) { - free_tcp_session(session); + free_tcp_session(session, true); return ADAPTER_STATUS_ERROR; } @@ -461,15 +461,17 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) return ret; } -void -oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint) +bool +oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint, + bool notify_session_end) { pthread_mutex_lock(&dev->tcp.mutex); tcp_session_t *session = find_session_by_endpoint(endpoint); if (session) { - free_tcp_session(session); + free_tcp_session(session, notify_session_end); } pthread_mutex_unlock(&dev->tcp.mutex); + return session != NULL; } static int @@ -764,7 +766,7 @@ oc_tcp_connectivity_shutdown(ip_context_t *dev) while (session != NULL) { next = session->next; if (session->endpoint.device == dev->device) { - free_tcp_session(session); + free_tcp_session(session, true); } session = next; } diff --git a/port/android/tcpadapter.h b/port/android/tcpadapter.h index 3d400e875d..ba30d698d3 100644 --- a/port/android/tcpadapter.h +++ b/port/android/tcpadapter.h @@ -39,7 +39,8 @@ void oc_tcp_add_socks_to_fd_set(ip_context_t *dev); adapter_receive_state_t oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message); -void oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint); +bool oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint, + bool notify_session_end); #ifdef __cplusplus } diff --git a/port/esp32/adapter/src/ipadapter.c b/port/esp32/adapter/src/ipadapter.c index 1f2dac88fc..a9d636ce05 100644 --- a/port/esp32/adapter/src/ipadapter.c +++ b/port/esp32/adapter/src/ipadapter.c @@ -1617,13 +1617,21 @@ oc_connectivity_shutdown(size_t device) #ifdef OC_TCP void oc_connectivity_end_session(const oc_endpoint_t *endpoint) +{ + oc_connectivity_end_session_v1(endpoint, true); +} + +bool +oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, + bool notify_session_end) { if (endpoint->flags & TCP) { ip_context_t *dev = get_ip_context_for_device(endpoint->device); if (dev) { - oc_tcp_end_session(dev, endpoint); + return oc_tcp_end_session(dev, endpoint, notify_session_end); } } + return false; } #endif /* OC_TCP */ diff --git a/port/esp32/adapter/src/tcpadapter.c b/port/esp32/adapter/src/tcpadapter.c index 45acfc8a67..27fa90d70b 100644 --- a/port/esp32/adapter/src/tcpadapter.c +++ b/port/esp32/adapter/src/tcpadapter.c @@ -159,11 +159,11 @@ oc_tcp_add_socks_to_fd_set(ip_context_t *dev) } static void -free_tcp_session(tcp_session_t *session) +free_tcp_session(tcp_session_t *session, bool notify_session_end) { oc_list_remove(session_list, session); - if (!oc_session_events_disconnect_is_ongoing()) { + if (!oc_session_events_disconnect_is_ongoing() && notify_session_end) { oc_session_end_event(&session->endpoint); } @@ -374,13 +374,13 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) if (count < 0) { OC_ERR("recv error! %d", errno); - free_tcp_session(session); + free_tcp_session(session, true); ret_with_code(ADAPTER_STATUS_ERROR); } else if (count == 0) { OC_DBG("peer closed TCP session\n"); - free_tcp_session(session); + free_tcp_session(session, true); ret_with_code(ADAPTER_STATUS_NONE); } @@ -401,7 +401,7 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) oc_tcp_get_total_length_from_message_header(message); if (length_from_header < 0) { OC_ERR("invalid message size in header"); - free_tcp_session(session); + free_tcp_session(session, true); ret_with_code(ADAPTER_STATUS_ERROR); } @@ -411,7 +411,7 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) OC_ERR( "total receive length(%zu) is bigger than message buffer size(%zu)", total_length, oc_message_buffer_size(message)); - free_tcp_session(session); + free_tcp_session(session, true); ret_with_code(ADAPTER_STATUS_ERROR); } OC_DBG("tcp packet total length : %zu bytes.", total_length); @@ -421,7 +421,7 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) } while (total_length > message->length); if (!oc_tcp_is_valid_message(message)) { - free_tcp_session(session); + free_tcp_session(session, true); ret_with_code(ADAPTER_STATUS_ERROR); } @@ -434,15 +434,17 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) return ret; } -void -oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint) +bool +oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint, + bool notify_session_end) { pthread_mutex_lock(&dev->tcp.mutex); tcp_session_t *session = find_session_by_endpoint(endpoint); if (session) { - free_tcp_session(session); + free_tcp_session(session, notify_session_end); } pthread_mutex_unlock(&dev->tcp.mutex); + return session != NULL; } static int @@ -724,7 +726,7 @@ oc_tcp_connectivity_shutdown(ip_context_t *dev) while (session != NULL) { next = session->next; if (session->endpoint.device == dev->device) { - free_tcp_session(session); + free_tcp_session(session, true); } session = next; } diff --git a/port/esp32/adapter/src/tcpadapter.h b/port/esp32/adapter/src/tcpadapter.h index 3d400e875d..ba30d698d3 100644 --- a/port/esp32/adapter/src/tcpadapter.h +++ b/port/esp32/adapter/src/tcpadapter.h @@ -39,7 +39,8 @@ void oc_tcp_add_socks_to_fd_set(ip_context_t *dev); adapter_receive_state_t oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message); -void oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint); +bool oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint, + bool notify_session_end); #ifdef __cplusplus } diff --git a/port/linux/ipadapter.c b/port/linux/ipadapter.c index 7a15a0e6b9..60ca9290fc 100644 --- a/port/linux/ipadapter.c +++ b/port/linux/ipadapter.c @@ -1577,12 +1577,20 @@ oc_connectivity_shutdown(size_t device) } #ifdef OC_TCP -void -oc_connectivity_end_session(const oc_endpoint_t *endpoint) +bool +oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, + bool notify_session_end) { if ((endpoint->flags & TCP) != 0 && oc_get_ip_context_for_device(endpoint->device) != NULL) { - tcp_end_session(endpoint); + return tcp_end_session(endpoint, notify_session_end); } + return false; +} + +void +oc_connectivity_end_session(const oc_endpoint_t *endpoint) +{ + oc_connectivity_end_session_v1(endpoint, true); } #endif /* OC_TCP */ diff --git a/port/linux/tcpsession.c b/port/linux/tcpsession.c index 344583bb94..eeed5c9553 100644 --- a/port/linux/tcpsession.c +++ b/port/linux/tcpsession.c @@ -60,6 +60,7 @@ typedef struct tcp_session_t oc_endpoint_t endpoint; int sock; tcp_csm_state_t csm_state; + bool notify_session_end; } tcp_session_t; static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -95,6 +96,7 @@ typedef struct tcp_waiting_session_t OC_LIST_STRUCT(messages); on_tcp_connect_t on_tcp_connect; void *on_tcp_connect_data; + bool notify_session_end; } tcp_waiting_session_t; OC_LIST(g_waiting_session_list); ///< sessions waiting to open a connection, @@ -237,6 +239,7 @@ add_new_session_locked(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->endpoint.next = NULL; session->sock = sock; session->csm_state = state; + session->notify_session_end = true; oc_list_add(g_session_list, session); @@ -297,7 +300,8 @@ free_session_locked(tcp_session_t *session, bool signal) oc_list_remove(g_session_list, session); oc_list_remove(g_free_session_list_async, session); - if (!oc_session_events_disconnect_is_ongoing()) { + if (!oc_session_events_disconnect_is_ongoing() && + session->notify_session_end) { oc_session_end_event(&session->endpoint); } @@ -582,6 +586,7 @@ add_new_waiting_session_locked(int sock, ip_context_t *dev, ws->retry.count = 0; ws->on_tcp_connect = on_tcp_connect; ws->on_tcp_connect_data = on_tcp_connect_data; + ws->notify_session_end = true; #if OC_DBG_IS_ENABLED log_new_session(&ws->endpoint, sock, false); @@ -679,10 +684,11 @@ tcp_connect_locked(ip_context_t *dev, oc_endpoint_t *endpoint, #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ static void -free_session_async_locked(tcp_session_t *s) +free_session_async_locked(tcp_session_t *s, bool notify_session_end) { oc_list_remove(g_session_list, s); oc_list_add(g_free_session_list_async, s); + s->notify_session_end = notify_session_end; signal_network_thread(&s->dev->tcp); OC_DBG("signaled network event thread to monitor that the session needs to " @@ -692,10 +698,12 @@ free_session_async_locked(tcp_session_t *s) #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT static void -free_waiting_session_async_locked(tcp_waiting_session_t *ws) +free_waiting_session_async_locked(tcp_waiting_session_t *ws, + bool notify_session_end) { oc_list_remove(g_waiting_session_list, ws); oc_list_add(g_free_waiting_session_list_async, ws); + ws->notify_session_end = notify_session_end; signal_network_thread(&ws->dev->tcp); OC_DBG("signaled network event thread to monitor that the session needs to " @@ -704,27 +712,28 @@ free_waiting_session_async_locked(tcp_waiting_session_t *ws) } #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ -void -tcp_end_session(const oc_endpoint_t *endpoint) +bool +tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end) { pthread_mutex_lock(&g_mutex); tcp_session_t *s = find_session_by_endpoint_locked(endpoint); if (s != NULL) { - free_session_async_locked(s); + free_session_async_locked(s, notify_session_end); pthread_mutex_unlock(&g_mutex); - return; + return true; } #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT tcp_waiting_session_t *ws = find_waiting_session_by_endpoint_locked(endpoint); if (ws != NULL) { - free_waiting_session_async_locked(ws); + free_waiting_session_async_locked(ws, notify_session_end); pthread_mutex_unlock(&g_mutex); - return; + return true; } #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ pthread_mutex_unlock(&g_mutex); + return false; } #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT diff --git a/port/linux/tcpsession.h b/port/linux/tcpsession.h index cd4488e794..f5211f60fd 100644 --- a/port/linux/tcpsession.h +++ b/port/linux/tcpsession.h @@ -105,7 +105,7 @@ adapter_receive_state_t tcp_receive_message(ip_context_t *dev, fd_set *fds, * @brief Schedule the session associated with the endpoint to be stopped and * deallocated (if it exists). */ -void tcp_end_session(const oc_endpoint_t *endpoint); +bool tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end); /** * @brief Handle data received on the signal pipe. diff --git a/port/oc_connectivity.h b/port/oc_connectivity.h index 0b6e2b15fa..fb89df95a8 100644 --- a/port/oc_connectivity.h +++ b/port/oc_connectivity.h @@ -158,11 +158,14 @@ int oc_send_buffer(oc_message_t *message); void oc_send_discovery_request(oc_message_t *message); /** - * @brief end session for the specific endpoint + * @brief end TCP session for the specific endpoint. * * @param endpoint the endpoint to close the session for + * + * @deprecated replaced by oc_close_session in v2.2.5.14 */ -void oc_connectivity_end_session(const oc_endpoint_t *endpoint); +void oc_connectivity_end_session(const oc_endpoint_t *endpoint) + OC_DEPRECATED("replaced by oc_close_session in v2.2.5.14"); #ifdef OC_DNS_LOOKUP /** diff --git a/port/oc_connectivity_internal.h b/port/oc_connectivity_internal.h index fa522b28c4..fd7cbb7528 100644 --- a/port/oc_connectivity_internal.h +++ b/port/oc_connectivity_internal.h @@ -98,6 +98,17 @@ void handle_session_event_callback(const oc_endpoint_t *endpoint, oc_session_state_t state); #endif /* OC_SESSION_EVENTS */ +/** + * @brief end TCP session for the specific endpoint. + * + * @param endpoint the endpoint to close the session for + * @param notify_session_end send the notification about the disconnection + * session. + * @return bool true if the session will be closed + */ +bool oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, + bool notify_session_end); + #ifdef __cplusplus } #endif diff --git a/port/windows/ipadapter.c b/port/windows/ipadapter.c index 34589fb061..0690f73c34 100644 --- a/port/windows/ipadapter.c +++ b/port/windows/ipadapter.c @@ -1684,13 +1684,21 @@ oc_connectivity_shutdown(size_t device) #ifdef OC_TCP void oc_connectivity_end_session(const oc_endpoint_t *endpoint) +{ + oc_connectivity_end_session_v1(endpoint, true); +} + +bool +oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, + bool notify_session_end) { if (endpoint->flags & TCP) { ip_context_t *dev = get_ip_context_for_device(endpoint->device); - if (dev != NULL) { - oc_tcp_end_session(endpoint); + if (dev) { + return oc_tcp_end_session(endpoint, notify_session_end); } } + return false; } #endif /* OC_TCP */ diff --git a/port/windows/tcpadapter.c b/port/windows/tcpadapter.c index 0eea6b9f6c..1e94488407 100644 --- a/port/windows/tcpadapter.c +++ b/port/windows/tcpadapter.c @@ -54,6 +54,7 @@ typedef struct tcp_session SOCKET sock; HANDLE sock_event; tcp_csm_state_t csm_state; + bool notify_session_end; } tcp_session_t; OC_LIST(session_list); @@ -184,7 +185,8 @@ free_tcp_session(tcp_session_t *session) free_tcp_session_locked(session, &endpoint, &sock, &sock_event); WSACloseEvent(sock_event); closesocket(sock); - if (!oc_session_events_disconnect_is_ongoing()) { + if (!oc_session_events_disconnect_is_ongoing() && + session->notify_session_end) { oc_session_end_event(&endpoint); } @@ -192,10 +194,11 @@ free_tcp_session(tcp_session_t *session) } static void -free_tcp_session_async_locked(tcp_session_t *session) +free_tcp_session_async_locked(tcp_session_t *session, bool notify_session_end) { oc_list_remove(session_list, session); oc_list_add(free_session_list_async, session); + session->notify_session_end = notify_session_end; if (!SetEvent(session->dev->tcp.signal_event)) { OC_ERR("could not trigger signal event (%ld)\n", GetLastError()); @@ -234,6 +237,7 @@ add_new_session_locked(SOCKET sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->sock = sock; session->csm_state = state; session->sock_event = sock_event; + session->notify_session_end = true; oc_list_add(session_list, session); @@ -313,15 +317,16 @@ find_session_by_endpoint_locked(const oc_endpoint_t *endpoint) return session; } -void -oc_tcp_end_session(const oc_endpoint_t *endpoint) +bool +oc_tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end) { oc_tcp_adapter_mutex_lock(); tcp_session_t *session = find_session_by_endpoint_locked(endpoint); if (session) { - free_tcp_session_async_locked(session); + free_tcp_session_async_locked(session, notify_session_end); } oc_tcp_adapter_mutex_unlock(); + return session != NULL; } static SOCKET diff --git a/port/windows/tcpadapter.h b/port/windows/tcpadapter.h index 23be79cd5e..74f6962678 100644 --- a/port/windows/tcpadapter.h +++ b/port/windows/tcpadapter.h @@ -33,7 +33,7 @@ void oc_tcp_connectivity_shutdown(ip_context_t *dev); int oc_tcp_send_buffer(ip_context_t *dev, oc_message_t *message, const struct sockaddr_storage *receiver); -void oc_tcp_end_session(const oc_endpoint_t *endpoint); +bool oc_tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end); void oc_tcp_adapter_mutex_init(void); diff --git a/security/oc_tls.c b/security/oc_tls.c index 92949f3d88..18a033e949 100644 --- a/security/oc_tls.c +++ b/security/oc_tls.c @@ -462,7 +462,8 @@ tls_drop_endpoint_events(const oc_endpoint_t *endpoint) } static void -oc_tls_free_peer(oc_tls_peer_t *peer, bool inactivity_cb, bool from_reset) +oc_tls_free_peer(oc_tls_peer_t *peer, bool inactivity_cb, bool from_reset, + bool notify_session_end) { #if OC_DBG_IS_ENABLED // GCOVR_EXCL_START @@ -539,10 +540,10 @@ oc_tls_free_peer(oc_tls_peer_t *peer, bool inactivity_cb, bool from_reset) #ifdef OC_TCP if (endpoint.flags & TCP) { - oc_connectivity_end_session(&endpoint); - } else + oc_connectivity_end_session_v1(&endpoint, false); + } #endif /* OC_TCP */ - { + if (notify_session_end) { oc_handle_session(&endpoint, OC_SESSION_DISCONNECTED); } } @@ -569,11 +570,11 @@ oc_tls_peer_is_doc(const oc_endpoint_t *endpoint) } void -oc_tls_remove_peer(const oc_endpoint_t *endpoint) +oc_tls_remove_peer(const oc_endpoint_t *endpoint, bool notify_session_end) { oc_tls_peer_t *peer = oc_tls_get_peer(endpoint); if (peer != NULL) { - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, notify_session_end); } else { tls_drop_endpoint_events(endpoint); } @@ -587,7 +588,7 @@ oc_tls_close_peer(oc_tls_peer_t *peer, bool from_reset) if ((peer->endpoint.flags & TCP) == 0) { mbedtls_ssl_close_notify(&peer->ssl_ctx); } - oc_tls_free_peer(peer, false, from_reset); + oc_tls_free_peer(peer, false, from_reset, true); } void @@ -663,7 +664,7 @@ oc_dtls_inactive(void *data) mbedtls_ssl_close_notify(&peer->ssl_ctx); } OC_DBG("oc_tls: Removing inactive peer"); - oc_tls_free_peer(peer, true, false); + oc_tls_free_peer(peer, true, false, true); return OC_EVENT_DONE; } @@ -733,7 +734,7 @@ check_retry_timers(void) &peer->ssl_ctx, (const unsigned char *)&peer->endpoint.addr, sizeof(peer->endpoint.addr)) != 0) { TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_set_client_transport_id", ret); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); peer = next; continue; } @@ -741,7 +742,7 @@ check_retry_timers(void) if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_handshake", ret); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); } } } @@ -2156,7 +2157,7 @@ oc_tls_add_new_peer(oc_tls_new_peer_params_t params) } if (oc_tls_peer_ssl_init(peer) != 0) { - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); return NULL; } @@ -2222,7 +2223,7 @@ oc_tls_shutdown(void) { oc_tls_peer_t *p = oc_list_pop(g_tls_peers); while (p != NULL) { - oc_tls_free_peer(p, false, true); + oc_tls_free_peer(p, false, true, true); p = oc_list_pop(g_tls_peers); } #ifdef OC_PKI @@ -2542,7 +2543,7 @@ oc_tls_send_message_internal(oc_message_t *message) ? "ssl_write_tcp" : "mbedtls_ssl_write", ret); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); } else { length = message->length; } @@ -2595,7 +2596,7 @@ write_application_data(oc_tls_peer_t *peer) ? "ssl_write_tcp" : "mbedtls_ssl_write", ret); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); break; } message = (oc_message_t *)oc_list_pop(peer->send_q); @@ -2609,7 +2610,7 @@ oc_tls_handshake(oc_tls_peer_t *peer) if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_handshake", ret); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); return; } if (ret == 0) { @@ -2634,7 +2635,7 @@ oc_tls_on_tcp_connect(const oc_endpoint_t *endpoint, int state, void *data) return; } OC_ERR("oc_tls_on_tcp_connect: ends with error state: %d", state); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); } #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ @@ -2702,7 +2703,7 @@ oc_tls_init_connection(oc_message_t *message) OC_ERR( "oc_tls_init_connection: oc_tcp_connect returns unexpected state: %d", state); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); oc_message_unref(message); return; } @@ -2781,7 +2782,7 @@ tls_read_application_data_tcp(oc_tls_peer_t *peer) OC_ERR("oc_tls_tcp: total receive length(%ld) is bigger than max pdu " "size(%ld)", (long)total_length, (long)OC_PDU_SIZE); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); return; } want_read = total_length - peer->processed_recv_message->length; @@ -2809,7 +2810,7 @@ tls_read_application_data_tcp(oc_tls_peer_t *peer) mbedtls_ssl_close_notify(&peer->ssl_ctx); } TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_read", ret); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); return; } peer->processed_recv_message->length += ret; @@ -2847,7 +2848,7 @@ tls_handshake_step(oc_tls_peer_t *peer) &peer->ssl_ctx, (const unsigned char *)&peer->endpoint.addr, sizeof(peer->endpoint.addr)) != 0) { TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_set_client_transport_id", ret); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); return; } continue; @@ -2858,7 +2859,7 @@ tls_handshake_step(oc_tls_peer_t *peer) break; } TLS_LOG_MBEDTLS_ERROR("mbedtls_ssl_handshake_step", ret); - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); return; } } while (peer->ssl_ctx.state != MBEDTLS_SSL_HANDSHAKE_OVER); @@ -2913,7 +2914,7 @@ tls_read_application_data_udp(oc_tls_peer_t *peer) mbedtls_ssl_close_notify(&peer->ssl_ctx); mbedtls_ssl_close_notify(&peer->ssl_ctx); } - oc_tls_free_peer(peer, false, false); + oc_tls_free_peer(peer, false, false, true); return; } diff --git a/security/oc_tls_internal.h b/security/oc_tls_internal.h index 527e89341b..3af3eb5c8a 100644 --- a/security/oc_tls_internal.h +++ b/security/oc_tls_internal.h @@ -160,8 +160,9 @@ oc_tls_pki_verification_params_t oc_tls_peer_pki_default_verification_params( * @brief Remove and deallocate the peer for the endpoint. * * @param endpoint the endpoint + * @param notify_session_end notify session end event */ -void oc_tls_remove_peer(const oc_endpoint_t *endpoint); +void oc_tls_remove_peer(const oc_endpoint_t *endpoint, bool notify_session_end); /** * @brief Remove TLS peers matching filter. diff --git a/security/unittest/acltest.cpp b/security/unittest/acltest.cpp index 621be3b8da..b8f58c132c 100644 --- a/security/unittest/acltest.cpp +++ b/security/unittest/acltest.cpp @@ -320,7 +320,7 @@ TEST_F(TestAcl, oc_sec_check_acl_FailInsecureDOC) resource.device = kDeviceID; EXPECT_FALSE(oc_sec_check_acl(OC_GET, &resource, &ep)); - oc_tls_remove_peer(&ep); + oc_tls_remove_peer(&ep, true); } #ifdef OC_HAS_FEATURE_RESOURCE_ACCESS_IN_RFOTM @@ -397,7 +397,7 @@ TEST_F(TestAcl, oc_sec_check_acl_DOCAccessToDCR) EXPECT_TRUE(oc_sec_check_acl(OC_GET, resource, &ep)); - oc_tls_remove_peer(&ep); + oc_tls_remove_peer(&ep, true); } TEST_F(TestAcl, oc_sec_check_acl_GETinRFOTM) @@ -643,7 +643,7 @@ TEST_F(TestAcl, oc_sec_check_acl_AccessToSVRBySubject) EXPECT_FALSE(oc_sec_check_acl(OC_FETCH, doxm, &ep)); oc_sec_acl_clear(kDeviceID, nullptr, nullptr); - oc_tls_remove_peer(&ep); + oc_tls_remove_peer(&ep, true); } TEST_F(TestAcl, oc_sec_check_acl_AccessToSVRByPSK) @@ -731,7 +731,7 @@ TEST_F(TestAcl, oc_sec_check_acl_AccessToSVRByPSK) oc_sec_acl_clear(kDeviceID, nullptr, nullptr); peer->ssl_ctx.session = nullptr; - oc_tls_remove_peer(&ep); + oc_tls_remove_peer(&ep, true); } #if defined(OC_DYNAMIC_ALLOCATION) && defined(OC_PKI) @@ -781,7 +781,7 @@ TEST_F(TestAcl, oc_sec_check_acl_AccessToSVRByOwnerRoleCred) ASSERT_NE(-1, credid); checkAccessToResource(doxm, &ep); - oc_tls_remove_peer(&ep); + oc_tls_remove_peer(&ep, true); } TEST_F(TestAcl, oc_sec_check_acl_AccessToSVRByNonOwnerRoleCred) @@ -839,7 +839,7 @@ TEST_F(TestAcl, oc_sec_check_acl_AccessToSVRByNonOwnerRoleCred) checkAccessToResource(doxm, &ep, false, true, true, false); oc_sec_acl_clear(kDeviceID, nullptr, nullptr); - oc_tls_remove_peer(&ep); + oc_tls_remove_peer(&ep, true); } #endif /* OC_DYNAMIC_ALLOCATION && OC_PKI */ diff --git a/security/unittest/rolestest.cpp b/security/unittest/rolestest.cpp index 50594fef0d..bfbe8210d8 100644 --- a/security/unittest/rolestest.cpp +++ b/security/unittest/rolestest.cpp @@ -79,7 +79,7 @@ class TestRolesWithServer : public testing::Test { void TearDown() override { for (auto &peer : peers_) { - oc_tls_remove_peer(&peer->endpoint); + oc_tls_remove_peer(&peer->endpoint, true); } peers_.clear(); diff --git a/security/unittest/tlstest.cpp b/security/unittest/tlstest.cpp index 70147d9829..bd07c55a65 100644 --- a/security/unittest/tlstest.cpp +++ b/security/unittest/tlstest.cpp @@ -176,7 +176,7 @@ TEST_F(TestEventsWithServer, DropOutputMessages) oc_send_message(msg); EXPECT_LT(0, countInboundOrOutboundEvents()); - oc_tls_remove_peer(&ep); + oc_tls_remove_peer(&ep, true); ASSERT_EQ(0, countInboundOrOutboundEvents()); } @@ -208,7 +208,7 @@ TEST_F(TestEventsWithServer, DropOutputMessagesTCP) oc_send_message(msg); EXPECT_LT(0, countInboundOrOutboundEvents()); - oc_tls_remove_peer(&ep); + oc_tls_remove_peer(&ep, true); ASSERT_EQ(0, countInboundOrOutboundEvents()); } #endif /* OC_TCP */ diff --git a/swig/swig_interfaces/oc_connectivity.i b/swig/swig_interfaces/oc_connectivity.i index 91d90e6254..f55bc60a7f 100644 --- a/swig/swig_interfaces/oc_connectivity.i +++ b/swig/swig_interfaces/oc_connectivity.i @@ -58,6 +58,7 @@ void jni_connectivity_shutdown(size_t device) %} %ignore oc_send_discovery_request; %ignore oc_connectivity_end_session; +%ignore oc_connectivity_end_session_v1; %ignore oc_dns_lookup; %ignore oc_connectivity_get_endpoints; %ignore handle_network_interface_event_callback; From e0b00f6adae48aeb5535a7f50536c007a85b4167 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Tue, 21 May 2024 14:09:29 +0000 Subject: [PATCH 2/4] tcp: pair connection with the tls peer --- api/oc_client_api.c | 5 +-- api/oc_endpoint.c | 30 +++++++++++++++++ api/oc_tcp.c | 10 ++++++ api/oc_tcp_internal.h | 4 +++ include/oc_endpoint.h | 6 +++- port/android/ipadapter.c | 10 ++++-- port/android/tcpadapter.c | 8 ++++- port/android/tcpadapter.h | 3 +- port/esp32/adapter/src/ipadapter.c | 10 ++++-- port/esp32/adapter/src/tcpadapter.c | 8 ++++- port/esp32/adapter/src/tcpadapter.h | 3 +- port/linux/ipadapter.c | 9 +++-- port/linux/tcpsession.c | 36 +++++++++++++++++--- port/linux/tcpsession.h | 3 +- port/oc_connectivity_internal.h | 4 ++- port/windows/ipadapter.c | 9 +++-- port/windows/tcpadapter.c | 9 ++++- port/windows/tcpadapter.h | 3 +- security/oc_tls.c | 51 +++++++++++++++++++++++------ 19 files changed, 183 insertions(+), 38 deletions(-) diff --git a/api/oc_client_api.c b/api/oc_client_api.c index fbfe120532..7c805e9c45 100644 --- a/api/oc_client_api.c +++ b/api/oc_client_api.c @@ -967,8 +967,9 @@ oc_close_session(const oc_endpoint_t *endpoint) #endif /* OC_SECURITY */ } else if (endpoint->flags & TCP) { #ifdef OC_TCP - if (oc_connectivity_end_session_v1(endpoint, false)) { - oc_handle_session(endpoint, OC_SESSION_DISCONNECTED); + oc_endpoint_t session_endpoint; + while (oc_connectivity_end_session_v1(endpoint, false, &session_endpoint)) { + oc_handle_session(&session_endpoint, OC_SESSION_DISCONNECTED); } #endif /* OC_TCP */ } diff --git a/api/oc_endpoint.c b/api/oc_endpoint.c index 45a489f664..5a126231fb 100644 --- a/api/oc_endpoint.c +++ b/api/oc_endpoint.c @@ -675,6 +675,18 @@ oc_endpoint_compare_address(const oc_endpoint_t *ep1, const oc_endpoint_t *ep2) return -1; } +#ifdef OC_TCP +static int +oc_endpoint_compare_session_ids(const oc_endpoint_t *ep1, + const oc_endpoint_t *ep2) +{ + if (ep1->session_id == 0 || ep2->session_id == 0) { + return 0; // session_id == 0 means any + } + return ep1->session_id == ep2->session_id ? 0 : -1; +} +#endif + int oc_endpoint_compare(const oc_endpoint_t *ep1, const oc_endpoint_t *ep2) { @@ -690,7 +702,11 @@ oc_endpoint_compare(const oc_endpoint_t *ep1, const oc_endpoint_t *ep2) if (ep1->flags & IPV6) { if (memcmp(ep1->addr.ipv6.address, ep2->addr.ipv6.address, 16) == 0 && ep1->addr.ipv6.port == ep2->addr.ipv6.port) { +#ifdef OC_TCP + return oc_endpoint_compare_session_ids(ep1, ep2); +#else /* OC_TCP */ return 0; +#endif /* !OC_TCP */ } return -1; } @@ -698,11 +714,25 @@ oc_endpoint_compare(const oc_endpoint_t *ep1, const oc_endpoint_t *ep2) else if (ep1->flags & IPV4) { if (memcmp(ep1->addr.ipv4.address, ep2->addr.ipv4.address, 4) == 0 && ep1->addr.ipv4.port == ep2->addr.ipv4.port) { +#ifdef OC_TCP + return oc_endpoint_compare_session_ids(ep1, ep2); +#else /* OC_TCP */ return 0; +#endif /* !OC_TCP */ } return -1; } #endif /* OC_IPV4 */ + +#ifdef OC_TCP + else if (ep1->flags & TCP) { + if (memcmp(ep1->addr.ipv6.address, ep2->addr.ipv6.address, 16) == 0 && + ep1->addr.ipv6.port == ep2->addr.ipv6.port) { + return 0; + } + return -1; + } +#endif // TODO: Add support for other endpoint types return -1; } diff --git a/api/oc_tcp.c b/api/oc_tcp.c index 02c6f290ef..dc56566030 100644 --- a/api/oc_tcp.c +++ b/api/oc_tcp.c @@ -24,6 +24,7 @@ #include "oc_endpoint.h" #include "port/oc_connectivity.h" #include "oc_tcp_internal.h" +#include "util/oc_atomic.h" #ifdef OC_SECURITY #include #ifdef OC_OSCORE @@ -31,6 +32,15 @@ #endif /* OC_OSCORE */ #endif /* OC_SECURITY */ +static OC_ATOMIC_UINT32_T g_tcp_session_id = 0; + +uint32_t +oc_tcp_get_new_session_id(void) +{ + uint32_t v = OC_ATOMIC_INCREMENT32(g_tcp_session_id); + return (v == 0) ? OC_ATOMIC_INCREMENT32(g_tcp_session_id) : v; +} + #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT #include "port/oc_allocator_internal.h" diff --git a/api/oc_tcp_internal.h b/api/oc_tcp_internal.h index 26c05b812b..9248280f26 100644 --- a/api/oc_tcp_internal.h +++ b/api/oc_tcp_internal.h @@ -23,6 +23,7 @@ #ifdef OC_TCP +#include #include "messaging/coap/constants.h" #include "port/oc_connectivity.h" #include "oc_endpoint.h" @@ -34,6 +35,9 @@ extern "C" { #define OC_TCP_DEFAULT_RECEIVE_SIZE \ (COAP_TCP_DEFAULT_HEADER_LEN + COAP_TCP_MAX_EXTENDED_LENGTH_LEN) +/** @brief Get new tcp session ID */ +uint32_t oc_tcp_get_new_session_id(void); + #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT typedef struct oc_tcp_on_connect_event_s diff --git a/include/oc_endpoint.h b/include/oc_endpoint.h index d60dcbd07b..ca25526ec1 100644 --- a/include/oc_endpoint.h +++ b/include/oc_endpoint.h @@ -98,7 +98,7 @@ typedef struct oc_endpoint_t oc_ipv4_addr_t ipv4; ///< ipv4 address oc_le_addr_t bt; ///< blue tooth address } addr, addr_local; - unsigned interface_index; ///< interface index (valid intefaces are >0, 0 + unsigned interface_index; ///< interface index (valid interfaces are >0, 0 ///< means no index or error) uint8_t priority; ///< priority ocf_version_t version; ///< ocf version @@ -106,6 +106,10 @@ typedef struct oc_endpoint_t uint8_t piv[OSCORE_PIV_LEN]; uint8_t piv_len; #endif /* OC_OSCORE */ +#ifdef OC_TCP + uint32_t session_id; ///< session id for pairing tls peer with tcp session - 0 + ///< means any +#endif } oc_endpoint_t; #define oc_make_ipv4_endpoint(__name__, __flags__, __port__, ...) \ diff --git a/port/android/ipadapter.c b/port/android/ipadapter.c index e7d43bfd4c..9a769fef83 100644 --- a/port/android/ipadapter.c +++ b/port/android/ipadapter.c @@ -1630,17 +1630,21 @@ oc_connectivity_shutdown(size_t device) void oc_connectivity_end_session(const oc_endpoint_t *endpoint) { - oc_connectivity_end_session_v1(endpoint, true); + while (oc_connectivity_end_session_v1(endpoint, true, NULL)) { + // no-op + } } bool oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, - bool notify_session_end) + bool notify_session_end, + oc_endpoint_t *session_endpoint) { if (endpoint->flags & TCP) { ip_context_t *dev = get_ip_context_for_device(endpoint->device); if (dev) { - return oc_tcp_end_session(dev, endpoint, notify_session_end); + return oc_tcp_end_session(dev, endpoint, notify_session_end, + session_endpoint); } } return false; diff --git a/port/android/tcpadapter.c b/port/android/tcpadapter.c index 97ae5a5092..23cbb3da5c 100644 --- a/port/android/tcpadapter.c +++ b/port/android/tcpadapter.c @@ -235,6 +235,9 @@ add_new_session(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->endpoint.next = NULL; session->sock = sock; session->csm_state = state; + if (session->endpoint.session_id == 0) { + session->endpoint.session_id = oc_tcp_get_new_session_id(); + } oc_list_add(session_list, session); @@ -463,11 +466,14 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) bool oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint, - bool notify_session_end) + bool notify_session_end, oc_endpoint_t *session_endpoint) { pthread_mutex_lock(&dev->tcp.mutex); tcp_session_t *session = find_session_by_endpoint(endpoint); if (session) { + if (session_endpoint) { + memcpy(session_endpoint, &session->endpoint, sizeof(oc_endpoint_t)); + } free_tcp_session(session, notify_session_end); } pthread_mutex_unlock(&dev->tcp.mutex); diff --git a/port/android/tcpadapter.h b/port/android/tcpadapter.h index ba30d698d3..a48c870b6c 100644 --- a/port/android/tcpadapter.h +++ b/port/android/tcpadapter.h @@ -40,7 +40,8 @@ adapter_receive_state_t oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message); bool oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint, - bool notify_session_end); + bool notify_session_end, + oc_endpoint_t *session_endpoint); #ifdef __cplusplus } diff --git a/port/esp32/adapter/src/ipadapter.c b/port/esp32/adapter/src/ipadapter.c index a9d636ce05..3946e1cd12 100644 --- a/port/esp32/adapter/src/ipadapter.c +++ b/port/esp32/adapter/src/ipadapter.c @@ -1618,17 +1618,21 @@ oc_connectivity_shutdown(size_t device) void oc_connectivity_end_session(const oc_endpoint_t *endpoint) { - oc_connectivity_end_session_v1(endpoint, true); + while (oc_connectivity_end_session_v1(endpoint, true, NULL)) { + // no-op + } } bool oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, - bool notify_session_end) + bool notify_session_end, + oc_endpoint_t *session_endpoint) { if (endpoint->flags & TCP) { ip_context_t *dev = get_ip_context_for_device(endpoint->device); if (dev) { - return oc_tcp_end_session(dev, endpoint, notify_session_end); + return oc_tcp_end_session(dev, endpoint, notify_session_end, + session_endpoint); } } return false; diff --git a/port/esp32/adapter/src/tcpadapter.c b/port/esp32/adapter/src/tcpadapter.c index 27fa90d70b..49e8788a07 100644 --- a/port/esp32/adapter/src/tcpadapter.c +++ b/port/esp32/adapter/src/tcpadapter.c @@ -205,6 +205,9 @@ add_new_session(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->endpoint.next = NULL; session->sock = sock; session->csm_state = state; + if (session->endpoint.session_id == 0) { + session->endpoint.session_id = oc_tcp_get_new_session_id(); + } oc_list_add(session_list, session); @@ -436,11 +439,14 @@ oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message) bool oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint, - bool notify_session_end) + bool notify_session_end, oc_endpoint_t *session_endpoint) { pthread_mutex_lock(&dev->tcp.mutex); tcp_session_t *session = find_session_by_endpoint(endpoint); if (session) { + if (session_endpoint) { + memcpy(session_endpoint, &session->endpoint, sizeof(oc_endpoint_t)); + } free_tcp_session(session, notify_session_end); } pthread_mutex_unlock(&dev->tcp.mutex); diff --git a/port/esp32/adapter/src/tcpadapter.h b/port/esp32/adapter/src/tcpadapter.h index ba30d698d3..a48c870b6c 100644 --- a/port/esp32/adapter/src/tcpadapter.h +++ b/port/esp32/adapter/src/tcpadapter.h @@ -40,7 +40,8 @@ adapter_receive_state_t oc_tcp_receive_message(ip_context_t *dev, fd_set *fds, oc_message_t *message); bool oc_tcp_end_session(ip_context_t *dev, const oc_endpoint_t *endpoint, - bool notify_session_end); + bool notify_session_end, + oc_endpoint_t *session_endpoint); #ifdef __cplusplus } diff --git a/port/linux/ipadapter.c b/port/linux/ipadapter.c index 60ca9290fc..646fdec057 100644 --- a/port/linux/ipadapter.c +++ b/port/linux/ipadapter.c @@ -1579,11 +1579,12 @@ oc_connectivity_shutdown(size_t device) #ifdef OC_TCP bool oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, - bool notify_session_end) + bool notify_session_end, + oc_endpoint_t *session_endpoint) { if ((endpoint->flags & TCP) != 0 && oc_get_ip_context_for_device(endpoint->device) != NULL) { - return tcp_end_session(endpoint, notify_session_end); + return tcp_end_session(endpoint, notify_session_end, session_endpoint); } return false; } @@ -1591,6 +1592,8 @@ oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, void oc_connectivity_end_session(const oc_endpoint_t *endpoint) { - oc_connectivity_end_session_v1(endpoint, true); + while (oc_connectivity_end_session_v1(endpoint, true, NULL)) { + // no-op + } } #endif /* OC_TCP */ diff --git a/port/linux/tcpsession.c b/port/linux/tcpsession.c index eeed5c9553..97c7f72c8b 100644 --- a/port/linux/tcpsession.c +++ b/port/linux/tcpsession.c @@ -211,9 +211,24 @@ log_new_session(oc_endpoint_t *endpoint, int sock, bool is_connected) addr = oc_string(ep); } OC_DBG("new TCP session endpoint: %s, endpoint interface: %d, sock: %d, " - "connected: %d", - addr, endpoint->interface_index, sock, (int)is_connected); + "connected: %d, session_id: %u", + addr, endpoint->interface_index, sock, (int)is_connected, + (unsigned)endpoint->session_id); } + +static void +log_free_session(oc_endpoint_t *endpoint, int sock) +{ + oc_string64_t ep; + const char *addr = ""; + if (oc_endpoint_to_string64(endpoint, &ep)) { + addr = oc_string(ep); + } + OC_DBG("free TCP session endpoint: %s, endpoint interface: %d, sock: %d, " + "session_id: %u", + addr, endpoint->interface_index, sock, (unsigned)endpoint->session_id); +} + #endif /* OC_DBG_IS_ENABLED */ static tcp_session_t * @@ -240,6 +255,9 @@ add_new_session_locked(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->sock = sock; session->csm_state = state; session->notify_session_end = true; + if (session->endpoint.session_id == 0) { + session->endpoint.session_id = oc_tcp_get_new_session_id(); + } oc_list_add(g_session_list, session); @@ -311,8 +329,9 @@ free_session_locked(tcp_session_t *session, bool signal) signal_network_thread(&session->dev->tcp); } close(session->sock); - - OC_DBG("free TCP session(%p, fd=%d)", (void *)session, session->sock); +#if OC_DBG_IS_ENABLED + log_free_session(&session->endpoint, session->sock); +#endif /* OC_DBG_IS_ENABLED */ oc_memb_free(&g_tcp_session_s, session); } @@ -713,12 +732,16 @@ free_waiting_session_async_locked(tcp_waiting_session_t *ws, #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ bool -tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end) +tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end, + oc_endpoint_t *session_endpoint) { pthread_mutex_lock(&g_mutex); tcp_session_t *s = find_session_by_endpoint_locked(endpoint); if (s != NULL) { free_session_async_locked(s, notify_session_end); + if (session_endpoint) { + memcpy(session_endpoint, &s->endpoint, sizeof(oc_endpoint_t)); + } pthread_mutex_unlock(&g_mutex); return true; } @@ -727,6 +750,9 @@ tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end) tcp_waiting_session_t *ws = find_waiting_session_by_endpoint_locked(endpoint); if (ws != NULL) { free_waiting_session_async_locked(ws, notify_session_end); + if (session_endpoint) { + memcpy(session_endpoint, &ws->endpoint, sizeof(oc_endpoint_t)); + } pthread_mutex_unlock(&g_mutex); return true; } diff --git a/port/linux/tcpsession.h b/port/linux/tcpsession.h index f5211f60fd..50100b69b0 100644 --- a/port/linux/tcpsession.h +++ b/port/linux/tcpsession.h @@ -105,7 +105,8 @@ adapter_receive_state_t tcp_receive_message(ip_context_t *dev, fd_set *fds, * @brief Schedule the session associated with the endpoint to be stopped and * deallocated (if it exists). */ -bool tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end); +bool tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end, + oc_endpoint_t *session_endpoint); /** * @brief Handle data received on the signal pipe. diff --git a/port/oc_connectivity_internal.h b/port/oc_connectivity_internal.h index fd7cbb7528..2f10d3159b 100644 --- a/port/oc_connectivity_internal.h +++ b/port/oc_connectivity_internal.h @@ -104,10 +104,12 @@ void handle_session_event_callback(const oc_endpoint_t *endpoint, * @param endpoint the endpoint to close the session for * @param notify_session_end send the notification about the disconnection * session. + * @param session_endpoint the endpoint of the session with session id * @return bool true if the session will be closed */ bool oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, - bool notify_session_end); + bool notify_session_end, + oc_endpoint_t *session_endpoint); #ifdef __cplusplus } diff --git a/port/windows/ipadapter.c b/port/windows/ipadapter.c index 0690f73c34..4bb322ef38 100644 --- a/port/windows/ipadapter.c +++ b/port/windows/ipadapter.c @@ -1685,17 +1685,20 @@ oc_connectivity_shutdown(size_t device) void oc_connectivity_end_session(const oc_endpoint_t *endpoint) { - oc_connectivity_end_session_v1(endpoint, true); + while (oc_connectivity_end_session_v1(endpoint, true, NULL)) { + // no-op + } } bool oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, - bool notify_session_end) + bool notify_session_end, + oc_endpoint_t *session_endpoint) { if (endpoint->flags & TCP) { ip_context_t *dev = get_ip_context_for_device(endpoint->device); if (dev) { - return oc_tcp_end_session(endpoint, notify_session_end); + return oc_tcp_end_session(endpoint, notify_session_end, session_endpoint); } } return false; diff --git a/port/windows/tcpadapter.c b/port/windows/tcpadapter.c index 1e94488407..1af90757db 100644 --- a/port/windows/tcpadapter.c +++ b/port/windows/tcpadapter.c @@ -238,6 +238,9 @@ add_new_session_locked(SOCKET sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->csm_state = state; session->sock_event = sock_event; session->notify_session_end = true; + if (session->endpoint.session_id == 0) { + session->endpoint.session_id = oc_tcp_get_new_session_id(); + } oc_list_add(session_list, session); @@ -318,11 +321,15 @@ find_session_by_endpoint_locked(const oc_endpoint_t *endpoint) } bool -oc_tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end) +oc_tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end, + oc_endpoint_t *session_endpoint) { oc_tcp_adapter_mutex_lock(); tcp_session_t *session = find_session_by_endpoint_locked(endpoint); if (session) { + if (session_endpoint) { + memcpy(session_endpoint, &session->endpoint, sizeof(oc_endpoint_t)); + } free_tcp_session_async_locked(session, notify_session_end); } oc_tcp_adapter_mutex_unlock(); diff --git a/port/windows/tcpadapter.h b/port/windows/tcpadapter.h index 74f6962678..7425672224 100644 --- a/port/windows/tcpadapter.h +++ b/port/windows/tcpadapter.h @@ -33,7 +33,8 @@ void oc_tcp_connectivity_shutdown(ip_context_t *dev); int oc_tcp_send_buffer(ip_context_t *dev, oc_message_t *message, const struct sockaddr_storage *receiver); -bool oc_tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end); +bool oc_tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end, + oc_endpoint_t *session_endpoint); void oc_tcp_adapter_mutex_init(void); diff --git a/security/oc_tls.c b/security/oc_tls.c index 18a033e949..9c8b7cde4f 100644 --- a/security/oc_tls.c +++ b/security/oc_tls.c @@ -540,7 +540,7 @@ oc_tls_free_peer(oc_tls_peer_t *peer, bool inactivity_cb, bool from_reset, #ifdef OC_TCP if (endpoint.flags & TCP) { - oc_connectivity_end_session_v1(&endpoint, false); + oc_connectivity_end_session_v1(&endpoint, false, NULL); } #endif /* OC_TCP */ if (notify_session_end) { @@ -570,14 +570,29 @@ oc_tls_peer_is_doc(const oc_endpoint_t *endpoint) } void -oc_tls_remove_peer(const oc_endpoint_t *endpoint, bool notify_session_end) +oc_tls_remove_peer(const oc_endpoint_t *orig_endpoint, bool notify_session_end) { - oc_tls_peer_t *peer = oc_tls_get_peer(endpoint); - if (peer != NULL) { + oc_endpoint_t endpoint; + oc_endpoint_copy(&endpoint, orig_endpoint); + oc_tls_peer_t *peer = oc_tls_get_peer(&endpoint); + if (peer == NULL) { + tls_drop_endpoint_events(&endpoint); + return; + } + do { oc_tls_free_peer(peer, false, false, notify_session_end); - } else { - tls_drop_endpoint_events(endpoint); +#ifdef OC_TCP + if ((endpoint.flags & TCP) != 0 || endpoint.session_id != 0) { + break; + } +#endif /* OC_TCP */ + peer = oc_tls_get_peer(&endpoint); + } while (peer != NULL); +#ifdef OC_TCP + if ((endpoint.flags & TCP) == 0 && endpoint.session_id == 0) { + tls_drop_endpoint_events(&endpoint); } +#endif /* OC_TCP */ } static void @@ -2284,11 +2299,19 @@ oc_tls_init_context(void) } static void -tls_close_connection(const oc_endpoint_t *endpoint, bool from_reset) +tls_close_connection(const oc_endpoint_t *orig_endpoint, bool from_reset) { - oc_tls_peer_t *peer = oc_tls_get_peer(endpoint); - if (peer != NULL) { + oc_endpoint_t endpoint; + oc_endpoint_copy(&endpoint, orig_endpoint); + oc_tls_peer_t *peer = oc_tls_get_peer(&endpoint); + while (peer != NULL) { oc_tls_close_peer(peer, from_reset); +#ifdef OC_TCP + if ((endpoint.flags & TCP) != 0 || endpoint.session_id != 0) { + break; + } +#endif /* OC_TCP */ + peer = oc_tls_get_peer(&endpoint); } } @@ -2684,6 +2707,12 @@ oc_tls_init_connection(oc_message_t *message) return; } +#ifdef OC_TCP + if ((peer->endpoint.flags & TCP) != 0 && peer->endpoint.session_id == 0) { + peer->endpoint.session_id = oc_tcp_get_new_session_id(); + } +#endif + #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT if ((peer->endpoint.flags & TCP) != 0) { int state = oc_tcp_connect(&peer->endpoint, oc_tls_on_tcp_connect, NULL); @@ -3054,7 +3083,9 @@ close_all_tls_sessions_for_device_reset(size_t device) while (p != NULL) { oc_tls_peer_t *next = p->next; if (p->endpoint.device == device) { - tls_close_connection(&p->endpoint, true); + oc_endpoint_t endpoint; + oc_endpoint_copy(&endpoint, &p->endpoint); + tls_close_connection(&endpoint, true); } p = next; } From 629c3d9bba0c4f195c0cbf343e5455e830ffc2aa Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Fri, 31 May 2024 20:58:06 +0200 Subject: [PATCH 3/4] fixup! tcp: pair connection with the tls peer --- api/oc_client_api.c | 13 +++- api/oc_endpoint.c | 13 +--- api/oc_session_events.c | 6 ++ api/oc_session_events_internal.h | 63 ++++++++++--------- api/oc_tcp.c | 18 +++--- api/oc_tcp_internal.h | 2 +- port/android/tcpadapter.c | 21 ++++--- port/esp32/adapter/src/tcpadapter.c | 27 +++++---- port/linux/tcpsession.c | 94 ++++++++++++++++++++--------- port/linux/tcpsession.h | 17 +++--- port/oc_connectivity_internal.h | 53 +++++++++++----- port/windows/tcpadapter.c | 38 ++++++++---- security/oc_tls.c | 59 +++++++++--------- security/oc_tls_internal.h | 2 +- 14 files changed, 263 insertions(+), 163 deletions(-) diff --git a/api/oc_client_api.c b/api/oc_client_api.c index 7c805e9c45..645ea65c5a 100644 --- a/api/oc_client_api.c +++ b/api/oc_client_api.c @@ -961,16 +961,23 @@ oc_do_ip_discovery_at_endpoint(const char *rt, oc_discovery_handler_t handler, void oc_close_session(const oc_endpoint_t *endpoint) { - if (endpoint->flags & SECURED) { #ifdef OC_SECURITY + if ((endpoint->flags & SECURED) != 0) { oc_tls_close_connection(endpoint); + return; + } #endif /* OC_SECURITY */ - } else if (endpoint->flags & TCP) { #ifdef OC_TCP + if ((endpoint->flags & TCP) != 0) { oc_endpoint_t session_endpoint; while (oc_connectivity_end_session_v1(endpoint, false, &session_endpoint)) { oc_handle_session(&session_endpoint, OC_SESSION_DISCONNECTED); } -#endif /* OC_TCP */ + return; } +#endif /* OC_TCP */ + +#if !defined(OC_TCP) && !defined(OC_SECURITY) + (void)endpoint; +#endif /* !OC_TCP && !OC_SECURITY */ } diff --git a/api/oc_endpoint.c b/api/oc_endpoint.c index 5a126231fb..ff5bd19c24 100644 --- a/api/oc_endpoint.c +++ b/api/oc_endpoint.c @@ -685,7 +685,7 @@ oc_endpoint_compare_session_ids(const oc_endpoint_t *ep1, } return ep1->session_id == ep2->session_id ? 0 : -1; } -#endif +#endif /* OC_TCP */ int oc_endpoint_compare(const oc_endpoint_t *ep1, const oc_endpoint_t *ep2) @@ -711,7 +711,7 @@ oc_endpoint_compare(const oc_endpoint_t *ep1, const oc_endpoint_t *ep2) return -1; } #ifdef OC_IPV4 - else if (ep1->flags & IPV4) { + if (ep1->flags & IPV4) { if (memcmp(ep1->addr.ipv4.address, ep2->addr.ipv4.address, 4) == 0 && ep1->addr.ipv4.port == ep2->addr.ipv4.port) { #ifdef OC_TCP @@ -724,15 +724,6 @@ oc_endpoint_compare(const oc_endpoint_t *ep1, const oc_endpoint_t *ep2) } #endif /* OC_IPV4 */ -#ifdef OC_TCP - else if (ep1->flags & TCP) { - if (memcmp(ep1->addr.ipv6.address, ep2->addr.ipv6.address, 16) == 0 && - ep1->addr.ipv6.port == ep2->addr.ipv6.port) { - return 0; - } - return -1; - } -#endif // TODO: Add support for other endpoint types return -1; } diff --git a/api/oc_session_events.c b/api/oc_session_events.c index 4d19107e20..94ef2e39e4 100644 --- a/api/oc_session_events.c +++ b/api/oc_session_events.c @@ -133,6 +133,9 @@ oc_session_start_event(const oc_endpoint_t *endpoint) return; } + // only a specific session should be connected + assert(endpoint->session_id != 0); + oc_endpoint_t *ep = oc_new_endpoint(); memcpy(ep, endpoint, sizeof(oc_endpoint_t)); ep->next = NULL; @@ -152,6 +155,9 @@ oc_session_end_event(const oc_endpoint_t *endpoint) return; } + // only a specific session should be disconnected + assert(endpoint->session_id != 0); + oc_endpoint_t *ep = oc_new_endpoint(); memcpy(ep, endpoint, sizeof(oc_endpoint_t)); ep->next = NULL; diff --git a/api/oc_session_events_internal.h b/api/oc_session_events_internal.h index 0fa18b6cf7..416f11516b 100644 --- a/api/oc_session_events_internal.h +++ b/api/oc_session_events_internal.h @@ -22,11 +22,22 @@ #include "oc_endpoint.h" #include "oc_session_events.h" #include "util/oc_process.h" +#include "util/oc_features.h" #ifdef __cplusplus extern "C" { #endif +/** + * @brief Invoke all session handlers associated with given endpoint + * + * @param endpoint endpoint of the session event (cannot be NULLL) + * @param state new session state + */ +void oc_handle_session(const oc_endpoint_t *endpoint, oc_session_state_t state); + +#ifdef OC_SESSION_EVENTS + #define OC_SESSION_EVENT_API_V0 (0) #define OC_SESSION_EVENT_API_V1 (1) @@ -61,6 +72,30 @@ typedef struct oc_session_event_cb void *user_data; } oc_session_event_cb_t; +/** + * @brief Find first session event callback matching the input parameters. + * + * @param cb handler to match + * @param user_data match user data (only valid for v1 handlers) + * @param ignore_user_data ignore user data for match (only valid for v1 + * handlers) + * @return oc_session_event_cb_t* first matched session event callback + * @return NULL if no match is found + */ +oc_session_event_cb_t *oc_session_event_callback_find( + session_event_versioned_handler_t cb, const void *user_data, + bool ignore_user_data); + +/** + * @brief Remove all previously registered session event notifications + * callbacks. + */ +void oc_session_events_remove_all_callbacks(void); + +#endif /* OC_SESSION_EVENTS */ + +#ifdef OC_TCP + OC_PROCESS_NAME(oc_session_events); /** @@ -77,14 +112,6 @@ void oc_session_start_event(const oc_endpoint_t *endpoint); */ void oc_session_end_event(const oc_endpoint_t *endpoint); -/** - * @brief Invoke all session handlers associated with given endpoint - * - * @param endpoint endpoint of the session event (cannot be NULLL) - * @param state new session state - */ -void oc_handle_session(const oc_endpoint_t *endpoint, oc_session_state_t state); - /** * @brief Check if session events are currently in the process of being * disconnected. @@ -95,25 +122,7 @@ void oc_handle_session(const oc_endpoint_t *endpoint, oc_session_state_t state); */ bool oc_session_events_disconnect_is_ongoing(void); -/** - * @brief Find first session event callback matching the input parameters. - * - * @param cb handler to match - * @param user_data match user data (only valid for v1 handlers) - * @param ignore_user_data ignore user data for match (only valid for v1 - * handlers) - * @return oc_session_event_cb_t* first matched session event callback - * @return NULL if no match is found - */ -oc_session_event_cb_t *oc_session_event_callback_find( - session_event_versioned_handler_t cb, const void *user_data, - bool ignore_user_data); - -/** - * @brief Remove all previously registered session event notifications - * callbacks. - */ -void oc_session_events_remove_all_callbacks(void); +#endif /* OC_TCP */ #ifdef __cplusplus } diff --git a/api/oc_tcp.c b/api/oc_tcp.c index dc56566030..17c1a4fa87 100644 --- a/api/oc_tcp.c +++ b/api/oc_tcp.c @@ -32,15 +32,6 @@ #endif /* OC_OSCORE */ #endif /* OC_SECURITY */ -static OC_ATOMIC_UINT32_T g_tcp_session_id = 0; - -uint32_t -oc_tcp_get_new_session_id(void) -{ - uint32_t v = OC_ATOMIC_INCREMENT32(g_tcp_session_id); - return (v == 0) ? OC_ATOMIC_INCREMENT32(g_tcp_session_id) : v; -} - #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT #include "port/oc_allocator_internal.h" @@ -96,6 +87,15 @@ oc_tcp_on_connect_event_free(oc_tcp_on_connect_event_t *event) #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ +static OC_ATOMIC_UINT32_T g_tcp_session_id = 0; + +uint32_t +oc_tcp_get_new_session_id(void) +{ + uint32_t v = OC_ATOMIC_INCREMENT32(g_tcp_session_id); + return (v == 0) ? OC_ATOMIC_INCREMENT32(g_tcp_session_id) : v; +} + bool oc_tcp_is_valid_header(const uint8_t *data, size_t data_size, bool is_tls) { diff --git a/api/oc_tcp_internal.h b/api/oc_tcp_internal.h index 9248280f26..2c9923de28 100644 --- a/api/oc_tcp_internal.h +++ b/api/oc_tcp_internal.h @@ -23,10 +23,10 @@ #ifdef OC_TCP -#include #include "messaging/coap/constants.h" #include "port/oc_connectivity.h" #include "oc_endpoint.h" +#include #ifdef __cplusplus extern "C" { diff --git a/port/android/tcpadapter.c b/port/android/tcpadapter.c index 23cbb3da5c..c4d805ef91 100644 --- a/port/android/tcpadapter.c +++ b/port/android/tcpadapter.c @@ -214,7 +214,7 @@ free_tcp_session(tcp_session_t *session, bool notify_session_end) static int add_new_session(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, - tcp_csm_state_t state) + uint32_t session_id, tcp_csm_state_t state) { long if_index = get_interface_index(sock); if (if_index == -1) { @@ -235,14 +235,16 @@ add_new_session(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->endpoint.next = NULL; session->sock = sock; session->csm_state = state; - if (session->endpoint.session_id == 0) { + if (session_id == 0) { session->endpoint.session_id = oc_tcp_get_new_session_id(); + } else { + session->endpoint.session_id = session_id; } oc_list_add(session_list, session); - if (!(endpoint->flags & SECURED)) { - oc_session_start_event(endpoint); + if ((session->endpoint.flags & SECURED) == 0) { + oc_session_start_event(&session->endpoint); } OC_DBG("recorded new TCP session"); @@ -280,7 +282,8 @@ accept_new_session(ip_context_t *dev, int fd, fd_set *setfds, FD_CLR(fd, setfds); - if (add_new_session(new_socket, dev, endpoint, CSM_NONE) < 0) { + if (add_new_session(new_socket, dev, endpoint, /*session_id*/ 0, CSM_NONE) < + 0) { OC_ERR("could not record new TCP session"); close(new_socket); return -1; @@ -495,6 +498,7 @@ get_session_socket(const oc_endpoint_t *endpoint) static int initiate_new_session(ip_context_t *dev, oc_endpoint_t *endpoint, + uint32_t session_id, const struct sockaddr_storage *receiver) { int sock = -1; @@ -517,7 +521,7 @@ initiate_new_session(ip_context_t *dev, oc_endpoint_t *endpoint, OC_DBG("successfully initiated TCP connection"); - if (add_new_session(sock, dev, endpoint, CSM_SENT) < 0) { + if (add_new_session(sock, dev, endpoint, session_id, CSM_SENT) < 0) { OC_ERR("could not record new TCP session"); close(sock); return -1; @@ -549,8 +553,9 @@ oc_tcp_send_buffer(ip_context_t *dev, oc_message_t *message, OC_ERR("connection was closed"); goto oc_tcp_send_buffer_done; } - if ((send_sock = initiate_new_session(dev, &message->endpoint, receiver)) < - 0) { + if ((send_sock = + initiate_new_session(dev, &message->endpoint, + message->endpoint.session_id, receiver)) < 0) { OC_ERR("could not initiate new TCP session"); goto oc_tcp_send_buffer_done; } diff --git a/port/esp32/adapter/src/tcpadapter.c b/port/esp32/adapter/src/tcpadapter.c index 49e8788a07..577d36f040 100644 --- a/port/esp32/adapter/src/tcpadapter.c +++ b/port/esp32/adapter/src/tcpadapter.c @@ -32,16 +32,16 @@ #include "port/oc_tcp_socket_internal.h" #include "tcpadapter.h" #include "util/oc_memb.h" +#include "vfs_pipe.h" #include #include #include +#include #include -// #include -#include "esp_netif.h" -#include "vfs_pipe.h" #include #include +#include #include #include @@ -184,7 +184,7 @@ free_tcp_session(tcp_session_t *session, bool notify_session_end) static int add_new_session(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, - tcp_csm_state_t state) + uint32_t session_id, tcp_csm_state_t state) { int if_index = get_interface_index(sock); if (if_index < 0) { @@ -205,14 +205,16 @@ add_new_session(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->endpoint.next = NULL; session->sock = sock; session->csm_state = state; - if (session->endpoint.session_id == 0) { + if (session_id == 0) { session->endpoint.session_id = oc_tcp_get_new_session_id(); + } else { + session->endpoint.session_id = session_id; } oc_list_add(session_list, session); - if (!(endpoint->flags & SECURED)) { - oc_session_start_event(endpoint); + if ((session->endpoint.flags & SECURED) == 0) { + oc_session_start_event(&session->endpoint); } OC_DBG("recorded new TCP session"); @@ -251,7 +253,8 @@ accept_new_session(ip_context_t *dev, int fd, fd_set *setfds, FD_CLR(fd, setfds); - if (add_new_session(new_socket, dev, endpoint, CSM_NONE) < 0) { + if (add_new_session(new_socket, dev, endpoint, /*session_id*/ 0, CSM_NONE) < + 0) { OC_ERR("could not record new TCP session"); close(new_socket); return -1; @@ -468,6 +471,7 @@ get_session_socket(const oc_endpoint_t *endpoint) static int initiate_new_session(ip_context_t *dev, oc_endpoint_t *endpoint, + uint32_t session_id, const struct sockaddr_storage *receiver) { int sock = -1; @@ -490,7 +494,7 @@ initiate_new_session(ip_context_t *dev, oc_endpoint_t *endpoint, OC_DBG("successfully initiated TCP connection"); - if (add_new_session(sock, dev, endpoint, CSM_SENT) < 0) { + if (add_new_session(sock, dev, endpoint, session_id, CSM_SENT) < 0) { OC_ERR("could not record new TCP session"); close(sock); return -1; @@ -522,8 +526,9 @@ oc_tcp_send_buffer(ip_context_t *dev, oc_message_t *message, OC_ERR("connection was closed"); goto oc_tcp_send_buffer_done; } - if ((send_sock = initiate_new_session(dev, &message->endpoint, receiver)) < - 0) { + if ((send_sock = + initiate_new_session(dev, &message->endpoint, + message->endpoint.session_id, receiver)) < 0) { OC_ERR("could not initiate new TCP session"); goto oc_tcp_send_buffer_done; } diff --git a/port/linux/tcpsession.c b/port/linux/tcpsession.c index 97c7f72c8b..5d535f11c1 100644 --- a/port/linux/tcpsession.c +++ b/port/linux/tcpsession.c @@ -233,7 +233,7 @@ log_free_session(oc_endpoint_t *endpoint, int sock) static tcp_session_t * add_new_session_locked(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, - tcp_csm_state_t state) + uint32_t session_id, tcp_csm_state_t state) { long if_index = get_interface_index(sock); if (if_index < 0) { @@ -255,8 +255,10 @@ add_new_session_locked(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->sock = sock; session->csm_state = state; session->notify_session_end = true; - if (session->endpoint.session_id == 0) { + if (session_id == 0) { session->endpoint.session_id = oc_tcp_get_new_session_id(); + } else { + session->endpoint.session_id = session_id; } oc_list_add(g_session_list, session); @@ -302,7 +304,8 @@ accept_new_session_locked(ip_context_t *dev, int fd, fd_set *setfds, #endif /* !OC_IPV4 */ } - if (add_new_session_locked(new_socket, dev, endpoint, CSM_NONE) == NULL) { + if (add_new_session_locked(new_socket, dev, endpoint, /*session_id*/ 0, + CSM_NONE) == NULL) { OC_ERR("could not record new TCP session"); close(new_socket); return -1; @@ -552,10 +555,10 @@ find_session_by_endpoint_locked(const oc_endpoint_t *endpoint) static tcp_session_t * tcp_create_session_locked(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, - bool signal) + uint32_t session_id, bool signal) { tcp_session_t *session = - add_new_session_locked(sock, dev, endpoint, CSM_SENT); + add_new_session_locked(sock, dev, endpoint, session_id, CSM_SENT); if (session == NULL) { OC_ERR("could not record new TCP session"); return NULL; @@ -598,6 +601,7 @@ add_new_waiting_session_locked(int sock, ip_context_t *dev, ws->dev = dev; memcpy(&ws->endpoint, endpoint, sizeof(oc_endpoint_t)); + ws->endpoint.session_id = oc_tcp_get_new_session_id(); ws->endpoint.next = NULL; ws->sock = sock; OC_LIST_STRUCT_INIT(ws, messages); @@ -679,8 +683,9 @@ tcp_connect_locked(ip_context_t *dev, oc_endpoint_t *endpoint, oc_tcp_socket_t cs = oc_tcp_socket_connect(endpoint, receiver); if (cs.state == OC_TCP_SOCKET_STATE_CONNECTED) { OC_DBG("successfully initiated TCP connection"); - s = tcp_create_session_locked(cs.fd, dev, endpoint, true); + s = tcp_create_session_locked(cs.fd, dev, endpoint, /*session_id*/ 0, true); if (s != NULL) { + res.session = s; res.created = true; return res; } @@ -1115,8 +1120,8 @@ tcp_try_connect_waiting_session_locked(tcp_waiting_session_t *ws, int *err) return false; } - tcp_session_t *s = - tcp_create_session_locked(ws->sock, ws->dev, &ws->endpoint, false); + tcp_session_t *s = tcp_create_session_locked(ws->sock, ws->dev, &ws->endpoint, + ws->endpoint.session_id, false); if (s == NULL) { return false; } @@ -1190,8 +1195,8 @@ tcp_retry_waiting_session_locked(tcp_waiting_session_t *ws, oc_tcp_socket_t cs = oc_tcp_socket_connect(&ws->endpoint, NULL); if (cs.state == OC_TCP_SOCKET_STATE_CONNECTED) { OC_DBG("successfully initiated TCP connection"); - tcp_session_t *s = - tcp_create_session_locked(cs.fd, ws->dev, &ws->endpoint, false); + tcp_session_t *s = tcp_create_session_locked( + cs.fd, ws->dev, &ws->endpoint, ws->endpoint.session_id, false); if (s == NULL) { OC_ERR("cannot allocate ongoing TCP connection"); return -1; @@ -1301,40 +1306,71 @@ tcp_process_waiting_sessions(fd_set *fds) return ret; } -static int -oc_tcp_connect_to_endpoint(ip_context_t *dev, oc_endpoint_t *endpoint, - on_tcp_connect_t on_tcp_connect, - void *on_tcp_connect_data) +static oc_tcp_connect_result_t +tcp_connect_to_endpoint(ip_context_t *dev, oc_endpoint_t *endpoint, + on_tcp_connect_t on_tcp_connect, + void *on_tcp_connect_data) { struct sockaddr_storage receiver = oc_socket_get_address(endpoint); pthread_mutex_lock(&g_mutex); tcp_connect_result_t res = tcp_connect_locked( dev, endpoint, &receiver, on_tcp_connect, on_tcp_connect_data); + bool is_connected = false; + uint32_t session_id = 0; + if (res.session != NULL) { + is_connected = true; + session_id = res.session->endpoint.session_id; + } else if (res.waiting_session != NULL) { + session_id = res.waiting_session->endpoint.session_id; + } pthread_mutex_unlock(&g_mutex); - if (res.session == NULL && res.waiting_session == NULL) { - return OC_TCP_SOCKET_ERROR; + if (session_id == 0) { + return (oc_tcp_connect_result_t){ + .error = OC_TCP_SOCKET_ERROR, + }; } - bool is_connected = res.session != NULL; if (!res.created) { - return is_connected ? OC_TCP_SOCKET_ERROR_EXISTS_CONNECTED - : OC_TCP_SOCKET_ERROR_EXISTS_CONNECTING; - } - - return is_connected ? OC_TCP_SOCKET_STATE_CONNECTED - : OC_TCP_SOCKET_STATE_CONNECTING; + oc_tcp_socket_error_t err = is_connected + ? OC_TCP_SOCKET_ERROR_EXISTS_CONNECTED + : OC_TCP_SOCKET_ERROR_EXISTS_CONNECTING; + return (oc_tcp_connect_result_t){ + .session_id = session_id, + .error = err, + }; + } + + oc_tcp_socket_state_t state = is_connected ? OC_TCP_SOCKET_STATE_CONNECTED + : OC_TCP_SOCKET_STATE_CONNECTING; + return (oc_tcp_connect_result_t){ + .state = state, + .session_id = session_id, + }; } -int -oc_tcp_connect(oc_endpoint_t *endpoint, on_tcp_connect_t on_tcp_connect, - void *on_tcp_connect_data) +oc_tcp_connect_result_t +oc_tcp_connect_to_endpoint(oc_endpoint_t *endpoint, + on_tcp_connect_t on_tcp_connect, + void *on_tcp_connect_data) { + assert((endpoint->flags & TCP) != 0); ip_context_t *dev = oc_get_ip_context_for_device(endpoint->device); if (dev == NULL) { OC_ERR("cannot find ip-context for device(%zu)", endpoint->device); - return -1; + return (oc_tcp_connect_result_t){ + .error = -1, + }; } - return oc_tcp_connect_to_endpoint(dev, endpoint, on_tcp_connect, - on_tcp_connect_data); + return tcp_connect_to_endpoint(dev, endpoint, on_tcp_connect, + on_tcp_connect_data); +} + +int +oc_tcp_connect(oc_endpoint_t *endpoint, on_tcp_connect_t on_tcp_connect, + void *on_tcp_connect_data) +{ + oc_tcp_connect_result_t ret = + oc_tcp_connect_to_endpoint(endpoint, on_tcp_connect, on_tcp_connect_data); + return ret.error != 0 ? ret.error : (int)ret.state; } #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ diff --git a/port/linux/tcpsession.h b/port/linux/tcpsession.h index 50100b69b0..e26d684c42 100644 --- a/port/linux/tcpsession.h +++ b/port/linux/tcpsession.h @@ -17,20 +17,22 @@ * ****************************************************************************/ -#ifndef TCP_SESION_H -#define TCP_SESION_H +#ifndef TCP_SESSION_H +#define TCP_SESSION_H + +#include "util/oc_features.h" + +#ifdef OC_TCP #include "port/oc_clock.h" #include "port/oc_connectivity.h" -#include "util/oc_features.h" #include "ipcontext.h" #include "oc_endpoint.h" #include "tcpcontext.h" + #include #include -#ifdef OC_TCP - #ifdef __cplusplus extern "C" { #endif @@ -106,7 +108,7 @@ adapter_receive_state_t tcp_receive_message(ip_context_t *dev, fd_set *fds, * deallocated (if it exists). */ bool tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end, - oc_endpoint_t *session_endpoint); + oc_endpoint_t *session_endpoint) OC_NONNULL(1); /** * @brief Handle data received on the signal pipe. @@ -119,6 +121,7 @@ void tcp_session_handle_signal(void); void tcp_session_shutdown(const ip_context_t *dev); #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT + /** * @brief Iterate over TCP sessions waiting for connection. Deallocate expired * sessions. Retry the connection process for sessions that haven't reached the @@ -155,4 +158,4 @@ bool tcp_process_waiting_sessions(fd_set *fds); #endif /* OC_TCP */ -#endif /* TCP_SESION_H */ +#endif /* TCP_SESSION_H */ diff --git a/port/oc_connectivity_internal.h b/port/oc_connectivity_internal.h index 2f10d3159b..2438489849 100644 --- a/port/oc_connectivity_internal.h +++ b/port/oc_connectivity_internal.h @@ -25,6 +25,7 @@ #include "oc_network_events.h" #include "oc_session_events.h" #include "port/oc_connectivity.h" +#include "util/oc_compiler.h" #include "util/oc_features.h" #include #include @@ -64,20 +65,6 @@ void oc_connectivity_shutdown(size_t device); */ int oc_send_buffer2(oc_message_t *message, bool queue); -#ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT -typedef struct -{ - uint8_t max_count; ///< maximal number of retries for opening a single TCP - /// connection (default: 5) - uint16_t timeout; ///< timeout of a single retry in seconds (default: 5) -} oc_tcp_connect_retry_t; - -#define OC_TCP_CONNECT_RETRY_MAX_COUNT 5 -#define OC_TCP_CONNECT_RETRY_TIMEOUT 5 - -void oc_tcp_set_connect_retry(uint8_t max_count, uint16_t timeout); -#endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ - #ifdef OC_NETWORK_MONITOR /** * @brief the callback function for an network change @@ -98,8 +85,10 @@ void handle_session_event_callback(const oc_endpoint_t *endpoint, oc_session_state_t state); #endif /* OC_SESSION_EVENTS */ +#ifdef OC_TCP + /** - * @brief end TCP session for the specific endpoint. + * @brief End TCP session for the specific endpoint. * * @param endpoint the endpoint to close the session for * @param notify_session_end send the notification about the disconnection @@ -109,7 +98,39 @@ void handle_session_event_callback(const oc_endpoint_t *endpoint, */ bool oc_connectivity_end_session_v1(const oc_endpoint_t *endpoint, bool notify_session_end, - oc_endpoint_t *session_endpoint); + oc_endpoint_t *session_endpoint) + OC_NONNULL(1); + +#ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT + +typedef struct +{ + uint8_t max_count; ///< maximal number of retries for opening a single TCP + /// connection (default: 5) + uint16_t timeout; ///< timeout of a single retry in seconds (default: 5) +} oc_tcp_connect_retry_t; + +#define OC_TCP_CONNECT_RETRY_MAX_COUNT 5 +#define OC_TCP_CONNECT_RETRY_TIMEOUT 5 + +/** @brief Connect to endpoint and return connection state and session id */ +typedef struct +{ + uint32_t session_id; + oc_tcp_socket_state_t state; + int error; +} oc_tcp_connect_result_t; + +/** @brief Connect to TCP endpoint and return connection state and session id */ +oc_tcp_connect_result_t oc_tcp_connect_to_endpoint( + oc_endpoint_t *endpoint, on_tcp_connect_t on_tcp_connect, + void *on_tcp_connect_data) OC_NONNULL(1); + +void oc_tcp_set_connect_retry(uint8_t max_count, uint16_t timeout); + +#endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ + +#endif /* OC_TCP */ #ifdef __cplusplus } diff --git a/port/windows/tcpadapter.c b/port/windows/tcpadapter.c index 1af90757db..0ae0ae622f 100644 --- a/port/windows/tcpadapter.c +++ b/port/windows/tcpadapter.c @@ -140,8 +140,9 @@ get_interface_index(SOCKET sock) struct sockaddr_in6 *a = (struct sockaddr_in6 *)&iface->addr; struct sockaddr_in6 *b = (struct sockaddr_in6 *)&addr; if (memcmp(a->sin6_addr.s6_addr, b->sin6_addr.s6_addr, 16) == 0) { + long if_index = iface->if_index; free_network_addresses(ifaddr_list); - return iface->if_index; + return if_index; } } #ifdef OC_IPV4 @@ -149,8 +150,9 @@ get_interface_index(SOCKET sock) struct sockaddr_in *a = (struct sockaddr_in *)&iface->addr; struct sockaddr_in *b = (struct sockaddr_in *)&addr; if (a->sin_addr.s_addr == b->sin_addr.s_addr) { + long if_index = iface->if_index; free_network_addresses(ifaddr_list); - return iface->if_index; + return if_index; } } #endif /* OC_IPV4 */ @@ -162,7 +164,8 @@ get_interface_index(SOCKET sock) static void free_tcp_session_locked(tcp_session_t *session, oc_endpoint_t *endpoint, - SOCKET *sock, HANDLE *sock_event) + SOCKET *sock, HANDLE *sock_event, + bool *notify_session_end) { oc_tcp_adapter_mutex_lock(); oc_list_remove(session_list, session); @@ -170,6 +173,9 @@ free_tcp_session_locked(tcp_session_t *session, oc_endpoint_t *endpoint, sizeof(session->endpoint)); *sock = session->sock; *sock_event = session->sock_event; + if (notify_session_end != NULL) { + *notify_session_end = session->notify_session_end; + } oc_memb_free(&tcp_session_s, session); oc_tcp_adapter_mutex_unlock(); @@ -182,11 +188,12 @@ free_tcp_session(tcp_session_t *session) oc_endpoint_t endpoint; SOCKET sock; HANDLE sock_event; - free_tcp_session_locked(session, &endpoint, &sock, &sock_event); + bool notify_session_end; + free_tcp_session_locked(session, &endpoint, &sock, &sock_event, + ¬ify_session_end); WSACloseEvent(sock_event); closesocket(sock); - if (!oc_session_events_disconnect_is_ongoing() && - session->notify_session_end) { + if (!oc_session_events_disconnect_is_ongoing() && notify_session_end) { oc_session_end_event(&endpoint); } @@ -208,7 +215,7 @@ free_tcp_session_async_locked(tcp_session_t *session, bool notify_session_end) static int add_new_session_locked(SOCKET sock, ip_context_t *dev, oc_endpoint_t *endpoint, - tcp_csm_state_t state) + uint32_t session_id, tcp_csm_state_t state) { HANDLE sock_event = WSACreateEvent(); if (WSAEventSelect(sock, sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR) { @@ -238,14 +245,16 @@ add_new_session_locked(SOCKET sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->csm_state = state; session->sock_event = sock_event; session->notify_session_end = true; - if (session->endpoint.session_id == 0) { + if (session_id == 0) { session->endpoint.session_id = oc_tcp_get_new_session_id(); + } else { + session->endpoint.session_id = session_id; } oc_list_add(session_list, session); - if (!(endpoint->flags & SECURED)) { - oc_session_start_event(endpoint); + if ((session->endpoint.flags & SECURED) == 0) { + oc_session_start_event(&session->endpoint); } OC_DBG("recorded new TCP session"); @@ -283,7 +292,8 @@ accept_new_session(ip_context_t *dev, SOCKET fd, oc_endpoint_t *endpoint) } oc_tcp_adapter_mutex_lock(); - if (add_new_session_locked(new_socket, dev, endpoint, CSM_NONE) < 0) { + if (add_new_session_locked(new_socket, dev, endpoint, /*session_id*/ 0, + CSM_NONE) < 0) { oc_tcp_adapter_mutex_unlock(); OC_ERR("could not record new TCP session"); closesocket(new_socket); @@ -351,6 +361,7 @@ get_session_socket_locked(oc_endpoint_t *endpoint) static SOCKET initiate_new_session_locked(ip_context_t *dev, oc_endpoint_t *endpoint, + uint32_t session_id, const struct sockaddr_storage *receiver) { SOCKET sock = INVALID_SOCKET; @@ -374,7 +385,7 @@ initiate_new_session_locked(ip_context_t *dev, oc_endpoint_t *endpoint, OC_DBG("successfully initiated TCP connection"); - if (add_new_session_locked(sock, dev, endpoint, CSM_SENT) < 0) { + if (add_new_session_locked(sock, dev, endpoint, session_id, CSM_SENT) < 0) { OC_ERR("could not record new TCP session"); closesocket(sock); return INVALID_SOCKET; @@ -403,6 +414,7 @@ oc_tcp_send_buffer(ip_context_t *dev, oc_message_t *message, goto oc_tcp_send_buffer_done; } if ((send_sock = initiate_new_session_locked(dev, &message->endpoint, + message->endpoint.session_id, receiver)) == INVALID_SOCKET) { OC_ERR("could not initiate new TCP session"); goto oc_tcp_send_buffer_done; @@ -975,7 +987,7 @@ oc_tcp_connectivity_shutdown(ip_context_t *dev) oc_endpoint_t endpoint; SOCKET sock; HANDLE sock_event; - free_tcp_session_locked(session, &endpoint, &sock, &sock_event); + free_tcp_session_locked(session, &endpoint, &sock, &sock_event, NULL); WSACloseEvent(sock_event); closesocket(sock); if (!oc_session_events_disconnect_is_ongoing()) { diff --git a/security/oc_tls.c b/security/oc_tls.c index 9c8b7cde4f..58df3f2e8f 100644 --- a/security/oc_tls.c +++ b/security/oc_tls.c @@ -570,27 +570,27 @@ oc_tls_peer_is_doc(const oc_endpoint_t *endpoint) } void -oc_tls_remove_peer(const oc_endpoint_t *orig_endpoint, bool notify_session_end) +oc_tls_remove_peer(const oc_endpoint_t *endpoint, bool notify_session_end) { - oc_endpoint_t endpoint; - oc_endpoint_copy(&endpoint, orig_endpoint); - oc_tls_peer_t *peer = oc_tls_get_peer(&endpoint); + oc_endpoint_t ep_copy; + oc_endpoint_copy(&ep_copy, endpoint); + oc_tls_peer_t *peer = oc_tls_get_peer(&ep_copy); if (peer == NULL) { - tls_drop_endpoint_events(&endpoint); + tls_drop_endpoint_events(&ep_copy); return; } do { oc_tls_free_peer(peer, false, false, notify_session_end); #ifdef OC_TCP - if ((endpoint.flags & TCP) != 0 || endpoint.session_id != 0) { + if ((ep_copy.flags & TCP) != 0 || ep_copy.session_id != 0) { break; } #endif /* OC_TCP */ - peer = oc_tls_get_peer(&endpoint); + peer = oc_tls_get_peer(&ep_copy); } while (peer != NULL); #ifdef OC_TCP - if ((endpoint.flags & TCP) == 0 && endpoint.session_id == 0) { - tls_drop_endpoint_events(&endpoint); + if ((ep_copy.flags & TCP) == 0 && ep_copy.session_id == 0) { + tls_drop_endpoint_events(&ep_copy); } #endif /* OC_TCP */ } @@ -2299,19 +2299,19 @@ oc_tls_init_context(void) } static void -tls_close_connection(const oc_endpoint_t *orig_endpoint, bool from_reset) +tls_close_connection(const oc_endpoint_t *endpoint, bool from_reset) { - oc_endpoint_t endpoint; - oc_endpoint_copy(&endpoint, orig_endpoint); - oc_tls_peer_t *peer = oc_tls_get_peer(&endpoint); + oc_endpoint_t ep_copy; + oc_endpoint_copy(&ep_copy, endpoint); + oc_tls_peer_t *peer = oc_tls_get_peer(&ep_copy); while (peer != NULL) { oc_tls_close_peer(peer, from_reset); #ifdef OC_TCP - if ((endpoint.flags & TCP) != 0 || endpoint.session_id != 0) { + if ((ep_copy.flags & TCP) != 0 || ep_copy.session_id != 0) { break; } #endif /* OC_TCP */ - peer = oc_tls_get_peer(&endpoint); + peer = oc_tls_get_peer(&ep_copy); } } @@ -2708,22 +2708,26 @@ oc_tls_init_connection(oc_message_t *message) } #ifdef OC_TCP - if ((peer->endpoint.flags & TCP) != 0 && peer->endpoint.session_id == 0) { - peer->endpoint.session_id = oc_tcp_get_new_session_id(); - } -#endif + if ((peer->endpoint.flags & TCP) != 0) { +#ifndef OC_HAS_FEATURE_TCP_ASYNC_CONNECT + if (peer->endpoint.session_id == 0) { + peer->endpoint.session_id = oc_tcp_get_new_session_id(); + } +#endif /* !OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT - if ((peer->endpoint.flags & TCP) != 0) { - int state = oc_tcp_connect(&peer->endpoint, oc_tls_on_tcp_connect, NULL); - if (state == OC_TCP_SOCKET_STATE_CONNECTED || - state == OC_TCP_SOCKET_ERROR_EXISTS_CONNECTED) { + oc_tcp_connect_result_t res = + oc_tcp_connect_to_endpoint(&peer->endpoint, oc_tls_on_tcp_connect, NULL); + if (res.state == OC_TCP_SOCKET_STATE_CONNECTED || + res.error == OC_TCP_SOCKET_ERROR_EXISTS_CONNECTED) { + peer->endpoint.session_id = res.session_id; oc_tls_handshake(peer); oc_message_unref(message); return; } - if (state == OC_TCP_SOCKET_STATE_CONNECTING || - state == OC_TCP_SOCKET_ERROR_EXISTS_CONNECTING) { + if (res.state == OC_TCP_SOCKET_STATE_CONNECTING || + res.error == OC_TCP_SOCKET_ERROR_EXISTS_CONNECTING) { + peer->endpoint.session_id = res.session_id; // just wait for connection to be established; oc_tls_handshake or // oc_tls_free_peer will be called from oc_tls_on_tcp_connect oc_message_unref(message); @@ -2731,12 +2735,13 @@ oc_tls_init_connection(oc_message_t *message) } OC_ERR( "oc_tls_init_connection: oc_tcp_connect returns unexpected state: %d", - state); + res.state); oc_tls_free_peer(peer, false, false, true); oc_message_unref(message); return; - } #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ + } +#endif /* OC_TCP */ oc_tls_handshake(peer); oc_message_unref(message); } diff --git a/security/oc_tls_internal.h b/security/oc_tls_internal.h index 3af3eb5c8a..592f68c554 100644 --- a/security/oc_tls_internal.h +++ b/security/oc_tls_internal.h @@ -160,7 +160,7 @@ oc_tls_pki_verification_params_t oc_tls_peer_pki_default_verification_params( * @brief Remove and deallocate the peer for the endpoint. * * @param endpoint the endpoint - * @param notify_session_end notify session end event + * @param notify_session_end send session end notification */ void oc_tls_remove_peer(const oc_endpoint_t *endpoint, bool notify_session_end); From ff1c658592a1ee6aa5bbc0b9f0470ae94a4b9a77 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Sat, 1 Jun 2024 15:58:45 +0200 Subject: [PATCH 4/4] fixup! tcp: pair connection with the tls peer --- port/android/tcpadapter.c | 38 ++++++++++++++---- port/esp32/adapter/src/tcpadapter.c | 38 ++++++++++++++---- port/linux/tcpsession.c | 60 +++++++++++++++++++++++++---- port/oc_connectivity_internal.h | 11 ++++++ port/unittest/connectivitytest.cpp | 37 +++++++++++++++++- port/windows/tcpadapter.c | 42 ++++++++++++++++---- 6 files changed, 197 insertions(+), 29 deletions(-) diff --git a/port/android/tcpadapter.c b/port/android/tcpadapter.c index c4d805ef91..ccb81ec61b 100644 --- a/port/android/tcpadapter.c +++ b/port/android/tcpadapter.c @@ -28,6 +28,7 @@ #include "oc_endpoint.h" #include "oc_session_events.h" #include "port/oc_assert.h" +#include "port/oc_connectivity_internal.h" #include "port/oc_log_internal.h" #include "port/oc_tcp_socket_internal.h" #include "tcpadapter.h" @@ -228,18 +229,16 @@ add_new_session(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, return -1; } - endpoint->interface_index = (unsigned)if_index; - session->dev = dev; + endpoint->interface_index = (unsigned)if_index; + if (session_id == 0) { + session_id = oc_tcp_get_new_session_id(); + } + endpoint->session_id = session_id; memcpy(&session->endpoint, endpoint, sizeof(oc_endpoint_t)); session->endpoint.next = NULL; session->sock = sock; session->csm_state = state; - if (session_id == 0) { - session->endpoint.session_id = oc_tcp_get_new_session_id(); - } else { - session->endpoint.session_id = session_id; - } oc_list_add(session_list, session); @@ -315,6 +314,22 @@ find_session_by_endpoint(const oc_endpoint_t *endpoint) return session; } +static tcp_session_t * +find_session_by_id(uint32_t session_id) +{ + tcp_session_t *session = oc_list_head(session_list); + while (session != NULL && session->endpoint.session_id != session_id) { + session = session->next; + } + + if (!session) { + OC_DBG("could not find ongoing TCP session for session id %d", session_id); + return NULL; + } + OC_DBG("found TCP session for session id %d", session_id); + return session; +} + static tcp_session_t * get_ready_to_read_session(fd_set *setfds) { @@ -796,6 +811,15 @@ oc_tcp_connection_state(const oc_endpoint_t *endpoint) return -1; } +int +oc_tcp_session_state(uint32_t session_id) +{ + if (find_session_by_id(session_id) != NULL) { + return OC_TCP_SOCKET_STATE_CONNECTED; + } + return -1; +} + tcp_csm_state_t oc_tcp_get_csm_state(const oc_endpoint_t *endpoint) { diff --git a/port/esp32/adapter/src/tcpadapter.c b/port/esp32/adapter/src/tcpadapter.c index 577d36f040..b07c29e2ca 100644 --- a/port/esp32/adapter/src/tcpadapter.c +++ b/port/esp32/adapter/src/tcpadapter.c @@ -28,6 +28,7 @@ #include "oc_endpoint.h" #include "oc_session_events.h" #include "port/oc_assert.h" +#include "port/oc_connectivity_internal.h" #include "port/oc_log_internal.h" #include "port/oc_tcp_socket_internal.h" #include "tcpadapter.h" @@ -198,18 +199,16 @@ add_new_session(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, return -1; } - endpoint->interface_index = (unsigned)if_index; - session->dev = dev; + endpoint->interface_index = (unsigned)if_index; + if (session_id == 0) { + session_id = oc_tcp_get_new_session_id(); + } + endpoint->session_id = session_id; memcpy(&session->endpoint, endpoint, sizeof(oc_endpoint_t)); session->endpoint.next = NULL; session->sock = sock; session->csm_state = state; - if (session_id == 0) { - session->endpoint.session_id = oc_tcp_get_new_session_id(); - } else { - session->endpoint.session_id = session_id; - } oc_list_add(session_list, session); @@ -286,6 +285,22 @@ find_session_by_endpoint(const oc_endpoint_t *endpoint) return session; } +static tcp_session_t * +find_session_by_id(uint32_t session_id) +{ + tcp_session_t *session = oc_list_head(session_list); + while (session != NULL && session->endpoint.session_id != session_id) { + session = session->next; + } + + if (!session) { + OC_DBG("could not find ongoing TCP session for session id %d", session_id); + return NULL; + } + OC_DBG("found TCP session for session id %d", session_id); + return session; +} + static tcp_session_t * get_ready_to_read_session(fd_set *setfds) { @@ -756,6 +771,15 @@ oc_tcp_connection_state(const oc_endpoint_t *endpoint) return -1; } +int +oc_tcp_session_state(uint32_t session_id) +{ + if (find_session_by_id(session_id) != NULL) { + return OC_TCP_SOCKET_STATE_CONNECTED; + } + return -1; +} + tcp_csm_state_t oc_tcp_get_csm_state(const oc_endpoint_t *endpoint) { diff --git a/port/linux/tcpsession.c b/port/linux/tcpsession.c index 5d535f11c1..4199e259fa 100644 --- a/port/linux/tcpsession.c +++ b/port/linux/tcpsession.c @@ -205,6 +205,7 @@ get_interface_index(int sock) static void log_new_session(oc_endpoint_t *endpoint, int sock, bool is_connected) { + // GCOVR_EXCL_START oc_string64_t ep; const char *addr = ""; if (oc_endpoint_to_string64(endpoint, &ep)) { @@ -214,11 +215,13 @@ log_new_session(oc_endpoint_t *endpoint, int sock, bool is_connected) "connected: %d, session_id: %u", addr, endpoint->interface_index, sock, (int)is_connected, (unsigned)endpoint->session_id); + // GCOVR_EXCL_STOP } static void log_free_session(oc_endpoint_t *endpoint, int sock) { + // GCOVR_EXCL_START oc_string64_t ep; const char *addr = ""; if (oc_endpoint_to_string64(endpoint, &ep)) { @@ -227,6 +230,7 @@ log_free_session(oc_endpoint_t *endpoint, int sock) OC_DBG("free TCP session endpoint: %s, endpoint interface: %d, sock: %d, " "session_id: %u", addr, endpoint->interface_index, sock, (unsigned)endpoint->session_id); + // GCOVR_EXCL_STOP } #endif /* OC_DBG_IS_ENABLED */ @@ -250,16 +254,16 @@ add_new_session_locked(int sock, ip_context_t *dev, oc_endpoint_t *endpoint, session->dev = dev; endpoint->interface_index = (unsigned)if_index; + if (session_id == 0) { + session_id = oc_tcp_get_new_session_id(); + } + endpoint->session_id = session_id; memcpy(&session->endpoint, endpoint, sizeof(oc_endpoint_t)); session->endpoint.next = NULL; + session->endpoint.interface_index = (unsigned)if_index; session->sock = sock; session->csm_state = state; session->notify_session_end = true; - if (session_id == 0) { - session->endpoint.session_id = oc_tcp_get_new_session_id(); - } else { - session->endpoint.session_id = session_id; - } oc_list_add(g_session_list, session); @@ -304,8 +308,8 @@ accept_new_session_locked(ip_context_t *dev, int fd, fd_set *setfds, #endif /* !OC_IPV4 */ } - if (add_new_session_locked(new_socket, dev, endpoint, /*session_id*/ 0, - CSM_NONE) == NULL) { + if (add_new_session_locked(new_socket, dev, endpoint, + /*session_id*/ 0, CSM_NONE) == NULL) { OC_ERR("could not record new TCP session"); close(new_socket); return -1; @@ -551,6 +555,16 @@ find_session_by_endpoint_locked(const oc_endpoint_t *endpoint) return session; } +static tcp_session_t * +find_session_by_id_locked(uint32_t session_id) +{ + tcp_session_t *session = oc_list_head(g_session_list); + while (session != NULL && session->endpoint.session_id != session_id) { + session = session->next; + } + return session; +} + #ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT static tcp_session_t * @@ -586,6 +600,17 @@ find_waiting_session_by_endpoint_locked(const oc_endpoint_t *endpoint) return ws; } +static tcp_waiting_session_t * +find_waiting_session_by_id_locked(uint32_t session_id) +{ + tcp_waiting_session_t *ws = + (tcp_waiting_session_t *)oc_list_head(g_waiting_session_list); + while (ws != NULL && ws->endpoint.session_id != session_id) { + ws = ws->next; + } + return ws; +} + static tcp_waiting_session_t * add_new_waiting_session_locked(int sock, ip_context_t *dev, const oc_endpoint_t *endpoint, @@ -879,6 +904,24 @@ oc_tcp_connection_state(const oc_endpoint_t *endpoint) return -1; } +int +oc_tcp_session_state(uint32_t session_id) +{ + pthread_mutex_lock(&g_mutex); + if (find_session_by_id_locked(session_id) != NULL) { + pthread_mutex_unlock(&g_mutex); + return OC_TCP_SOCKET_STATE_CONNECTED; + } +#ifdef OC_HAS_FEATURE_TCP_ASYNC_CONNECT + if (find_waiting_session_by_id_locked(session_id) != NULL) { + pthread_mutex_unlock(&g_mutex); + return OC_TCP_SOCKET_STATE_CONNECTING; + } +#endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ + pthread_mutex_unlock(&g_mutex); + return -1; +} + static int tcp_send_message(int sockfd, const oc_message_t *message) { @@ -1370,6 +1413,9 @@ oc_tcp_connect(oc_endpoint_t *endpoint, on_tcp_connect_t on_tcp_connect, { oc_tcp_connect_result_t ret = oc_tcp_connect_to_endpoint(endpoint, on_tcp_connect, on_tcp_connect_data); + if (ret.session_id != 0) { + endpoint->session_id = ret.session_id; + } return ret.error != 0 ? ret.error : (int)ret.state; } diff --git a/port/oc_connectivity_internal.h b/port/oc_connectivity_internal.h index 2438489849..413cab1b0c 100644 --- a/port/oc_connectivity_internal.h +++ b/port/oc_connectivity_internal.h @@ -130,6 +130,17 @@ void oc_tcp_set_connect_retry(uint8_t max_count, uint16_t timeout); #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ +/** + * @brief Get state of TCP connection for given session id. + * + * @param session_id session id + * @return OC_TCP_SOCKET_STATE_CONNECTED TCP connection exists and it is ongoing + * @return OC_TCP_SOCKET_STATE_CONNECTING TCP connection is waiting to be + * established + * @return -1 otherwise + */ +int oc_tcp_session_state(uint32_t session_id); + #endif /* OC_TCP */ #ifdef __cplusplus diff --git a/port/unittest/connectivitytest.cpp b/port/unittest/connectivitytest.cpp index f5a747cee9..52b7b3b1d5 100644 --- a/port/unittest/connectivitytest.cpp +++ b/port/unittest/connectivitytest.cpp @@ -42,6 +42,8 @@ #include #include +using namespace std::chrono_literals; + static constexpr size_t kDeviceID = 0; class TestConnectivity : public testing::Test { @@ -462,11 +464,14 @@ TEST_F(TestConnectivityWithServer, oc_tcp_update_csm_state_P) coap_serialize_message(&packet, msg->data, oc_message_buffer_size(msg)); oc_send_buffer(msg); + ep.session_id = msg->endpoint.session_id; oc_message_unref(msg); #endif /* OC_HAS_FEATURE_TCP_ASYNC_CONNECT */ #ifdef OC_TCP EXPECT_EQ(OC_TCP_SOCKET_STATE_CONNECTED, oc_tcp_connection_state(&ep)); + ASSERT_NE(0, ep.session_id); + EXPECT_EQ(OC_TCP_SOCKET_STATE_CONNECTED, oc_tcp_session_state(ep.session_id)); #endif /* OC_TCP */ EXPECT_EQ(0, oc_tcp_update_csm_state(&ep, CSM_DONE)); @@ -526,7 +531,7 @@ TEST_F(TestConnectivityWithServer, oc_tcp_connect_timeout) return; } - EXPECT_EQ(OC_TCP_SOCKET_STATE_CONNECTING, ret); + ASSERT_EQ(OC_TCP_SOCKET_STATE_CONNECTING, ret); oc_message_t *msg = oc_allocate_message(); memcpy(&msg->endpoint, &ep, sizeof(oc_endpoint_t)); @@ -544,6 +549,36 @@ TEST_F(TestConnectivityWithServer, oc_tcp_connect_timeout) restore_defaults(); } +TEST_F(TestConnectivityWithServer, oc_tcp_cleanup_waiting_session) +{ + auto addr = "coap+tcp://[::1]:12345"; + oc_endpoint_t ep1 = + oc::endpoint::FromString(addr); // reachable address, but inactive port + + oc_tcp_connect_result_t ret1 = + oc_tcp_connect_to_endpoint(&ep1, nullptr, nullptr); + ASSERT_EQ(0, ret1.error); + ASSERT_EQ(OC_TCP_SOCKET_STATE_CONNECTING, ret1.state); + ASSERT_NE(0, ret1.session_id); + + // disconnect is asynchronous, we should be able to open a new session to + // the same endpoint + oc_close_session(&ep1); + + oc_endpoint_t ep2 = oc::endpoint::FromString(addr); + oc_tcp_connect_result_t ret2 = + oc_tcp_connect_to_endpoint(&ep2, nullptr, nullptr); + ASSERT_EQ(0, ret2.error); + ASSERT_EQ(OC_TCP_SOCKET_STATE_CONNECTING, ret2.state); + ASSERT_NE(0, ret2.session_id); + + oc::TestDevice::PoolEventsMsV1(20ms); + + EXPECT_EQ(-1, oc_tcp_session_state(ret1.session_id)); + EXPECT_EQ(OC_TCP_SOCKET_STATE_CONNECTING, + oc_tcp_session_state(ret2.session_id)); +} + #endif /* __linux__ */ TEST_F(TestConnectivityWithServer, oc_tcp_connect_repeat_fail) diff --git a/port/windows/tcpadapter.c b/port/windows/tcpadapter.c index 0ae0ae622f..ed53f61a2b 100644 --- a/port/windows/tcpadapter.c +++ b/port/windows/tcpadapter.c @@ -22,9 +22,9 @@ #include "api/oc_session_events_internal.h" #include "api/oc_tcp_internal.h" #include "port/oc_assert.h" +#include "port/oc_connectivity_internal.h" #include "port/oc_fcntl_internal.h" #include "port/oc_log_internal.h" -#include "util/oc_memb.h" #include "port/oc_tcp_socket_internal.h" #include "ipcontext.h" #include "messaging/coap/coap_internal.h" @@ -33,6 +33,7 @@ #include "oc_endpoint.h" #include "oc_session_events.h" #include "tcpadapter.h" +#include "util/oc_memb.h" #include #include @@ -237,19 +238,18 @@ add_new_session_locked(SOCKET sock, ip_context_t *dev, oc_endpoint_t *endpoint, return SOCKET_ERROR; } + session->dev = dev; endpoint->interface_index = (unsigned)if_index; + if (session_id == 0) { + session_id = oc_tcp_get_new_session_id(); + } + endpoint->session_id = session_id; memcpy(&session->endpoint, endpoint, sizeof(oc_endpoint_t)); - session->dev = dev; session->endpoint.next = NULL; session->sock = sock; session->csm_state = state; session->sock_event = sock_event; session->notify_session_end = true; - if (session_id == 0) { - session->endpoint.session_id = oc_tcp_get_new_session_id(); - } else { - session->endpoint.session_id = session_id; - } oc_list_add(session_list, session); @@ -330,6 +330,22 @@ find_session_by_endpoint_locked(const oc_endpoint_t *endpoint) return session; } +static tcp_session_t * +find_session_by_id_locked(uint32_t session_id) +{ + tcp_session_t *session = oc_list_head(session_list); + while (session != NULL && session->endpoint.session_id != session_id) { + session = session->next; + } + + if (!session) { + OC_DBG("could not find ongoing TCP session for session id %d", session_id); + return NULL; + } + OC_DBG("found TCP session for session id %d", session_id); + return session; +} + bool oc_tcp_end_session(const oc_endpoint_t *endpoint, bool notify_session_end, oc_endpoint_t *session_endpoint) @@ -1016,6 +1032,18 @@ oc_tcp_connection_state(const oc_endpoint_t *endpoint) return -1; } +int +oc_tcp_session_state(uint32_t session_id) +{ + oc_tcp_adapter_mutex_lock(); + tcp_session_t *session = find_session_by_id_locked(session_id); + oc_tcp_adapter_mutex_unlock(); + if (session != NULL) { + return OC_TCP_SOCKET_STATE_CONNECTED; + } + return -1; +} + tcp_csm_state_t oc_tcp_get_csm_state(const oc_endpoint_t *endpoint) {