mirror of
https://github.com/obgm/libcoap.git
synced 2026-11-08 18:32:53 +03:00
https://tools.ietf.org/html/rfc7641#section-4.5 In order not to cause congestion, servers MUST strictly limit the number of simultaneous outstanding notifications/responses that they transmit to a given client to NSTART (1 by default; see Section 4.7 of RFC 7252 [RFC7252]). An outstanding notification/response is either a confirmable message for which an acknowledgement has not yet been received and whose last retransmission attempt has not yet timed out or a non-confirmable message for which the waiting time that results from the following rate-limiting rules has not yet elapsed. Delay sending of PDUs if active CON request waiting for ACK. Do not start of another Observer unsolicited response if active CON waiting waiting for ACK. Display outgoing PDU if log level DEBUG or higher to help troubleshooting. This does not fix the ratelimiting of non-confirmable messages, which should be handled by the application.
472 lines
16 KiB
C
472 lines
16 KiB
C
/* coap_session.h -- Session management for libcoap
|
|
*
|
|
* Copyright (C) 2017 Jean-Claue Michelou <jcm@spinetix.com>
|
|
*
|
|
* This file is part of the CoAP library libcoap. Please see
|
|
* README for terms of use.
|
|
*/
|
|
|
|
#ifndef _SESSION_H_
|
|
#define _SESSION_H_
|
|
|
|
|
|
#include "coap_io.h"
|
|
#include "coap_time.h"
|
|
#include "pdu.h"
|
|
|
|
struct coap_endpoint_t;
|
|
struct coap_context_t;
|
|
struct coap_queue_t;
|
|
|
|
/**
|
|
* Abstraction of a fixed point number that can be used where necessary instead
|
|
* of a float. 1,000 fractional bits equals one integer
|
|
*/
|
|
typedef struct coap_fixed_point_t {
|
|
uint16_t integer_part; /**< Integer part of fixed point variable */
|
|
uint16_t fractional_part; /**< Fractional part of fixed point variable
|
|
1/1000 (3 points) precision */
|
|
} coap_fixed_point_t;
|
|
|
|
#define COAP_DEFAULT_SESSION_TIMEOUT 300
|
|
|
|
#define COAP_PROTO_NOT_RELIABLE(p) ((p)==COAP_PROTO_UDP || (p)==COAP_PROTO_DTLS)
|
|
#define COAP_PROTO_RELIABLE(p) ((p)==COAP_PROTO_TCP || (p)==COAP_PROTO_TLS)
|
|
|
|
typedef uint8_t coap_session_type_t;
|
|
/**
|
|
* coap_session_type_t values
|
|
*/
|
|
#define COAP_SESSION_TYPE_CLIENT 1 /**< client-side */
|
|
#define COAP_SESSION_TYPE_SERVER 2 /**< server-side */
|
|
#define COAP_SESSION_TYPE_HELLO 3 /**< server-side ephemeral session for responding to a client hello */
|
|
|
|
typedef uint8_t coap_session_state_t;
|
|
/**
|
|
* coap_session_state_t values
|
|
*/
|
|
#define COAP_SESSION_STATE_NONE 0
|
|
#define COAP_SESSION_STATE_CONNECTING 1
|
|
#define COAP_SESSION_STATE_HANDSHAKE 2
|
|
#define COAP_SESSION_STATE_CSM 3
|
|
#define COAP_SESSION_STATE_ESTABLISHED 4
|
|
|
|
typedef struct coap_session_t {
|
|
struct coap_session_t *next;
|
|
coap_proto_t proto; /**< protocol used */
|
|
coap_session_type_t type; /**< client or server side socket */
|
|
coap_session_state_t state; /**< current state of relationaship with peer */
|
|
unsigned ref; /**< reference count from queues */
|
|
unsigned tls_overhead; /**< overhead of TLS layer */
|
|
unsigned mtu; /**< path or CSM mtu */
|
|
coap_address_t local_if; /**< optional local interface address */
|
|
coap_address_t remote_addr; /**< remote address and port */
|
|
coap_address_t local_addr; /**< local address and port */
|
|
int ifindex; /**< interface index */
|
|
coap_socket_t sock; /**< socket object for the session, if any */
|
|
struct coap_endpoint_t *endpoint; /**< session's endpoint */
|
|
struct coap_context_t *context; /**< session's context */
|
|
void *tls; /**< security parameters */
|
|
uint16_t tx_mid; /**< the last message id that was used in this session */
|
|
uint8_t con_active; /**< Active CON request sent */
|
|
struct coap_queue_t *sendqueue; /**< list of messages waiting to be sent */
|
|
size_t partial_write; /**< if > 0 indicates number of bytes already written from the pdu at the head of sendqueue */
|
|
uint8_t read_header[8]; /**< storage space for header of incoming message header */
|
|
size_t partial_read; /**< if > 0 indicates number of bytes already read for an incoming message */
|
|
coap_pdu_t *partial_pdu; /**< incomplete incoming pdu */
|
|
coap_tick_t last_rx_tx;
|
|
coap_tick_t last_tx_rst;
|
|
uint8_t *psk_identity;
|
|
size_t psk_identity_len;
|
|
uint8_t *psk_key;
|
|
size_t psk_key_len;
|
|
void *app; /**< application-specific data */
|
|
unsigned int max_retransmit; /**< maximum re-transmit count (default 4) */
|
|
coap_fixed_point_t ack_timeout; /**< timeout waiting for ack (default 2 secs) */
|
|
coap_fixed_point_t ack_random_factor; /**< ack random factor backoff (default 1.5) */
|
|
unsigned int dtls_timeout_count; /**<dtls setup retry counter */
|
|
} coap_session_t;
|
|
|
|
/**
|
|
* Increment reference counter on a session.
|
|
*
|
|
* @param session The CoAP session.
|
|
* @return same as session
|
|
*/
|
|
coap_session_t *coap_session_reference(coap_session_t *session);
|
|
|
|
/**
|
|
* Decrement reference counter on a session.
|
|
* Note that the session may be deleted as a result and should not be used
|
|
* after this call.
|
|
*
|
|
* @param session The CoAP session.
|
|
*/
|
|
void coap_session_release(coap_session_t *session);
|
|
|
|
/**
|
|
* Stores @p data with the given session. This function overwrites any value
|
|
* that has previously been stored with @p session.
|
|
*/
|
|
void coap_session_set_app_data(coap_session_t *session, void *data);
|
|
|
|
/**
|
|
* Returns any application-specific data that has been stored with @p
|
|
* session using the function coap_session_set_app_data(). This function will
|
|
* return @c NULL if no data has been stored.
|
|
*/
|
|
void *coap_session_get_app_data(const coap_session_t *session);
|
|
|
|
/**
|
|
* Notify session that it has failed connecting or has been disconnected.
|
|
*
|
|
* @param session The CoAP session.
|
|
*/
|
|
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason);
|
|
|
|
/**
|
|
* Notify session that the remote peer is no longer listening.
|
|
*
|
|
* @param session The CoAP session.
|
|
*/
|
|
void coap_session_reset(coap_session_t *session);
|
|
|
|
/**
|
|
* Notify session transport has just connected and CSM exchange can now start.
|
|
*
|
|
* @param session The CoAP session.
|
|
*/
|
|
void coap_session_send_csm(coap_session_t *session);
|
|
|
|
/**
|
|
* Notify session that it has just connected or reconnected.
|
|
*
|
|
* @param session The CoAP session.
|
|
*/
|
|
void coap_session_connected(coap_session_t *session);
|
|
|
|
/**
|
|
* Set the session MTU. This is the maximum message size that can be sent,
|
|
* excluding IP and UDP overhead.
|
|
*
|
|
* @param session The CoAP session.
|
|
* @param mtu maximum message size
|
|
*/
|
|
void coap_session_set_mtu(coap_session_t *session, unsigned mtu);
|
|
|
|
/**
|
|
* Get maximum acceptable PDU size
|
|
*
|
|
* @param session The CoAP session.
|
|
* @return maximum PDU size, not including header (but including token).
|
|
*/
|
|
size_t coap_session_max_pdu_size(coap_session_t *session);
|
|
|
|
/**
|
|
* Creates a new client session to the designated server.
|
|
* @param ctx The CoAP context.
|
|
* @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.
|
|
* @param server The server's address. If the port number is zero, the default port for the protocol will be used.
|
|
* @param proto Protocol.
|
|
*
|
|
* @return A new CoAP session or NULL if failed. Call coap_session_release to free.
|
|
*/
|
|
coap_session_t *coap_new_client_session(
|
|
struct coap_context_t *ctx,
|
|
const coap_address_t *local_if,
|
|
const coap_address_t *server,
|
|
coap_proto_t proto
|
|
);
|
|
|
|
/**
|
|
* Creates a new client session to the designated server with PSK credentials
|
|
* @param ctx The CoAP context.
|
|
* @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.
|
|
* @param server The server's address. If the port number is zero, the default port for the protocol will be used.
|
|
* @param identity PSK client identity
|
|
* @param identity_len Length PSK client identity
|
|
* @param key PSK shared key
|
|
* @param key_len PSK shared key length
|
|
* @param proto Protocol.
|
|
*
|
|
* @return A new CoAP session or NULL if failed. Call coap_session_release to free.
|
|
*/
|
|
coap_session_t *coap_new_client_session_psk(
|
|
struct coap_context_t *ctx,
|
|
const coap_address_t *local_if,
|
|
const coap_address_t *server,
|
|
coap_proto_t proto,
|
|
const char *identity,
|
|
const uint8_t *key,
|
|
unsigned key_len
|
|
);
|
|
|
|
struct coap_dtls_pki_t;
|
|
|
|
/**
|
|
* Creates a new client session to the designated server with PKI credentials
|
|
* @param ctx The CoAP context.
|
|
* @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.
|
|
* @param server The server's address. If the port number is zero, the default
|
|
* port for the protocol will be used.
|
|
* @param proto CoAP Protocol.
|
|
* @param setup_data PKI parameters.
|
|
*
|
|
* @return A new CoAP session or NULL if failed. Call coap_session_release()
|
|
* to free.
|
|
*/
|
|
coap_session_t *coap_new_client_session_pki(
|
|
struct coap_context_t *ctx,
|
|
const coap_address_t *local_if,
|
|
const coap_address_t *server,
|
|
coap_proto_t proto,
|
|
struct coap_dtls_pki_t *setup_data
|
|
);
|
|
|
|
/**
|
|
* Creates a new server session for the specified endpoint.
|
|
* @param ctx The CoAP context.
|
|
* @param ep An endpoint where an incoming connection request is pending.
|
|
*
|
|
* @return A new CoAP session or NULL if failed. Call coap_session_release to free.
|
|
*/
|
|
coap_session_t *coap_new_server_session(
|
|
struct coap_context_t *ctx,
|
|
struct coap_endpoint_t *ep
|
|
);
|
|
|
|
/**
|
|
* Function interface for datagram data transmission. This function returns
|
|
* the number of bytes that have been transmitted, or a value less than zero
|
|
* on error.
|
|
*
|
|
* @param session Session to send data on.
|
|
* @param data The data to send.
|
|
* @param datalen The actual length of @p data.
|
|
*
|
|
* @return The number of bytes written on success, or a value
|
|
* less than zero on error.
|
|
*/
|
|
ssize_t coap_session_send(coap_session_t *session,
|
|
const uint8_t *data, size_t datalen);
|
|
|
|
/**
|
|
* Function interface for stream data transmission. This function returns
|
|
* the number of bytes that have been transmitted, or a value less than zero
|
|
* on error. The number of bytes written may be less than datalen because of
|
|
* congestion control.
|
|
*
|
|
* @param session Session to send data on.
|
|
* @param data The data to send.
|
|
* @param datalen The actual length of @p data.
|
|
*
|
|
* @return The number of bytes written on success, or a value
|
|
* less than zero on error.
|
|
*/
|
|
ssize_t coap_session_write(coap_session_t *session,
|
|
const uint8_t *data, size_t datalen);
|
|
|
|
/**
|
|
* Send a pdu according to the session's protocol. This function returns
|
|
* the number of bytes that have been transmitted, or a value less than zero
|
|
* on error.
|
|
*
|
|
* @param session Session to send pdu on.
|
|
* @param pdu The pdu to send.
|
|
*
|
|
* @return The number of bytes written on success, or a value
|
|
* less than zero on error.
|
|
*/
|
|
ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu);
|
|
|
|
|
|
/**
|
|
* Get session description.
|
|
*
|
|
* @param session The CoAP session.
|
|
* @return description string
|
|
*/
|
|
const char *coap_session_str(const coap_session_t *session);
|
|
|
|
ssize_t
|
|
coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu,
|
|
struct coap_queue_t *node);
|
|
/**
|
|
* Abstraction of virtual endpoint that can be attached to coap_context_t. The
|
|
* tuple (handle, addr) must uniquely identify this endpoint.
|
|
*/
|
|
typedef struct coap_endpoint_t {
|
|
struct coap_endpoint_t *next;
|
|
struct coap_context_t *context; /**< endpoint's context */
|
|
coap_proto_t proto; /**< protocol used on this interface */
|
|
uint16_t default_mtu; /**< default mtu for this interface */
|
|
coap_socket_t sock; /**< socket object for the interface, if any */
|
|
coap_address_t bind_addr; /**< local interface address */
|
|
coap_session_t *sessions; /**< list of active sessions */
|
|
coap_session_t hello; /**< special session of DTLS hello messages */
|
|
} coap_endpoint_t;
|
|
|
|
/**
|
|
* Create a new endpoint for communicating with peers.
|
|
*
|
|
* @param context The coap context that will own the new endpoint
|
|
* @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.
|
|
* @param proto Protocol used on this endpoint
|
|
*/
|
|
|
|
coap_endpoint_t *coap_new_endpoint(struct coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto);
|
|
|
|
/**
|
|
* Set the endpoint's default MTU. This is the maximum message size that can be
|
|
* sent, excluding IP and UDP overhead.
|
|
*
|
|
* @param session The CoAP session.
|
|
* @param mtu maximum message size
|
|
*/
|
|
void coap_endpoint_set_default_mtu(coap_endpoint_t *ep, unsigned mtu);
|
|
|
|
void coap_free_endpoint(coap_endpoint_t *ep);
|
|
|
|
|
|
/**
|
|
* Get endpoint description.
|
|
*
|
|
* @param session The CoAP endpoint.
|
|
* @return description string
|
|
*/
|
|
const char *coap_endpoint_str(const coap_endpoint_t *endpoint);
|
|
|
|
/**
|
|
* Lookup the server session for the packet received on an endpoint, or create
|
|
* a new one.
|
|
*
|
|
* @param endpoint Active endpoint the packet was received on.
|
|
* @param packet Received packet.
|
|
* @return The CoAP session.
|
|
*/
|
|
coap_session_t *coap_endpoint_get_session(coap_endpoint_t *endpoint,
|
|
const struct coap_packet_t *packet, coap_tick_t now);
|
|
|
|
coap_session_t *coap_endpoint_new_dtls_session(coap_endpoint_t *endpoint,
|
|
const struct coap_packet_t *packet, coap_tick_t now);
|
|
|
|
coap_session_t *coap_session_get_by_peer(struct coap_context_t *ctx,
|
|
const struct coap_address_t *remote_addr, int ifindex);
|
|
|
|
void coap_session_free(coap_session_t *session);
|
|
|
|
/**
|
|
* @defgroup cc Rate Control
|
|
* The transmission parameters for CoAP rate control ("Congestion
|
|
* Control" in stream-oriented protocols) are defined in
|
|
* https://tools.ietf.org/html/rfc7252#section-4.8
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Number of seconds when to expect an ACK or a response to an
|
|
* outstanding CON message.
|
|
* RFC 7252, Section 4.8 Default value of ACK_TIMEOUT is 2
|
|
*/
|
|
#define COAP_DEFAULT_ACK_TIMEOUT ((coap_fixed_point_t){2,0})
|
|
|
|
/**
|
|
* A factor that is used to randomize the wait time before a message
|
|
* is retransmitted to prevent synchronization effects.
|
|
* RFC 7252, Section 4.8 Default value of ACK_RANDOM_FACTOR is 1.5
|
|
*/
|
|
#define COAP_DEFAULT_ACK_RANDOM_FACTOR ((coap_fixed_point_t){1,500})
|
|
|
|
/**
|
|
* Number of message retransmissions before message sending is stopped
|
|
* RFC 7252, Section 4.8 Default value of MAX_RETRANSMIT is 4
|
|
*/
|
|
#define COAP_DEFAULT_MAX_RETRANSMIT 4
|
|
|
|
/**
|
|
* The number of simultaneous outstanding interactions that a client
|
|
* maintains to a given server.
|
|
* RFC 7252, Section 4.8 Default value of NSTART is 1
|
|
*/
|
|
#define COAP_DEFAULT_NSTART 1
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* Set the CoAP maximum retransmit count before failure
|
|
*
|
|
* Number of message retransmissions before message sending is stopped
|
|
*
|
|
* @param session The CoAP session.
|
|
* @param value The value to set to. The default is 4 and should not normally
|
|
* get changed.
|
|
*/
|
|
void coap_session_set_max_retransmit(coap_session_t *session,
|
|
unsigned int value);
|
|
|
|
/**
|
|
* Set the CoAP initial ack response timeout before the next re-transmit
|
|
*
|
|
* Number of seconds when to expect an ACK or a response to an
|
|
* outstanding CON message.
|
|
*
|
|
* @param session The CoAP session.
|
|
* @param value The value to set to. The default is 2 and should not normally
|
|
* get changed.
|
|
*/
|
|
void coap_session_set_ack_timeout(coap_session_t *session,
|
|
coap_fixed_point_t value);
|
|
|
|
/**
|
|
* Set the CoAP ack randomize factor
|
|
*
|
|
* A factor that is used to randomize the wait time before a message
|
|
* is retransmitted to prevent synchronization effects.
|
|
*
|
|
* @param session The CoAP session.
|
|
* @param value The value to set to. The default is 1.5 and should not normally
|
|
* get changed.
|
|
*/
|
|
void coap_session_set_ack_random_factor(coap_session_t *session,
|
|
coap_fixed_point_t value);
|
|
|
|
/**
|
|
* Get the CoAP maximum retransmit before failure
|
|
*
|
|
* Number of message retransmissions before message sending is stopped
|
|
*
|
|
* @param session The CoAP session.
|
|
*
|
|
* @return Current maximum retransmit value
|
|
*/
|
|
unsigned int coap_session_get_max_transmit(coap_session_t *session);
|
|
|
|
/**
|
|
* Get the CoAP initial ack response timeout before the next re-transmit
|
|
*
|
|
* Number of seconds when to expect an ACK or a response to an
|
|
* outstanding CON message.
|
|
*
|
|
* @param session The CoAP session.
|
|
*
|
|
* @return Current ack response timeout value
|
|
*/
|
|
coap_fixed_point_t coap_session_get_ack_timeout(coap_session_t *session);
|
|
|
|
/**
|
|
* Get the CoAP ack randomize factor
|
|
*
|
|
* A factor that is used to randomize the wait time before a message
|
|
* is retransmitted to prevent synchronization effects.
|
|
*
|
|
* @param session The CoAP session.
|
|
*
|
|
* @return Current ack randomize value
|
|
*/
|
|
coap_fixed_point_t coap_session_get_ack_random_factor(coap_session_t *session);
|
|
|
|
#endif /* _SESSION_H */
|