11 #ifndef COAP_SESSION_C_
12 #define COAP_SESSION_C_
16 #ifdef COAP_EPOLL_SUPPORT
17 #include <sys/epoll.h>
18 #include <sys/timerfd.h>
76 assert(session->
ref > 0);
87 session->
app = app_data;
104 memset(session, 0,
sizeof(*session));
105 session->
proto = proto;
106 session->
type = type;
171 assert(session->
ref == 0);
188 size_t max_with_header = (size_t)(session->
mtu - session->
tls_overhead);
190 return max_with_header > 4 ? max_with_header - 4 : 0;
192 if (max_with_header <= 2)
195 return max_with_header - 2;
197 return max_with_header - 3;
199 return max_with_header - 4;
201 return max_with_header - 6;
205 #if defined(WITH_CONTIKI) || defined(WITH_LWIP)
217 ssize_t bytes_written;
226 if (bytes_written == (ssize_t)datalen) {
234 return bytes_written;
239 if (bytes_written > 0) {
243 }
else if (bytes_written < 0) {
247 return bytes_written;
257 assert(removed == node);
265 if (q->
id == pdu->
tid) {
295 if (session->
mtu == 0)
350 ssize_t bytes_written;
371 if (bytes_written < 0)
374 if (bytes_written <= 0 || (
size_t)bytes_written < q->pdu->used_size + q->
pdu->
hdr_size) {
377 if (bytes_written > 0)
393 #ifndef WITHOUT_OBSERVE
464 unsigned int num_idle = 0;
465 unsigned int num_hs = 0;
487 if (oldest_hs == NULL ||
498 if (oldest_hs == NULL ||
510 else if (oldest_hs) {
521 "Oustanding sessions in COAP_SESSION_STATE_HANDSHAKE too "
522 "large. New request ignored\n");
543 #define OFF_CONTENT_TYPE 0
544 #define DTLS_CT_ALERT 21
545 #define DTLS_CT_HANDSHAKE 22
546 #define OFF_HANDSHAKE_TYPE 13
547 #define DTLS_HT_CLIENT_HELLO 1
551 size_t length = packet->pbuf->len;
554 size_t length = packet->
length;
558 "coap_dtls_hello: ContentType %d Short Packet (%zu < %d) dropped\n",
568 "coap_dtls_hello: ContentType %d Handshake %d dropped\n",
608 #ifdef COAP_EPOLL_SUPPORT
615 struct epoll_event event;
627 memset(&event, 0,
sizeof(event));
628 event.events = events;
629 event.data.ptr = sock;
631 ret = epoll_ctl(context->epfd, EPOLL_CTL_ADD, sock->
fd, &event);
634 "%s: epoll_ctl ADD failed: %s (%d)\n",
654 local_if, server, 0, ctx, NULL);
675 #ifdef COAP_EPOLL_SUPPORT
676 coap_epoll_ctl_add(&session->
sock,
786 const char *identity,
795 if (identity && (strlen(identity) > 0)) {
796 size_t identity_len = strlen(identity);
813 if (key && key_len > 0) {
816 memcpy(session->
psk_key, key, key_len);
856 "coap_new_client_session_pki: Wrong version of setup_data\n");
887 &ep->
bind_addr, NULL, NULL, 0, ctx, ep );
898 #ifdef COAP_EPOLL_SUPPORT
899 coap_epoll_ctl_add(&session->
sock,
938 "coap_new_endpoint: one of coap_context_set_psk() or "
939 "coap_context_set_pki() not called\n");
968 #ifndef INET6_ADDRSTRLEN
969 #define INET6_ADDRSTRLEN 40
987 #ifdef COAP_EPOLL_SUPPORT
988 coap_epoll_ctl_add(&ep->
sock,
1014 assert(session->
ref == 0);
1015 if (session->
ref == 0) {
1050 static char szSession[256];
1051 char *p = szSession, *end = szSession +
sizeof(szSession);
1053 (
unsigned char*)p, end - p) > 0)
1061 (
unsigned char*)p, end - p) > 0)
1064 if (session->
ifindex > 0 && p + 1 < end)
1065 p += snprintf(p, end - p,
" (if%d)", session->
ifindex);
1089 static char szEndpoint[128];
1090 char *p = szEndpoint, *end = szEndpoint +
sizeof(szEndpoint);
void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b.
COAP_STATIC_INLINE void coap_address_copy(coap_address_t *dst, const coap_address_t *src)
Pulls together all the internal only header files.
int coap_socket_connect_udp(coap_socket_t *sock, const coap_address_t *local_if, const coap_address_t *server, int default_port, coap_address_t *local_addr, coap_address_t *remote_addr)
int coap_socket_bind_tcp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
void coap_socket_close(coap_socket_t *sock)
ssize_t coap_socket_send(coap_socket_t *sock, coap_session_t *session, const uint8_t *data, size_t data_len)
void coap_mfree_endpoint(struct coap_endpoint_t *ep)
ssize_t coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len)
struct coap_endpoint_t * coap_malloc_endpoint(void)
int coap_socket_connect_tcp1(coap_socket_t *sock, const coap_address_t *local_if, const coap_address_t *server, int default_port, coap_address_t *local_addr, coap_address_t *remote_addr)
int coap_socket_bind_udp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
int coap_socket_accept_tcp(coap_socket_t *server, coap_socket_t *new_client, coap_address_t *local_addr, coap_address_t *remote_addr)
const char * coap_socket_strerror(void)
#define COAP_SOCKET_WANT_ACCEPT
non blocking server socket is waiting for accept
#define COAP_SOCKET_NOT_EMPTY
the socket is not empty
#define COAP_SOCKET_BOUND
the socket is bound
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
@ COAP_NACK_NOT_DELIVERABLE
#define COAP_SOCKET_WANT_CONNECT
non blocking client socket is waiting for connect
#define COAP_SOCKET_CONNECTED
the socket is connected
#define COAP_SOCKET_EMPTY
coap_socket_flags_t values
void * coap_dtls_new_client_session(coap_session_t *session UNUSED)
int coap_dtls_context_set_psk(coap_context_t *ctx UNUSED, const char *hint UNUSED, coap_dtls_role_t role UNUSED)
void * coap_tls_new_client_session(coap_session_t *session UNUSED, int *connected UNUSED)
void * coap_tls_new_server_session(coap_session_t *session UNUSED, int *connected UNUSED)
void * coap_dtls_new_server_session(coap_session_t *session UNUSED)
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx UNUSED)
void coap_tls_free_session(coap_session_t *coap_session UNUSED)
void coap_dtls_free_session(coap_session_t *coap_session UNUSED)
int coap_dtls_context_set_pki(coap_context_t *ctx UNUSED, coap_dtls_pki_t *setup_data UNUSED, coap_dtls_role_t role UNUSED)
unsigned int coap_dtls_get_overhead(coap_session_t *session UNUSED)
void coap_session_set_max_retransmit(coap_session_t *session, unsigned int value)
Set the CoAP maximum retransmit count before failure.
coap_session_t * coap_endpoint_get_session(coap_endpoint_t *endpoint, const coap_packet_t *packet, coap_tick_t now)
void * coap_session_get_app_data(const coap_session_t *session)
Returns any application-specific data that has been stored with session using the function coap_sessi...
void coap_free_endpoint(coap_endpoint_t *ep)
ssize_t coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node)
void coap_session_set_app_data(coap_session_t *session, void *app_data)
Stores data with the given session.
void coap_session_set_mtu(coap_session_t *session, unsigned mtu)
Set the session MTU.
#define DTLS_HT_CLIENT_HELLO
void coap_session_send_csm(coap_session_t *session)
Notify session transport has just connected and CSM exchange can now start.
#define OFF_HANDSHAKE_TYPE
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)
Creates a new client session to the designated server with PSK credentials.
size_t coap_session_max_pdu_size(const coap_session_t *session)
Get maximum acceptable PDU size.
ssize_t coap_session_send(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for datagram data transmission.
void coap_session_set_ack_random_factor(coap_session_t *session, coap_fixed_point_t value)
Set the CoAP ack randomize factor.
static coap_session_t * coap_make_session(coap_proto_t proto, coap_session_type_t type, const coap_address_t *local_if, const coap_address_t *local_addr, const coap_address_t *remote_addr, int ifindex, coap_context_t *context, coap_endpoint_t *endpoint)
unsigned int coap_session_get_max_transmit(coap_session_t *session)
Get the CoAP maximum retransmit before failure.
coap_session_t * coap_session_reference(coap_session_t *session)
Increment reference counter on a session.
#define DTLS_CT_HANDSHAKE
static coap_session_t * coap_session_create_client(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto)
coap_session_t * coap_session_get_by_peer(coap_context_t *ctx, const coap_address_t *remote_addr, int ifindex)
void coap_endpoint_set_default_mtu(coap_endpoint_t *ep, unsigned mtu)
Set the endpoint's default MTU.
void coap_session_release(coap_session_t *session)
Decrement reference counter on a session.
coap_fixed_point_t coap_session_get_ack_timeout(coap_session_t *session)
Get the CoAP initial ack response timeout before the next re-transmit.
void coap_session_set_ack_timeout(coap_session_t *session, coap_fixed_point_t value)
Set the CoAP initial ack response timeout before the next re-transmit.
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
void coap_session_free(coap_session_t *session)
coap_tid_t coap_session_send_ping(coap_session_t *session)
Send a ping message for the session.
coap_endpoint_t * coap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto)
Create a new endpoint for communicating with peers.
void coap_session_mfree(coap_session_t *session)
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, coap_dtls_pki_t *setup_data)
Creates a new client session to the designated server with PKI credentials.
static coap_session_t * coap_session_accept(coap_session_t *session)
static coap_session_t * coap_session_connect(coap_session_t *session)
coap_session_t * coap_new_server_session(struct coap_context_t *ctx, coap_endpoint_t *ep)
Creates a new server session for the specified endpoint.
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
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.
ssize_t coap_session_write(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for stream data transmission.
coap_fixed_point_t coap_session_get_ack_random_factor(coap_session_t *session)
Get the CoAP ack randomize factor.
#define SESSIONS_ADD(e, obj)
#define SESSIONS_ITER_SAFE(e, el, rtmp)
#define COAP_PARTIAL_SESSION_TIMEOUT_TICKS
#define COAP_SESSION_STATE_HANDSHAKE
uint8_t coap_session_state_t
#define COAP_SESSION_STATE_CSM
#define SESSIONS_DELETE(e, obj)
#define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS
uint8_t coap_session_type_t
#define COAP_SESSION_TYPE_CLIENT
coap_session_type_t values
#define COAP_SESSION_TYPE_HELLO
server-side ephemeral session for responding to a client hello
#define COAP_PROTO_NOT_RELIABLE(p)
#define COAP_SESSION_STATE_CONNECTING
#define COAP_PROTO_RELIABLE(p)
#define COAP_SESSION_STATE_NONE
coap_session_state_t values
#define COAP_SESSION_STATE_ESTABLISHED
#define SESSIONS_ITER(e, el, rtmp)
#define COAP_SESSION_TYPE_SERVER
server-side
#define SESSIONS_FIND(e, k, res)
unsigned int coap_encode_var_safe(uint8_t *buf, size_t length, unsigned int val)
Encodes multiple-length byte sequences.
#define COAP_DEFAULT_ACK_RANDOM_FACTOR
A factor that is used to randomize the wait time before a message is retransmitted to prevent synchro...
#define COAP_DEFAULT_MAX_RETRANSMIT
Number of message retransmissions before message sending is stopped RFC 7252, Section 4....
#define COAP_DEFAULT_ACK_TIMEOUT
Number of seconds when to expect an ACK or a response to an outstanding CON message.
#define COAP_DEFAULT_NSTART
The number of simultaneous outstanding interactions that a client maintains to a given server.
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
coap_session_t * coap_session_new_dtls_session(coap_session_t *session, coap_tick_t now)
Create a new DTLS session for the session.
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
int coap_tls_is_supported(void)
Check whether TLS is available.
#define COAP_DTLS_PKI_SETUP_VERSION
Latest PKI setup version.
int coap_dtls_is_supported(void)
Check whether DTLS is available.
#define COAP_EVENT_TCP_CLOSED
#define COAP_EVENT_SESSION_CONNECTED
CSM exchange events for reliable protocols only.
#define COAP_EVENT_SESSION_FAILED
#define COAP_EVENT_TCP_FAILED
#define COAP_EVENT_SESSION_CLOSED
#define COAP_EVENT_DTLS_CONNECTED
#define COAP_EVENT_TCP_CONNECTED
TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS.
coap_log_t coap_get_log_level(void)
Get the current logging level.
size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len)
Print the address into the defined buffer.
const char * coap_session_str(const coap_session_t *session)
Get session description.
const char * coap_endpoint_str(const coap_endpoint_t *endpoint)
Get endpoint description.
#define coap_log(level,...)
Logging function.
#define prng(Buf, Length)
Fills Buf with Length bytes of random data.
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
COAP_STATIC_INLINE void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
COAP_STATIC_INLINE void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
int coap_delete_node(coap_queue_t *node)
Destroys specified node.
coap_queue_t * coap_new_node(void)
Creates a new node suitable for adding to the CoAP sendqueue.
int coap_remove_from_queue(coap_queue_t **queue, coap_session_t *session, coap_tid_t id, coap_queue_t **node)
This function removes the element with given id from the list given list.
int coap_handle_event(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
coap_tid_t coap_wait_ack(coap_context_t *context, coap_session_t *session, coap_queue_t *node)
unsigned int coap_calc_timeout(coap_session_t *session, unsigned char r)
Calculates the initial timeout based on the session CoAP transmission parameters 'ack_timeout',...
ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu)
Send a pdu according to the session's protocol.
coap_tid_t coap_send(coap_session_t *session, coap_pdu_t *pdu)
Sends a CoAP message to given peer.
void coap_cancel_session_messages(coap_context_t *context, coap_session_t *session, coap_nack_reason_t reason)
Cancels all outstanding messages for session session.
COAP_STATIC_INLINE uint16_t coap_new_message_id(coap_session_t *session)
Returns a new message id and updates session->tx_mid accordingly.
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
coap_pdu_t * coap_pdu_init(uint8_t type, uint8_t code, uint16_t tid, size_t size)
Creates a new CoAP PDU with at least enough storage space for the given size maximum message size.
size_t coap_add_option(coap_pdu_t *pdu, uint16_t type, size_t len, const uint8_t *data)
Adds option of given type to pdu that is passed as first parameter.
size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto)
Compose the protocol specific header for the specified PDU.
#define COAP_PROTO_NONE
coap_proto_t values
#define COAP_DEFAULT_PORT
#define COAP_SIGNALING_CSM
#define COAP_MAX_MESSAGE_SIZE_TCP8
#define COAP_DEFAULT_MAX_PDU_RX_SIZE
#define COAP_MAX_MESSAGE_SIZE_TCP0
#define COAPS_DEFAULT_PORT
int coap_tid_t
coap_tid_t is used to store CoAP transaction id, i.e.
#define COAP_SIGNALING_PING
#define COAP_MAX_MESSAGE_SIZE_TCP16
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
#define COAP_INVALID_TID
Indicates an invalid transaction id.
void coap_delete_observers(coap_context_t *context, coap_session_t *session)
Removes any subscription for session and releases the allocated storage.
coap_address_t remote
remote address and port
coap_address_t local
local address and port
multi-purpose address abstraction
The CoAP stack's global state is stored in a coap_context_t object.
coap_session_t * sessions
client sessions
coap_nack_handler_t nack_handler
unsigned int max_handshake_sessions
Maximum number of simultaneous negotating sessions per endpoint.
coap_endpoint_t * endpoint
the endpoints used for listening
unsigned int max_idle_sessions
Maximum number of simultaneous unused sessions per endpoint.
The structure used for defining the PKI setup data to be used.
Abstraction of virtual endpoint that can be attached to coap_context_t.
struct coap_context_t * context
endpoint's context
uint16_t default_mtu
default mtu for this interface
struct coap_session_t * sessions
hash table or list of active sessions
coap_address_t bind_addr
local interface address
coap_socket_t sock
socket object for the interface, if any
coap_proto_t proto
protocol used on this interface
Abstraction of a fixed point number that can be used where necessary instead of a float.
uint16_t fractional_part
Fractional part of fixed point variable 1/1000 (3 points) precision.
uint16_t integer_part
Integer part of fixed point variable.
size_t length
length of payload
coap_addr_tuple_t addr_info
local and remote addresses
unsigned char payload[COAP_RXBUFFER_SIZE]
payload
int ifindex
the interface index
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
uint16_t tid
transaction id, if any, in regular host byte order
uint8_t hdr_size
actaul size used for protocol-specific header
size_t used_size
used bytes of storage for token, options and payload
coap_session_t * session
the CoAP session
coap_pdu_t * pdu
the CoAP PDU to send
unsigned int timeout
the randomized timeout value
struct coap_queue_t * next
coap_tick_t t
when to send PDU for the next time
coap_tid_t id
CoAP transaction id.
coap_socket_t sock
socket object for the session, if any
unsigned int max_retransmit
maximum re-transmit count (default 4)
coap_pdu_t * partial_pdu
incomplete incoming pdu
struct coap_endpoint_t * endpoint
session's endpoint
unsigned tls_overhead
overhead of TLS layer
coap_session_state_t state
current state of relationaship with peer
coap_addr_tuple_t addr_info
key: remote/local address info
coap_proto_t proto
protocol used
uint16_t tx_mid
the last message id that was used in this session
unsigned ref
reference count from queues
struct coap_queue_t * delayqueue
list of delayed messages waiting to be sent
struct coap_context_t * context
session's context
size_t partial_read
if > 0 indicates number of bytes already read for an incoming message
int dtls_event
Tracking any (D)TLS events on this sesison.
void * tls
security parameters
coap_fixed_point_t ack_random_factor
ack random factor backoff (default 1.5)
uint8_t con_active
Active CON request sent.
void * app
application-specific data
coap_address_t local_if
optional local interface address
coap_fixed_point_t ack_timeout
timeout waiting for ack (default 2 secs)
unsigned mtu
path or CSM mtu
coap_session_type_t type
client or server side socket
coap_tid_t last_ping_mid
the last keepalive message id that was used in this session
size_t partial_write
if > 0 indicates number of bytes already written from the pdu at the head of sendqueue
int ifindex
interface index
struct coap_endpoint_t * endpoint
struct coap_session_t * session
coap_socket_flags_t flags
#define LL_DELETE(head, del)
#define LL_FOREACH(head, el)
#define LL_PREPEND(head, add)
#define LL_APPEND(head, add)
#define LL_FOREACH_SAFE(head, el, tmp)