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