1/* 2 * coap_session_internal.h -- Structures, Enums & Functions that are not 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_session_internal.h 15 * @brief CoAP session internal information 16 */ 17 18#ifndef COAP_SESSION_INTERNAL_H_ 19#define COAP_SESSION_INTERNAL_H_ 20 21#include "coap_internal.h" 22#include "coap_io_internal.h" 23#include "coap_ws_internal.h" 24 25#define COAP_DEFAULT_SESSION_TIMEOUT 300 26#define COAP_PARTIAL_SESSION_TIMEOUT_TICKS (30 * COAP_TICKS_PER_SECOND) 27#define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS 100 28 29/** 30 * @ingroup internal_api 31 * @defgroup session_internal Sessions 32 * Internal API for handling Sessions 33 * @{ 34 */ 35 36/** 37 * Only used for servers for hashing incoming packets. Cannot have local IP 38 * address as this may be an initial multicast and subsequent unicast address 39 */ 40struct coap_addr_hash_t { 41 coap_address_t remote; /**< remote address and port */ 42 uint16_t lport; /**< local port */ 43 coap_proto_t proto; /**< CoAP protocol */ 44}; 45 46typedef enum { 47 COAP_OSCORE_B_2_NONE = 0, 48 COAP_OSCORE_B_2_STEP_1, 49 COAP_OSCORE_B_2_STEP_2, 50 COAP_OSCORE_B_2_STEP_3, 51 COAP_OSCORE_B_2_STEP_4, 52 COAP_OSCORE_B_2_STEP_5, 53} COAP_OSCORE_B_2_STEP; 54 55/** 56 * coap_ext_token_check_t values 57 */ 58typedef enum coap_ext_token_check_t { 59 COAP_EXT_T_NOT_CHECKED = 0, /**< Not checked */ 60 COAP_EXT_T_CHECKED, /**< Token size valid */ 61 COAP_EXT_T_CHECKING, /**< Token size check request sent */ 62} coap_ext_token_check_t; 63 64/** 65 * Abstraction of virtual session that can be attached to coap_context_t 66 * (client) or coap_endpoint_t (server). 67 */ 68struct coap_session_t { 69 coap_proto_t proto; /**< protocol used */ 70 coap_session_type_t type; /**< client or server side socket */ 71 coap_session_state_t state; /**< current state of relationship with 72 peer */ 73 unsigned ref; /**< reference count from queues */ 74 size_t tls_overhead; /**< overhead of TLS layer */ 75 size_t mtu; /**< path or CSM mtu (xmt) */ 76 size_t csm_rcv_mtu; /**< CSM mtu (rcv) */ 77 coap_addr_hash_t addr_hash; /**< Address hash for server incoming packets */ 78 UT_hash_handle hh; 79 coap_addr_tuple_t addr_info; /**< remote/local address info */ 80 int ifindex; /**< interface index */ 81 coap_socket_t sock; /**< socket object for the session, if 82 any */ 83#if COAP_SERVER_SUPPORT 84 coap_endpoint_t *endpoint; /**< session's endpoint */ 85#endif /* COAP_SERVER_SUPPORT */ 86 coap_context_t *context; /**< session's context */ 87 void *tls; /**< security parameters */ 88 uint16_t tx_mid; /**< the last message id that was used in 89 this session */ 90 uint8_t con_active; /**< Active CON request sent */ 91 uint8_t csm_block_supported; /**< CSM TCP blocks supported */ 92 coap_mid_t last_ping_mid; /**< the last keepalive message id that was 93 used in this session */ 94 coap_queue_t *delayqueue; /**< list of delayed messages waiting to 95 be sent */ 96 coap_lg_xmit_t *lg_xmit; /**< list of large transmissions */ 97#if COAP_CLIENT_SUPPORT 98 coap_lg_crcv_t *lg_crcv; /**< Client list of expected large receives */ 99#endif /* COAP_CLIENT_SUPPORT */ 100#if COAP_SERVER_SUPPORT 101 coap_lg_srcv_t *lg_srcv; /**< Server list of expected large receives */ 102#endif /* COAP_SERVER_SUPPORT */ 103 size_t partial_write; /**< if > 0 indicates number of bytes 104 already written from the pdu at the 105 head of sendqueue */ 106 uint8_t read_header[8]; /**< storage space for header of incoming 107 message header */ 108 size_t partial_read; /**< if > 0 indicates number of bytes 109 already read for an incoming message */ 110 coap_pdu_t *partial_pdu; /**< incomplete incoming pdu */ 111 coap_tick_t last_rx_tx; 112 coap_tick_t last_tx_rst; 113 coap_tick_t last_ping; 114 coap_tick_t last_pong; 115 coap_tick_t csm_tx; 116 coap_dtls_cpsk_t cpsk_setup_data; /**< client provided PSK initial setup 117 data */ 118 coap_bin_const_t *psk_identity; /**< If client, this field contains the 119 current identity for server; When this 120 field is NULL, the current identity is 121 contained in cpsk_setup_data 122 123 If server, this field contains the client 124 provided identity. 125 126 Value maintained internally */ 127 coap_bin_const_t *psk_key; /**< If client, this field contains the 128 current pre-shared key for server; 129 When this field is NULL, the current 130 key is contained in cpsk_setup_data 131 132 If server, this field contains the 133 client's current key. 134 135 Value maintained internally */ 136 coap_bin_const_t *psk_hint; /**< If client, this field contains the 137 server provided identity hint. 138 139 If server, this field contains the 140 current hint for the client; When this 141 field is NULL, the current hint is 142 contained in context->spsk_setup_data 143 144 Value maintained internally */ 145 void *app; /**< application-specific data */ 146 coap_fixed_point_t ack_timeout; /**< timeout waiting for ack 147 (default 2.0 secs) */ 148 coap_fixed_point_t ack_random_factor; /**< ack random factor backoff (default 149 1.5) */ 150 uint16_t max_retransmit; /**< maximum re-transmit count 151 (default 4) */ 152 uint16_t nstart; /**< maximum concurrent confirmable xmits 153 (default 1) */ 154 coap_fixed_point_t default_leisure; /**< Mcast leisure time 155 (default 5.0 secs) */ 156 uint32_t probing_rate; /**< Max transfer wait when remote is not 157 respoding (default 1 byte/sec) */ 158#if COAP_Q_BLOCK_SUPPORT 159 uint16_t max_payloads; /**< maximum Q-BlockX payloads before delay 160 (default 10) */ 161 uint16_t non_max_retransmit; /**< maximum Q-BlockX non re-transmit count 162 (default 4) */ 163 coap_fixed_point_t non_timeout; /**< Q-BlockX timeout waiting for response 164 (default 2.0 secs) */ 165 coap_fixed_point_t non_receive_timeout; /**< Q-BlockX receive timeout before 166 requesting missing packets. 167 (default 4.0 secs) */ 168 coap_fixed_point_t non_probing_wait_base; /**< Q-BlockX max wait time base 169 while probing 170 (default 247.0 secs) */ 171 coap_fixed_point_t non_partial_timeout; /**< Q-BlockX time to wait before 172 discarding partial data for a body. 173 (default 247.0 secs) */ 174#endif /* COAP_Q_BLOCK_SUPPORT */ 175 unsigned int dtls_timeout_count; /**< dtls setup retry counter */ 176 int dtls_event; /**< Tracking any (D)TLS events on this 177 session */ 178 uint32_t tx_rtag; /**< Next Request-Tag number to use */ 179 uint8_t csm_bert_rem_support; /**< CSM TCP BERT blocks supported (remote) */ 180 uint8_t csm_bert_loc_support; /**< CSM TCP BERT blocks supported (local) */ 181 uint8_t block_mode; /**< Zero or more COAP_BLOCK_ or'd options */ 182 uint8_t doing_first; /**< Set if doing client's first request */ 183 uint8_t proxy_session; /**< Set if this is an ongoing proxy session */ 184 uint8_t delay_recursive; /**< Set if in coap_client_delay_first() */ 185 uint8_t no_observe_cancel; /**< Set if do not cancel observe on session 186 close */ 187#if COAP_OSCORE_SUPPORT 188 uint8_t oscore_encryption; /**< OSCORE is used for this session */ 189 COAP_OSCORE_B_2_STEP b_2_step; /**< Appendix B.2 negotiation step */ 190 oscore_recipient_ctx_t *recipient_ctx; /**< OSCORE recipient context 191 for session */ 192 oscore_association_t *associations; /**< OSCORE set of response 193 associations */ 194 uint64_t oscore_r2; /**< R2 for RFC8613 Appendix B.2 */ 195#endif /* COAP_OSCORE_SUPPORT */ 196#if COAP_WS_SUPPORT 197 coap_ws_state_t *ws; /**< WS state */ 198 coap_str_const_t *ws_host; /**< Host to use in WS Request */ 199#endif /* COAP_WS_SUPPORT */ 200 volatile uint8_t max_token_checked; /**< Check for max token size 201 coap_ext_token_check_t */ 202 uint16_t remote_test_mid; /**< mid used for checking remote 203 support */ 204 uint32_t max_token_size; /**< Largest token size supported RFC8974 */ 205 uint64_t tx_token; /**< Next token number to use */ 206 coap_bin_const_t *last_token; /** last token used to make a request */ 207 coap_bin_const_t *echo; /**< Echo value to send with next request */ 208 coap_mid_t last_ack_mid; /**< The last ACK mid that has been 209 been processed */ 210 coap_mid_t last_con_mid; /**< The last CON mid that has been 211 been processed */ 212}; 213 214#if COAP_SERVER_SUPPORT 215/** 216 * Abstraction of virtual endpoint that can be attached to coap_context_t. The 217 * keys (port, bind_addr) must uniquely identify this endpoint. 218 */ 219struct coap_endpoint_t { 220 struct coap_endpoint_t *next; 221 coap_context_t *context; /**< endpoint's context */ 222 coap_proto_t proto; /**< protocol used on this interface */ 223 uint16_t default_mtu; /**< default mtu for this interface */ 224 coap_socket_t sock; /**< socket object for the interface, if 225 any */ 226 coap_address_t bind_addr; /**< local interface address */ 227 coap_session_t *sessions; /**< hash table or list of active sessions */ 228}; 229#endif /* COAP_SERVER_SUPPORT */ 230 231coap_fixed_point_t coap_multi_fixed_fixed(coap_fixed_point_t fp1, 232 coap_fixed_point_t fp2); 233 234coap_fixed_point_t coap_multi_fixed_uint(coap_fixed_point_t fp1, 235 uint32_t u2); 236 237coap_fixed_point_t coap_add_fixed_fixed(coap_fixed_point_t fp1, 238 coap_fixed_point_t fp2); 239 240coap_fixed_point_t coap_add_fixed_uint(coap_fixed_point_t fp1, 241 uint32_t u2); 242 243coap_fixed_point_t coap_sub_fixed_uint(coap_fixed_point_t fp1, 244 uint32_t u2); 245 246coap_fixed_point_t coap_div_fixed_uint(coap_fixed_point_t fp1, uint32_t u2); 247 248coap_fixed_point_t coap_get_non_timeout_random(coap_session_t *session); 249 250coap_tick_t coap_get_non_timeout_random_ticks(coap_session_t *session); 251 252 253/** 254 * Notify session transport has just connected and CSM exchange can now start. 255 * 256 * @param session The CoAP session. 257 */ 258void coap_session_send_csm(coap_session_t *session); 259 260/** 261 * Notify session that it has just connected or reconnected. 262 * 263 * @param session The CoAP session. 264 */ 265void coap_session_connected(coap_session_t *session); 266 267/** 268 * Refresh the session's current Identity Hint (PSK). 269 * Note: A copy of @p psk_hint is maintained in the session by libcoap. 270 * 271 * @param session The current coap_session_t object. 272 * @param psk_hint If NULL, the Identity Hint will revert to the 273 * initial Identity Hint used at session setup. 274 * 275 * @return @c 1 if successful, else @c 0. 276 */ 277int coap_session_refresh_psk_hint(coap_session_t *session, 278 const coap_bin_const_t *psk_hint); 279 280/** 281 * Refresh the session's current pre-shared key (PSK). 282 * Note: A copy of @p psk_key is maintained in the session by libcoap. 283 * 284 * @param session The current coap_session_t object. 285 * @param psk_key If NULL, the pre-shared key will revert to the 286 * initial pre-shared key used at session setup. 287 * 288 * @return @c 1 if successful, else @c 0. 289 */ 290int coap_session_refresh_psk_key(coap_session_t *session, 291 const coap_bin_const_t *psk_key); 292 293/** 294 * Refresh the session's current pre-shared identity (PSK). 295 * Note: A copy of @p psk_identity is maintained in the session by libcoap. 296 * 297 * @param session The current coap_session_t object. 298 * @param psk_identity If NULL, the pre-shared identity will revert to the 299 * initial pre-shared key used as session setup. 300 * 301 * @return @c 1 if successful, else @c 0. 302 */ 303int coap_session_refresh_psk_identity(coap_session_t *session, 304 const coap_bin_const_t *psk_identity); 305 306#if COAP_SERVER_SUPPORT 307/** 308 * Creates a new server session for the specified endpoint. 309 * @param ctx The CoAP context. 310 * @param ep An endpoint where an incoming connection request is pending. 311 * 312 * @return A new CoAP session or NULL if failed. Call coap_session_release to 313 * add to unused queue. 314 */ 315coap_session_t *coap_new_server_session( 316 coap_context_t *ctx, 317 coap_endpoint_t *ep 318); 319#endif /* COAP_SERVER_SUPPORT */ 320 321/** 322 * Layer function interface for layer below session accept/connect being 323 * established. This function initiates a CSM request for reliable protocols, 324 * or coap_session_connect() for un-reliable protocols. 325 * 326 * @param session Session that the lower layer accept/connect was done on. 327 * 328 */ 329void coap_session_establish(coap_session_t *session); 330 331/** 332 * Send a pdu according to the session's protocol. This function returns 333 * the number of bytes that have been transmitted, or a value less than zero 334 * on error. 335 * 336 * @param session Session to send pdu on. 337 * @param pdu The pdu to send. 338 * 339 * @return The number of bytes written on success, or a value 340 * less than zero on error. 341 */ 342ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu); 343 344ssize_t coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, 345 coap_queue_t *node); 346 347#if COAP_SERVER_SUPPORT 348/** 349 * Lookup the server session for the packet received on an endpoint, or create 350 * a new one. 351 * 352 * @param endpoint Active endpoint the packet was received on. 353 * @param packet Received packet. 354 * @param now The current time in ticks. 355 * @return The CoAP session or @c NULL if error. 356 */ 357coap_session_t *coap_endpoint_get_session(coap_endpoint_t *endpoint, 358 const coap_packet_t *packet, coap_tick_t now); 359#endif /* COAP_SERVER_SUPPORT */ 360 361/** 362 * Get maximum acceptable receive PDU size 363 * 364 * @param session The CoAP session. 365 * @return maximum PDU size, not including header (but including token). 366 */ 367size_t coap_session_max_pdu_rcv_size(const coap_session_t *session); 368 369/** 370 * Create a new DTLS session for the @p session. 371 * Note: the @p session is released if no DTLS server session can be created. 372 * 373 * @ingroup dtls_internal 374 * 375 * @param session Session to add DTLS session to 376 * @param now The current time in ticks. 377 * 378 * @return CoAP session or @c NULL if error. 379 */ 380coap_session_t *coap_session_new_dtls_session(coap_session_t *session, 381 coap_tick_t now); 382 383void coap_session_free(coap_session_t *session); 384void coap_session_mfree(coap_session_t *session); 385 386#define COAP_SESSION_REF(s) ((s)->ref 387 388/* RFC7252 */ 389#define COAP_ACK_TIMEOUT(s) ((s)->ack_timeout) 390#define COAP_ACK_RANDOM_FACTOR(s) ((s)->ack_random_factor) 391#define COAP_MAX_RETRANSMIT(s) ((s)->max_retransmit) 392#define COAP_NSTART(s) ((s)->nstart) 393#define COAP_DEFAULT_LEISURE(s) ((s)->default_leisure) 394#define COAP_PROBING_RATE(s) ((s)->probing_rate) 395/* RFC9177 */ 396#define COAP_MAX_PAYLOADS(s) ((s)->max_payloads) 397#define COAP_NON_MAX_RETRANSMIT(s) ((s)->non_max_retransmit) 398#define COAP_NON_TIMEOUT(s) ((s)->non_timeout) 399#define COAP_NON_TIMEOUT_TICKS(s) \ 400 (COAP_NON_TIMEOUT(s).integer_part * COAP_TICKS_PER_SECOND + \ 401 COAP_NON_TIMEOUT(s).fractional_part * COAP_TICKS_PER_SECOND / 1000) 402#define COAP_NON_RECEIVE_TIMEOUT(s) ((s)->non_receive_timeout) 403#define COAP_NON_PROBING_WAIT_BASE(s) ((s)->non_probing_wait_base) 404#define COAP_NON_PARTIAL_TIMEOUT(s) ((s)->non_partial_timeout) 405 406/** 407 * The DEFAULT_LEISURE definition for the session (s). 408 * 409 * RFC 7252, Section 4.8 410 * Initial value 5.0 seconds 411 */ 412#define COAP_DEFAULT_LEISURE_TICKS(s) \ 413 (COAP_DEFAULT_LEISURE(s).integer_part * COAP_TICKS_PER_SECOND + \ 414 COAP_DEFAULT_LEISURE(s).fractional_part * COAP_TICKS_PER_SECOND / 1000) 415/** 416 * The MAX_TRANSMIT_SPAN definition for the session (s). 417 * 418 * RFC 7252, Section 4.8.2 Calculation of MAX_TRAMSMIT_SPAN 419 * ACK_TIMEOUT * ((2 ** (MAX_RETRANSMIT)) - 1) * ACK_RANDOM_FACTOR 420 */ 421#define COAP_MAX_TRANSMIT_SPAN(s) \ 422 (((s)->ack_timeout.integer_part * 1000 + (s)->ack_timeout.fractional_part) * \ 423 ((1 << ((s)->max_retransmit)) -1) * \ 424 ((s)->ack_random_factor.integer_part * 1000 + \ 425 (s)->ack_random_factor.fractional_part) \ 426 / 1000000) 427 428/** 429 * The MAX_TRANSMIT_WAIT definition for the session (s). 430 * 431 * RFC 7252, Section 4.8.2 Calculation of MAX_TRAMSMIT_WAIT 432 * ACK_TIMEOUT * ((2 ** (MAX_RETRANSMIT + 1)) - 1) * ACK_RANDOM_FACTOR 433 */ 434#define COAP_MAX_TRANSMIT_WAIT(s) \ 435 (((s)->ack_timeout.integer_part * 1000 + (s)->ack_timeout.fractional_part) * \ 436 ((1 << ((s)->max_retransmit + 1)) -1) * \ 437 ((s)->ack_random_factor.integer_part * 1000 + \ 438 (s)->ack_random_factor.fractional_part) \ 439 / 1000000) 440 441#define COAP_MAX_TRANSMIT_WAIT_TICKS(s) \ 442 (COAP_MAX_TRANSMIT_WAIT(s) * COAP_TICKS_PER_SECOND) 443 444/** 445 * The PROCESSING_DELAY definition for the session (s). 446 * 447 * RFC 7252, Section 4.8.2 Calculation of PROCESSING_DELAY 448 * PROCESSING_DELAY set to ACK_TIMEOUT 449 */ 450#define COAP_PROCESSING_DELAY(s) \ 451 (((s)->ack_timeout.integer_part * 1000 + (s)->ack_timeout.fractional_part + \ 452 500) / 1000) 453 454/** 455 * The MAX_RTT definition for the session (s). 456 * 457 * RFC 7252, Section 4.8.2 Calculation of MAX_RTT 458 * (2 * MAX_LATENCY) + PROCESSING_DELAY 459 */ 460#define COAP_MAX_RTT(s) \ 461 ((2 * COAP_DEFAULT_MAX_LATENCY) + COAP_PROCESSING_DELAY(s)) 462 463/** 464 * The EXCHANGE_LIFETIME definition for the session (s). 465 * 466 * RFC 7252, Section 4.8.2 Calculation of EXCHANGE_LIFETIME 467 * MAX_TRANSMIT_SPAN + (2 * MAX_LATENCY) + PROCESSING_DELAY 468 */ 469#define COAP_EXCHANGE_LIFETIME(s) \ 470 (COAP_MAX_TRANSMIT_SPAN(s) + (2 * COAP_DEFAULT_MAX_LATENCY) + \ 471 COAP_PROCESSING_DELAY(s)) 472 473/** 474 * The NON_LIFETIME definition for the session (s). 475 * 476 * RFC 7252, Section 4.8.2 Calculation of NON_LIFETIME 477 * MAX_TRANSMIT_SPAN + MAX_LATENCY 478 */ 479#define COAP_NON_LIFETIME(s) \ 480 (COAP_MAX_TRANSMIT_SPAN(s) + COAP_DEFAULT_MAX_LATENCY) 481 482/** 483 * The NON_RECEIVE_TIMEOUT definition for the session (s). 484 * 485 * RFC9177 Section 6.2 486 * 2 * NON_TIMEOUT 487 */ 488#define COAP_NON_RECEIVE_TIMEOUT_TICKS(s) ( \ 489 COAP_NON_RECEIVE_TIMEOUT(s).integer_part * COAP_TICKS_PER_SECOND + \ 490 COAP_NON_RECEIVE_TIMEOUT(s).fractional_part * COAP_TICKS_PER_SECOND / 1000) 491 492/** 493 * The NON_PROBING_WAIT definition for the session (s). 494 * 495 * RFC9177 Section 6.2 496 * NON_PROBING_WAIT = NON_TIMEOUT * ((2 ** NON_MAX_RETRANSMIT) - 1) * 497 * ACK_RANDOM_FACTOR + (2 * MAX_LATENCY) + NON_TIMEOUT_RANDOM 498 * Default is 247-248 seconds 499 */ 500#define COAP_NON_PROBING_WAIT(s) \ 501 coap_add_fixed_fixed(COAP_NON_PROBING_WAIT_BASE(s), \ 502 COAP_NON_TIMEOUT_RANDOM(s)) 503 504#define COAP_NON_PROBING_WAIT_TICKS(s) \ 505 (COAP_NON_PROBING_WAIT(s).integer_part * COAP_TICKS_PER_SECOND + \ 506 COAP_NON_PROBING_WAIT(s).fractional_part * COAP_TICKS_PER_SECOND / 1000) 507 508/** 509 * The NON_PARTIAL_TIMEOUT definition for the session (s). 510 * 511 * RFC9177 Section 6.2 512 * Initial value EXCHANGE_LIFETIME (247 seconds) 513 */ 514#define COAP_NON_PARTIAL_TIMEOUT_TICKS(s) \ 515 (COAP_NON_PARTIAL_TIMEOUT(s).integer_part * COAP_TICKS_PER_SECOND + \ 516 COAP_NON_PARTIAL_TIMEOUT(s).fractional_part * COAP_TICKS_PER_SECOND / 1000) 517 518/** 519 * The NON_TIMEOUT_RANDOM definition for the session (s). 520 * 521 * RFC9177 Section 6.2 522 * Default is 2-3 seconds 523 */ 524#define COAP_NON_TIMEOUT_RANDOM(s) \ 525 coap_get_non_timeout_random(s) 526 527/** @} */ 528 529#define SESSIONS_ADD(e, obj) \ 530 HASH_ADD(hh, (e), addr_hash, sizeof((obj)->addr_hash), (obj)) 531 532#define SESSIONS_DELETE(e, obj) \ 533 HASH_DELETE(hh, (e), (obj)) 534 535#define SESSIONS_ITER(e, el, rtmp) \ 536 HASH_ITER(hh, (e), el, rtmp) 537 538#define SESSIONS_ITER_SAFE(e, el, rtmp) \ 539 for ((el) = (e); (el) && ((rtmp) = (el)->hh.next, 1); (el) = (rtmp)) 540 541#define SESSIONS_FIND(e, k, res) { \ 542 HASH_FIND(hh, (e), &(k), sizeof(k), (res)); \ 543 } 544 545#endif /* COAP_SESSION_INTERNAL_H_ */ 546