1 /* coap_session.h -- Session management for libcoap
2 *
3 * Copyright (C) 2017 Jean-Claue Michelou <jcm@spinetix.com>
4 *
5  * SPDX-License-Identifier: BSD-2-Clause
6  *
7 * This file is part of the CoAP library libcoap. Please see
8 * README for terms of use.
9 */
10 
11 /**
12  * @file coap_session.h
13  * @brief Defines the application visible session information
14  */
15 
16 #ifndef COAP_SESSION_H_
17 #define COAP_SESSION_H_
18 
19 /**
20  * @defgroup session Sessions
21  * API functions for CoAP Sessions
22  * @{
23  */
24 
25 /**
26 * Abstraction of a fixed point number that can be used where necessary instead
27 * of a float.  1,000 fractional bits equals one integer
28 */
29 typedef struct coap_fixed_point_t {
30   uint16_t integer_part;    /**< Integer part of fixed point variable */
31   uint16_t fractional_part; /**< Fractional part of fixed point variable
32                                 1/1000 (3 points) precision */
33 } coap_fixed_point_t;
34 
35 #define COAP_PROTO_NOT_RELIABLE(p) ((p)==COAP_PROTO_UDP || (p)==COAP_PROTO_DTLS)
36 #define COAP_PROTO_RELIABLE(p) ((p)==COAP_PROTO_TCP || (p)==COAP_PROTO_TLS)
37 
38 /**
39  * coap_session_type_t values
40  */
41 typedef enum coap_session_type_t {
42   COAP_SESSION_TYPE_NONE = 0, /**< Not defined */
43   COAP_SESSION_TYPE_CLIENT,   /**< client-side */
44   COAP_SESSION_TYPE_SERVER,   /**< server-side */
45   COAP_SESSION_TYPE_HELLO,    /**< server-side ephemeral session for
46                                    responding to a client hello */
47 } coap_session_type_t;
48 
49 /**
50  * coap_session_state_t values
51  */
52 typedef enum coap_session_state_t {
53   COAP_SESSION_STATE_NONE = 0,
54   COAP_SESSION_STATE_CONNECTING,
55   COAP_SESSION_STATE_HANDSHAKE,
56   COAP_SESSION_STATE_CSM,
57   COAP_SESSION_STATE_ESTABLISHED,
58 } coap_session_state_t;
59 
60 /**
61  * Increment reference counter on a session.
62  *
63  * @param session The CoAP session.
64  * @return same as session
65  */
66 coap_session_t *coap_session_reference(coap_session_t *session);
67 
68 /**
69  * Decrement reference counter on a session.
70  * Note that the session may be deleted as a result and should not be used
71  * after this call.
72  *
73  * @param session The CoAP session.
74  */
75 void coap_session_release(coap_session_t *session);
76 
77 /**
78  * Notify session that it has failed.  This cleans up any outstanding / queued
79  * transmissions, observations etc..
80  *
81  * @param session The CoAP session.
82  * @param reason The reason why the session was disconnected.
83  */
84 void coap_session_disconnected(coap_session_t *session,
85                                coap_nack_reason_t reason);
86 
87 /**
88  * Stores @p data with the given session. This function overwrites any value
89  * that has previously been stored with @p session.
90  *
91  * @param session The CoAP session.
92  * @param data The pointer to the data to store.
93  */
94 void coap_session_set_app_data(coap_session_t *session, void *data);
95 
96 /**
97  * Returns any application-specific data that has been stored with @p
98  * session using the function coap_session_set_app_data(). This function will
99  * return @c NULL if no data has been stored.
100  *
101  * @param session The CoAP session.
102  *
103  * @return Pointer to the stored data or @c NULL.
104  */
105 void *coap_session_get_app_data(const coap_session_t *session);
106 
107 /**
108  * Get the remote IP address from the session.
109  *
110  * @param session The CoAP session.
111  *
112  * @return The session's remote address or @c NULL on failure.
113  */
114 const coap_address_t *coap_session_get_addr_remote(
115                                                const coap_session_t *session);
116 
117 /**
118  * Get the local IP address from the session.
119  *
120  * @param session The CoAP session.
121  *
122  * @return The session's local address or @c NULL on failure.
123  */
124 const coap_address_t *coap_session_get_addr_local(
125                                                const coap_session_t *session);
126 
127 /**
128  * Get the session protocol type
129  *
130  * @param session The CoAP session.
131  *
132  * @return The session's protocol type
133  */
134 coap_proto_t coap_session_get_proto(const coap_session_t *session);
135 
136 /**
137  * Get the session type
138  *
139  * @param session The CoAP session.
140  *
141  * @return The session's type
142  */
143 coap_session_type_t coap_session_get_type(const coap_session_t *session);
144 
145 /**
146  * Get the session state
147  *
148  * @param session The CoAP session.
149  *
150  * @return The session's state
151  */
152 coap_session_state_t coap_session_get_state(const coap_session_t *session);
153 
154 /**
155  * Get the session if index
156  *
157  * @param session The CoAP session.
158  *
159  * @return The session's if index, or @c -1 on error.
160  */
161 int coap_session_get_ifindex(const coap_session_t *session);
162 
163 /**
164  * Get the session TLS security ptr (TLS type dependent)
165  *
166  * OpenSSL:  SSL*
167  * GnuTLS:   gnutls_session_t (implicit *)
168  * Mbed TLS: mbedtls_ssl_context*
169  * TinyDTLS: struct dtls_context*
170  *
171  * @param session The CoAP session.
172  * @param tls_lib Updated with the library type.
173  *
174  * @return The session TLS ptr or @c NULL if not set up
175  */
176 void *coap_session_get_tls(const coap_session_t *session,
177                            coap_tls_library_t *tls_lib);
178 
179 /**
180  * Get the session context
181  *
182  * @param session The CoAP session.
183  *
184  * @return The session's context
185  */
186 coap_context_t *coap_session_get_context(const coap_session_t *session);
187 
188 /**
189  * Set the session type to client. Typically used in a call-home server.
190  * The session needs to be of type COAP_SESSION_TYPE_SERVER.
191  * Note: If this function is successful, the session reference count is
192  * incremented and a subsequent coap_session_release() taking the
193  * reference count to 0 will cause the session to be freed off.
194  *
195  * @param session The CoAP session.
196  *
197  * @return @c 1 if updated, @c 0 on failure.
198  */
199 int coap_session_set_type_client(coap_session_t *session);
200 
201 /**
202  * Set the session MTU. This is the maximum message size that can be sent,
203  * excluding IP and UDP overhead.
204  *
205  * @param session The CoAP session.
206  * @param mtu maximum message size
207  */
208 void coap_session_set_mtu(coap_session_t *session, unsigned mtu);
209 
210 /**
211  * Get maximum acceptable PDU size
212  *
213  * @param session The CoAP session.
214  * @return maximum PDU size, not including header (but including token).
215  */
216 size_t coap_session_max_pdu_size(const coap_session_t *session);
217 
218 /**
219 * Creates a new client session to the designated server.
220 * @param ctx The CoAP context.
221 * @param local_if Address of local interface. It is recommended to use NULL to let the operating system choose a suitable local interface. If an address is specified, the port number should be zero, which means that a free port is automatically selected.
222 * @param server The server's address. If the port number is zero, the default port for the protocol will be used.
223 * @param proto Protocol.
224 *
225 * @return A new CoAP session or NULL if failed. Call coap_session_release to free.
226 */
227 coap_session_t *coap_new_client_session(
228   coap_context_t *ctx,
229   const coap_address_t *local_if,
230   const coap_address_t *server,
231   coap_proto_t proto
232 );
233 
234 /**
235 * Creates a new client session to the designated server with PSK credentials
236 * @param ctx The CoAP context.
237 * @param local_if Address of local interface. It is recommended to use NULL to let the operating system choose a suitable local interface. If an address is specified, the port number should be zero, which means that a free port is automatically selected.
238 * @param server The server's address. If the port number is zero, the default port for the protocol will be used.
239 * @param proto Protocol.
240 * @param identity PSK client identity
241 * @param key PSK shared key
242 * @param key_len PSK shared key length
243 *
244 * @return A new CoAP session or NULL if failed. Call coap_session_release to free.
245 */
246 coap_session_t *coap_new_client_session_psk(
247   coap_context_t *ctx,
248   const coap_address_t *local_if,
249   const coap_address_t *server,
250   coap_proto_t proto,
251   const char *identity,
252   const uint8_t *key,
253   unsigned key_len
254 );
255 
256 /**
257 * Creates a new client session to the designated server with PSK credentials
258 * @param ctx The CoAP context.
259 * @param local_if Address of local interface. It is recommended to use NULL to
260 *                 let the operating system choose a suitable local interface.
261 *                 If an address is specified, the port number should be zero,
262 *                 which means that a free port is automatically selected.
263 * @param server The server's address. If the port number is zero, the default
264 *               port for the protocol will be used.
265 * @param proto CoAP Protocol.
266 * @param setup_data PSK parameters.
267 *
268 * @return A new CoAP session or NULL if failed. Call coap_session_release()
269 *         to free.
270 */
271 coap_session_t *coap_new_client_session_psk2(
272   coap_context_t *ctx,
273   const coap_address_t *local_if,
274   const coap_address_t *server,
275   coap_proto_t proto,
276   coap_dtls_cpsk_t *setup_data
277 );
278 
279 /**
280  * Get the server session's current Identity Hint (PSK).
281  *
282  * @param session  The current coap_session_t object.
283  *
284  * @return @c hint if successful, else @c NULL.
285  */
286 const coap_bin_const_t * coap_session_get_psk_hint(
287                                                const coap_session_t *session);
288 
289 /**
290  * Get the session's current pre-shared key (PSK).
291  *
292  * @param session  The current coap_session_t object.
293  *
294  * @return @c psk_key if successful, else @c NULL.
295  */
296 const coap_bin_const_t * coap_session_get_psk_key(
297                                                const coap_session_t *session);
298 
299 /**
300 * Creates a new client session to the designated server with PKI credentials
301 * @param ctx The CoAP context.
302 * @param local_if Address of local interface. It is recommended to use NULL to
303 *                 let the operating system choose a suitable local interface.
304 *                 If an address is specified, the port number should be zero,
305 *                 which means that a free port is automatically selected.
306 * @param server The server's address. If the port number is zero, the default
307 *               port for the protocol will be used.
308 * @param proto CoAP Protocol.
309 * @param setup_data PKI parameters.
310 *
311 * @return A new CoAP session or NULL if failed. Call coap_session_release()
312 *         to free.
313 */
314 coap_session_t *coap_new_client_session_pki(
315   coap_context_t *ctx,
316   const coap_address_t *local_if,
317   const coap_address_t *server,
318   coap_proto_t proto,
319   coap_dtls_pki_t *setup_data
320 );
321 
322 /**
323  * Initializes the token value to use as a starting point.
324  *
325  * @param session The current coap_session_t object.
326  * @param length  The length of the token (0 - 8 bytes).
327  * @param token   The token data.
328  *
329  */
330 void coap_session_init_token(coap_session_t *session, size_t length,
331                              const uint8_t *token);
332 
333 /**
334  * Creates a new token for use.
335  *
336  * @param session The current coap_session_t object.
337  * @param length  Updated with the length of the new token.
338  * @param token   Updated with the new token data (must be 8 bytes long).
339  *
340  */
341 void coap_session_new_token(coap_session_t *session, size_t *length,
342                                       uint8_t *token);
343 
344 /**
345  * @ingroup logging
346  * Get session description.
347  *
348  * @param session  The CoAP session.
349  * @return description string.
350  */
351 const char *coap_session_str(const coap_session_t *session);
352 
353 /**
354 * Create a new endpoint for communicating with peers.
355 *
356 * @param context        The coap context that will own the new endpoint
357 * @param listen_addr    Address the endpoint will listen for incoming requests on or originate outgoing requests from. Use NULL to specify that no incoming request will be accepted and use a random endpoint.
358 * @param proto          Protocol used on this endpoint
359 */
360 
361 coap_endpoint_t *coap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto);
362 
363 /**
364 * Set the endpoint's default MTU. This is the maximum message size that can be
365 * sent, excluding IP and UDP overhead.
366 *
367 * @param endpoint The CoAP endpoint.
368 * @param mtu maximum message size
369 */
370 void coap_endpoint_set_default_mtu(coap_endpoint_t *endpoint, unsigned mtu);
371 
372 void coap_free_endpoint(coap_endpoint_t *ep);
373 
374 /** @} */
375 
376 /**
377  * @ingroup logging
378 * Get endpoint description.
379 *
380 * @param endpoint  The CoAP endpoint.
381 * @return description string.
382 */
383 const char *coap_endpoint_str(const coap_endpoint_t *endpoint);
384 
385 coap_session_t *coap_session_get_by_peer(const coap_context_t *ctx,
386   const coap_address_t *remote_addr, int ifindex);
387 
388  /**
389   * @defgroup cc Rate Control
390   * The transmission parameters for CoAP rate control ("Congestion
391   * Control" in stream-oriented protocols) are defined in
392   * https://tools.ietf.org/html/rfc7252#section-4.8
393   * @{
394   */
395 
396   /**
397    * Number of seconds when to expect an ACK or a response to an
398    * outstanding CON message.
399    * RFC 7252, Section 4.8 Default value of ACK_TIMEOUT is 2
400    *
401    * Configurable using coap_session_set_ack_timeout()
402    */
403 #define COAP_DEFAULT_ACK_TIMEOUT ((coap_fixed_point_t){2,0})
404 
405   /**
406    * A factor that is used to randomize the wait time before a message
407    * is retransmitted to prevent synchronization effects.
408    * RFC 7252, Section 4.8 Default value of ACK_RANDOM_FACTOR is 1.5
409    *
410    * Configurable using coap_session_set_ack_random_factor()
411    */
412 #define COAP_DEFAULT_ACK_RANDOM_FACTOR ((coap_fixed_point_t){1,500})
413 
414   /**
415    * Number of message retransmissions before message sending is stopped
416    * RFC 7252, Section 4.8 Default value of MAX_RETRANSMIT is 4
417    *
418    * Configurable using coap_session_set_max_retransmit()
419    */
420 #define COAP_DEFAULT_MAX_RETRANSMIT  4
421 
422   /**
423    * The number of simultaneous outstanding interactions that a client
424    * maintains to a given server.
425    * RFC 7252, Section 4.8 Default value of NSTART is 1
426    */
427 #define COAP_DEFAULT_NSTART 1
428 
429   /**
430    * The maximum number of seconds before sending back a response to a
431    * multicast request.
432    * RFC 7252, Section 4.8 DEFAULT_LEISURE is 5.
433    */
434 #ifndef COAP_DEFAULT_LEISURE
435 #define COAP_DEFAULT_LEISURE (5U)
436 #endif /* COAP_DEFAULT_LEISURE */
437 
438   /**
439    * The MAX_TRANSMIT_SPAN definition for the session (s).
440    *
441    * RFC 7252, Section 4.8.2 Calculation of MAX_TRAMSMIT_SPAN
442    *  ACK_TIMEOUT * ((2 ** (MAX_RETRANSMIT)) - 1) * ACK_RANDOM_FACTOR
443    */
444 #define COAP_MAX_TRANSMIT_SPAN(s) \
445  ((s->ack_timeout.integer_part * 1000 + s->ack_timeout.fractional_part) * \
446   ((1 << (s->max_retransmit)) -1) * \
447   (s->ack_random_factor.integer_part * 1000 + \
448    s->ack_random_factor.fractional_part) \
449   / 1000000)
450 
451   /**
452    * The MAX_TRANSMIT_WAIT definition for the session (s).
453    *
454    * RFC 7252, Section 4.8.2 Calculation of MAX_TRAMSMIT_WAIT
455    *  ACK_TIMEOUT * ((2 ** (MAX_RETRANSMIT + 1)) - 1) * ACK_RANDOM_FACTOR
456    */
457 #define COAP_MAX_TRANSMIT_WAIT(s) \
458  ((s->ack_timeout.integer_part * 1000 + s->ack_timeout.fractional_part) * \
459   ((1 << (s->max_retransmit + 1)) -1) * \
460   (s->ack_random_factor.integer_part * 1000 + \
461    s->ack_random_factor.fractional_part) \
462   / 1000000)
463 
464   /**
465    * The MAX_LATENCY definition.
466    * RFC 7252, Section 4.8.2 MAX_LATENCY is 100.
467    */
468 #define COAP_MAX_LATENCY 100
469 
470   /**
471    * The PROCESSING_DELAY definition for the session (s).
472    *
473    * RFC 7252, Section 4.8.2 Calculation of PROCESSING_DELAY
474    *  PROCESSING_DELAY set to ACK_TIMEOUT
475    */
476 #define COAP_PROCESSING_DELAY(s) \
477  ((s->ack_timeout.integer_part * 1000 + s->ack_timeout.fractional_part + 500) \
478   / 1000)
479 
480   /**
481    * The MAX_RTT definition for the session (s).
482    *
483    * RFC 7252, Section 4.8.2 Calculation of MAX_RTT
484    *  (2 * MAX_LATENCY) + PROCESSING_DELAY
485    */
486 #define COAP_MAX_RTT(s) \
487  ((2 * COAP_MAX_LATENCY) + COAP_PROCESSING_DELAY(s))
488 
489   /**
490    * The EXCHANGE_LIFETIME definition for the session (s).
491    *
492    * RFC 7252, Section 4.8.2 Calculation of EXCHANGE_LIFETIME
493    *  MAX_TRANSMIT_SPAN + (2 * MAX_LATENCY) + PROCESSING_DELAY
494    */
495 #define COAP_EXCHANGE_LIFETIME(s) \
496  (COAP_MAX_TRANSMIT_SPAN(s) + (2 * COAP_MAX_LATENCY) + COAP_PROCESSING_DELAY(s))
497 
498   /**
499    * The NON_LIFETIME definition for the session (s).
500    *
501    * RFC 7252, Section 4.8.2 Calculation of NON_LIFETIME
502    *  MAX_TRANSMIT_SPAN + MAX_LATENCY
503    */
504 #define COAP_NON_LIFETIME(s) \
505  (COAP_MAX_TRANSMIT_SPAN(s) + COAP_MAX_LATENCY)
506 
507       /** @} */
508 
509 /**
510 * Set the CoAP maximum retransmit count before failure
511 *
512 * Number of message retransmissions before message sending is stopped
513 *
514 * @param session The CoAP session.
515 * @param value The value to set to. The default is 4 and should not normally
516 *              get changed.
517 */
518 void coap_session_set_max_retransmit(coap_session_t *session,
519                                      unsigned int value);
520 
521 /**
522 * Set the CoAP initial ack response timeout before the next re-transmit
523 *
524 * Number of seconds when to expect an ACK or a response to an
525 * outstanding CON message.
526 *
527 * @param session The CoAP session.
528 * @param value The value to set to. The default is 2 and should not normally
529 *              get changed.
530 */
531 void coap_session_set_ack_timeout(coap_session_t *session,
532                                   coap_fixed_point_t value);
533 
534 /**
535 * Set the CoAP ack randomize factor
536 *
537 * A factor that is used to randomize the wait time before a message
538 * is retransmitted to prevent synchronization effects.
539 *
540 * @param session The CoAP session.
541 * @param value The value to set to. The default is 1.5 and should not normally
542 *              get changed.
543 */
544 void coap_session_set_ack_random_factor(coap_session_t *session,
545                                         coap_fixed_point_t value);
546 
547 /**
548 * Get the CoAP maximum retransmit before failure
549 *
550 * Number of message retransmissions before message sending is stopped
551 *
552 * @param session The CoAP session.
553 *
554 * @return Current maximum retransmit value
555 */
556 unsigned int coap_session_get_max_retransmit(const coap_session_t *session);
557 
558 /**
559 * Get the CoAP initial ack response timeout before the next re-transmit
560 *
561 * Number of seconds when to expect an ACK or a response to an
562 * outstanding CON message.
563 *
564 * @param session The CoAP session.
565 *
566 * @return Current ack response timeout value
567 */
568 coap_fixed_point_t coap_session_get_ack_timeout(const coap_session_t *session);
569 
570 /**
571 * Get the CoAP ack randomize factor
572 *
573 * A factor that is used to randomize the wait time before a message
574 * is retransmitted to prevent synchronization effects.
575 *
576 * @param session The CoAP session.
577 *
578 * @return Current ack randomize value
579 */
580 coap_fixed_point_t coap_session_get_ack_random_factor(
581                                                const coap_session_t *session);
582 
583 /**
584  * Send a ping message for the session.
585  * @param session The CoAP session.
586  *
587  * @return COAP_INVALID_MID if there is an error
588  */
589 coap_mid_t coap_session_send_ping(coap_session_t *session);
590 
591 #endif  /* COAP_SESSION_H */
592