diff --git a/examples/lwip/client-coap.c b/examples/lwip/client-coap.c index 947bb35535..0429cadcf6 100644 --- a/examples/lwip/client-coap.c +++ b/examples/lwip/client-coap.c @@ -12,17 +12,6 @@ #include "coap_config.h" -#if COAP_THREAD_SAFE -/* - * Unfortunately, this needs to be set so that locking mapping of coap_ - * functions does not take place in this file. coap.h includes coap_mem.h which - * includes lwip headers (lwippools.h) which includes coap_internal.h which - * includes coap_threadsafe_internal.h which does the mapping unless - * COAP_THREAD_IGNORE_LOCKED_MAPPING is set. - */ -#define COAP_THREAD_IGNORE_LOCKED_MAPPING -#endif - #include #include #include diff --git a/examples/lwip/server-coap.c b/examples/lwip/server-coap.c index e26d05cf4b..d2aefd4c5e 100644 --- a/examples/lwip/server-coap.c +++ b/examples/lwip/server-coap.c @@ -12,17 +12,6 @@ #include "coap_config.h" -#if COAP_THREAD_SAFE -/* - * Unfortunately, this needs to be set so that locking mapping of coap_ - * functions does not take place in this file. coap.h includes coap_mem.h which - * includes lwip headers (lwippools.h) which includes coap_internal.h which - * includes coap_threadsafe_internal.h which does the mapping unless - * COAP_THREAD_IGNORE_LOCKED_MAPPING is set. - */ -#define COAP_THREAD_IGNORE_LOCKED_MAPPING -#endif - #include #include "server-coap.h" diff --git a/include/coap3/coap_block.h b/include/coap3/coap_block.h index 1c1fb1197d..fbf64c3b03 100644 --- a/include/coap3/coap_block.h +++ b/include/coap3/coap_block.h @@ -423,8 +423,8 @@ COAP_API int coap_add_data_large_response(coap_resource_t *resource, * @param context The coap_context_t object. * @param block_mode Zero or more COAP_BLOCK_ or'd options */ -void coap_context_set_block_mode(coap_context_t *context, - uint32_t block_mode); +COAP_API void coap_context_set_block_mode(coap_context_t *context, + uint32_t block_mode); /** * Set the context level maximum block size that the server supports when sending @@ -440,7 +440,7 @@ void coap_context_set_block_mode(coap_context_t *context, * @param max_block_size The maximum block size a server supports. Can be 0 * (reset), or must be 16, 32, 64, 128, 256, 512 or 1024. */ -int coap_context_set_max_block_size(coap_context_t *context, size_t max_block_size); +COAP_API int coap_context_set_max_block_size(coap_context_t *context, size_t max_block_size); /**@}*/ diff --git a/include/coap3/coap_block_internal.h b/include/coap3/coap_block_internal.h index c51efdcbbe..41abb6d653 100644 --- a/include/coap3/coap_block_internal.h +++ b/include/coap3/coap_block_internal.h @@ -419,6 +419,45 @@ void coap_check_code_lg_xmit(const coap_session_t *session, const coap_resource_t *resource, const coap_string_t *query); +/** + * Set the context level CoAP block handling bits for handling RFC7959. + * These bits flow down to a session when a session is created and if the peer + * does not support something, an appropriate bit may get disabled in the + * session block_mode. + * The session block_mode then flows down into coap_crcv_t or coap_srcv_t where + * again an appropriate bit may get disabled. + * + * Note: This function must be called before the session is set up. + * + * Note: COAP_BLOCK_USE_LIBCOAP must be set if libcoap is to do all the + * block tracking and requesting, otherwise the application will have to do + * all of this work (the default if coap_context_set_block_mode() is not + * called). + * + * @param context The coap_context_t object. + * @param block_mode Zero or more COAP_BLOCK_ or'd options + */ +void coap_context_set_block_mode_lkd(coap_context_t *context, + uint32_t block_mode); + +/** + * Set the context level maximum block size that the server supports when sending + * or receiving packets with Block1 or Block2 options. + * This maximum block size flows down to a session when a session is created. + * + * Note: This function must be called before the session is set up. + * + * Note: This function must be called before the session is set up. + * + * Note: COAP_BLOCK_USE_LIBCOAP must be set using coap_context_set_block_mode() + * if libcoap is to do this work. + * + * @param context The coap_context_t object. + * @param max_block_size The maximum block size a server supports. Can be 0 + * (reset), or must be 16, 32, 64, 128, 256, 512 or 1024. + */ +int coap_context_set_max_block_size_lkd(coap_context_t *context, size_t max_block_size); + #if COAP_CLIENT_SUPPORT /** * Associates given data with the @p pdu that is passed as second parameter. diff --git a/include/coap3/coap_layers_internal.h b/include/coap3/coap_layers_internal.h index 74ddc4f0aa..a90b1f882c 100644 --- a/include/coap3/coap_layers_internal.h +++ b/include/coap3/coap_layers_internal.h @@ -84,8 +84,8 @@ typedef ssize_t (*coap_layer_write_t)(coap_session_t *session, * session->lfunc[_this_layer_].l_establish(session) * (or done at any point when layer is established). * If the establishment of a layer fails, then - * coap_session_disconnected(session, COAP_NACK_xxx_LAYER_FAILED) must be - * called. + * coap_session_disconnected_lkd(session, COAP_NACK_xxx_LAYER_FAILED) must + * be called. * * @param session Session being established */ diff --git a/include/coap3/coap_mutex_internal.h b/include/coap3/coap_mutex_internal.h index aaca90cf6e..ec91f6c1b8 100644 --- a/include/coap3/coap_mutex_internal.h +++ b/include/coap3/coap_mutex_internal.h @@ -161,239 +161,4 @@ extern coap_mutex_t m_persist_add; #endif /* COAP_CONSTRAINED_STACK */ -/* - * Support thread safe access into libcoap - * - * Locking at different component levels (i.e context and session) is - * problematic in that coap_process_io() needs to lock the context as - * it scans for all the sessions and then could lock the session being - * processed as well - but context needs to remain locked as a list is - * being scanned. - * - * Then if the session process needs to update context ( e.g. delayqueue), - * context needs to be locked. So, if coap_send() is done on a session, - * it has to be locked, but a retransmission of a PDU by coap_process_io() - * has the context already locked. - * - * So the initial support for thread safe is done at the context level. - * - * New model, simplifying debugging and better documentation. - * - * Any public API call needs to potentially lock context, as there may be - * multiple contexts. If a public API needs thread safe protection, the - * coap_X() function locks the context lock, calls the coap_X_lkd() function - * that does all the work and on return unlocks the context before returning - * to the caller of coap_X(). - * - * Any internal libcoap calls that are to the public API coap_X() must call - * coap_X_lkd() if the calling code is already locked. - * - * Old, equivalent model - * - * Any public API call needs to potentially lock context, as there may be - * multiple contexts. If a public API needs thread safe protection, a - * locking wrapper for coap_X() is added to src/coap_threadsafe.c which then - * calls the coap_X_locked() function of coap_X() having locked context. - * - * Then an entry is added to include/coap3/coap_threadsafe_internal.h to map - * all the coap_X() definitions and calls within the libcoap code to - * coap_X_locked() (with the exception of src/coap_threadsafe.c). - * - * A second entry is added to include/coap3/coap_threadsafe_internal.h which - * defines the coap_X_locked() function header. - * - * Any call-back into app space must be done by using the coap_lock_callback() - * (or coap_lock_callback_ret()) wrapper. - * - * Note: - * libcoap may call a handler, which may in turn call into libcoap, which may - * then call a handler. context will remain locked thoughout this process. - * - * Any wait on select() or equivalent when a thread is waiting on an event - * must be preceded by unlock context, and then context re-locked after - * return; - * - * To check for recursive deadlocks, COAP_THREAD_RECURSIVE_CHECK needs to be - * defined. - * - * If thread safe is not enabled, then coap_threadsafe.c and - * coap_threadsafe_internal.h do nothing. - */ -#if COAP_THREAD_SAFE -# if COAP_THREAD_RECURSIVE_CHECK - -/* - * Locking, with deadlock detection - */ -typedef struct coap_lock_t { - coap_mutex_t mutex; - coap_thread_pid_t pid; - coap_thread_pid_t freeing_pid; - const char *lock_file; - unsigned int lock_line; - unsigned int unlock_line; - const char *unlock_file; - const char *callback_file; - unsigned int callback_line; - unsigned int being_freed; - unsigned int in_callback; - unsigned int lock_count; -} coap_lock_t; - -void coap_lock_unlock_func(coap_lock_t *lock, const char *file, int line); -int coap_lock_lock_func(coap_lock_t *lock, const char *file, int line); - -#define coap_lock_lock(s,failed) do { \ - assert(s); \ - if (!coap_lock_lock_func(&(s)->lock, __FILE__, __LINE__)) { \ - failed; \ - } \ - } while (0) - -#define coap_lock_unlock(s) do { \ - assert(s); \ - coap_lock_unlock_func(&(s)->lock, __FILE__, __LINE__); \ - } while (0) - -#define coap_lock_callback(s,func) do { \ - coap_lock_check_locked(s); \ - (s)->lock.in_callback++; \ - (s)->lock.callback_file = __FILE__; \ - (s)->lock.callback_line = __LINE__; \ - func; \ - (s)->lock.in_callback--; \ - } while (0) - -#define coap_lock_callback_ret(r,s,func) do { \ - coap_lock_check_locked(s); \ - (s)->lock.in_callback++; \ - (s)->lock.callback_file = __FILE__; \ - (s)->lock.callback_line = __LINE__; \ - r = func; \ - (s)->lock.in_callback--; \ - } while (0) - -#define coap_lock_callback_release(s,func,fail) do { \ - coap_lock_check_locked(s); \ - coap_lock_unlock(s); \ - func; \ - coap_lock_lock(s,fail); \ - } while (0) - -#define coap_lock_callback_ret_release(r,s,func,fail) do { \ - coap_lock_check_locked(s); \ - coap_lock_unlock(s); \ - r = func; \ - coap_lock_lock(s,fail); \ - } while (0) - -# else /* ! COAP_THREAD_RECURSIVE_CHECK */ - -/* - * Locking, but no deadlock detection - */ -typedef struct coap_lock_t { - coap_mutex_t mutex; - coap_thread_pid_t pid; - coap_thread_pid_t freeing_pid; - uint32_t being_freed; - uint32_t in_callback; - volatile uint32_t lock_count; -} coap_lock_t; - -void coap_lock_unlock_func(coap_lock_t *lock); -int coap_lock_lock_func(coap_lock_t *lock); - -#define coap_lock_lock(s,failed) do { \ - assert(s); \ - if (!coap_lock_lock_func(&(s)->lock)) { \ - failed; \ - } \ - } while (0) - -#define coap_lock_unlock(s) do { \ - assert(s); \ - coap_lock_unlock_func(&(s)->lock); \ - } while (0) - -#define coap_lock_callback(s,func) do { \ - coap_lock_check_locked(s); \ - (s)->lock.in_callback++; \ - func; \ - (s)->lock.in_callback--; \ - } while (0) - -#define coap_lock_callback_ret(r,s,func) do { \ - coap_lock_check_locked(s); \ - (s)->lock.in_callback++; \ - r = func; \ - (s)->lock.in_callback--; \ - } while (0) - -#define coap_lock_callback_release(s,func,fail) do { \ - coap_lock_check_locked(s); \ - coap_lock_unlock(s); \ - func; \ - coap_lock_lock(s,fail); \ - } while (0) - -#define coap_lock_callback_ret_release(r,s,func,fail) do { \ - coap_lock_check_locked(s); \ - coap_lock_unlock(s); \ - r = func; \ - coap_lock_lock(s,fail); \ - } while (0) - -# endif /* ! COAP_THREAD_RECURSIVE_CHECK */ - -#define coap_lock_init(s) do { \ - assert(s); \ - memset(&((s)->lock), 0, sizeof((s)->lock)); \ - coap_mutex_init(&(s)->lock.mutex); \ - } while (0) - -#define coap_lock_being_freed(s,failed) do { \ - coap_lock_lock(s,failed); \ - (s)->lock.being_freed = 1; \ - (s)->lock.freeing_pid = coap_thread_pid; \ - coap_lock_unlock(s); \ - } while (0) - -#define coap_lock_check_locked(s) do { \ - assert((s) && \ - coap_thread_pid == ((s)->lock.being_freed ? (s)->lock.freeing_pid : \ - (s)->lock.pid)); \ - } while (0) - -#define coap_lock_invert(s,func,f) do { \ - coap_lock_check_locked(s); \ - if (!(s)->lock.being_freed) { \ - coap_lock_unlock(s); \ - func; \ - coap_lock_lock(s,f); \ - } else { \ - func; \ - } \ - } while (0) - -#else /* ! COAP_THREAD_SAFE */ - -/* - * No locking - single thread - */ -typedef coap_mutex_t coap_lock_t; - -#define coap_lock_lock(s,failed) -#define coap_lock_unlock(s) -#define coap_lock_init(s) -#define coap_lock_being_freed(s,failed) -#define coap_lock_check_locked(s) {} -#define coap_lock_callback(s,func) func -#define coap_lock_callback_ret(r,s,func) ret = func -#define coap_lock_callback_release(s,func,fail) func -#define coap_lock_callback_ret_release(r,s,func,fail) ret = func -#define coap_lock_invert(s,func,f) func - -#endif /* ! COAP_THREAD_SAFE */ - #endif /* COAP_MUTEX_INTERNAL_H_ */ diff --git a/include/coap3/coap_net.h b/include/coap3/coap_net.h index 29ca4d2aca..ebb650aa8e 100644 --- a/include/coap3/coap_net.h +++ b/include/coap3/coap_net.h @@ -149,7 +149,7 @@ void coap_register_pong_handler(coap_context_t *context, * @param ctx The context to use. * @param type The option type to register. */ -void coap_register_option(coap_context_t *ctx, uint16_t type); +COAP_API void coap_register_option(coap_context_t *ctx, uint16_t type); /** * Creates a new coap_context_t object that will hold the CoAP stack status. @@ -170,8 +170,8 @@ coap_context_t *coap_new_context(const coap_address_t *listen_addr); * * @return @c 1 if successful, else @c 0. */ -int coap_context_set_psk(coap_context_t *context, const char *hint, - const uint8_t *key, size_t key_len); +COAP_API int coap_context_set_psk(coap_context_t *context, const char *hint, + const uint8_t *key, size_t key_len); /** * Set the context's default PSK hint and/or key for a server. @@ -182,8 +182,8 @@ int coap_context_set_psk(coap_context_t *context, const char *hint, * * @return @c 1 if successful, else @c 0. */ -int coap_context_set_psk2(coap_context_t *context, - coap_dtls_spsk_t *setup_data); +COAP_API int coap_context_set_psk2(coap_context_t *context, + coap_dtls_spsk_t *setup_data); /** * Set the context's default PKI information for a server. @@ -194,8 +194,8 @@ int coap_context_set_psk2(coap_context_t *context, * * @return @c 1 if successful, else @c 0. */ -int coap_context_set_pki(coap_context_t *context, - const coap_dtls_pki_t *setup_data); +COAP_API int coap_context_set_pki(coap_context_t *context, + const coap_dtls_pki_t *setup_data); /** * Set the context's default Root CA information for a client or server. @@ -208,9 +208,9 @@ int coap_context_set_pki(coap_context_t *context, * * @return @c 1 if successful, else @c 0. */ -int coap_context_set_pki_root_cas(coap_context_t *context, - const char *ca_file, - const char *ca_dir); +COAP_API int coap_context_set_pki_root_cas(coap_context_t *context, + const char *ca_file, + const char *ca_dir); /** * Set the context keepalive timer for sessions. @@ -458,10 +458,10 @@ coap_pdu_t *coap_new_error_response(const coap_pdu_t *request, * @return The message id if the message was sent, or @c * COAP_INVALID_MID otherwise. */ -coap_mid_t coap_send_error(coap_session_t *session, - const coap_pdu_t *request, - coap_pdu_code_t code, - coap_opt_filter_t *opts); +COAP_API coap_mid_t coap_send_error(coap_session_t *session, + const coap_pdu_t *request, + coap_pdu_code_t code, + coap_opt_filter_t *opts); /** * Helper function to create and send a message with @p type (usually ACK or @@ -474,8 +474,8 @@ coap_mid_t coap_send_error(coap_session_t *session, * @return message id on success or @c COAP_INVALID_MID * otherwise. */ -coap_mid_t coap_send_message_type(coap_session_t *session, const coap_pdu_t *request, - coap_pdu_type_t type); +COAP_API coap_mid_t coap_send_message_type(coap_session_t *session, const coap_pdu_t *request, + coap_pdu_type_t type); /** * Sends an ACK message with code @c 0 for the specified @p request to @p dst. @@ -488,7 +488,7 @@ coap_mid_t coap_send_message_type(coap_session_t *session, const coap_pdu_t *req * @return The message id if ACK was sent or @c * COAP_INVALID_MID on error. */ -coap_mid_t coap_send_ack(coap_session_t *session, const coap_pdu_t *request); +COAP_API coap_mid_t coap_send_ack(coap_session_t *session, const coap_pdu_t *request); /** * Sends an RST message with code @c 0 for the specified @p request to @p dst. @@ -501,7 +501,7 @@ coap_mid_t coap_send_ack(coap_session_t *session, const coap_pdu_t *request); * @return The message id if RST was sent or @c * COAP_INVALID_MID on error. */ -coap_mid_t coap_send_rst(coap_session_t *session, const coap_pdu_t *request); +COAP_API coap_mid_t coap_send_rst(coap_session_t *session, const coap_pdu_t *request); /** * Sends a CoAP message to given peer. The memory that is @@ -514,7 +514,7 @@ coap_mid_t coap_send_rst(coap_session_t *session, const coap_pdu_t *request); * @return The message id of the sent message or @c * COAP_INVALID_MID on error. */ -coap_mid_t coap_send(coap_session_t *session, coap_pdu_t *pdu); +COAP_API coap_mid_t coap_send(coap_session_t *session, coap_pdu_t *pdu); #define coap_send_large(session, pdu) coap_send(session, pdu) @@ -560,8 +560,8 @@ void coap_ticks(coap_tick_t *); * * @return 0 on success, -1 on error */ -int coap_join_mcast_group_intf(coap_context_t *ctx, const char *groupname, - const char *ifname); +COAP_API int coap_join_mcast_group_intf(coap_context_t *ctx, const char *groupname, + const char *ifname); #define coap_join_mcast_group(ctx, groupname) \ (coap_join_mcast_group_intf(ctx, groupname, NULL)) diff --git a/include/coap3/coap_net_internal.h b/include/coap3/coap_net_internal.h index 24b95b6b68..0c0b28547f 100644 --- a/include/coap3/coap_net_internal.h +++ b/include/coap3/coap_net_internal.h @@ -20,6 +20,7 @@ #include "coap_internal.h" #include "coap_subscribe.h" +#include "coap_threadsafe_internal.h" /** * @ingroup internal_api @@ -501,6 +502,96 @@ int coap_handle_event_lkd(coap_context_t *context, */ int coap_can_exit_lkd(coap_context_t *context); +/** + * Function interface for joining a multicast group for listening for the + * currently defined endpoints that are UDP. + * + * Note: This function must be called in the locked state. + * + * @param ctx The current context. + * @param groupname The name of the group that is to be joined for listening. + * @param ifname Network interface to join the group on, or NULL if first + * appropriate interface is to be chosen by the O/S. + * + * @return 0 on success, -1 on error + */ +int coap_join_mcast_group_intf_lkd(coap_context_t *ctx, const char *groupname, + const char *ifname); + +/** + * Registers the option type @p type with the given context object @p ctx. + * + * Note: This function must be called in the locked state. + * + * @param ctx The context to use. + * @param type The option type to register. + */ +void coap_register_option_lkd(coap_context_t *ctx, uint16_t type); + +/** + * Set the context's default PKI information for a server. + * + * Note: This function must be called in the locked state. + * + * @param context The current coap_context_t object. + * @param setup_data If NULL, PKI authentication will fail. Certificate + * information required. + * + * @return @c 1 if successful, else @c 0. + */ +int coap_context_set_pki_lkd(coap_context_t *context, + const coap_dtls_pki_t *setup_data); + +/** + * Set the context's default Root CA information for a client or server. + * + * Note: This function must be called in the locked state. + * + * @param context The current coap_context_t object. + * @param ca_file If not NULL, is the full path name of a PEM encoded + * file containing all the Root CAs to be used. + * @param ca_dir If not NULL, points to a directory containing PEM + * encoded files containing all the Root CAs to be used. + * + * @return @c 1 if successful, else @c 0. + */ +int coap_context_set_pki_root_cas_lkd(coap_context_t *context, + const char *ca_file, + const char *ca_dir); + +/** + * Set the context's default PSK hint and/or key for a server. + * + * @deprecated Use coap_context_set_psk2() instead. + * + * Note: This function must be called in the locked state. + * + * @param context The current coap_context_t object. + * @param hint The default PSK server hint sent to a client. If NULL, PSK + * authentication is disabled. Empty string is a valid hint. + * @param key The default PSK key. If NULL, PSK authentication will fail. + * @param key_len The default PSK key's length. If @p 0, PSK authentication will + * fail. + * + * @return @c 1 if successful, else @c 0. + */ +int coap_context_set_psk_lkd(coap_context_t *context, const char *hint, + const uint8_t *key, size_t key_len); + +/** + * Set the context's default PSK hint and/or key for a server. + * + * Note: This function must be called in the locked state. + * + * @param context The current coap_context_t object. + * @param setup_data If NULL, PSK authentication will fail. PSK + * information required. + * + * @return @c 1 if successful, else @c 0. + */ +int coap_context_set_psk2_lkd(coap_context_t *context, + coap_dtls_spsk_t *setup_data); + /** @} */ /** @@ -686,6 +777,89 @@ int coap_io_process_with_fds_lkd(coap_context_t *ctx, uint32_t timeout_ms, fd_set *exceptfds); #endif /* ! RIOT_VERSION && ! WITH_CONTIKI */ +/** +* Sends a CoAP message to given peer. The memory that is +* allocated for the pdu will be released by coap_send_lkd(). +* The caller must not use or delete the pdu after calling coap_send_lkd(). + * + * Note: This function must be called in the locked state. +* +* @param session The CoAP session. +* @param pdu The CoAP PDU to send. +* +* @return The message id of the sent message or @c +* COAP_INVALID_MID on error. +*/ +coap_mid_t coap_send_lkd(coap_session_t *session, coap_pdu_t *pdu); + +/** + * Sends an error response with code @p code for request @p request to @p dst. + * @p opts will be passed to coap_new_error_response() to copy marked options + * from the request. This function returns the message id if the message was + * sent, or @c COAP_INVALID_MID otherwise. + * + * Note: This function must be called in the locked state. + * + * @param session The CoAP session. + * @param request The original request to respond to. + * @param code The response code. + * @param opts A filter that specifies the options to copy from the + * @p request. + * + * @return The message id if the message was sent, or @c + * COAP_INVALID_MID otherwise. + */ +coap_mid_t coap_send_error_lkd(coap_session_t *session, + const coap_pdu_t *request, + coap_pdu_code_t code, + coap_opt_filter_t *opts); + +/** + * Helper function to create and send a message with @p type (usually ACK or + * RST). This function returns @c COAP_INVALID_MID when the message was not + * sent, a valid transaction id otherwise. + * + * Note: This function must be called in the locked state. + * + * @param session The CoAP session. + * @param request The request that should be responded to. + * @param type Which type to set. + * @return message id on success or @c COAP_INVALID_MID + * otherwise. + */ +coap_mid_t coap_send_message_type_lkd(coap_session_t *session, const coap_pdu_t *request, + coap_pdu_type_t type); + +/** + * Sends an ACK message with code @c 0 for the specified @p request to @p dst. + * This function returns the corresponding message id if the message was + * sent or @c COAP_INVALID_MID on error. + * + * Note: This function must be called in the locked state. + * + * @param session The CoAP session. + * @param request The request to be acknowledged. + * + * @return The message id if ACK was sent or @c + * COAP_INVALID_MID on error. + */ +coap_mid_t coap_send_ack_lkd(coap_session_t *session, const coap_pdu_t *request); + +/** + * Sends an RST message with code @c 0 for the specified @p request to @p dst. + * This function returns the corresponding message id if the message was + * sent or @c COAP_INVALID_MID on error. + * + * Note: This function must be called in the locked state. + * + * @param session The CoAP session. + * @param request The request to be reset. + * + * @return The message id if RST was sent or @c + * COAP_INVALID_MID on error. + */ +coap_mid_t coap_send_rst_lkd(coap_session_t *session, const coap_pdu_t *request); + /**@}*/ extern int coap_started; diff --git a/include/coap3/coap_oscore_internal.h b/include/coap3/coap_oscore_internal.h index 7762e6f491..96e64ff4d0 100644 --- a/include/coap3/coap_oscore_internal.h +++ b/include/coap3/coap_oscore_internal.h @@ -211,7 +211,7 @@ int coap_delete_oscore_recipient_lkd(coap_context_t *context, * @param oscore_conf OSCORE configuration information. This structure is * freed off by this call. * - * @return A new CoAP session or NULL if failed. Call coap_session_release() + * @return A new CoAP session or NULL if failed. Call coap_session_release_lkd() * to free. */ coap_session_t *coap_new_client_session_oscore_lkd(coap_context_t *ctx, @@ -238,7 +238,7 @@ coap_session_t *coap_new_client_session_oscore_lkd(coap_context_t *ctx, * @param oscore_conf OSCORE configuration information. This structure is * freed off by this call. * - * @return A new CoAP session or NULL if failed. Call coap_session_release() + * @return A new CoAP session or NULL if failed. Call coap_session_release_lkd() * to free. */ coap_session_t *coap_new_client_session_oscore_pki_lkd(coap_context_t *ctx, @@ -266,7 +266,7 @@ coap_session_t *coap_new_client_session_oscore_pki_lkd(coap_context_t *ctx, * @param oscore_conf OSCORE configuration information. This structure is * freed off by this call. * - * @return A new CoAP session or NULL if failed. Call coap_session_release() + * @return A new CoAP session or NULL if failed. Call coap_session_release_lkd() * to free. */ coap_session_t *coap_new_client_session_oscore_psk_lkd(coap_context_t *ctx, diff --git a/include/coap3/coap_pdu.h b/include/coap3/coap_pdu.h index f72d253059..e51345d423 100644 --- a/include/coap3/coap_pdu.h +++ b/include/coap3/coap_pdu.h @@ -422,11 +422,11 @@ void coap_delete_pdu(coap_pdu_t *pdu); * * @return The duplicated PDU or @c NULL if failure. */ -coap_pdu_t *coap_pdu_duplicate(const coap_pdu_t *old_pdu, - coap_session_t *session, - size_t token_length, - const uint8_t *token, - coap_opt_filter_t *drop_options); +COAP_API coap_pdu_t *coap_pdu_duplicate(const coap_pdu_t *old_pdu, + coap_session_t *session, + size_t token_length, + const uint8_t *token, + coap_opt_filter_t *drop_options); /** * Parses @p data into the CoAP PDU structure given in @p result. diff --git a/include/coap3/coap_pdu_internal.h b/include/coap3/coap_pdu_internal.h index 5a4c130f6c..aabc362a8b 100644 --- a/include/coap3/coap_pdu_internal.h +++ b/include/coap3/coap_pdu_internal.h @@ -371,6 +371,27 @@ int coap_option_check_repeatable(coap_option_num_t number); coap_pdu_t *coap_new_pdu_lkd(coap_pdu_type_t type, coap_pdu_code_t code, coap_session_t *session); +/** + * Duplicate an existing PDU. Specific options can be ignored and not copied + * across. The PDU data payload is not copied across. + * + * Note: This function must be called in the locked state. + * + * @param old_pdu The PDU to duplicate + * @param session The session that will be using this PDU. + * @param token_length The length of the token to use in this duplicated PDU. + * @param token The token to use in this duplicated PDU. + * @param drop_options A list of options not to copy into the duplicated PDU. + * If @c NULL, then all options are copied across. + * + * @return The duplicated PDU or @c NULL if failure. + */ +coap_pdu_t *coap_pdu_duplicate_lkd(const coap_pdu_t *old_pdu, + coap_session_t *session, + size_t token_length, + const uint8_t *token, + coap_opt_filter_t *drop_options); + /** @} */ #endif /* COAP_COAP_PDU_INTERNAL_H_ */ diff --git a/include/coap3/coap_session.h b/include/coap3/coap_session.h index e09e479aa7..2573c000cc 100644 --- a/include/coap3/coap_session.h +++ b/include/coap3/coap_session.h @@ -66,7 +66,7 @@ typedef enum coap_session_state_t { * @param session The CoAP session. * @return same as session */ -coap_session_t *coap_session_reference(coap_session_t *session); +COAP_API coap_session_t *coap_session_reference(coap_session_t *session); /** * Decrement reference counter on a session. @@ -75,7 +75,7 @@ coap_session_t *coap_session_reference(coap_session_t *session); * * @param session The CoAP session. */ -void coap_session_release(coap_session_t *session); +COAP_API void coap_session_release(coap_session_t *session); /** * Notify session that it has failed. This cleans up any outstanding / queued @@ -84,8 +84,8 @@ void coap_session_release(coap_session_t *session); * @param session The CoAP session. * @param reason The reason why the session was disconnected. */ -void coap_session_disconnected(coap_session_t *session, - coap_nack_reason_t reason); +COAP_API void coap_session_disconnected(coap_session_t *session, + coap_nack_reason_t reason); /** * Stores @p data with the given session. This function overwrites any value @@ -238,7 +238,7 @@ void coap_session_set_mtu(coap_session_t *session, unsigned mtu); * * @return maximum PDU size, not including header (but including token). */ -size_t coap_session_max_pdu_size(const coap_session_t *session); +COAP_API size_t coap_session_max_pdu_size(const coap_session_t *session); /** * Creates a new client session to the designated server. @@ -422,7 +422,7 @@ void coap_endpoint_set_default_mtu(coap_endpoint_t *endpoint, unsigned mtu); * * @param endpoint The endpoint to release. */ -void coap_free_endpoint(coap_endpoint_t *endpoint); +COAP_API void coap_free_endpoint(coap_endpoint_t *endpoint); /** * Get the session associated with the specified @p remote_addr and @p index. @@ -795,13 +795,14 @@ coap_fixed_point_t coap_session_get_non_receive_timeout( const coap_session_t *session); /** @} */ + /** * Send a ping message for the session. * @param session The CoAP session. * * @return COAP_INVALID_MID if there is an error */ -coap_mid_t coap_session_send_ping(coap_session_t *session); +COAP_API coap_mid_t coap_session_send_ping(coap_session_t *session); /** * Disable client automatically sending observe cancel on session close diff --git a/include/coap3/coap_session_internal.h b/include/coap3/coap_session_internal.h index 8883df9156..80fcf9509e 100644 --- a/include/coap3/coap_session_internal.h +++ b/include/coap3/coap_session_internal.h @@ -270,6 +270,28 @@ void coap_session_send_csm(coap_session_t *session); */ void coap_session_connected(coap_session_t *session); +/** + * Notify session that it has failed. This cleans up any outstanding / queued + * transmissions, observations etc.. + * + * Note: This function must be called in the locked state. + * + * @param session The CoAP session. + * @param reason The reason why the session was disconnected. + */ +void coap_session_disconnected_lkd(coap_session_t *session, + coap_nack_reason_t reason); + +/** + * Send a ping message for the session. + * @param session The CoAP session. + * + * Note: This function must be called in the locked state. + * + * @return COAP_INVALID_MID if there is an error + */ +coap_mid_t coap_session_send_ping_lkd(coap_session_t *session); + /** * Refresh the session's current Identity Hint (PSK). * Note: A copy of @p psk_hint is maintained in the session by libcoap. @@ -316,7 +338,7 @@ int coap_session_refresh_psk_identity(coap_session_t *session, * @param ep An endpoint where an incoming connection request is pending. * @param extra Available for use by any underlying network stack. * - * @return A new CoAP session or NULL if failed. Call coap_session_release to + * @return A new CoAP session or NULL if failed. Call coap_session_release_lkd to * add to unused queue. */ coap_session_t *coap_new_server_session(coap_context_t *ctx, @@ -334,6 +356,27 @@ coap_session_t *coap_new_server_session(coap_context_t *ctx, */ void coap_session_establish(coap_session_t *session); +/** + * Increment reference counter on a session. + * + * Note: This function must be called in the locked state. + * + * @param session The CoAP session. + * @return same as session + */ +coap_session_t *coap_session_reference_lkd(coap_session_t *session); + +/** + * Decrement reference counter on a session. + * Note that the session may be deleted as a result and should not be used + * after this call. + * + * Note: This function must be called in the locked state. + * + * @param session The CoAP session. + */ +void coap_session_release_lkd(coap_session_t *session); + /** * Send a pdu according to the session's protocol. This function returns * the number of bytes that have been transmitted, or a value less than zero @@ -366,6 +409,8 @@ coap_session_t *coap_endpoint_get_session(coap_endpoint_t *endpoint, /** * Create a new endpoint for communicating with peers. * + * Note: This function must be called in the locked state. + * * @param context The coap context that will own the new endpoint, * @param listen_addr Address the endpoint will listen for incoming requests * on or originate outgoing requests from. Use NULL to @@ -378,6 +423,15 @@ coap_session_t *coap_endpoint_get_session(coap_endpoint_t *endpoint, coap_endpoint_t *coap_new_endpoint_lkd(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto); +/** + * Release an endpoint and all the structures associated with it. + * + * Note: This function must be called in the locked state. + * + * @param endpoint The endpoint to release. + */ +void coap_free_endpoint_lkd(coap_endpoint_t *endpoint); + #endif /* COAP_SERVER_SUPPORT */ /** @@ -388,6 +442,17 @@ coap_endpoint_t *coap_new_endpoint_lkd(coap_context_t *context, const coap_addre */ size_t coap_session_max_pdu_rcv_size(const coap_session_t *session); +/** + * Get maximum acceptable PDU size + * + * Note: This function must be called in the locked state. + * + * @param session The CoAP session. + * + * @return maximum PDU size, not including header (but including token). + */ +size_t coap_session_max_pdu_size_lkd(const coap_session_t *session); + /** * Creates a new client session to the designated server. * @@ -402,7 +467,7 @@ size_t coap_session_max_pdu_rcv_size(const coap_session_t *session); * for the protocol will be used. * @param proto Protocol. * - * @return A new CoAP session or NULL if failed. Call coap_session_release to free. + * @return A new CoAP session or NULL if failed. Call coap_session_release_lkd to free. */ coap_session_t *coap_new_client_session_lkd( coap_context_t *ctx, @@ -426,7 +491,7 @@ coap_session_t *coap_new_client_session_lkd( * @param proto CoAP Protocol. * @param setup_data PKI parameters. * - * @return A new CoAP session or NULL if failed. Call coap_session_release() + * @return A new CoAP session or NULL if failed. Call coap_session_release_lkd() * to free. */ coap_session_t *coap_new_client_session_pki_lkd(coap_context_t *ctx, @@ -455,7 +520,7 @@ coap_session_t *coap_new_client_session_pki_lkd(coap_context_t *ctx, * @param key PSK shared key * @param key_len PSK shared key length * - * @return A new CoAP session or NULL if failed. Call coap_session_release to free. + * @return A new CoAP session or NULL if failed. Call coap_session_release_lkd to free. */ coap_session_t *coap_new_client_session_psk_lkd(coap_context_t *ctx, const coap_address_t *local_if, @@ -481,7 +546,7 @@ coap_session_t *coap_new_client_session_psk_lkd(coap_context_t *ctx, * @param proto CoAP Protocol. * @param setup_data PSK parameters. * - * @return A new CoAP session or NULL if failed. Call coap_session_release() + * @return A new CoAP session or NULL if failed. Call coap_session_release_lkd() * to free. */ coap_session_t *coap_new_client_session_psk2_lkd(coap_context_t *ctx, diff --git a/include/coap3/coap_subscribe.h b/include/coap3/coap_subscribe.h index 220665e486..8c5005fbba 100644 --- a/include/coap3/coap_subscribe.h +++ b/include/coap3/coap_subscribe.h @@ -213,12 +213,12 @@ void coap_persist_track_funcs(coap_context_t *context, * * @return ptr to subscription if success else @c NULL. */ -coap_subscription_t *coap_persist_observe_add(coap_context_t *context, - coap_proto_t e_proto, - const coap_address_t *e_listen_addr, - const coap_addr_tuple_t *s_addr_info, - const coap_bin_const_t *raw_packet, - const coap_bin_const_t *oscore_info); +COAP_API coap_subscription_t *coap_persist_observe_add(coap_context_t *context, + coap_proto_t e_proto, + const coap_address_t *e_listen_addr, + const coap_addr_tuple_t *s_addr_info, + const coap_bin_const_t *raw_packet, + const coap_bin_const_t *oscore_info); /** * Start up persist tracking using the libcoap module. If the files already @@ -237,11 +237,11 @@ coap_subscription_t *coap_persist_observe_add(coap_context_t *context, * * @return @c 1 if success else @c 0. */ -int coap_persist_startup(coap_context_t *context, - const char *dyn_resource_save_file, - const char *observe_save_file, - const char *obs_cnt_save_file, - uint32_t save_freq); +COAP_API int coap_persist_startup(coap_context_t *context, + const char *dyn_resource_save_file, + const char *observe_save_file, + const char *obs_cnt_save_file, + uint32_t save_freq); /** * Stop tracking persist information, leaving the current persist information @@ -255,7 +255,7 @@ int coap_persist_startup(coap_context_t *context, * * @param context The context that tracking information is to be stopped on. */ -void coap_persist_stop(coap_context_t *context); +COAP_API void coap_persist_stop(coap_context_t *context); /** * Sets the current observe number value. diff --git a/include/coap3/coap_subscribe_internal.h b/include/coap3/coap_subscribe_internal.h index 59d0984b0c..ef3e00e812 100644 --- a/include/coap3/coap_subscribe_internal.h +++ b/include/coap3/coap_subscribe_internal.h @@ -178,6 +178,74 @@ void coap_check_notify_lkd(coap_context_t *context); */ void coap_persist_cleanup(coap_context_t *context); +/** + * Set up an active subscription for an observe that was previously active + * over a coap-server inadvertant restart. + * + * Only UDP sessions currently supported. + * + * Note: This function must be called in the locked state. + * + * @param context The context that the session is to be associated with. + * @param e_proto The CoAP protocol in use for the session / endpoint. + * @param e_listen_addr The IP/port that the endpoint is listening on. + * @param s_addr_info Local / Remote IP addresses. ports etc. of previous + * session. + * @param raw_packet L7 packet as seen on the wire (could be concatenated if + * Block1 FETCH is being used). + * @param oscore_info Has OSCORE information if OSCORE is protecting the + * session or NULL if OSCORE is not in use. + * + * @return ptr to subscription if success else @c NULL. + */ +coap_subscription_t *coap_persist_observe_add_lkd(coap_context_t *context, + coap_proto_t e_proto, + const coap_address_t *e_listen_addr, + const coap_addr_tuple_t *s_addr_info, + const coap_bin_const_t *raw_packet, + const coap_bin_const_t *oscore_info); + +/** + * Start up persist tracking using the libcoap module. If the files already + * exist with saved data, then this information is used in building back + * up the persist information. + * + * Note: This function must be called in the locked state. + * + * @param context The current CoAP context. + * @param dyn_resource_save_file File where dynamically created resource + * information is stored or NULL if not required. + * @param observe_save_file File where observe information is stored or NULL + * if not required. + * @param obs_cnt_save_file File where resource observe counter information + * is stored or NULL if not required. + * @param save_freq Frequency of change of observe value for calling + * the save observe counter logic. + * + * @return @c 1 if success else @c 0. + */ +int coap_persist_startup_lkd(coap_context_t *context, + const char *dyn_resource_save_file, + const char *observe_save_file, + const char *obs_cnt_save_file, + uint32_t save_freq); + +/** + * Stop tracking persist information, leaving the current persist information + * in the files defined in coap_persist_startup(). It is then safe to call + * coap_free_context() to close the application down cleanly. + * + * Note: This function must be called in the locked state. + * + * Alternatively, if coap_persist_track_funcs() was called, then this will + * disable all the callbacks, as well as making sure that no 4.04 is sent out + * for any active observe subscriptions when the resource is deleted after + * subsequently calling coap_free_context(). + * + * @param context The context that tracking information is to be stopped on. + */ +void coap_persist_stop_lkd(coap_context_t *context); + #endif /* COAP_SERVER_SUPPORT */ #if COAP_CLIENT_SUPPORT diff --git a/include/coap3/coap_threadsafe_internal.h b/include/coap3/coap_threadsafe_internal.h index fcafd951fa..9234634f95 100644 --- a/include/coap3/coap_threadsafe_internal.h +++ b/include/coap3/coap_threadsafe_internal.h @@ -17,91 +17,232 @@ #ifndef COAP_THREADSAFE_INTERNAL_H_ #define COAP_THREADSAFE_INTERNAL_H_ +/* + * Support thread safe access into libcoap + * + * Locking at different component levels (i.e context and session) is + * problematic in that coap_process_io() needs to lock the context as + * it scans for all the sessions and then could lock the session being + * processed as well - but context needs to remain locked as a list is + * being scanned. + * + * Then if the session process needs to update context ( e.g. delayqueue), + * context needs to be locked. So, if coap_send() is done on a session, + * it has to be locked, but a retransmission of a PDU by coap_process_io() + * has the context already locked. + * + * So the initial support for thread safe is done at the context level. + * + * Any public API call needs to potentially lock context, as there may be + * multiple contexts. If a public API needs thread safe protection, the + * coap_X() function locks the context lock, calls the coap_X_lkd() function + * that does all the work and on return unlocks the context before returning + * to the caller of coap_X(). + * + * Any internal libcoap calls that are to the public API coap_X() must call + * coap_X_lkd() if the calling code is already locked. + * + * Any call-back into app space must be done by using the coap_lock_callback() + * (or coap_lock_callback_ret()) wrapper where the context remains locked. + * + * Note: + * libcoap may call a handler, which may in turn call into libcoap, which may + * then call a handler. context will remain locked thoughout this process. + * + * Alternatively, coap_lock_callback_release() (or + * coap_lock_callback_ret_release()), is used where the context is unlocked + * for the duration of the call-back. Used for things like a request + * handler which could be busy for some time. + * + * Note: On return from the call-back, the code has to be careful not to + * use memory locations that make have been updated in the call-back by + * calling a Public API. + * + * Any wait on select() or equivalent when a thread is waiting on an event + * must be preceded by unlock context, and then context re-locked after + * return; + * + * To check for recursive deadlocks, COAP_THREAD_RECURSIVE_CHECK needs to be + * defined. + * + * If thread safe is not enabled, then locking of the context does not take + * place. + */ #if COAP_THREAD_SAFE +# if COAP_THREAD_RECURSIVE_CHECK + +/* + * Locking, with deadlock detection + */ +typedef struct coap_lock_t { + coap_mutex_t mutex; + coap_thread_pid_t pid; + coap_thread_pid_t freeing_pid; + const char *lock_file; + unsigned int lock_line; + unsigned int unlock_line; + const char *unlock_file; + const char *callback_file; + unsigned int callback_line; + unsigned int being_freed; + unsigned int in_callback; + unsigned int lock_count; +} coap_lock_t; + +void coap_lock_unlock_func(coap_lock_t *lock, const char *file, int line); +int coap_lock_lock_func(coap_lock_t *lock, const char *file, int line); + +#define coap_lock_lock(s,failed) do { \ + assert(s); \ + if (!coap_lock_lock_func(&(s)->lock, __FILE__, __LINE__)) { \ + failed; \ + } \ + } while (0) + +#define coap_lock_unlock(s) do { \ + assert(s); \ + coap_lock_unlock_func(&(s)->lock, __FILE__, __LINE__); \ + } while (0) + +#define coap_lock_callback(s,func) do { \ + coap_lock_check_locked(s); \ + (s)->lock.in_callback++; \ + (s)->lock.callback_file = __FILE__; \ + (s)->lock.callback_line = __LINE__; \ + func; \ + (s)->lock.in_callback--; \ + } while (0) + +#define coap_lock_callback_ret(r,s,func) do { \ + coap_lock_check_locked(s); \ + (s)->lock.in_callback++; \ + (s)->lock.callback_file = __FILE__; \ + (s)->lock.callback_line = __LINE__; \ + r = func; \ + (s)->lock.in_callback--; \ + } while (0) + +#define coap_lock_callback_release(s,func,fail) do { \ + coap_lock_check_locked(s); \ + coap_lock_unlock(s); \ + func; \ + coap_lock_lock(s,fail); \ + } while (0) + +#define coap_lock_callback_ret_release(r,s,func,fail) do { \ + coap_lock_check_locked(s); \ + coap_lock_unlock(s); \ + r = func; \ + coap_lock_lock(s,fail); \ + } while (0) + +# else /* ! COAP_THREAD_RECURSIVE_CHECK */ + +/* + * Locking, but no deadlock detection + */ +typedef struct coap_lock_t { + coap_mutex_t mutex; + coap_thread_pid_t pid; + coap_thread_pid_t freeing_pid; + uint32_t being_freed; + uint32_t in_callback; + volatile uint32_t lock_count; +} coap_lock_t; + +void coap_lock_unlock_func(coap_lock_t *lock); +int coap_lock_lock_func(coap_lock_t *lock); + +#define coap_lock_lock(s,failed) do { \ + assert(s); \ + if (!coap_lock_lock_func(&(s)->lock)) { \ + failed; \ + } \ + } while (0) + +#define coap_lock_unlock(s) do { \ + assert(s); \ + coap_lock_unlock_func(&(s)->lock); \ + } while (0) + +#define coap_lock_callback(s,func) do { \ + coap_lock_check_locked(s); \ + (s)->lock.in_callback++; \ + func; \ + (s)->lock.in_callback--; \ + } while (0) + +#define coap_lock_callback_ret(r,s,func) do { \ + coap_lock_check_locked(s); \ + (s)->lock.in_callback++; \ + r = func; \ + (s)->lock.in_callback--; \ + } while (0) + +#define coap_lock_callback_release(s,func,fail) do { \ + coap_lock_check_locked(s); \ + coap_lock_unlock(s); \ + func; \ + coap_lock_lock(s,fail); \ + } while (0) + +#define coap_lock_callback_ret_release(r,s,func,fail) do { \ + coap_lock_check_locked(s); \ + coap_lock_unlock(s); \ + r = func; \ + coap_lock_lock(s,fail); \ + } while (0) + +# endif /* ! COAP_THREAD_RECURSIVE_CHECK */ + +#define coap_lock_init(s) do { \ + assert(s); \ + memset(&((s)->lock), 0, sizeof((s)->lock)); \ + coap_mutex_init(&(s)->lock.mutex); \ + } while (0) + +#define coap_lock_being_freed(s,failed) do { \ + coap_lock_lock(s,failed); \ + (s)->lock.being_freed = 1; \ + (s)->lock.freeing_pid = coap_thread_pid; \ + coap_lock_unlock(s); \ + } while (0) + +#define coap_lock_check_locked(s) do { \ + assert((s) && \ + coap_thread_pid == ((s)->lock.being_freed ? (s)->lock.freeing_pid : \ + (s)->lock.pid)); \ + } while (0) + +#define coap_lock_invert(s,func,f) do { \ + coap_lock_check_locked(s); \ + if (!(s)->lock.being_freed) { \ + coap_lock_unlock(s); \ + func; \ + coap_lock_lock(s,f); \ + } else { \ + func; \ + } \ + } while (0) + +#else /* ! COAP_THREAD_SAFE */ + +/* + * No locking - single thread + */ +typedef coap_mutex_t coap_lock_t; + +#define coap_lock_lock(s,failed) +#define coap_lock_unlock(s) +#define coap_lock_init(s) +#define coap_lock_being_freed(s,failed) +#define coap_lock_check_locked(s) {} +#define coap_lock_callback(s,func) func +#define coap_lock_callback_ret(r,s,func) ret = func +#define coap_lock_callback_release(s,func,fail) func +#define coap_lock_callback_ret_release(r,s,func,fail) ret = func +#define coap_lock_invert(s,func,f) func -/* *INDENT-OFF* */ -#ifndef COAP_THREAD_IGNORE_LOCKED_MAPPING - -#define coap_context_set_block_mode(c,b) coap_context_set_block_mode_locked(c,b) -#define coap_context_set_max_block_size(c,m) coap_context_set_max_block_size_locked(c,m) -#define coap_context_set_pki(c,s) coap_context_set_pki_locked(c,s) -#define coap_context_set_pki_root_cas(c,f,d) coap_context_set_pki_root_cas_locked(c,f,d) -#define coap_context_set_psk(c,h,k,l) coap_context_set_psk_locked(c,h,k,l) -#define coap_context_set_psk2(c,s) coap_context_set_psk2_locked(c,s) -#define coap_free_endpoint(e) coap_free_endpoint_locked(e) -#define coap_join_mcast_group_intf(c,g,i) coap_join_mcast_group_intf_locked(c,g,i) -#define coap_persist_observe_add(c,p,l,a,r,o) coap_persist_observe_add_locked(c,p,l,a,r,o) -#define coap_persist_startup(c,d,o,m,s) coap_persist_startup_locked(c,d,o,m,s) -#define coap_persist_stop(c) coap_persist_stop_locked(c) -#define coap_pdu_duplicate(o,s,l,t,d) coap_pdu_duplicate_locked(o,s,l,t,d) -#define coap_register_option(c,t) coap_register_option_locked(c,t) -#define coap_send(s,p) coap_send_locked(s,p) -#define coap_send_ack(s,r) coap_send_ack_locked(s,r) -#define coap_send_error(s,r,c,o) coap_send_error_locked(s,r,c,o) -#define coap_send_message_type(s,r,t) coap_send_message_type_locked(s,r,t) -#define coap_send_rst(s,r) coap_send_rst_locked(s,r) -#define coap_session_max_pdu_size(s) coap_session_max_pdu_size_locked(s) -#define coap_session_reference(s) coap_session_reference_locked(s) -#define coap_session_release(s) coap_session_release_locked(s) -#define coap_session_disconnected(s,r) coap_session_disconnected_locked(s,r) -#define coap_session_send_ping(s) coap_session_send_ping_locked(s) - -#endif /* ! COAP_THREAD_IGNORE_LOCKED_MAPPING */ - -/* Locked equivalend functions */ - -void coap_context_set_block_mode_locked(coap_context_t *context, - uint32_t block_mode); -int coap_context_set_max_block_size_locked(coap_context_t *context, - size_t max_block_size); -int coap_context_set_pki_locked(coap_context_t *ctx, - const coap_dtls_pki_t *setup_data); -int coap_context_set_pki_root_cas_locked(coap_context_t *ctx, - const char *ca_file, const char *ca_dir); -int coap_context_set_psk_locked(coap_context_t *ctx, const char *hint, - const uint8_t *key, size_t key_len); -int coap_context_set_psk2_locked(coap_context_t *ctx, - coap_dtls_spsk_t *setup_data); -void coap_free_endpoint_locked(coap_endpoint_t *ep); -int coap_join_mcast_group_intf_locked(coap_context_t *ctx, const char *group_name, - const char *ifname); -coap_subscription_t *coap_persist_observe_add_locked(coap_context_t *context, - coap_proto_t e_proto, - const coap_address_t *e_listen_addr, - const coap_addr_tuple_t *s_addr_info, - const coap_bin_const_t *raw_packet, - const coap_bin_const_t *oscore_info); -int coap_persist_startup_locked(coap_context_t *context, - const char *dyn_resource_save_file, - const char *observe_save_file, - const char *obs_cnt_save_file, - uint32_t save_freq); -void coap_persist_stop_locked(coap_context_t *context); -size_t coap_session_max_pdu_size_locked(const coap_session_t *session); -coap_pdu_t *coap_pdu_duplicate_locked(const coap_pdu_t *old_pdu, - coap_session_t *session, - size_t token_length, - const uint8_t *token, - coap_opt_filter_t *drop_options); -void coap_register_option_locked(coap_context_t *ctx, uint16_t type); -int coap_resource_set_dirty_locked(coap_resource_t *r, - const coap_string_t *query); -coap_mid_t coap_send_locked(coap_session_t *session, coap_pdu_t *pdu); -coap_mid_t coap_send_ack_locked(coap_session_t *session, const coap_pdu_t *request); -coap_mid_t coap_send_error_locked(coap_session_t *session, const coap_pdu_t *request, - coap_pdu_code_t code, coap_opt_filter_t *opts); -coap_mid_t coap_send_message_type_locked(coap_session_t *session, - const coap_pdu_t *request, - coap_pdu_type_t type); -coap_mid_t coap_send_rst_locked(coap_session_t *session, const coap_pdu_t *request); -void coap_session_disconnected_locked(coap_session_t *session, - coap_nack_reason_t reason); -coap_session_t *coap_session_reference_locked(coap_session_t *session); -void coap_session_release_locked(coap_session_t *session); -coap_mid_t coap_session_send_ping_locked(coap_session_t *session); - -/* *INDENT-ON* */ - -#endif /* COAP_THREAD_SAFE */ +#endif /* ! COAP_THREAD_SAFE */ #endif /* COAP_THREADSAFE_INTERNAL_H_ */ diff --git a/man/coap_locking.txt.in b/man/coap_locking.txt.in index 7fe42ba61b..96fdb2e57e 100644 --- a/man/coap_locking.txt.in +++ b/man/coap_locking.txt.in @@ -85,30 +85,29 @@ not multi-thread access safe. COAP_THREAD_RECURSIVE_CHECK If set, and COAP_THREAD_SAFE is set, checks that if a lock is locked, it reports that the same lock is being (re-)locked. -Currently, locking is only done at the _context_ level for the public API +Currently, locking is only done at the _context_ level for the Public API functions where appropriate. Per _session_ was also considered, but things became complicated with one thread locking _context_ / _session_ and another thread trying to lock _session_ / _context_ in a different order. In principal, libcoap code internally should only unlock _context_ when waiting -on a *select*() or equivalent, and then lock up again on function return. - -_context_ needs to remain locked whenever a callback handler is called, and it is -possible / likely that the handler will call a public API which potentially could -try to re-lock the same lock. By using *coap_lock_callback*() (or -*coap_lock_callback_ret*()), the locking logic can detect that this lock request -is from a callback handler and so continue without any deadlocks. - -If COAP_THREAD_SAFE is set, then all the necessary public APIs are defined in -src/coap_threadsafe.c. These public APIs then call the same function after -locking, but with _locked appended to the function name. In otherwords, -*coap_X*() calls *coap_lock_lock*(), then calls *coap_X_locked*(), and finally -calls *coap_lock_unlock*() before returning. - -The internal renaming of *coap_X*() functions to *coap_X_locked*() is done by -macros in include/coap3/coap_threadsafe_internal.h, which also provides the -*coap_X_locked*() function definitions. - +on a *select*() or equivalent, or when calling a request handler, and then lock +up again on function return. Any other unlock - app call-back - lock needs to +be carefully analyzed as to any potential issues being created by the +app call-back if it calls any Public API, updating any data that is relied on +after lock takes place. + +coap_lock_callback() (or coap_lock_callback_ret()) wrapper leaves the _context_ +locked when calling app call-back, but allows the app call-back to call a +Public API when in the locked state. + +coap_lock_callback_release() (or coap_lock_callback_ret_release()) unlocks +_context_ when calling app call-back. The allows the app call-back to go off +and do other slow/blocking activity. Any calls to a Public API then locks up +_context_ before preceding. + +Any libcoap code that runs with _context_ locked should not call a Public API, +but call the _lkd equivalent (if available). FUNCTIONS --------- diff --git a/src/coap_async.c b/src/coap_async.c index 75de18ae4a..60115ab11f 100644 --- a/src/coap_async.c +++ b/src/coap_async.c @@ -89,8 +89,8 @@ coap_register_async_lkd(coap_session_t *session, LL_PREPEND(session->context->async_state, s); /* Note that this generates a new MID */ - s->pdu = coap_pdu_duplicate(request, session, request->actual_token.length, - request->actual_token.s, NULL); + s->pdu = coap_pdu_duplicate_lkd(request, session, request->actual_token.length, + request->actual_token.s, NULL); if (s->pdu == NULL) { coap_free_async_lkd(session, s); coap_log_crit("coap_register_async: insufficient memory\n"); @@ -101,7 +101,7 @@ coap_register_async_lkd(coap_session_t *session, coap_add_data(s->pdu, len, data); } - s->session = coap_session_reference(session); + s->session = coap_session_reference_lkd(session); coap_async_set_delay_lkd(s, delay); @@ -183,7 +183,7 @@ coap_free_async_sub(coap_context_t *context, coap_async_t *s) { if (s) { LL_DELETE(context->async_state,s); if (s->session) { - coap_session_release(s->session); + coap_session_release_lkd(s->session); } if (s->pdu) { coap_delete_pdu(s->pdu); diff --git a/src/coap_block.c b/src/coap_block.c index 1df3e77752..d61e1f4e2c 100644 --- a/src/coap_block.c +++ b/src/coap_block.c @@ -375,9 +375,17 @@ coap_add_data_blocked_response(const coap_pdu_t *request, (const unsigned char *)coap_response_phrase(response->code)); } -void +COAP_API void coap_context_set_block_mode(coap_context_t *context, uint32_t block_mode) { + coap_lock_lock(context, return); + coap_context_set_block_mode_lkd(context, block_mode); + coap_lock_unlock(context); +} + +void +coap_context_set_block_mode_lkd(coap_context_t *context, + uint32_t block_mode) { coap_lock_check_locked(context); if (!(block_mode & COAP_BLOCK_USE_LIBCOAP)) block_mode = 0; @@ -389,8 +397,19 @@ coap_context_set_block_mode(coap_context_t *context, #endif /* ! COAP_Q_BLOCK_SUPPORT */ } +COAP_API int +coap_context_set_max_block_size(coap_context_t *context, + size_t max_block_size) { + int ret; + + coap_lock_lock(context, return 0); + ret = coap_context_set_max_block_size_lkd(context, max_block_size); + coap_lock_unlock(context); + return ret; +} + int -coap_context_set_max_block_size(coap_context_t *context, size_t max_block_size) { +coap_context_set_max_block_size_lkd(coap_context_t *context, size_t max_block_size) { switch (max_block_size) { case 0: case 16: @@ -466,11 +485,11 @@ coap_cancel_observe_lkd(coap_session_t *session, coap_binary_t *token, lg_crcv->obs_token[0] : (coap_bin_const_t *)lg_crcv->app_token : (coap_bin_const_t *)lg_crcv->app_token; - coap_pdu_t *pdu = coap_pdu_duplicate(&lg_crcv->pdu, - session, - otoken->length, - otoken->s, - NULL); + coap_pdu_t *pdu = coap_pdu_duplicate_lkd(&lg_crcv->pdu, + session, + otoken->length, + otoken->s, + NULL); lg_crcv->observe_set = 0; if (pdu == NULL) @@ -558,8 +577,8 @@ coap_retransmit_oscore_pdu(coap_session_t *session, ++lg_crcv->retry_counter); ltoken_len = coap_encode_var_safe8(ltoken, sizeof(token), token); /* There could be a Block option in pdu */ - resend_pdu = coap_pdu_duplicate(pdu, session, ltoken_len, - ltoken, NULL); + resend_pdu = coap_pdu_duplicate_lkd(pdu, session, ltoken_len, + ltoken, NULL); if (!resend_pdu) goto error; if (echo) { @@ -1319,8 +1338,8 @@ coap_build_missing_pdu(coap_session_t *session, coap_lg_crcv_t *p) { memset(&drop_options, 0, sizeof(coap_opt_filter_t)); coap_option_filter_set(&drop_options, COAP_OPTION_Q_BLOCK2); coap_option_filter_set(&drop_options, COAP_OPTION_OBSERVE); - pdu = coap_pdu_duplicate(&p->pdu, session, len, buf, - &drop_options); + pdu = coap_pdu_duplicate_lkd(&p->pdu, session, len, buf, + &drop_options); if (!pdu) return NULL; pdu->type = p->last_type; @@ -1509,7 +1528,7 @@ pdu_408_build(coap_session_t *session, coap_lg_srcv_t *p) { pdu = coap_pdu_init(COAP_MESSAGE_NON, COAP_RESPONSE_CODE(408), coap_new_message_id_lkd(session), - coap_session_max_pdu_size(session)); + coap_session_max_pdu_size_lkd(session)); if (!pdu) return NULL; if (p->last_token) @@ -1770,7 +1789,7 @@ coap_block_check_lg_srcv_timeouts(coap_session_t *session, coap_tick_t now, pdu = coap_pdu_init(COAP_MESSAGE_NON, COAP_RESPONSE_CODE(408), coap_new_message_id_lkd(session), - coap_session_max_pdu_size(session)); + coap_session_max_pdu_size_lkd(session)); if (pdu) { if (p->last_token) coap_add_token(pdu, p->last_token->length, p->last_token->s); @@ -1849,9 +1868,9 @@ coap_send_q_blocks(coap_session_t *session, memset(&drop_options, 0, sizeof(coap_opt_filter_t)); coap_option_filter_set(&drop_options, lg_xmit->option); - block_pdu = coap_pdu_duplicate(pdu, session, - ltoken_length, - ptoken, &drop_options); + block_pdu = coap_pdu_duplicate_lkd(pdu, session, + ltoken_length, + ptoken, &drop_options); if (block_pdu->type == COAP_MESSAGE_ACK) block_pdu->type = COAP_MESSAGE_CON; } @@ -1892,8 +1911,8 @@ coap_send_q_blocks(coap_session_t *session, ltoken_length = coap_encode_var_safe8(ltoken, sizeof(token), token); ptoken = ltoken; } - t_pdu = coap_pdu_duplicate(block_pdu, session, - ltoken_length, ptoken, &drop_options); + t_pdu = coap_pdu_duplicate_lkd(block_pdu, session, + ltoken_length, ptoken, &drop_options); } if (!coap_update_option(block_pdu, lg_xmit->option, coap_encode_var_safe(buf, @@ -2166,7 +2185,7 @@ coap_block_test_q_block(coap_session_t *session, coap_pdu_t *actual) { /* RFC9177 Section 4.1 when checking if available */ pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_GET, coap_new_message_id_lkd(session), - coap_session_max_pdu_size(session)); + coap_session_max_pdu_size_lkd(session)); if (!pdu) { return COAP_INVALID_MID; } @@ -2583,11 +2602,11 @@ coap_handle_request_send_block(coap_session_t *session, if (block.num != 0) coap_option_filter_set(&drop_options, COAP_OPTION_OBSERVE); if (out_blocks[i].is_continue) { - out_pdu = coap_pdu_duplicate(&p->pdu, session, p->pdu.actual_token.length, - p->pdu.actual_token.s, &drop_options); + out_pdu = coap_pdu_duplicate_lkd(&p->pdu, session, p->pdu.actual_token.length, + p->pdu.actual_token.s, &drop_options); } else { - out_pdu = coap_pdu_duplicate(&p->pdu, session, pdu->actual_token.length, - pdu->actual_token.s, &drop_options); + out_pdu = coap_pdu_duplicate_lkd(&p->pdu, session, pdu->actual_token.length, + pdu->actual_token.s, &drop_options); } if (!out_pdu) { goto internal_issue; @@ -3071,11 +3090,11 @@ coap_handle_request_put_block(coap_context_t *context, response->code = COAP_RESPONSE_CODE(231); } else { /* Need to separately respond to this request */ - coap_pdu_t *tmp_pdu = coap_pdu_duplicate(response, - session, - response->actual_token.length, - response->actual_token.s, - NULL); + coap_pdu_t *tmp_pdu = coap_pdu_duplicate_lkd(response, + session, + response->actual_token.length, + response->actual_token.s, + NULL); if (tmp_pdu) { tmp_pdu->code = COAP_RESPONSE_CODE(231); coap_send_internal(session, tmp_pdu); @@ -3227,7 +3246,7 @@ check_freshness(coap_session_t *session, coap_pdu_t *rcvd, coap_pdu_t *sent, ++lg_crcv->retry_counter); } ltoken_len = coap_encode_var_safe8(ltoken, sizeof(token), token); - echo_pdu = coap_pdu_duplicate(sent, session, ltoken_len, ltoken, NULL); + echo_pdu = coap_pdu_duplicate_lkd(sent, session, ltoken_len, ltoken, NULL); if (!echo_pdu) return 0; if (!coap_insert_option(echo_pdu, COAP_OPTION_ECHO, @@ -3396,7 +3415,7 @@ coap_handle_response_send_block(coap_session_t *session, coap_pdu_t *sent, } } } - pdu = coap_pdu_duplicate(&p->pdu, session, len, buf, NULL); + pdu = coap_pdu_duplicate_lkd(&p->pdu, session, len, buf, NULL); if (!pdu) goto fail_body; @@ -3493,8 +3512,8 @@ coap_handle_response_send_block(coap_session_t *session, coap_pdu_t *sent, /* Build the next PDU request based off the skeletal PDU */ token = STATE_TOKEN_FULL(p->b.b1.state_token,++p->b.b1.count); ltoken_length = coap_encode_var_safe8(ltoken, sizeof(token), token); - pdu = coap_pdu_duplicate(&p->pdu, session, ltoken_length, - ltoken, NULL); + pdu = coap_pdu_duplicate_lkd(&p->pdu, session, ltoken_length, + ltoken, NULL); if (!pdu) goto fail_body; @@ -3779,7 +3798,7 @@ coap_handle_response_get_block(coap_context_t *context, coap_session_new_token(session, &len, buf); memset(&drop_options, 0, sizeof(coap_opt_filter_t)); coap_option_filter_set(&drop_options, COAP_OPTION_OBSERVE); - pdu = coap_pdu_duplicate(&p->pdu, session, len, buf, &drop_options); + pdu = coap_pdu_duplicate_lkd(&p->pdu, session, len, buf, &drop_options); if (!pdu) goto fail_resp; @@ -3906,7 +3925,7 @@ coap_handle_response_get_block(coap_context_t *context, /* Ask for the next block */ token = STATE_TOKEN_FULL(p->state_token, ++p->retry_counter); len = coap_encode_var_safe8(buf, sizeof(token), token); - pdu = coap_pdu_duplicate(&p->pdu, session, len, buf, NULL); + pdu = coap_pdu_duplicate_lkd(&p->pdu, session, len, buf, NULL); if (!pdu) goto fail_resp; @@ -4003,12 +4022,12 @@ coap_handle_response_get_block(coap_context_t *context, /* context is being freed off */ assert(0)); if (ret == COAP_RESPONSE_FAIL) { - coap_send_rst(session, rcvd); + coap_send_rst_lkd(session, rcvd); } else { - coap_send_ack(session, rcvd); + coap_send_ack_lkd(session, rcvd); } } else { - coap_send_ack(session, rcvd); + coap_send_ack_lkd(session, rcvd); } ack_rst_sent = 1; if (p->observe_set == 0) { @@ -4166,7 +4185,7 @@ coap_handle_response_get_block(coap_context_t *context, skip_app_handler: if (!ack_rst_sent) - coap_send_ack(session, rcvd); + coap_send_ack_lkd(session, rcvd); return 1; } #endif /* COAP_CLIENT_SUPPORT */ diff --git a/src/coap_dtls.c b/src/coap_dtls.c index 3cff97092e..46ee15bdb6 100644 --- a/src/coap_dtls.c +++ b/src/coap_dtls.c @@ -275,7 +275,7 @@ coap_dtls_establish(coap_session_t *session) { #endif /* COAP_SERVER_SUPPORT */ if (!session->tls) { - coap_session_disconnected(session, COAP_NACK_TLS_LAYER_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_LAYER_FAILED); return; } coap_ticks(&session->last_rx_tx); @@ -304,7 +304,7 @@ coap_tls_establish(coap_session_t *session) { #endif /* COAP_SERVER_SUPPORT */ if (!session->tls) { - coap_session_disconnected(session, COAP_NACK_TLS_LAYER_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_LAYER_FAILED); return; } coap_ticks(&session->last_rx_tx); diff --git a/src/coap_gnutls.c b/src/coap_gnutls.c index 75a8860222..f3325f733d 100644 --- a/src/coap_gnutls.c +++ b/src/coap_gnutls.c @@ -2341,7 +2341,7 @@ coap_dtls_send(coap_session_t *c_session, coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session); if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); ret = -1; } } @@ -2407,7 +2407,7 @@ coap_dtls_handle_timeout(coap_session_t *c_session) { (do_gnutls_handshake(c_session, g_env) < 0)) { /* Too many retries */ g_env->doing_dtls_timeout = 0; - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); return 1; } else { g_env->doing_dtls_timeout = 0; @@ -2488,12 +2488,12 @@ coap_dtls_receive(coap_session_t *c_session, const uint8_t *data, } if (c_session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session); if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); ssl_data = NULL; ret = -1; } @@ -2815,12 +2815,12 @@ coap_tls_write(coap_session_t *c_session, const uint8_t *data, } if (c_session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session); if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); ret = -1; } } @@ -2896,12 +2896,12 @@ coap_tls_read(coap_session_t *c_session, uint8_t *data, size_t data_len) { } if (c_session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session); if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); ret = -1; } } diff --git a/src/coap_io.c b/src/coap_io.c index 7a3e1d9642..533af38f6c 100644 --- a/src/coap_io.c +++ b/src/coap_io.c @@ -1350,7 +1350,7 @@ coap_io_prepare_io_lkd(coap_context_t *ctx, timeout = s_timeout; } /* Make sure the session object is not deleted in any callbacks */ - coap_session_reference(s); + coap_session_reference_lkd(s); /* Check any DTLS timeouts and expire if appropriate */ if (check_dtls_timeouts && s->state == COAP_SESSION_STATE_HANDSHAKE && s->proto == COAP_PROTO_DTLS && s->tls) { @@ -1403,7 +1403,7 @@ coap_io_prepare_io_lkd(coap_context_t *ctx, } #endif /* COAP_Q_BLOCK_SUPPORT */ release_1: - coap_session_release(s); + coap_session_release_lkd(s); } } } @@ -1415,7 +1415,7 @@ coap_io_prepare_io_lkd(coap_context_t *ctx, ctx->ping_timeout > 0) { if (s->last_rx_tx + ctx->ping_timeout * COAP_TICKS_PER_SECOND <= now) { /* Time to send a ping */ - if ((s->last_ping_mid = coap_session_send_ping(s)) == COAP_INVALID_MID) + if ((s->last_ping_mid = coap_session_send_ping_lkd(s)) == COAP_INVALID_MID) /* Some issue - not safe to continue processing */ continue; if (s->last_ping > 0 && s->last_pong < s->last_ping) { @@ -1447,7 +1447,7 @@ coap_io_prepare_io_lkd(coap_context_t *ctx, #endif /* !COAP_DISABLE_TCP */ /* Make sure the session object is not deleted in any callbacks */ - coap_session_reference(s); + coap_session_reference_lkd(s); /* Check any DTLS timeouts and expire if appropriate */ if (s->state == COAP_SESSION_STATE_HANDSHAKE && s->proto == COAP_PROTO_DTLS && s->tls) { @@ -1504,7 +1504,7 @@ coap_io_prepare_io_lkd(coap_context_t *ctx, } #endif /* ! COAP_EPOLL_SUPPORT && ! WITH_LWIP && ! RIOT_VERSION */ release_2: - coap_session_release(s); + coap_session_release_lkd(s); } #endif /* COAP_CLIENT_SUPPORT */ diff --git a/src/coap_io_lwip.c b/src/coap_io_lwip.c index 9f09f15407..4d93377b04 100644 --- a/src/coap_io_lwip.c +++ b/src/coap_io_lwip.c @@ -185,7 +185,7 @@ coap_recvc(void *arg, struct udp_pcb *upcb, struct pbuf *p, * https://rfc-editor.org/rfc/rfc7252#section-4.3 MAY send RST */ if (session) - coap_send_rst(session, pdu); + coap_send_rst_lkd(session, pdu); coap_delete_pdu(pdu); return; } @@ -280,7 +280,7 @@ coap_udp_recvs(void *arg, struct udp_pcb *upcb, struct pbuf *p, * https://rfc-editor.org/rfc/rfc7252#section-4.3 MAY send RST */ if (session && pdu) - coap_send_rst(session, pdu); + coap_send_rst_lkd(session, pdu); coap_delete_pdu(pdu); coap_free_packet(packet); coap_lock_unlock(ep->context); @@ -450,10 +450,10 @@ do_tcp_err(void *arg, err_t err) { /* * as per tcp_err() documentation, the corresponding pcb is already freed * when this callback is called. So, stop a double free when - * coap_session_disconnected() eventually coap_socket_close() is called. + * coap_session_disconnected_lkd() eventually coap_socket_close() is called. */ session->sock.tcp_pcb = NULL; - coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + coap_session_disconnected_lkd(session, COAP_NACK_NOT_DELIVERABLE); } /** Callback from lwIP when a TCP packet is received. @@ -474,7 +474,7 @@ coap_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { tcp_recv(sock->tcp_pcb, NULL); tcp_close(sock->tcp_pcb); sock->tcp_pcb = NULL; - coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + coap_session_disconnected_lkd(session, COAP_NACK_NOT_DELIVERABLE); return ERR_OK; } else if (err != ERR_OK) { /* cleanup, for unknown reason */ diff --git a/src/coap_mbedtls.c b/src/coap_mbedtls.c index 6c70f4f875..10560aaae5 100644 --- a/src/coap_mbedtls.c +++ b/src/coap_mbedtls.c @@ -2039,12 +2039,12 @@ coap_dtls_send(coap_session_t *c_session, } if (c_session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session); if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); ret = -1; } } @@ -2121,7 +2121,7 @@ coap_dtls_handle_timeout(coap_session_t *c_session) { if ((++c_session->dtls_timeout_count > c_session->max_retransmit) || (do_mbedtls_handshake(c_session, m_env) < 0)) { /* Too many retries */ - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); return 1; } return 0; @@ -2214,12 +2214,12 @@ coap_dtls_receive(coap_session_t *c_session, } } if (c_session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session); if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); ssl_data = NULL; ret = -1; } @@ -2457,12 +2457,12 @@ coap_tls_write(coap_session_t *c_session, const uint8_t *data, } if (c_session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session); if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); ret = -1; } } @@ -2535,12 +2535,12 @@ coap_tls_read(coap_session_t *c_session, uint8_t *data, size_t data_len) { } if (c_session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session); if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR || c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(c_session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(c_session, COAP_NACK_TLS_FAILED); ret = -1; } } diff --git a/src/coap_net.c b/src/coap_net.c index e18df96f46..0e19c4f5d7 100644 --- a/src/coap_net.c +++ b/src/coap_net.c @@ -235,7 +235,7 @@ coap_delete_node_lkd(coap_queue_t *node) { if (node->session->context->sendqueue) { LL_DELETE(node->session->context->sendqueue, node); } - coap_session_release(node->session); + coap_session_release_lkd(node->session); } coap_free_node(node); @@ -344,11 +344,24 @@ coap_get_session_server_psk_hint(const coap_session_t *session) { return NULL; } -int +COAP_API int coap_context_set_psk(coap_context_t *ctx, const char *hint, const uint8_t *key, size_t key_len) { + int ret; + + coap_lock_lock(ctx, return 0); + ret = coap_context_set_psk_lkd(ctx, hint, key, key_len); + coap_lock_unlock(ctx); + return ret; +} + +int +coap_context_set_psk_lkd(coap_context_t *ctx, + const char *hint, + const uint8_t *key, + size_t key_len) { coap_dtls_spsk_t setup_data; coap_lock_check_locked(ctx); @@ -363,11 +376,21 @@ coap_context_set_psk(coap_context_t *ctx, setup_data.psk_info.key.length = key_len; } - return coap_context_set_psk2(ctx, &setup_data); + return coap_context_set_psk2_lkd(ctx, &setup_data); } -int +COAP_API int coap_context_set_psk2(coap_context_t *ctx, coap_dtls_spsk_t *setup_data) { + int ret; + + coap_lock_lock(ctx, return 0); + ret = coap_context_set_psk2_lkd(ctx, setup_data); + coap_lock_unlock(ctx); + return ret; +} + +int +coap_context_set_psk2_lkd(coap_context_t *ctx, coap_dtls_spsk_t *setup_data) { if (!setup_data) return 0; @@ -380,9 +403,20 @@ coap_context_set_psk2(coap_context_t *ctx, coap_dtls_spsk_t *setup_data) { return 0; } -int +COAP_API int coap_context_set_pki(coap_context_t *ctx, const coap_dtls_pki_t *setup_data) { + int ret; + + coap_lock_lock(ctx, return 0); + ret = coap_context_set_pki_lkd(ctx, setup_data); + coap_lock_unlock(ctx); + return ret; +} + +int +coap_context_set_pki_lkd(coap_context_t *ctx, + const coap_dtls_pki_t *setup_data) { coap_lock_check_locked(ctx); if (!setup_data) return 0; @@ -397,10 +431,22 @@ coap_context_set_pki(coap_context_t *ctx, } #endif /* ! COAP_SERVER_SUPPORT */ -int +COAP_API int coap_context_set_pki_root_cas(coap_context_t *ctx, const char *ca_file, const char *ca_dir) { + int ret; + + coap_lock_lock(ctx, return 0); + ret = coap_context_set_pki_root_cas_lkd(ctx, ca_file, ca_dir); + coap_lock_unlock(ctx); + return ret; +} + +int +coap_context_set_pki_root_cas_lkd(coap_context_t *ctx, + const char *ca_file, + const char *ca_dir) { if (coap_dtls_is_supported() || coap_tls_is_supported()) { return coap_dtls_context_set_pki_root_cas(ctx, ca_file, ca_dir); } @@ -679,7 +725,7 @@ coap_free_context_lkd(coap_context_t *context) { coap_endpoint_t *ep, *tmp; LL_FOREACH_SAFE(context->endpoint, ep, tmp) { - coap_free_endpoint(ep); + coap_free_endpoint_lkd(ep); } #endif /* COAP_SERVER_SUPPORT */ @@ -687,7 +733,7 @@ coap_free_context_lkd(coap_context_t *context) { coap_session_t *sp, *rtmp; SESSIONS_ITER_SAFE(context->sessions, sp, rtmp) { - coap_session_release(sp); + coap_session_release_lkd(sp); } #endif /* COAP_CLIENT_SUPPORT */ @@ -838,13 +884,33 @@ coap_option_check_critical(coap_session_t *session, return ok; } -coap_mid_t +COAP_API coap_mid_t coap_send_rst(coap_session_t *session, const coap_pdu_t *request) { - return coap_send_message_type(session, request, COAP_MESSAGE_RST); + coap_mid_t mid; + + coap_lock_lock(session->context, return COAP_INVALID_MID); + mid = coap_send_rst_lkd(session, request); + coap_lock_unlock(session->context); + return mid; } coap_mid_t +coap_send_rst_lkd(coap_session_t *session, const coap_pdu_t *request) { + return coap_send_message_type_lkd(session, request, COAP_MESSAGE_RST); +} + +COAP_API coap_mid_t coap_send_ack(coap_session_t *session, const coap_pdu_t *request) { + coap_mid_t mid; + + coap_lock_lock(session->context, return COAP_INVALID_MID); + mid = coap_send_ack_lkd(session, request); + coap_lock_unlock(session->context); + return mid; +} + +coap_mid_t +coap_send_ack_lkd(coap_session_t *session, const coap_pdu_t *request) { coap_pdu_t *response; coap_mid_t result = COAP_INVALID_MID; @@ -910,11 +976,24 @@ coap_send_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node) { return bytes_written; } -coap_mid_t +COAP_API coap_mid_t coap_send_error(coap_session_t *session, const coap_pdu_t *request, coap_pdu_code_t code, coap_opt_filter_t *opts) { + coap_mid_t mid; + + coap_lock_lock(session->context, return COAP_INVALID_MID); + mid = coap_send_error_lkd(session, request, code, opts); + coap_lock_unlock(session->context); + return mid; +} + +coap_mid_t +coap_send_error_lkd(coap_session_t *session, + const coap_pdu_t *request, + coap_pdu_code_t code, + coap_opt_filter_t *opts) { coap_pdu_t *response; coap_mid_t result = COAP_INVALID_MID; @@ -928,9 +1007,20 @@ coap_send_error(coap_session_t *session, return result; } -coap_mid_t +COAP_API coap_mid_t coap_send_message_type(coap_session_t *session, const coap_pdu_t *request, coap_pdu_type_t type) { + coap_mid_t mid; + + coap_lock_lock(session->context, return COAP_INVALID_MID); + mid = coap_send_message_type_lkd(session, request, type); + coap_lock_unlock(session->context); + return mid; +} + +coap_mid_t +coap_send_message_type_lkd(coap_session_t *session, const coap_pdu_t *request, + coap_pdu_type_t type) { coap_pdu_t *response; coap_mid_t result = COAP_INVALID_MID; @@ -987,7 +1077,7 @@ coap_wait_ack(coap_context_t *context, coap_session_t *session, coap_queue_t *node) { coap_tick_t now; - node->session = coap_session_reference(session); + node->session = coap_session_reference_lkd(session); /* Set timer for pdu retransmission. If this is the first element in * the retransmission queue, the base time is set to the current @@ -1034,7 +1124,7 @@ coap_send_test_extended_token(coap_session_t *session) { /* https://rfc-editor.org/rfc/rfc8974#section-2.2.2 */ pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_REQUEST_CODE_GET, coap_new_message_id_lkd(session), - coap_session_max_pdu_size(session)); + coap_session_max_pdu_size_lkd(session)); if (!pdu) return COAP_INVALID_MID; @@ -1076,14 +1166,14 @@ coap_client_delay_first(coap_session_t *session) { * Need to wait for first request to get out and response back before * continuing.. Response handler has to clear doing_first if not an error. */ - coap_session_reference(session); + coap_session_reference_lkd(session); while (session->doing_first != 0) { int result = coap_io_process_lkd(session->context, 1000); if (result < 0) { session->doing_first = 0; session->delay_recursive = 0; - coap_session_release(session); + coap_session_release_lkd(session); return 0; } @@ -1115,7 +1205,7 @@ coap_client_delay_first(coap_session_t *session) { } } session->delay_recursive = 0; - coap_session_release(session); + coap_session_release_lkd(session); } #else /* ! COAP_CLIENT_SUPPORT */ (void)session; @@ -1151,8 +1241,18 @@ coap_check_code_class(coap_session_t *session, coap_pdu_t *pdu) { return 1; } -coap_mid_t +COAP_API coap_mid_t coap_send(coap_session_t *session, coap_pdu_t *pdu) { + coap_mid_t mid; + + coap_lock_lock(session->context, return COAP_INVALID_MID); + mid = coap_send_lkd(session, pdu); + coap_lock_unlock(session->context); + return mid; +} + +coap_mid_t +coap_send_lkd(coap_session_t *session, coap_pdu_t *pdu) { coap_mid_t mid = COAP_INVALID_MID; #if COAP_CLIENT_SUPPORT coap_lg_crcv_t *lg_crcv = NULL; @@ -1865,7 +1965,7 @@ coap_connect_session(coap_session_t *session, coap_tick_t now) { session->sock.lfunc[COAP_LAYER_SESSION].l_establish(session); } else { coap_handle_event_lkd(session->context, COAP_EVENT_TCP_FAILED, session); - coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + coap_session_disconnected_lkd(session, COAP_NACK_NOT_DELIVERABLE); } #endif /* !COAP_DISABLE_TCP */ } @@ -1928,7 +2028,7 @@ coap_read_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now) if (bytes_read < 0) { if (bytes_read == -2) /* Reset the session back to startup defaults */ - coap_session_disconnected(session, COAP_NACK_ICMP_ISSUE); + coap_session_disconnected_lkd(session, COAP_NACK_ICMP_ISSUE); } else if (bytes_read > 0) { session->last_rx_tx = now; /* coap_netif_dgrm_read() updates session->addr_info from packet->addr_info */ @@ -1944,7 +2044,7 @@ coap_read_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now) packet->payload, packet->length); if (bytes_read < 0) { - coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + coap_session_disconnected_lkd(session, COAP_NACK_NOT_DELIVERABLE); } else if (bytes_read > 2) { coap_pdu_t *pdu; @@ -2082,7 +2182,7 @@ coap_read_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now) } } while (bytes_read == 0 && retry); if (bytes_read < 0) - coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + coap_session_disconnected_lkd(session, COAP_NACK_NOT_DELIVERABLE); #endif /* !COAP_DISABLE_TCP */ } #if COAP_CONSTRAINED_STACK @@ -2190,14 +2290,14 @@ coap_io_do_io_lkd(coap_context_t *ctx, coap_tick_t now) { #endif /* !COAP_DISABLE_TCP */ SESSIONS_ITER_SAFE(ep->sessions, s, rtmp) { /* Make sure the session object is not deleted in one of the callbacks */ - coap_session_reference(s); + coap_session_reference_lkd(s); if ((s->sock.flags & COAP_SOCKET_CAN_READ) != 0) { coap_read_session(ctx, s, now); } if ((s->sock.flags & COAP_SOCKET_CAN_WRITE) != 0) { coap_write_session(ctx, s, now); } - coap_session_release(s); + coap_session_release_lkd(s); } } #endif /* COAP_SERVER_SUPPORT */ @@ -2205,7 +2305,7 @@ coap_io_do_io_lkd(coap_context_t *ctx, coap_tick_t now) { #if COAP_CLIENT_SUPPORT SESSIONS_ITER_SAFE(ctx->sessions, s, rtmp) { /* Make sure the session object is not deleted in one of the callbacks */ - coap_session_reference(s); + coap_session_reference_lkd(s); if ((s->sock.flags & COAP_SOCKET_CAN_CONNECT) != 0) { coap_connect_session(s, now); } @@ -2215,7 +2315,7 @@ coap_io_do_io_lkd(coap_context_t *ctx, coap_tick_t now) { if ((s->sock.flags & COAP_SOCKET_CAN_WRITE) != 0 && s->ref > 1) { coap_write_session(ctx, s, now); } - coap_session_release(s); + coap_session_release_lkd(s); } #endif /* COAP_CLIENT_SUPPORT */ #endif /* ! COAP_EPOLL_SUPPORT */ @@ -2285,7 +2385,7 @@ coap_io_do_epoll_lkd(coap_context_t *ctx, struct epoll_event *events, size_t nev /* Make sure the session object is not deleted in one of the callbacks */ - coap_session_reference(session); + coap_session_reference_lkd(session); #if COAP_CLIENT_SUPPORT if ((sock->flags & COAP_SOCKET_WANT_CONNECT) && (events[j].events & (EPOLLOUT|EPOLLERR|EPOLLHUP|EPOLLRDHUP))) { @@ -2315,7 +2415,7 @@ coap_io_do_epoll_lkd(coap_context_t *ctx, struct epoll_event *events, size_t nev coap_write_session(session->context, session, now); } /* Now dereference session so it can go away if needed */ - coap_session_release(session); + coap_session_release_lkd(session); } } else if (ctx->eptimerfd != -1) { /* @@ -2377,7 +2477,7 @@ coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, * https://rfc-editor.org/rfc/rfc7252#section-4.2 MUST send RST * https://rfc-editor.org/rfc/rfc7252#section-4.3 MAY send RST */ - coap_send_rst(session, pdu); + coap_send_rst_lkd(session, pdu); coap_delete_pdu(pdu); return -1; } @@ -2941,7 +3041,7 @@ handle_request(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu if (async->delay == 0 || async->delay > now) { /* re-transmit missing ACK (only if CON) */ coap_log_info("Retransmit async response\n"); - coap_send_ack(session, pdu); + coap_send_ack_lkd(session, pdu); /* and do not pass on to the upper layers */ return; } @@ -3189,7 +3289,7 @@ handle_request(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu response = coap_pdu_init(pdu->type == COAP_MESSAGE_CON ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON, - 0, pdu->mid, coap_session_max_pdu_size(session)); + 0, pdu->mid, coap_session_max_pdu_size_lkd(session)); if (!response) { coap_log_err("could not create response PDU\n"); resp = 500; @@ -3295,7 +3395,7 @@ handle_request(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu send_early_empty_ack = 1; } if (send_early_empty_ack) { - coap_send_ack(session, pdu); + coap_send_ack_lkd(session, pdu); if (pdu->mid == session->last_con_mid) { /* request has already been processed - do not process it again */ coap_log_debug("Duplicate request with mid=0x%04x - not processed\n", @@ -3507,9 +3607,9 @@ handle_response(coap_context_t *context, coap_session_t *session, if (rcvd->mid == session->last_con_mid) { /* Duplicate response: send ACK/RST, but don't process */ if (session->last_con_handler_res == COAP_RESPONSE_OK) - coap_send_ack(session, rcvd); + coap_send_ack_lkd(session, rcvd); else - coap_send_rst(session, rcvd); + coap_send_rst_lkd(session, rcvd); return; } session->last_con_mid = rcvd->mid; @@ -3564,7 +3664,7 @@ handle_response(coap_context_t *context, coap_session_t *session, /* See if need to send next block to server */ if (coap_handle_response_send_block(session, sent, rcvd)) { /* Next block transmitted, no need to inform app */ - coap_send_ack(session, rcvd); + coap_send_ack_lkd(session, rcvd); return; } @@ -3588,14 +3688,14 @@ handle_response(coap_context_t *context, coap_session_t *session, /* context is being freed off */ return); if (ret == COAP_RESPONSE_FAIL && rcvd->type != COAP_MESSAGE_ACK) { - coap_send_rst(session, rcvd); + coap_send_rst_lkd(session, rcvd); session->last_con_handler_res = COAP_RESPONSE_FAIL; } else { - coap_send_ack(session, rcvd); + coap_send_ack_lkd(session, rcvd); session->last_con_handler_res = COAP_RESPONSE_OK; } } else { - coap_send_ack(session, rcvd); + coap_send_ack_lkd(session, rcvd); session->last_con_handler_res = COAP_RESPONSE_OK; } } @@ -3670,7 +3770,7 @@ handle_signaling(coap_context_t *context, coap_session_t *session, } } else if (pdu->code == COAP_SIGNALING_CODE_RELEASE || pdu->code == COAP_SIGNALING_CODE_ABORT) { - coap_session_disconnected(session, COAP_NACK_RST); + coap_session_disconnected_lkd(session, COAP_NACK_RST); } } #endif /* !COAP_DISABLE_TCP */ @@ -3701,7 +3801,7 @@ check_token_size(coap_session_t *session, const coap_pdu_t *pdu) { } } else { /* Indicate no extended token support */ - coap_send_rst(session, pdu); + coap_send_rst_lkd(session, pdu); } return 0; } @@ -3732,7 +3832,7 @@ coap_dispatch(coap_context_t *context, coap_session_t *session, pdu->code & 0x1f); packet_is_bad = 1; if (pdu->type == COAP_MESSAGE_CON) { - coap_send_message_type(session, pdu, COAP_MESSAGE_RST); + coap_send_message_type_lkd(session, pdu, COAP_MESSAGE_RST); } /* find message id in sendqueue to stop retransmission */ coap_remove_from_queue(&context->sendqueue, session, pdu->mid, &sent); @@ -3745,7 +3845,7 @@ coap_dispatch(coap_context_t *context, coap_session_t *session, if (!COAP_PDU_IS_SIGNALING(pdu) && coap_option_check_critical(session, pdu, &opt_filter) == 0) { if (pdu->type == COAP_MESSAGE_NON) { - coap_send_rst(session, pdu); + coap_send_rst_lkd(session, pdu); goto cleanup; } else if (pdu->type == COAP_MESSAGE_CON) { if (COAP_PDU_IS_REQUEST(pdu)) { @@ -3759,7 +3859,7 @@ coap_dispatch(coap_context_t *context, coap_session_t *session, coap_log_warn("coap_dispatch: error sending response\n"); } } else { - coap_send_rst(session, pdu); + coap_send_rst_lkd(session, pdu); } } goto cleanup; @@ -3951,14 +4051,14 @@ coap_dispatch(coap_context_t *context, coap_session_t *session, LL_FOREACH_SAFE(r->subscribers, obs, tmp) { if (obs->pdu->mid == pdu->mid && obs->session == session) { /* Need to do this now as session may get de-referenced */ - coap_session_reference(session); + coap_session_reference_lkd(session); coap_delete_observer(r, session, &obs->pdu->actual_token); if (context->nack_handler) { coap_lock_callback(context, context->nack_handler(session, NULL, COAP_NACK_RST, pdu->mid)); } - coap_session_release(session); + coap_session_release_lkd(session); goto cleanup; } } @@ -3977,7 +4077,7 @@ coap_dispatch(coap_context_t *context, coap_session_t *session, /* check for unknown critical options */ if (coap_option_check_critical(session, pdu, &opt_filter) == 0) { packet_is_bad = 1; - coap_send_rst(session, pdu); + coap_send_rst_lkd(session, pdu); goto cleanup; } if (!check_token_size(session, pdu)) { @@ -4000,7 +4100,7 @@ coap_dispatch(coap_context_t *context, coap_session_t *session, coap_log_warn("coap_dispatch: error sending response\n"); } } else { - coap_send_rst(session, pdu); + coap_send_rst_lkd(session, pdu); } goto cleanup; } @@ -4048,13 +4148,13 @@ coap_dispatch(coap_context_t *context, coap_session_t *session, coap_tick_t now; coap_ticks(&now); if (session->last_tx_rst + COAP_TICKS_PER_SECOND/4 < now) { - coap_send_message_type(session, pdu, COAP_MESSAGE_RST); + coap_send_message_type_lkd(session, pdu, COAP_MESSAGE_RST); session->last_tx_rst = now; } } } else { if (pdu->type == COAP_MESSAGE_CON) - coap_send_message_type(session, pdu, COAP_MESSAGE_RST); + coap_send_message_type_lkd(session, pdu, COAP_MESSAGE_RST); } } } @@ -4337,16 +4437,34 @@ coap_register_pong_handler(coap_context_t *context, context->pong_handler = handler; } -void +COAP_API void coap_register_option(coap_context_t *ctx, uint16_t type) { + coap_lock_lock(ctx, return); + coap_register_option_lkd(ctx, type); + coap_lock_unlock(ctx); +} + +void +coap_register_option_lkd(coap_context_t *ctx, uint16_t type) { coap_option_filter_set(&ctx->known_options, type); } #if ! defined WITH_CONTIKI && ! defined WITH_LWIP && ! defined RIOT_VERSION #if COAP_SERVER_SUPPORT -int +COAP_API int coap_join_mcast_group_intf(coap_context_t *ctx, const char *group_name, const char *ifname) { + int ret; + + coap_lock_lock(ctx, return -1); + ret = coap_join_mcast_group_intf_lkd(ctx, group_name, ifname); + coap_lock_unlock(ctx); + return ret; +} + +int +coap_join_mcast_group_intf_lkd(coap_context_t *ctx, const char *group_name, + const char *ifname) { #if COAP_IPV4_SUPPORT struct ip_mreq mreq4; #endif /* COAP_IPV4_SUPPORT */ diff --git a/src/coap_openssl.c b/src/coap_openssl.c index d795faebc9..23e5e1c639 100644 --- a/src/coap_openssl.c +++ b/src/coap_openssl.c @@ -3496,12 +3496,12 @@ coap_dtls_send(coap_session_t *session, } if (session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, session->dtls_event, session); if (session->dtls_event == COAP_EVENT_DTLS_ERROR || session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); r = -1; } } @@ -3550,7 +3550,7 @@ coap_dtls_handle_timeout(coap_session_t *session) { if ((++session->dtls_timeout_count > session->max_retransmit) || (DTLSv1_handle_timeout(ssl) < 0)) { /* Too many retries */ - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); return 1; } return 0; @@ -3638,12 +3638,12 @@ coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) r = -1; } if (session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, session->dtls_event, session); if (session->dtls_event == COAP_EVENT_DTLS_ERROR || session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); ssl_data = NULL; r = -1; } @@ -3931,12 +3931,12 @@ coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) { } if (session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, session->dtls_event, session); if (session->dtls_event == COAP_EVENT_DTLS_ERROR || session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); r = -1; } } @@ -4007,12 +4007,12 @@ coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) { } if (session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, session->dtls_event, session); if (session->dtls_event == COAP_EVENT_DTLS_ERROR || session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); r = -1; } } diff --git a/src/coap_oscore.c b/src/coap_oscore.c index 1c6c80e161..dc66010775 100644 --- a/src/coap_oscore.c +++ b/src/coap_oscore.c @@ -89,7 +89,7 @@ coap_new_client_session_oscore_lkd(coap_context_t *ctx, return NULL; if (coap_oscore_initiate(session, oscore_conf) == 0) { - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } return session; @@ -127,7 +127,7 @@ coap_new_client_session_oscore_psk_lkd(coap_context_t *ctx, return NULL; if (coap_oscore_initiate(session, oscore_conf) == 0) { - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } return session; @@ -165,7 +165,7 @@ coap_new_client_session_oscore_pki_lkd(coap_context_t *ctx, return NULL; if (coap_oscore_initiate(session, oscore_conf) == 0) { - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } return session; @@ -752,9 +752,9 @@ coap_oscore_new_pdu_encrypted_lkd(coap_session_t *session, if (session->b_2_step != COAP_OSCORE_B_2_NONE && !session->done_b_1_2) { size_t size; - association->sent_pdu = coap_pdu_duplicate(pdu, session, - pdu_token.length, - pdu_token.s, NULL); + association->sent_pdu = coap_pdu_duplicate_lkd(pdu, session, + pdu_token.length, + pdu_token.s, NULL); if (association->sent_pdu == NULL) goto error; if (coap_get_data(pdu, &size, &data)) { @@ -1494,7 +1494,7 @@ coap_oscore_decrypt_pdu(coap_session_t *session, &pdu->actual_token); if (session->con_active) session->con_active--; - coap_send_ack(session, pdu); + coap_send_ack_lkd(session, pdu); if (sent_pdu) { coap_log_oscore("Appendix B.2 retransmit pdu\n"); if (coap_retransmit_oscore_pdu(session, sent_pdu, NULL) == @@ -1644,7 +1644,7 @@ coap_oscore_decrypt_pdu(coap_session_t *session, if (session->con_active) session->con_active--; if (sent_pdu) { - coap_send_ack(session, pdu); + coap_send_ack_lkd(session, pdu); coap_log_debug("PDU requesting re-transmit\n"); coap_show_pdu(COAP_LOG_DEBUG, decrypt_pdu); coap_log_oscore("RFC9175 retransmit pdu\n"); @@ -1659,7 +1659,7 @@ coap_oscore_decrypt_pdu(coap_session_t *session, return decrypt_pdu; error: - coap_send_ack(session, pdu); + coap_send_ack_lkd(session, pdu); error_no_ack: if (association && association->is_observe == 0) oscore_delete_association(session, association); diff --git a/src/coap_pdu.c b/src/coap_pdu.c index b8341e5100..e116a1abfd 100644 --- a/src/coap_pdu.c +++ b/src/coap_pdu.c @@ -169,7 +169,7 @@ coap_new_pdu_lkd(coap_pdu_type_t type, coap_pdu_code_t code, coap_lock_check_locked(session->context); pdu = coap_pdu_init(type, code, coap_new_message_id_lkd(session), - coap_session_max_pdu_size(session)); + coap_session_max_pdu_size_lkd(session)); if (!pdu) coap_log_crit("coap_new_pdu: cannot allocate memory for new PDU\n"); return pdu; @@ -188,21 +188,40 @@ coap_delete_pdu(coap_pdu_t *pdu) { } } -/* - * Note: This does not include any data, just the token and options - */ -coap_pdu_t * +COAP_API coap_pdu_t * coap_pdu_duplicate(const coap_pdu_t *old_pdu, coap_session_t *session, size_t token_length, const uint8_t *token, coap_opt_filter_t *drop_options) { + coap_pdu_t *new_pdu; + + coap_lock_lock(session->context, return NULL); + new_pdu = coap_pdu_duplicate_lkd(old_pdu, + session, + token_length, + token, + drop_options); + coap_lock_unlock(session->context); + return new_pdu; +} + + +/* + * Note: This does not include any data, just the token and options + */ +coap_pdu_t * +coap_pdu_duplicate_lkd(const coap_pdu_t *old_pdu, + coap_session_t *session, + size_t token_length, + const uint8_t *token, + coap_opt_filter_t *drop_options) { uint8_t doing_first = session->doing_first; coap_pdu_t *pdu; coap_lock_check_locked(session->context); /* - * Need to make sure that coap_session_max_pdu_size() immediately + * Need to make sure that coap_session_max_pdu_size_lkd() immediately * returns, rather than wait for the first CSM response from remote * that indicates BERT size (TCP/TLS only) as this may be called early * the OSCORE logic. @@ -211,7 +230,7 @@ coap_pdu_duplicate(const coap_pdu_t *old_pdu, pdu = coap_pdu_init(old_pdu->type, old_pdu->code, coap_new_message_id_lkd(session), max(old_pdu->max_size, - coap_session_max_pdu_size(session))); + coap_session_max_pdu_size_lkd(session))); /* Restore any pending waits */ session->doing_first = doing_first; if (pdu == NULL) diff --git a/src/coap_resource.c b/src/coap_resource.c index e452908acf..fe34acd183 100644 --- a/src/coap_resource.c +++ b/src/coap_resource.c @@ -489,7 +489,7 @@ coap_free_resource(coap_resource_t *resource) { if (resource->context->observe_deleted) resource->context->observe_deleted(obs->session, obs, resource->context->observe_user_data); - coap_session_release(obs->session); + coap_session_release_lkd(obs->session); coap_delete_pdu(obs->pdu); coap_delete_cache_key(obs->cache_key); coap_free_type(COAP_SUBSCRIPTION, obs); @@ -822,8 +822,8 @@ coap_add_observer(coap_resource_t *resource, } coap_subscription_init(s); - s->pdu = coap_pdu_duplicate(request, session, token->length, - token->s, NULL); + s->pdu = coap_pdu_duplicate_lkd(request, session, token->length, + token->s, NULL); if (s->pdu == NULL) { coap_delete_cache_key(cache_key); coap_free_type(COAP_SUBSCRIPTION, s); @@ -847,7 +847,7 @@ coap_add_observer(coap_resource_t *resource, } } s->cache_key = cache_key; - s->session = coap_session_reference(session); + s->session = coap_session_reference_lkd(session); /* add subscriber to resource */ LL_PREPEND(resource->subscribers, s); @@ -995,7 +995,7 @@ coap_delete_observer(coap_resource_t *resource, coap_session_t *session, if (resource->subscribers && s) { LL_DELETE(resource->subscribers, s); - coap_session_release(session); + coap_session_release_lkd(session); coap_delete_pdu(s->pdu); coap_delete_cache_key(s->cache_key); coap_free_type(COAP_SUBSCRIPTION, s); @@ -1014,7 +1014,7 @@ coap_delete_observers(coap_context_t *context, coap_session_t *session) { context->observe_deleted(session, s, context->observe_user_data); assert(resource->subscribers); LL_DELETE(resource->subscribers, s); - coap_session_release(session); + coap_session_release_lkd(session); coap_delete_pdu(s->pdu); coap_delete_cache_key(s->cache_key); coap_free_type(COAP_SUBSCRIPTION, s); @@ -1071,7 +1071,8 @@ coap_notify_observers(coap_context_t *context, coap_resource_t *r, coap_mid_t mid = COAP_INVALID_MID; obs->dirty = 0; /* initialize response */ - response = coap_pdu_init(COAP_MESSAGE_CON, 0, 0, coap_session_max_pdu_size(obs->session)); + response = coap_pdu_init(COAP_MESSAGE_CON, 0, 0, + coap_session_max_pdu_size_lkd(obs->session)); if (!response) { obs->dirty = 1; r->partiallydirty = 1; diff --git a/src/coap_session.c b/src/coap_session.c index d00ea534ec..e73ead2e66 100644 --- a/src/coap_session.c +++ b/src/coap_session.c @@ -344,15 +344,35 @@ coap_session_get_non_receive_timeout(const coap_session_t *session) { #endif /* ! COAP_Q_BLOCK_SUPPORT */ } -coap_session_t * +COAP_API coap_session_t * coap_session_reference(coap_session_t *session) { - coap_lock_check_locked(session->context); + coap_lock_lock(session->context, return NULL); + coap_session_reference_lkd(session); + coap_lock_unlock(session->context); + return session; +} + +coap_session_t * +coap_session_reference_lkd(coap_session_t *session) { ++session->ref; return session; } -void +COAP_API void coap_session_release(coap_session_t *session) { + if (session) { +#if COAP_THREAD_SAFE + coap_context_t *context = session->context; +#endif /* COAP_THREAD_SAFE */ + + coap_lock_lock(context, return); + coap_session_release_lkd(session); + coap_lock_unlock(context); + } +} + +void +coap_session_release_lkd(coap_session_t *session) { if (session) { coap_lock_check_locked(session->context); #ifndef __COVERITY__ @@ -554,7 +574,7 @@ coap_session_free(coap_session_t *session) { if (session->ref) return; /* Make sure nothing gets deleted under our feet */ - coap_session_reference(session); + coap_session_reference_lkd(session); coap_session_mfree(session); #if COAP_SERVER_SUPPORT if (session->endpoint) { @@ -610,8 +630,24 @@ coap_session_max_pdu_rcv_size(const coap_session_t *session) { (size_t)(session->mtu - session->tls_overhead)); } -size_t +COAP_API size_t coap_session_max_pdu_size(const coap_session_t *session) { + size_t size; + coap_session_t *session_rw; + + /* + * Need to do this to not get a compiler warning about const parameters + * but need to maintain source code backward compatibility + */ + memcpy(&session_rw, &session, sizeof(session_rw)); + coap_lock_lock(session_rw->context, return 0); + size = coap_session_max_pdu_size_lkd(session_rw); + coap_lock_unlock(session_rw->context); + return size; +} + +size_t +coap_session_max_pdu_size_lkd(const coap_session_t *session) { size_t max_with_header; coap_lock_check_locked(session->context); @@ -660,7 +696,7 @@ coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *removed = NULL; coap_remove_from_queue(&session->context->sendqueue, session, node->id, &removed); assert(removed == node); - coap_session_release(node->session); + coap_session_release_lkd(node->session); node->session = NULL; node->t = 0; } else { @@ -720,14 +756,14 @@ coap_session_send_csm(coap_session_t *session) { buf) == 0) || coap_pdu_encode_header(pdu, session->proto) == 0 ) { - coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + coap_session_disconnected_lkd(session, COAP_NACK_NOT_DELIVERABLE); } else { ssize_t bytes_written; pdu->session = session; bytes_written = coap_session_send_pdu(session, pdu); if (bytes_written != (ssize_t)pdu->used_size + pdu->hdr_size) { - coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); + coap_session_disconnected_lkd(session, COAP_NACK_NOT_DELIVERABLE); } else { session->csm_rcv_mtu = session->context->csm_max_message_size; if (session->csm_rcv_mtu > COAP_BERT_BASE) @@ -741,8 +777,18 @@ coap_session_send_csm(coap_session_t *session) { } #endif /* !COAP_DISABLE_TCP */ -coap_mid_t +COAP_API coap_mid_t coap_session_send_ping(coap_session_t *session) { + coap_mid_t mid; + + coap_lock_lock(session->context, return COAP_INVALID_MID); + mid = coap_session_send_ping_lkd(session); + coap_lock_unlock(session->context); + return mid; +} + +coap_mid_t +coap_session_send_ping_lkd(coap_session_t *session) { coap_pdu_t *ping = NULL; coap_lock_check_locked(session->context); @@ -852,8 +898,15 @@ coap_nack_name(coap_nack_reason_t reason) { } #endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_DEBUG */ -void +COAP_API void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason) { + coap_lock_lock(session->context, return); + coap_session_disconnected_lkd(session, reason); + coap_lock_unlock(session->context); +} + +void +coap_session_disconnected_lkd(coap_session_t *session, coap_nack_reason_t reason) { #if !COAP_DISABLE_TCP coap_session_state_t state = session->state; #endif /* !COAP_DISABLE_TCP */ @@ -1204,7 +1257,7 @@ coap_session_create_client(coap_context_t *ctx, if (!session) goto error; - coap_session_reference(session); + coap_session_reference_lkd(session); session->sock.session = session; memcpy(&session->sock.lfunc, coap_layers_coap[proto], sizeof(session->sock.lfunc)); @@ -1258,12 +1311,12 @@ coap_session_create_client(coap_context_t *ctx, error: /* - * Need to add in the session as coap_session_release() + * Need to add in the session as coap_session_release_lkd() * will call SESSIONS_DELETE in coap_session_free(). */ if (session) SESSIONS_ADD(ctx->sessions, session); - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } @@ -1408,12 +1461,12 @@ coap_new_client_session_psk2_lkd(coap_context_t *ctx, setup_data->psk_info.identity.length); if (!session->psk_identity) { coap_log_warn("Cannot store session Identity (PSK)\n"); - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } } else if (coap_dtls_is_supported() || coap_tls_is_supported()) { coap_log_warn("Identity (PSK) not defined\n"); - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } @@ -1422,18 +1475,18 @@ coap_new_client_session_psk2_lkd(coap_context_t *ctx, setup_data->psk_info.key.length); if (!session->psk_key) { coap_log_warn("Cannot store session pre-shared key (PSK)\n"); - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } } else if (coap_dtls_is_supported() || coap_tls_is_supported()) { coap_log_warn("Pre-shared key (PSK) not defined\n"); - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } if (coap_dtls_is_supported() || coap_tls_is_supported()) { if (!coap_dtls_context_set_cpsk(ctx, setup_data)) { - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } } @@ -1602,7 +1655,7 @@ coap_new_client_session_pki_lkd(coap_context_t *ctx, if (coap_dtls_is_supported() || coap_tls_is_supported()) { /* we know that setup_data is not NULL */ if (!coap_dtls_context_set_pki(ctx, setup_data, COAP_DTLS_ROLE_CLIENT)) { - coap_session_release(session); + coap_session_release_lkd(session); return NULL; } } @@ -1648,7 +1701,7 @@ coap_new_server_session(coap_context_t *ctx, coap_endpoint_t *ep, void *extra) { error: /* - * Need to add in the session as coap_session_release() + * Need to add in the session as coap_session_release_lkd() * will call SESSIONS_DELETE in coap_session_free(). */ if (session) { @@ -1749,7 +1802,7 @@ int coap_session_set_type_client(coap_session_t *session) { #if COAP_SERVER_SUPPORT if (session && session->type == COAP_SESSION_TYPE_SERVER) { - coap_session_reference(session); + coap_session_reference_lkd(session); session->type = COAP_SESSION_TYPE_CLIENT; return 1; } @@ -1916,7 +1969,7 @@ coap_new_endpoint_lkd(coap_context_t *context, const coap_address_t *listen_addr return ep; error: - coap_free_endpoint(ep); + coap_free_endpoint_lkd(ep); return NULL; } @@ -1925,8 +1978,22 @@ coap_endpoint_set_default_mtu(coap_endpoint_t *ep, unsigned mtu) { ep->default_mtu = (uint16_t)mtu; } -void +COAP_API void coap_free_endpoint(coap_endpoint_t *ep) { + if (ep) { + coap_context_t *context = ep->context; + if (context) { + coap_lock_lock(context, return); + } + coap_free_endpoint_lkd(ep); + if (context) { + coap_lock_unlock(context); + } + } +} + +void +coap_free_endpoint_lkd(coap_endpoint_t *ep) { if (ep) { coap_session_t *session, *rtmp; diff --git a/src/coap_subscribe.c b/src/coap_subscribe.c index 87216cad6b..b4e6e2d004 100644 --- a/src/coap_subscribe.c +++ b/src/coap_subscribe.c @@ -45,13 +45,33 @@ coap_persist_track_funcs(coap_context_t *context, context->resource_deleted = resource_deleted; } -coap_subscription_t * +COAP_API coap_subscription_t * coap_persist_observe_add(coap_context_t *context, coap_proto_t e_proto, const coap_address_t *e_listen_addr, const coap_addr_tuple_t *s_addr_info, const coap_bin_const_t *raw_packet, const coap_bin_const_t *oscore_info) { + coap_subscription_t *subs; + + coap_lock_lock(context, return NULL); + subs = coap_persist_observe_add_lkd(context, + e_proto, + e_listen_addr, + s_addr_info, + raw_packet, + oscore_info); + coap_lock_unlock(context); + return subs; +} + +coap_subscription_t * +coap_persist_observe_add_lkd(coap_context_t *context, + coap_proto_t e_proto, + const coap_address_t *e_listen_addr, + const coap_addr_tuple_t *s_addr_info, + const coap_bin_const_t *raw_packet, + const coap_bin_const_t *oscore_info) { coap_session_t *session = NULL; const uint8_t *data; size_t data_len; @@ -439,11 +459,11 @@ coap_op_observe_load_disk(coap_context_t *ctx) { &s_addr_info, &raw_packet, &oscore_info)) break; coap_log_debug("persist: New session/observe being created\n"); - observe_key = coap_persist_observe_add(ctx, e_proto, - &e_listen_addr, - &s_addr_info, - raw_packet, - oscore_info); + observe_key = coap_persist_observe_add_lkd(ctx, e_proto, + &e_listen_addr, + &s_addr_info, + raw_packet, + oscore_info); if (observe_key) { if (!coap_op_observe_write(fp_new, observe_key, e_proto, e_listen_addr, s_addr_info, raw_packet, oscore_info)) @@ -1114,12 +1134,30 @@ coap_op_resource_deleted(coap_context_t *context, return 0; } -int +COAP_API int coap_persist_startup(coap_context_t *context, const char *dyn_resource_save_file, const char *observe_save_file, const char *obs_cnt_save_file, uint32_t save_freq) { + int ret; + + coap_lock_lock(context, return 0); + ret = coap_persist_startup_lkd(context, + dyn_resource_save_file, + observe_save_file, + obs_cnt_save_file, + save_freq); + coap_lock_unlock(context); + return ret; +} + +int +coap_persist_startup_lkd(coap_context_t *context, + const char *dyn_resource_save_file, + const char *observe_save_file, + const char *obs_cnt_save_file, + uint32_t save_freq) { coap_lock_check_locked(context); if (dyn_resource_save_file) { context->dyn_resource_save_file = @@ -1169,8 +1207,17 @@ coap_persist_cleanup(coap_context_t *context) { NULL, 0, NULL); } -void +COAP_API void coap_persist_stop(coap_context_t *context) { + if (!context) + return; + coap_lock_lock(context, return); + coap_persist_stop_lkd(context); + coap_lock_unlock(context); +} + +void +coap_persist_stop_lkd(coap_context_t *context) { if (context == NULL) return; coap_lock_check_locked(context); @@ -1178,7 +1225,7 @@ coap_persist_stop(coap_context_t *context) { coap_persist_cleanup(context); } #else /* ! COAP_WITH_OBSERVE_PERSIST */ -int +COAP_API int coap_persist_startup(coap_context_t *context, const char *dyn_resource_save_file, const char *observe_save_file, @@ -1192,7 +1239,7 @@ coap_persist_startup(coap_context_t *context, return 0; } -void +COAP_API void coap_persist_stop(coap_context_t *context) { context->observe_no_clear = 1; /* Close down any tracking */ diff --git a/src/coap_threadsafe.c b/src/coap_threadsafe.c index fa06dec7e7..db99461449 100644 --- a/src/coap_threadsafe.c +++ b/src/coap_threadsafe.c @@ -10,302 +10,12 @@ /** * @file coap_threadsafe.c - * @brief CoAP multithreading safe functions + * @brief CoAP multithreading locking check functions */ -/* - * Public API functions are being migrated across to just ahead of where - * the _locked() functions are for ease of maintenance, debugging and - * documentation. - * - * The internal equivalent of the public API function will get _locked appended - * to the function name, and all calls to this function within the libcoap - * library have the function updated with the _locked suffix. Appropriate - * entries for this function are removed from coap_threadsafe_internal.h. - */ -#include "coap_config.h" +#include "coap3/coap_libcoap_build.h" #if COAP_THREAD_SAFE -#define COAP_THREAD_IGNORE_LOCKED_MAPPING - -#include "coap3/coap_internal.h" - -#if COAP_SERVER_SUPPORT - -/* Server only wrapper functions */ - -int -coap_context_set_pki(coap_context_t *ctx, - const coap_dtls_pki_t *setup_data) { - int ret; - - coap_lock_lock(ctx, return 0); - ret = coap_context_set_pki_locked(ctx, setup_data); - coap_lock_unlock(ctx); - return ret; -} - -int -coap_context_set_psk(coap_context_t *ctx, - const char *hint, - const uint8_t *key, - size_t key_len) { - int ret; - - coap_lock_lock(ctx, return 0); - ret = coap_context_set_psk_locked(ctx, hint, key, key_len); - coap_lock_unlock(ctx); - return ret; -} - -int -coap_context_set_psk2(coap_context_t *ctx, coap_dtls_spsk_t *setup_data) { - int ret; - - coap_lock_lock(ctx, return 0); - ret = coap_context_set_psk2_locked(ctx, setup_data); - coap_lock_unlock(ctx); - return ret; -} - -void -coap_free_endpoint(coap_endpoint_t *ep) { - if (ep) { - coap_context_t *context = ep->context; - if (context) - coap_lock_lock(context, return); - coap_free_endpoint_locked(ep); - if (context) - coap_lock_unlock(context); - } -} - -int -coap_join_mcast_group_intf(coap_context_t *ctx, const char *group_name, - const char *ifname) { - int ret; - - coap_lock_lock(ctx, return -1); - ret = coap_join_mcast_group_intf_locked(ctx, group_name, ifname); - coap_lock_unlock(ctx); - return ret; -} - -coap_subscription_t * -coap_persist_observe_add(coap_context_t *context, - coap_proto_t e_proto, - const coap_address_t *e_listen_addr, - const coap_addr_tuple_t *s_addr_info, - const coap_bin_const_t *raw_packet, - const coap_bin_const_t *oscore_info) { - coap_subscription_t *subs; - - coap_lock_lock(context, return NULL); - subs = coap_persist_observe_add_locked(context, - e_proto, - e_listen_addr, - s_addr_info, - raw_packet, - oscore_info); - coap_lock_unlock(context); - return subs; -} - -int -coap_persist_startup(coap_context_t *context, - const char *dyn_resource_save_file, - const char *observe_save_file, - const char *obs_cnt_save_file, - uint32_t save_freq) { - int ret; - - coap_lock_lock(context, return 0); - ret = coap_persist_startup_locked(context, - dyn_resource_save_file, - observe_save_file, - obs_cnt_save_file, - save_freq); - coap_lock_unlock(context); - return ret; -} - -void -coap_persist_stop(coap_context_t *context) { - if (!context) - return; - coap_lock_lock(context, return); - coap_persist_stop_locked(context); - coap_lock_unlock(context); -} - -#endif /* COAP_SERVER_SUPPORT */ - -/* Both Client and Server wrapper functions */ - -void -coap_context_set_block_mode(coap_context_t *context, - uint32_t block_mode) { - coap_lock_lock(context, return); - coap_context_set_block_mode_locked(context, block_mode); - coap_lock_unlock(context); -} - -int -coap_context_set_max_block_size(coap_context_t *context, - size_t max_block_size) { - int ret; - - coap_lock_lock(context, return 0); - ret = coap_context_set_max_block_size_locked(context, max_block_size); - coap_lock_unlock(context); - return ret; -} - -int -coap_context_set_pki_root_cas(coap_context_t *ctx, - const char *ca_file, - const char *ca_dir) { - int ret; - - coap_lock_lock(ctx, return 0); - ret = coap_context_set_pki_root_cas_locked(ctx, ca_file, ca_dir); - coap_lock_unlock(ctx); - return ret; -} - -coap_pdu_t * -coap_pdu_duplicate(const coap_pdu_t *old_pdu, - coap_session_t *session, - size_t token_length, - const uint8_t *token, - coap_opt_filter_t *drop_options) { - coap_pdu_t *new_pdu; - - coap_lock_lock(session->context, return NULL); - new_pdu = coap_pdu_duplicate_locked(old_pdu, - session, - token_length, - token, - drop_options); - coap_lock_unlock(session->context); - return new_pdu; -} - - -void -coap_register_option(coap_context_t *ctx, uint16_t type) { - coap_lock_lock(ctx, return); - coap_register_option_locked(ctx, type); - coap_lock_unlock(ctx); -} - -coap_mid_t -coap_send(coap_session_t *session, coap_pdu_t *pdu) { - coap_mid_t mid; - - coap_lock_lock(session->context, return COAP_INVALID_MID); - mid = coap_send_locked(session, pdu); - coap_lock_unlock(session->context); - return mid; -} - -coap_mid_t -coap_send_ack(coap_session_t *session, const coap_pdu_t *request) { - coap_mid_t mid; - - coap_lock_lock(session->context, return COAP_INVALID_MID); - mid = coap_send_ack_locked(session, request); - coap_lock_unlock(session->context); - return mid; -} - -coap_mid_t -coap_send_error(coap_session_t *session, - const coap_pdu_t *request, - coap_pdu_code_t code, - coap_opt_filter_t *opts) { - coap_mid_t mid; - - coap_lock_lock(session->context, return COAP_INVALID_MID); - mid = coap_send_error_locked(session, request, code, opts); - coap_lock_unlock(session->context); - return mid; -} - - -coap_mid_t -coap_send_message_type(coap_session_t *session, const coap_pdu_t *request, - coap_pdu_type_t type) { - coap_mid_t mid; - - coap_lock_lock(session->context, return COAP_INVALID_MID); - mid = coap_send_message_type_locked(session, request, type); - coap_lock_unlock(session->context); - return mid; -} - -coap_mid_t -coap_send_rst(coap_session_t *session, const coap_pdu_t *request) { - coap_mid_t mid; - - coap_lock_lock(session->context, return COAP_INVALID_MID); - mid = coap_send_rst_locked(session, request); - coap_lock_unlock(session->context); - return mid; -} - -void -coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason) { - coap_lock_lock(session->context, return); - coap_session_disconnected_locked(session, reason); - coap_lock_unlock(session->context); -} - -size_t -coap_session_max_pdu_size(const coap_session_t *session) { - size_t size; - coap_session_t *session_rw; - - /* - * Need to do this to not get a compiler warning about const parameters - * but need to maintain source code backward compatibility - */ - memcpy(&session_rw, &session, sizeof(session_rw)); - coap_lock_lock(session_rw->context, return 0); - size = coap_session_max_pdu_size_locked(session_rw); - coap_lock_unlock(session_rw->context); - return size; -} - -coap_session_t * -coap_session_reference(coap_session_t *session) { - coap_lock_lock(session->context, return NULL); - coap_session_reference_locked(session); - coap_lock_unlock(session->context); - return session; -} - -void -coap_session_release(coap_session_t *session) { - if (session) { - coap_context_t *context = session->context; - - coap_lock_lock(context, return); - coap_session_release_locked(session); - coap_lock_unlock(context); - } -} - -coap_mid_t -coap_session_send_ping(coap_session_t *session) { - coap_mid_t mid; - - coap_lock_lock(session->context, return COAP_INVALID_MID); - mid = coap_session_send_ping_locked(session); - coap_lock_unlock(session->context); - return mid; -} - #if COAP_THREAD_RECURSIVE_CHECK void coap_lock_unlock_func(coap_lock_t *lock, const char *file, int line) { diff --git a/src/coap_tinydtls.c b/src/coap_tinydtls.c index 1dd57cab1a..bf699374ec 100644 --- a/src/coap_tinydtls.c +++ b/src/coap_tinydtls.c @@ -786,13 +786,13 @@ coap_dtls_send(coap_session_t *session, coap_log_warn("coap_dtls_send: cannot send PDU\n"); if (coap_event_dtls >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, coap_event_dtls, session); if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) coap_session_connected(session); else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); } return res; @@ -855,13 +855,13 @@ coap_dtls_receive(coap_session_t *session, } if (coap_event_dtls >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (coap_event_dtls != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, coap_event_dtls, session); if (coap_event_dtls == COAP_EVENT_DTLS_CONNECTED) coap_session_connected(session); else if (coap_event_dtls == COAP_EVENT_DTLS_CLOSED || coap_event_dtls == COAP_EVENT_DTLS_ERROR) { - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); err = -1; } } diff --git a/src/coap_wolfssl.c b/src/coap_wolfssl.c index 4960fd181d..e62cade802 100644 --- a/src/coap_wolfssl.c +++ b/src/coap_wolfssl.c @@ -2122,12 +2122,12 @@ coap_dtls_send(coap_session_t *session, } if (session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, session->dtls_event, session); if (session->dtls_event == COAP_EVENT_DTLS_ERROR || session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); r = -1; } } @@ -2177,7 +2177,7 @@ coap_dtls_handle_timeout(coap_session_t *session) { w_env->retry_scalar++; if (++session->dtls_timeout_count > session->max_retransmit) { /* Too many retries */ - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); return 1; } wolfSSL_dtls_retransmit(ssl); @@ -2285,12 +2285,12 @@ coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) r = -1; } if (session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, session->dtls_event, session); if (session->dtls_event == COAP_EVENT_DTLS_ERROR || session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); ssl_data = NULL; r = -1; } @@ -2630,12 +2630,12 @@ coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) { } if (session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, session->dtls_event, session); if (session->dtls_event == COAP_EVENT_DTLS_ERROR || session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); r = -1; } } @@ -2720,12 +2720,12 @@ coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) { } if (session->dtls_event >= 0) { - /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */ + /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */ if (session->dtls_event != COAP_EVENT_DTLS_CLOSED) coap_handle_event_lkd(session->context, session->dtls_event, session); if (session->dtls_event == COAP_EVENT_DTLS_ERROR || session->dtls_event == COAP_EVENT_DTLS_CLOSED) { - coap_session_disconnected(session, COAP_NACK_TLS_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_TLS_FAILED); r = -1; } } diff --git a/src/coap_ws.c b/src/coap_ws.c index 7e08939d2b..9d7f4f6cb5 100644 --- a/src/coap_ws.c +++ b/src/coap_ws.c @@ -209,7 +209,7 @@ coap_ws_write(coap_session_t *session, const uint8_t *data, size_t datalen) { if (!session->ws) { session->ws = coap_malloc_type(COAP_STRING, sizeof(coap_ws_state_t)); if (!session->ws) { - coap_session_disconnected(session, COAP_NACK_WS_LAYER_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_WS_LAYER_FAILED); return -1; } memset(session->ws, 0, sizeof(coap_ws_state_t)); @@ -579,7 +579,7 @@ coap_ws_read(coap_session_t *session, uint8_t *data, size_t datalen) { if (!session->ws) { session->ws = coap_malloc_type(COAP_STRING, sizeof(coap_ws_state_t)); if (!session->ws) { - coap_session_disconnected(session, COAP_NACK_WS_LAYER_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_WS_LAYER_FAILED); return -1; } memset(session->ws, 0, sizeof(coap_ws_state_t)); @@ -595,7 +595,7 @@ coap_ws_read(coap_session_t *session, uint8_t *data, size_t datalen) { session->sock.lfunc[COAP_LAYER_WS].l_write(session, (uint8_t *)buf, strlen(buf)); } - coap_session_disconnected(session, COAP_NACK_WS_LAYER_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_WS_LAYER_FAILED); return -1; } @@ -793,7 +793,7 @@ coap_ws_establish(coap_session_t *session) { if (!session->ws) { session->ws = coap_malloc_type(COAP_STRING, sizeof(coap_ws_state_t)); if (!session->ws) { - coap_session_disconnected(session, COAP_NACK_WS_LAYER_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_WS_LAYER_FAILED); return; } memset(session->ws, 0, sizeof(coap_ws_state_t)); @@ -807,7 +807,7 @@ coap_ws_establish(coap_session_t *session) { session->ws->state = COAP_SESSION_TYPE_CLIENT; if (!session->ws_host) { coap_log_err("WS Host not defined\n"); - coap_session_disconnected(session, COAP_NACK_WS_LAYER_FAILED); + coap_session_disconnected_lkd(session, COAP_NACK_WS_LAYER_FAILED); return; } coap_prng(session->ws->key, sizeof(session->ws->key)); diff --git a/src/oscore/oscore_context.c b/src/oscore/oscore_context.c index a0b024e0d0..4dd727c536 100644 --- a/src/oscore/oscore_context.c +++ b/src/oscore/oscore_context.c @@ -705,8 +705,8 @@ oscore_new_association(coap_session_t *session, size_t size; const uint8_t *data; - association->sent_pdu = coap_pdu_duplicate(sent_pdu, session, - token->length, token->s, NULL); + association->sent_pdu = coap_pdu_duplicate_lkd(sent_pdu, session, + token->length, token->s, NULL); if (association->sent_pdu == NULL) goto error; if (coap_get_data(sent_pdu, &size, &data)) { diff --git a/tests/test_common.h.in b/tests/test_common.h.in index 622bf9fbe5..b8d299a6c9 100644 --- a/tests/test_common.h.in +++ b/tests/test_common.h.in @@ -8,7 +8,4 @@ * README for terms of use. */ -/* We need to treat these tests as being an user application */ -#define COAP_THREAD_IGNORE_LOCKED_MAPPING - #include "coap@LIBCOAP_API_VERSION@/coap_internal.h"