• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * coap_net_internal.h -- CoAP context internal information
3  * exposed to application programming
4  *
5  * Copyright (C) 2010-2023 Olaf Bergmann <bergmann@tzi.org>
6  *
7  * SPDX-License-Identifier: BSD-2-Clause
8  *
9  * This file is part of the CoAP library libcoap. Please see README for terms
10  * of use.
11  */
12 
13 /**
14  * @file coap_net_internal.h
15  * @brief CoAP context internal information
16  */
17 
18 #ifndef COAP_NET_INTERNAL_H_
19 #define COAP_NET_INTERNAL_H_
20 
21 #include "coap_internal.h"
22 #include "coap_subscribe.h"
23 
24 /**
25  * @ingroup internal_api
26  * @defgroup context_internal Context Handling
27  * Internal API for Context Handling
28  * @{
29  */
30 
31 /**
32  * Queue entry
33  */
34 struct coap_queue_t {
35   struct coap_queue_t *next;
36   coap_tick_t t;                /**< when to send PDU for the next time */
37   unsigned char retransmit_cnt; /**< retransmission counter, will be removed
38                                  *    when zero */
39   uint8_t is_mcast;             /**< Set if this is a queued mcast response */
40   unsigned int timeout;         /**< the randomized timeout value */
41   coap_session_t *session;      /**< the CoAP session */
42   coap_mid_t id;                /**< CoAP message id */
43   coap_pdu_t *pdu;              /**< the CoAP PDU to send */
44 };
45 
46 /**
47  * The CoAP stack's global state is stored in a coap_context_t object.
48  */
49 struct coap_context_t {
50   coap_opt_filter_t known_options;
51 #if COAP_SERVER_SUPPORT
52   coap_resource_t *resources; /**< hash table or list of known
53                                    resources */
54   coap_resource_t *unknown_resource; /**< can be used for handling
55                                           unknown resources */
56   coap_resource_t *proxy_uri_resource; /**< can be used for handling
57                                             proxy URI resources */
58   coap_resource_release_userdata_handler_t release_userdata;
59   /**< function to  release user_data
60        when resource is deleted */
61 #endif /* COAP_SERVER_SUPPORT */
62 
63 #if COAP_ASYNC_SUPPORT
64   /**
65    * list of asynchronous message ids */
66   coap_async_t *async_state;
67 #endif /* COAP_ASYNC_SUPPORT */
68 
69   /**
70    * The time stamp in the first element of the sendqeue is relative
71    * to sendqueue_basetime. */
72   coap_tick_t sendqueue_basetime;
73   coap_queue_t *sendqueue;
74 #if COAP_SERVER_SUPPORT
75   coap_endpoint_t *endpoint;      /**< the endpoints used for listening  */
76 #endif /* COAP_SERVER_SUPPORT */
77 #if COAP_CLIENT_SUPPORT
78   coap_session_t *sessions;       /**< client sessions */
79 #endif /* COAP_CLIENT_SUPPORT */
80 
81 #ifdef WITH_CONTIKI
82   struct uip_udp_conn *conn;      /**< uIP connection object */
83   struct ctimer prepare_timer;    /**< fires when it's time to call
84                                        coap_io_prepare_io */
85 #endif /* WITH_CONTIKI */
86 
87 #ifdef WITH_LWIP
88   coap_lwip_input_wait_handler_t input_wait; /** Input wait / timeout handler if set */
89   void *input_arg;                /** argument to pass it input handler */
90   uint8_t timer_configured;       /**< Set to 1 when a retransmission is
91                                    *   scheduled using lwIP timers for this
92                                    *   context, otherwise 0. */
93 #endif /* WITH_LWIP */
94 #if COAP_OSCORE_SUPPORT
95   struct oscore_ctx_t *p_osc_ctx; /**< primary oscore context  */
96 #endif /* COAP_OSCORE_SUPPORT */
97 
98 #if COAP_CLIENT_SUPPORT
99   coap_response_handler_t response_handler; /**< Called when a response is
100                                                  received */
101 #endif /* COAP_CLIENT_SUPPORT */
102   coap_nack_handler_t nack_handler; /**< Called when a response issue has
103                                          occurred */
104   coap_ping_handler_t ping_handler; /**< Called when a CoAP ping is received */
105   coap_pong_handler_t pong_handler; /**< Called when a ping response
106                                          is received */
107 
108 #if COAP_SERVER_SUPPORT
109   coap_observe_added_t observe_added; /**< Called when there is a new observe
110                                            subscription request */
111   coap_observe_deleted_t observe_deleted; /**< Called when there is a observe
112                                            subscription de-register request */
113   void *observe_user_data; /**< App provided data for use in observe_added or
114                                 observe_deleted */
115   uint32_t observe_save_freq; /**< How frequently to update observe value */
116   coap_track_observe_value_t track_observe_value; /**< Callback to save observe
117                                                        value when updated */
118   coap_dyn_resource_added_t dyn_resource_added; /**< Callback to save dynamic
119                                                      resource when created */
120   coap_resource_deleted_t resource_deleted; /**< Invoked when resource
121                                                  is deleted */
122 #if COAP_WITH_OBSERVE_PERSIST
123   coap_bin_const_t *dyn_resource_save_file; /** Where dynamic resource requests
124                                                 that create resources are
125                                                 tracked */
126   coap_bin_const_t *obs_cnt_save_file; /** Where resource observe counters are
127                                             tracked */
128   coap_bin_const_t *observe_save_file; /** Where observes are tracked */
129   coap_pdu_t *unknown_pdu;        /** PDU used for unknown resource request */
130   coap_session_t *unknown_session; /** Session used for unknown resource request */
131 #endif /* COAP_WITH_OBSERVE_PERSIST */
132 #endif /* COAP_SERVER_SUPPORT */
133 
134   /**
135    * Callback function that is used to signal events to the
136    * application.  This field is set by coap_set_event_handler().
137    */
138   coap_event_handler_t handle_event;
139 
140   void *dtls_context;
141 
142 #if COAP_SERVER_SUPPORT
143   coap_dtls_spsk_t spsk_setup_data;  /**< Contains the initial PSK server setup
144                                           data */
145 #endif /* COAP_SERVER_SUPPORT */
146 
147   unsigned int session_timeout;    /**< Number of seconds of inactivity after
148                                         which an unused session will be closed.
149                                         0 means use default. */
150   unsigned int max_idle_sessions;  /**< Maximum number of simultaneous unused
151                                         sessions per endpoint. 0 means no
152                                         maximum. */
153   unsigned int max_handshake_sessions; /**< Maximum number of simultaneous
154                                             negotating sessions per endpoint. 0
155                                             means use default. */
156   unsigned int ping_timeout;           /**< Minimum inactivity time before
157                                             sending a ping message. 0 means
158                                             disabled. */
159   unsigned int csm_timeout;           /**< Timeout for waiting for a CSM from
160                                            the remote side. 0 means disabled. */
161   uint32_t csm_max_message_size;   /**< Value for CSM Max-Message-Size */
162   uint64_t etag;                   /**< Next ETag to use */
163 
164 #if COAP_SERVER_SUPPORT
165   coap_cache_entry_t *cache;       /**< CoAP cache-entry cache */
166   uint16_t *cache_ignore_options;  /**< CoAP options to ignore when creating a
167                                         cache-key */
168   size_t cache_ignore_count;       /**< The number of CoAP options to ignore
169                                         when creating a cache-key */
170 #endif /* COAP_SERVER_SUPPORT */
171   void *app;                       /**< application-specific data */
172   uint32_t max_token_size;         /**< Largest token size supported RFC8974 */
173 #ifdef COAP_EPOLL_SUPPORT
174   int epfd;                        /**< External FD for epoll */
175   int eptimerfd;                   /**< Internal FD for timeout */
176   coap_tick_t next_timeout;        /**< When the next timeout is to occur */
177 #else /* ! COAP_EPOLL_SUPPORT */
178   fd_set readfds, writefds, exceptfds; /**< Used for select call
179                                             in coap_io_process_with_fds() */
180   coap_socket_t *sockets[64];      /**< Track different socket information
181                                         in coap_io_process_with_fds */
182   unsigned int num_sockets;        /**< Number of sockets being tracked */
183 #endif /* ! COAP_EPOLL_SUPPORT */
184 #if COAP_SERVER_SUPPORT
185   uint8_t observe_pending;         /**< Observe response pending */
186   uint8_t observe_no_clear;        /**< Observe 4.04 not to be sent on deleting
187                                         resource */
188   uint8_t mcast_per_resource;      /**< Mcast controlled on a per resource
189                                         basis */
190 #endif /* COAP_SERVER_SUPPORT */
191   uint8_t block_mode;              /**< Zero or more COAP_BLOCK_ or'd options */
192 };
193 
194 /**
195  * Adds @p node to given @p queue, ordered by variable t in @p node.
196  *
197  * @param queue Queue to add to.
198  * @param node Node entry to add to Queue.
199  *
200  * @return @c 1 added to queue, @c 0 failure.
201  */
202 int coap_insert_node(coap_queue_t **queue, coap_queue_t *node);
203 
204 /**
205  * Destroys specified @p node.
206  *
207  * @param node Node entry to remove.
208  *
209  * @return @c 1 node deleted from queue, @c 0 failure.
210  */
211 int coap_delete_node(coap_queue_t *node);
212 
213 /**
214  * Removes all items from given @p queue and frees the allocated storage.
215  *
216  * Internal function.
217  *
218  * @param queue The queue to delete.
219  */
220 void coap_delete_all(coap_queue_t *queue);
221 
222 /**
223  * Creates a new node suitable for adding to the CoAP sendqueue.
224  *
225  * @return New node entry, or @c NULL if failure.
226  */
227 coap_queue_t *coap_new_node(void);
228 
229 /**
230  * Set sendqueue_basetime in the given context object @p ctx to @p now. This
231  * function returns the number of elements in the queue head that have timed
232  * out.
233  */
234 unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now);
235 
236 /**
237  * Returns the next pdu to send without removing from sendqeue.
238  */
239 coap_queue_t *coap_peek_next(coap_context_t *context);
240 
241 /**
242  * Returns the next pdu to send and removes it from the sendqeue.
243  */
244 coap_queue_t *coap_pop_next(coap_context_t *context);
245 
246 /**
247  * Handles retransmissions of confirmable messages
248  *
249  * @param context      The CoAP context.
250  * @param node         The node to retransmit.
251  *
252  * @return             The message id of the sent message or @c
253  *                     COAP_INVALID_MID on error.
254  */
255 coap_mid_t coap_retransmit(coap_context_t *context, coap_queue_t *node);
256 
257 /**
258  * Parses and interprets a CoAP datagram with context @p ctx. This function
259  * returns @c 0 if the datagram was handled, or a value less than zero on
260  * error.
261  *
262  * @param ctx    The current CoAP context.
263  * @param session The current CoAP session.
264  * @param data The received packet'd data.
265  * @param data_len The received packet'd data length.
266  *
267  * @return       @c 0 if message was handled successfully, or less than zero on
268  *               error.
269  */
270 int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *data, size_t data_len);
271 
272 /**
273  * This function removes the element with given @p id from the list given list.
274  * If @p id was found, @p node is updated to point to the removed element. Note
275  * that the storage allocated by @p node is @b not released. The caller must do
276  * this manually using coap_delete_node(). This function returns @c 1 if the
277  * element with id @p id was found, @c 0 otherwise. For a return value of @c 0,
278  * the contents of @p node is undefined.
279  *
280  * @param queue The queue to search for @p id.
281  * @param session The session to look for.
282  * @param id    The message id to look for.
283  * @param node  If found, @p node is updated to point to the removed node. You
284  *              must release the storage pointed to by @p node manually.
285  *
286  * @return      @c 1 if @p id was found, @c 0 otherwise.
287  */
288 int coap_remove_from_queue(coap_queue_t **queue,
289                            coap_session_t *session,
290                            coap_mid_t id,
291                            coap_queue_t **node);
292 
293 coap_mid_t coap_wait_ack(coap_context_t *context, coap_session_t *session,
294                          coap_queue_t *node);
295 
296 /**
297  * Cancels all outstanding messages for session @p session that have the specified
298  * token.
299  *
300  * @param context      The context in use.
301  * @param session      Session of the messages to remove.
302  * @param token        Message token.
303  */
304 void coap_cancel_all_messages(coap_context_t *context,
305                               coap_session_t *session,
306                               coap_bin_const_t *token);
307 
308 /**
309 * Cancels all outstanding messages for session @p session.
310 *
311 * @param context      The context in use.
312 * @param session      Session of the messages to remove.
313 * @param reason       The reasion for the session cancellation
314 */
315 void coap_cancel_session_messages(coap_context_t *context,
316                                   coap_session_t *session,
317                                   coap_nack_reason_t reason);
318 
319 /**
320  * Dispatches the PDUs from the receive queue in given context.
321  */
322 void coap_dispatch(coap_context_t *context, coap_session_t *session,
323                    coap_pdu_t *pdu);
324 
325 /**
326  * Verifies that @p pdu contains no unknown critical options. Options must be
327  * registered at @p ctx, using the function coap_register_option(). A basic set
328  * of options is registered automatically by coap_new_context(). This function
329  * returns @c 1 if @p pdu is ok, @c 0 otherwise. The given filter object @p
330  * unknown will be updated with the unknown options. As only @c COAP_MAX_OPT
331  * options can be signalled this way, remaining options must be examined
332  * manually.
333  *
334  * @code
335   coap_opt_filter_t f = COAP_OPT_NONE;
336   coap_opt_iterator_t opt_iter;
337 
338   if (coap_option_check_critical(session, pdu, f) == 0) {
339     coap_option_iterator_init(pdu, &opt_iter, f);
340 
341     while (coap_option_next(&opt_iter)) {
342       if (opt_iter.type & 0x01) {
343         ... handle unknown critical option in opt_iter ...
344       }
345     }
346   }
347    @endcode
348  *
349  * @param session  The current session.
350  * @param pdu      The PDU to check.
351  * @param unknown  The output filter that will be updated to indicate the
352  *                 unknown critical options found in @p pdu.
353  *
354  * @return         @c 1 if everything was ok, @c 0 otherwise.
355  */
356 int coap_option_check_critical(coap_session_t *session,
357                                coap_pdu_t *pdu,
358                                coap_opt_filter_t *unknown);
359 
360 /**
361  * Creates a new response for given @p request with the contents of @c
362  * .well-known/core. The result is NULL on error or a newly allocated PDU that
363  * must be either sent with coap_sent() or released by coap_delete_pdu().
364  *
365  * @param context The current coap context to use.
366  * @param session The CoAP session.
367  * @param request The request for @c .well-known/core .
368  *
369  * @return        A new 2.05 response for @c .well-known/core or NULL on error.
370  */
371 coap_pdu_t *coap_wellknown_response(coap_context_t *context,
372                                     coap_session_t *session,
373                                     coap_pdu_t *request);
374 
375 /**
376  * Calculates the initial timeout based on the session CoAP transmission
377  * parameters 'ack_timeout', 'ack_random_factor', and COAP_TICKS_PER_SECOND.
378  * The calculation requires 'ack_timeout' and 'ack_random_factor' to be in
379  * Qx.FRAC_BITS fixed point notation, whereas the passed parameter @p r
380  * is interpreted as the fractional part of a Q0.MAX_BITS random value.
381  *
382  * @param session session timeout is associated with
383  * @param r  random value as fractional part of a Q0.MAX_BITS fixed point
384  *           value
385  * @return   COAP_TICKS_PER_SECOND * 'ack_timeout' *
386  *           (1 + ('ack_random_factor' - 1) * r)
387  */
388 unsigned int coap_calc_timeout(coap_session_t *session, unsigned char r);
389 
390 /**
391  * Sends a CoAP message to given peer. The memory that is
392  * allocated for the pdu will be released by coap_send_internal().
393  * The caller must not use the pdu after calling coap_send_internal().
394  *
395  * If the response body is split into multiple payloads using blocks, libcoap
396  * will handle asking for the subsequent blocks and any necessary recovery
397  * needed.
398  *
399  * @param session   The CoAP session.
400  * @param pdu       The CoAP PDU to send.
401  *
402  * @return          The message id of the sent message or @c
403  *                  COAP_INVALID_MID on error.
404  */
405 coap_mid_t coap_send_internal(coap_session_t *session, coap_pdu_t *pdu);
406 
407 /**
408  * Delay the sending of the first client request until some other negotiation
409  * has completed.
410  *
411  * @param session   The CoAP session.
412  *
413  * @return          @c 1 if everything was ok, @c 0 otherwise.
414  */
415 int coap_client_delay_first(coap_session_t *session);
416 
417 /** @} */
418 
419 extern int coap_started;
420 
421 #endif /* COAP_NET_INTERNAL_H_ */
422