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 */ 40 struct 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 46 typedef 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 */ 58 typedef 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 */ 68 struct 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 */ 219 struct 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 231 coap_fixed_point_t coap_multi_fixed_fixed(coap_fixed_point_t fp1, 232 coap_fixed_point_t fp2); 233 234 coap_fixed_point_t coap_multi_fixed_uint(coap_fixed_point_t fp1, 235 uint32_t u2); 236 237 coap_fixed_point_t coap_add_fixed_fixed(coap_fixed_point_t fp1, 238 coap_fixed_point_t fp2); 239 240 coap_fixed_point_t coap_add_fixed_uint(coap_fixed_point_t fp1, 241 uint32_t u2); 242 243 coap_fixed_point_t coap_sub_fixed_uint(coap_fixed_point_t fp1, 244 uint32_t u2); 245 246 coap_fixed_point_t coap_div_fixed_uint(coap_fixed_point_t fp1, uint32_t u2); 247 248 coap_fixed_point_t coap_get_non_timeout_random(coap_session_t *session); 249 250 coap_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 */ 258 void 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 */ 265 void 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 */ 277 int 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 */ 290 int 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 */ 303 int 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 */ 315 coap_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 */ 329 void 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 */ 342 ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu); 343 344 ssize_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 */ 357 coap_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 */ 367 size_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 */ 380 coap_session_t *coap_session_new_dtls_session(coap_session_t *session, 381 coap_tick_t now); 382 383 void coap_session_free(coap_session_t *session); 384 void 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