1 /* coap_session.h -- Session management for libcoap 2 * 3 * Copyright (C) 2017 Jean-Claue Michelou <jcm@spinetix.com> 4 * 5 * This file is part of the CoAP library libcoap. Please see 6 * README for terms of use. 7 */ 8 9 /** 10 * @file coap_session.h 11 * @brief Defines the application visible session information 12 */ 13 14 #ifndef COAP_SESSION_H_ 15 #define COAP_SESSION_H_ 16 17 18 #include "coap_forward_decls.h" 19 #include "coap_io.h" 20 #include "coap_time.h" 21 #include "pdu.h" 22 #include "uthash.h" 23 24 /** 25 * Abstraction of a fixed point number that can be used where necessary instead 26 * of a float. 1,000 fractional bits equals one integer 27 */ 28 typedef struct coap_fixed_point_t { 29 uint16_t integer_part; /**< Integer part of fixed point variable */ 30 uint16_t fractional_part; /**< Fractional part of fixed point variable 31 1/1000 (3 points) precision */ 32 } coap_fixed_point_t; 33 34 #define COAP_DEFAULT_SESSION_TIMEOUT 300 35 #define COAP_PARTIAL_SESSION_TIMEOUT_TICKS (30 * COAP_TICKS_PER_SECOND) 36 #define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS 100 37 38 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS) 39 #define COAP_PROTO_NOT_RELIABLE(p) ((p)==COAP_PROTO_UDP || (p)==COAP_PROTO_DTLS) 40 #else 41 #define COAP_PROTO_NOT_RELIABLE(p) ((p)==COAP_PROTO_UDP) 42 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */ 43 #ifndef COAP_NO_TCP 44 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS) 45 #define COAP_PROTO_RELIABLE(p) ((p)==COAP_PROTO_TCP || (p)==COAP_PROTO_TLS) 46 #else 47 #define COAP_PROTO_RELIABLE(p) ((p)==COAP_PROTO_TCP) 48 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */ 49 #endif 50 51 typedef uint8_t coap_session_type_t; 52 /** 53 * coap_session_type_t values 54 */ 55 #define COAP_SESSION_TYPE_CLIENT 1 /**< client-side */ 56 #define COAP_SESSION_TYPE_SERVER 2 /**< server-side */ 57 #define COAP_SESSION_TYPE_HELLO 3 /**< server-side ephemeral session for responding to a client hello */ 58 59 typedef uint8_t coap_session_state_t; 60 /** 61 * coap_session_state_t values 62 */ 63 #define COAP_SESSION_STATE_NONE 0 64 #define COAP_SESSION_STATE_CONNECTING 1 65 #define COAP_SESSION_STATE_HANDSHAKE 2 66 #define COAP_SESSION_STATE_CSM 3 67 #define COAP_SESSION_STATE_ESTABLISHED 4 68 69 typedef struct coap_session_t { 70 coap_proto_t proto; /**< protocol used */ 71 coap_session_type_t type; /**< client or server side socket */ 72 coap_session_state_t state; /**< current state of relationaship with peer */ 73 unsigned ref; /**< reference count from queues */ 74 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS) 75 unsigned tls_overhead; /**< overhead of TLS layer */ 76 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */ 77 unsigned mtu; /**< path or CSM mtu */ 78 coap_address_t local_if; /**< optional local interface address */ 79 UT_hash_handle hh; 80 coap_addr_tuple_t addr_info; /**< key: remote/local address info */ 81 int ifindex; /**< interface index */ 82 coap_socket_t sock; /**< socket object for the session, if any */ 83 struct coap_endpoint_t *endpoint; /**< session's endpoint */ 84 struct coap_context_t *context; /**< session's context */ 85 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS) 86 void *tls; /**< security parameters */ 87 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */ 88 uint16_t tx_mid; /**< the last message id that was used in this session */ 89 uint8_t con_active; /**< Active CON request sent */ 90 coap_tid_t last_ping_mid; /**< the last keepalive message id that was used in this session */ 91 struct coap_queue_t *delayqueue; /**< list of delayed messages waiting to be sent */ 92 size_t partial_write; /**< if > 0 indicates number of bytes already written from the pdu at the head of sendqueue */ 93 uint8_t read_header[8]; /**< storage space for header of incoming message header */ 94 size_t partial_read; /**< if > 0 indicates number of bytes already read for an incoming message */ 95 coap_pdu_t *partial_pdu; /**< incomplete incoming pdu */ 96 coap_tick_t last_rx_tx; 97 coap_tick_t last_tx_rst; 98 coap_tick_t last_ping; 99 coap_tick_t last_pong; 100 coap_tick_t csm_tx; 101 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS) 102 uint8_t *psk_identity; 103 size_t psk_identity_len; 104 uint8_t *psk_key; 105 size_t psk_key_len; 106 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */ 107 void *app; /**< application-specific data */ 108 unsigned int max_retransmit; /**< maximum re-transmit count (default 4) */ 109 coap_fixed_point_t ack_timeout; /**< timeout waiting for ack (default 2 secs) */ 110 coap_fixed_point_t ack_random_factor; /**< ack random factor backoff (default 1.5) */ 111 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS) 112 unsigned int dtls_timeout_count; /**< dtls setup retry counter */ 113 int dtls_event; /**< Tracking any (D)TLS events on this sesison */ 114 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */ 115 } coap_session_t; 116 117 /** 118 * Increment reference counter on a session. 119 * 120 * @param session The CoAP session. 121 * @return same as session 122 */ 123 coap_session_t *coap_session_reference(coap_session_t *session); 124 125 /** 126 * Decrement reference counter on a session. 127 * Note that the session may be deleted as a result and should not be used 128 * after this call. 129 * 130 * @param session The CoAP session. 131 */ 132 void coap_session_release(coap_session_t *session); 133 134 /** 135 * Stores @p data with the given session. This function overwrites any value 136 * that has previously been stored with @p session. 137 */ 138 void coap_session_set_app_data(coap_session_t *session, void *data); 139 140 /** 141 * Returns any application-specific data that has been stored with @p 142 * session using the function coap_session_set_app_data(). This function will 143 * return @c NULL if no data has been stored. 144 */ 145 void *coap_session_get_app_data(const coap_session_t *session); 146 147 /** 148 * Notify session that it has failed. 149 * 150 * @param session The CoAP session. 151 * @param reason The reason why the session was disconnected. 152 */ 153 void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason); 154 155 /** 156 * Notify session transport has just connected and CSM exchange can now start. 157 * 158 * @param session The CoAP session. 159 */ 160 void coap_session_send_csm(coap_session_t *session); 161 162 /** 163 * Notify session that it has just connected or reconnected. 164 * 165 * @param session The CoAP session. 166 */ 167 void coap_session_connected(coap_session_t *session); 168 169 /** 170 * Set the session MTU. This is the maximum message size that can be sent, 171 * excluding IP and UDP overhead. 172 * 173 * @param session The CoAP session. 174 * @param mtu maximum message size 175 */ 176 void coap_session_set_mtu(coap_session_t *session, unsigned mtu); 177 178 /** 179 * Get maximum acceptable PDU size 180 * 181 * @param session The CoAP session. 182 * @return maximum PDU size, not including header (but including token). 183 */ 184 size_t coap_session_max_pdu_size(const coap_session_t *session); 185 186 /** 187 * Creates a new client session to the designated server. 188 * @param ctx The CoAP context. 189 * @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. 190 * @param server The server's address. If the port number is zero, the default port for the protocol will be used. 191 * @param proto Protocol. 192 * 193 * @return A new CoAP session or NULL if failed. Call coap_session_release to free. 194 */ 195 coap_session_t *coap_new_client_session( 196 struct coap_context_t *ctx, 197 const coap_address_t *local_if, 198 const coap_address_t *server, 199 coap_proto_t proto 200 ); 201 202 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS) 203 /** 204 * Creates a new client session to the designated server with PSK credentials 205 * @param ctx The CoAP context. 206 * @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. 207 * @param server The server's address. If the port number is zero, the default port for the protocol will be used. 208 * @param proto Protocol. 209 * @param identity PSK client identity 210 * @param key PSK shared key 211 * @param key_len PSK shared key length 212 * 213 * @return A new CoAP session or NULL if failed. Call coap_session_release to free. 214 */ 215 coap_session_t *coap_new_client_session_psk( 216 struct coap_context_t *ctx, 217 const coap_address_t *local_if, 218 const coap_address_t *server, 219 coap_proto_t proto, 220 const char *identity, 221 const uint8_t *key, 222 unsigned key_len 223 ); 224 225 /** 226 * Creates a new client session to the designated server with PKI credentials 227 * @param ctx The CoAP context. 228 * @param local_if Address of local interface. It is recommended to use NULL to 229 * let the operating system choose a suitable local interface. 230 * If an address is specified, the port number should be zero, 231 * which means that a free port is automatically selected. 232 * @param server The server's address. If the port number is zero, the default 233 * port for the protocol will be used. 234 * @param proto CoAP Protocol. 235 * @param setup_data PKI parameters. 236 * 237 * @return A new CoAP session or NULL if failed. Call coap_session_release() 238 * to free. 239 */ 240 coap_session_t *coap_new_client_session_pki( 241 struct coap_context_t *ctx, 242 const coap_address_t *local_if, 243 const coap_address_t *server, 244 coap_proto_t proto, 245 struct coap_dtls_pki_t *setup_data 246 ); 247 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */ 248 249 /** 250 * Creates a new server session for the specified endpoint. 251 * @param ctx The CoAP context. 252 * @param ep An endpoint where an incoming connection request is pending. 253 * 254 * @return A new CoAP session or NULL if failed. Call coap_session_release to free. 255 */ 256 coap_session_t *coap_new_server_session( 257 struct coap_context_t *ctx, 258 struct coap_endpoint_t *ep 259 ); 260 261 /** 262 * Function interface for datagram data transmission. This function returns 263 * the number of bytes that have been transmitted, or a value less than zero 264 * on error. 265 * 266 * @param session Session to send data on. 267 * @param data The data to send. 268 * @param datalen The actual length of @p data. 269 * 270 * @return The number of bytes written on success, or a value 271 * less than zero on error. 272 */ 273 ssize_t coap_session_send(coap_session_t *session, 274 const uint8_t *data, size_t datalen); 275 276 /** 277 * Function interface for stream data transmission. This function returns 278 * the number of bytes that have been transmitted, or a value less than zero 279 * on error. The number of bytes written may be less than datalen because of 280 * congestion control. 281 * 282 * @param session Session to send data on. 283 * @param data The data to send. 284 * @param datalen The actual length of @p data. 285 * 286 * @return The number of bytes written on success, or a value 287 * less than zero on error. 288 */ 289 ssize_t coap_session_write(coap_session_t *session, 290 const uint8_t *data, size_t datalen); 291 292 /** 293 * Send a pdu according to the session's protocol. This function returns 294 * the number of bytes that have been transmitted, or a value less than zero 295 * on error. 296 * 297 * @param session Session to send pdu on. 298 * @param pdu The pdu to send. 299 * 300 * @return The number of bytes written on success, or a value 301 * less than zero on error. 302 */ 303 ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu); 304 305 306 /** 307 * @ingroup logging 308 * Get session description. 309 * 310 * @param session The CoAP session. 311 * @return description string. 312 */ 313 const char *coap_session_str(const coap_session_t *session); 314 315 ssize_t 316 coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, 317 struct coap_queue_t *node); 318 319 /** 320 * Create a new endpoint for communicating with peers. 321 * 322 * @param context The coap context that will own the new endpoint 323 * @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. 324 * @param proto Protocol used on this endpoint 325 */ 326 327 coap_endpoint_t *coap_new_endpoint(struct coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto); 328 329 /** 330 * Set the endpoint's default MTU. This is the maximum message size that can be 331 * sent, excluding IP and UDP overhead. 332 * 333 * @param endpoint The CoAP endpoint. 334 * @param mtu maximum message size 335 */ 336 void coap_endpoint_set_default_mtu(coap_endpoint_t *endpoint, unsigned mtu); 337 338 void coap_free_endpoint(coap_endpoint_t *ep); 339 340 341 /** 342 * @ingroup logging 343 * Get endpoint description. 344 * 345 * @param endpoint The CoAP endpoint. 346 * @return description string. 347 */ 348 const char *coap_endpoint_str(const coap_endpoint_t *endpoint); 349 350 /** 351 * Lookup the server session for the packet received on an endpoint, or create 352 * a new one. 353 * 354 * @param endpoint Active endpoint the packet was received on. 355 * @param packet Received packet. 356 * @param now The current time in ticks. 357 * @return The CoAP session or @c NULL if error. 358 */ 359 coap_session_t *coap_endpoint_get_session(coap_endpoint_t *endpoint, 360 const struct coap_packet_t *packet, coap_tick_t now); 361 362 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS) 363 /** 364 * Create a new DTLS session for the @p session. 365 * Note: the @p session is released if no DTLS server session can be created. 366 * 367 * @ingroup dtls_internal 368 * 369 * @param session Session to add DTLS session to 370 * @param now The current time in ticks. 371 * 372 * @return CoAP session or @c NULL if error. 373 */ 374 coap_session_t *coap_session_new_dtls_session(coap_session_t *session, 375 coap_tick_t now); 376 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */ 377 378 coap_session_t *coap_session_get_by_peer(struct coap_context_t *ctx, 379 const struct coap_address_t *remote_addr, int ifindex); 380 381 void coap_session_free(coap_session_t *session); 382 void coap_session_mfree(coap_session_t *session); 383 384 /** 385 * @defgroup cc Rate Control 386 * The transmission parameters for CoAP rate control ("Congestion 387 * Control" in stream-oriented protocols) are defined in 388 * https://tools.ietf.org/html/rfc7252#section-4.8 389 * @{ 390 */ 391 392 /** 393 * Number of seconds when to expect an ACK or a response to an 394 * outstanding CON message. 395 * RFC 7252, Section 4.8 Default value of ACK_TIMEOUT is 2 396 */ 397 #define COAP_DEFAULT_ACK_TIMEOUT ((coap_fixed_point_t){2,0}) 398 399 /** 400 * A factor that is used to randomize the wait time before a message 401 * is retransmitted to prevent synchronization effects. 402 * RFC 7252, Section 4.8 Default value of ACK_RANDOM_FACTOR is 1.5 403 */ 404 #define COAP_DEFAULT_ACK_RANDOM_FACTOR ((coap_fixed_point_t){1,500}) 405 406 /** 407 * Number of message retransmissions before message sending is stopped 408 * RFC 7252, Section 4.8 Default value of MAX_RETRANSMIT is 4 409 */ 410 #define COAP_DEFAULT_MAX_RETRANSMIT 4 411 412 /** 413 * The number of simultaneous outstanding interactions that a client 414 * maintains to a given server. 415 * RFC 7252, Section 4.8 Default value of NSTART is 1 416 */ 417 #define COAP_DEFAULT_NSTART 1 418 419 /** @} */ 420 421 /** 422 * Set the CoAP maximum retransmit count before failure 423 * 424 * Number of message retransmissions before message sending is stopped 425 * 426 * @param session The CoAP session. 427 * @param value The value to set to. The default is 4 and should not normally 428 * get changed. 429 */ 430 void coap_session_set_max_retransmit(coap_session_t *session, 431 unsigned int value); 432 433 /** 434 * Set the CoAP initial ack response timeout before the next re-transmit 435 * 436 * Number of seconds when to expect an ACK or a response to an 437 * outstanding CON message. 438 * 439 * @param session The CoAP session. 440 * @param value The value to set to. The default is 2 and should not normally 441 * get changed. 442 */ 443 void coap_session_set_ack_timeout(coap_session_t *session, 444 coap_fixed_point_t value); 445 446 /** 447 * Set the CoAP ack randomize factor 448 * 449 * A factor that is used to randomize the wait time before a message 450 * is retransmitted to prevent synchronization effects. 451 * 452 * @param session The CoAP session. 453 * @param value The value to set to. The default is 1.5 and should not normally 454 * get changed. 455 */ 456 void coap_session_set_ack_random_factor(coap_session_t *session, 457 coap_fixed_point_t value); 458 459 /** 460 * Get the CoAP maximum retransmit before failure 461 * 462 * Number of message retransmissions before message sending is stopped 463 * 464 * @param session The CoAP session. 465 * 466 * @return Current maximum retransmit value 467 */ 468 unsigned int coap_session_get_max_transmit(coap_session_t *session); 469 470 /** 471 * Get the CoAP initial ack response timeout before the next re-transmit 472 * 473 * Number of seconds when to expect an ACK or a response to an 474 * outstanding CON message. 475 * 476 * @param session The CoAP session. 477 * 478 * @return Current ack response timeout value 479 */ 480 coap_fixed_point_t coap_session_get_ack_timeout(coap_session_t *session); 481 482 /** 483 * Get the CoAP ack randomize factor 484 * 485 * A factor that is used to randomize the wait time before a message 486 * is retransmitted to prevent synchronization effects. 487 * 488 * @param session The CoAP session. 489 * 490 * @return Current ack randomize value 491 */ 492 coap_fixed_point_t coap_session_get_ack_random_factor(coap_session_t *session); 493 494 /** 495 * Send a ping message for the session. 496 * @param session The CoAP session. 497 * 498 * @return COAP_INVALID_TID if there is an error 499 */ 500 coap_tid_t coap_session_send_ping(coap_session_t *session); 501 502 #define SESSIONS_ADD(e, obj) \ 503 HASH_ADD(hh, (e), addr_info, sizeof((obj)->addr_info), (obj)) 504 505 #define SESSIONS_DELETE(e, obj) \ 506 HASH_DELETE(hh, (e), (obj)) 507 508 #define SESSIONS_ITER(e, el, rtmp) \ 509 HASH_ITER(hh, (e), el, rtmp) 510 511 #define SESSIONS_ITER_SAFE(e, el, rtmp) \ 512 for ((el) = (e); (el) && ((rtmp) = (el)->hh.next, 1); (el) = (rtmp)) 513 514 #define SESSIONS_FIND(e, k, res) { \ 515 HASH_FIND(hh, (e), &(k), sizeof(k), (res)); \ 516 } 517 518 #endif /* COAP_SESSION_H */ 519