/* * coap_net_internal.h -- CoAP context internal information * exposed to application programming * * Copyright (C) 2010-2023 Olaf Bergmann * * SPDX-License-Identifier: BSD-2-Clause * * This file is part of the CoAP library libcoap. Please see README for terms * of use. */ /** * @file coap_net_internal.h * @brief CoAP context internal information */ #ifndef COAP_NET_INTERNAL_H_ #define COAP_NET_INTERNAL_H_ #include "coap_internal.h" #include "coap_subscribe.h" /** * @ingroup internal_api * @defgroup context_internal Context Handling * Internal API for Context Handling * @{ */ /** * Queue entry */ struct coap_queue_t { struct coap_queue_t *next; coap_tick_t t; /**< when to send PDU for the next time */ unsigned char retransmit_cnt; /**< retransmission counter, will be removed * when zero */ uint8_t is_mcast; /**< Set if this is a queued mcast response */ unsigned int timeout; /**< the randomized timeout value */ coap_session_t *session; /**< the CoAP session */ coap_mid_t id; /**< CoAP message id */ coap_pdu_t *pdu; /**< the CoAP PDU to send */ }; /** * The CoAP stack's global state is stored in a coap_context_t object. */ struct coap_context_t { coap_opt_filter_t known_options; #if COAP_SERVER_SUPPORT coap_resource_t *resources; /**< hash table or list of known resources */ coap_resource_t *unknown_resource; /**< can be used for handling unknown resources */ coap_resource_t *proxy_uri_resource; /**< can be used for handling proxy URI resources */ coap_resource_release_userdata_handler_t release_userdata; /**< function to release user_data when resource is deleted */ #endif /* COAP_SERVER_SUPPORT */ #if COAP_ASYNC_SUPPORT /** * list of asynchronous message ids */ coap_async_t *async_state; #endif /* COAP_ASYNC_SUPPORT */ /** * The time stamp in the first element of the sendqeue is relative * to sendqueue_basetime. */ coap_tick_t sendqueue_basetime; coap_queue_t *sendqueue; #if COAP_SERVER_SUPPORT coap_endpoint_t *endpoint; /**< the endpoints used for listening */ #endif /* COAP_SERVER_SUPPORT */ #if COAP_CLIENT_SUPPORT coap_session_t *sessions; /**< client sessions */ #endif /* COAP_CLIENT_SUPPORT */ #ifdef WITH_CONTIKI struct uip_udp_conn *conn; /**< uIP connection object */ struct ctimer prepare_timer; /**< fires when it's time to call coap_io_prepare_io */ #endif /* WITH_CONTIKI */ #ifdef WITH_LWIP coap_lwip_input_wait_handler_t input_wait; /** Input wait / timeout handler if set */ void *input_arg; /** argument to pass it input handler */ uint8_t timer_configured; /**< Set to 1 when a retransmission is * scheduled using lwIP timers for this * context, otherwise 0. */ #endif /* WITH_LWIP */ #if COAP_OSCORE_SUPPORT struct oscore_ctx_t *p_osc_ctx; /**< primary oscore context */ #endif /* COAP_OSCORE_SUPPORT */ #if COAP_CLIENT_SUPPORT coap_response_handler_t response_handler; /**< Called when a response is received */ #endif /* COAP_CLIENT_SUPPORT */ coap_nack_handler_t nack_handler; /**< Called when a response issue has occurred */ coap_ping_handler_t ping_handler; /**< Called when a CoAP ping is received */ coap_pong_handler_t pong_handler; /**< Called when a ping response is received */ #if COAP_SERVER_SUPPORT coap_observe_added_t observe_added; /**< Called when there is a new observe subscription request */ coap_observe_deleted_t observe_deleted; /**< Called when there is a observe subscription de-register request */ void *observe_user_data; /**< App provided data for use in observe_added or observe_deleted */ uint32_t observe_save_freq; /**< How frequently to update observe value */ coap_track_observe_value_t track_observe_value; /**< Callback to save observe value when updated */ coap_dyn_resource_added_t dyn_resource_added; /**< Callback to save dynamic resource when created */ coap_resource_deleted_t resource_deleted; /**< Invoked when resource is deleted */ #if COAP_WITH_OBSERVE_PERSIST coap_bin_const_t *dyn_resource_save_file; /** Where dynamic resource requests that create resources are tracked */ coap_bin_const_t *obs_cnt_save_file; /** Where resource observe counters are tracked */ coap_bin_const_t *observe_save_file; /** Where observes are tracked */ coap_pdu_t *unknown_pdu; /** PDU used for unknown resource request */ coap_session_t *unknown_session; /** Session used for unknown resource request */ #endif /* COAP_WITH_OBSERVE_PERSIST */ #endif /* COAP_SERVER_SUPPORT */ /** * Callback function that is used to signal events to the * application. This field is set by coap_set_event_handler(). */ coap_event_handler_t handle_event; void *dtls_context; #if COAP_SERVER_SUPPORT coap_dtls_spsk_t spsk_setup_data; /**< Contains the initial PSK server setup data */ #endif /* COAP_SERVER_SUPPORT */ unsigned int session_timeout; /**< Number of seconds of inactivity after which an unused session will be closed. 0 means use default. */ unsigned int max_idle_sessions; /**< Maximum number of simultaneous unused sessions per endpoint. 0 means no maximum. */ unsigned int max_handshake_sessions; /**< Maximum number of simultaneous negotating sessions per endpoint. 0 means use default. */ unsigned int ping_timeout; /**< Minimum inactivity time before sending a ping message. 0 means disabled. */ unsigned int csm_timeout; /**< Timeout for waiting for a CSM from the remote side. 0 means disabled. */ uint32_t csm_max_message_size; /**< Value for CSM Max-Message-Size */ uint64_t etag; /**< Next ETag to use */ #if COAP_SERVER_SUPPORT coap_cache_entry_t *cache; /**< CoAP cache-entry cache */ uint16_t *cache_ignore_options; /**< CoAP options to ignore when creating a cache-key */ size_t cache_ignore_count; /**< The number of CoAP options to ignore when creating a cache-key */ #endif /* COAP_SERVER_SUPPORT */ void *app; /**< application-specific data */ uint32_t max_token_size; /**< Largest token size supported RFC8974 */ #ifdef COAP_EPOLL_SUPPORT int epfd; /**< External FD for epoll */ int eptimerfd; /**< Internal FD for timeout */ coap_tick_t next_timeout; /**< When the next timeout is to occur */ #else /* ! COAP_EPOLL_SUPPORT */ fd_set readfds, writefds, exceptfds; /**< Used for select call in coap_io_process_with_fds() */ coap_socket_t *sockets[64]; /**< Track different socket information in coap_io_process_with_fds */ unsigned int num_sockets; /**< Number of sockets being tracked */ #endif /* ! COAP_EPOLL_SUPPORT */ #if COAP_SERVER_SUPPORT uint8_t observe_pending; /**< Observe response pending */ uint8_t observe_no_clear; /**< Observe 4.04 not to be sent on deleting resource */ uint8_t mcast_per_resource; /**< Mcast controlled on a per resource basis */ #endif /* COAP_SERVER_SUPPORT */ uint8_t block_mode; /**< Zero or more COAP_BLOCK_ or'd options */ }; /** * Adds @p node to given @p queue, ordered by variable t in @p node. * * @param queue Queue to add to. * @param node Node entry to add to Queue. * * @return @c 1 added to queue, @c 0 failure. */ int coap_insert_node(coap_queue_t **queue, coap_queue_t *node); /** * Destroys specified @p node. * * @param node Node entry to remove. * * @return @c 1 node deleted from queue, @c 0 failure. */ int coap_delete_node(coap_queue_t *node); /** * Removes all items from given @p queue and frees the allocated storage. * * Internal function. * * @param queue The queue to delete. */ void coap_delete_all(coap_queue_t *queue); /** * Creates a new node suitable for adding to the CoAP sendqueue. * * @return New node entry, or @c NULL if failure. */ coap_queue_t *coap_new_node(void); /** * Set sendqueue_basetime in the given context object @p ctx to @p now. This * function returns the number of elements in the queue head that have timed * out. */ unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now); /** * Returns the next pdu to send without removing from sendqeue. */ coap_queue_t *coap_peek_next(coap_context_t *context); /** * Returns the next pdu to send and removes it from the sendqeue. */ coap_queue_t *coap_pop_next(coap_context_t *context); /** * Handles retransmissions of confirmable messages * * @param context The CoAP context. * @param node The node to retransmit. * * @return The message id of the sent message or @c * COAP_INVALID_MID on error. */ coap_mid_t coap_retransmit(coap_context_t *context, coap_queue_t *node); /** * Parses and interprets a CoAP datagram with context @p ctx. This function * returns @c 0 if the datagram was handled, or a value less than zero on * error. * * @param ctx The current CoAP context. * @param session The current CoAP session. * @param data The received packet'd data. * @param data_len The received packet'd data length. * * @return @c 0 if message was handled successfully, or less than zero on * error. */ int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *data, size_t data_len); /** * This function removes the element with given @p id from the list given list. * If @p id was found, @p node is updated to point to the removed element. Note * that the storage allocated by @p node is @b not released. The caller must do * this manually using coap_delete_node(). This function returns @c 1 if the * element with id @p id was found, @c 0 otherwise. For a return value of @c 0, * the contents of @p node is undefined. * * @param queue The queue to search for @p id. * @param session The session to look for. * @param id The message id to look for. * @param node If found, @p node is updated to point to the removed node. You * must release the storage pointed to by @p node manually. * * @return @c 1 if @p id was found, @c 0 otherwise. */ int coap_remove_from_queue(coap_queue_t **queue, coap_session_t *session, coap_mid_t id, coap_queue_t **node); coap_mid_t coap_wait_ack(coap_context_t *context, coap_session_t *session, coap_queue_t *node); /** * Cancels all outstanding messages for session @p session that have the specified * token. * * @param context The context in use. * @param session Session of the messages to remove. * @param token Message token. */ void coap_cancel_all_messages(coap_context_t *context, coap_session_t *session, coap_bin_const_t *token); /** * Cancels all outstanding messages for session @p session. * * @param context The context in use. * @param session Session of the messages to remove. * @param reason The reasion for the session cancellation */ void coap_cancel_session_messages(coap_context_t *context, coap_session_t *session, coap_nack_reason_t reason); /** * Dispatches the PDUs from the receive queue in given context. */ void coap_dispatch(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu); /** * Verifies that @p pdu contains no unknown critical options. Options must be * registered at @p ctx, using the function coap_register_option(). A basic set * of options is registered automatically by coap_new_context(). This function * returns @c 1 if @p pdu is ok, @c 0 otherwise. The given filter object @p * unknown will be updated with the unknown options. As only @c COAP_MAX_OPT * options can be signalled this way, remaining options must be examined * manually. * * @code coap_opt_filter_t f = COAP_OPT_NONE; coap_opt_iterator_t opt_iter; if (coap_option_check_critical(session, pdu, f) == 0) { coap_option_iterator_init(pdu, &opt_iter, f); while (coap_option_next(&opt_iter)) { if (opt_iter.type & 0x01) { ... handle unknown critical option in opt_iter ... } } } @endcode * * @param session The current session. * @param pdu The PDU to check. * @param unknown The output filter that will be updated to indicate the * unknown critical options found in @p pdu. * * @return @c 1 if everything was ok, @c 0 otherwise. */ int coap_option_check_critical(coap_session_t *session, coap_pdu_t *pdu, coap_opt_filter_t *unknown); /** * Creates a new response for given @p request with the contents of @c * .well-known/core. The result is NULL on error or a newly allocated PDU that * must be either sent with coap_sent() or released by coap_delete_pdu(). * * @param context The current coap context to use. * @param session The CoAP session. * @param request The request for @c .well-known/core . * * @return A new 2.05 response for @c .well-known/core or NULL on error. */ coap_pdu_t *coap_wellknown_response(coap_context_t *context, coap_session_t *session, coap_pdu_t *request); /** * Calculates the initial timeout based on the session CoAP transmission * parameters 'ack_timeout', 'ack_random_factor', and COAP_TICKS_PER_SECOND. * The calculation requires 'ack_timeout' and 'ack_random_factor' to be in * Qx.FRAC_BITS fixed point notation, whereas the passed parameter @p r * is interpreted as the fractional part of a Q0.MAX_BITS random value. * * @param session session timeout is associated with * @param r random value as fractional part of a Q0.MAX_BITS fixed point * value * @return COAP_TICKS_PER_SECOND * 'ack_timeout' * * (1 + ('ack_random_factor' - 1) * r) */ unsigned int coap_calc_timeout(coap_session_t *session, unsigned char r); /** * Sends a CoAP message to given peer. The memory that is * allocated for the pdu will be released by coap_send_internal(). * The caller must not use the pdu after calling coap_send_internal(). * * If the response body is split into multiple payloads using blocks, libcoap * will handle asking for the subsequent blocks and any necessary recovery * needed. * * @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_internal(coap_session_t *session, coap_pdu_t *pdu); /** * Delay the sending of the first client request until some other negotiation * has completed. * * @param session The CoAP session. * * @return @c 1 if everything was ok, @c 0 otherwise. */ int coap_client_delay_first(coap_session_t *session); /** @} */ extern int coap_started; #endif /* COAP_NET_INTERNAL_H_ */