#ifndef COAP_SESSION_INTERNAL_H_
#define COAP_SESSION_INTERNAL_H_
#include "coap_internal.h"
#include "coap_io_internal.h"
#define COAP_DEFAULT_SESSION_TIMEOUT 300
#define COAP_PARTIAL_SESSION_TIMEOUT_TICKS (30 * COAP_TICKS_PER_SECOND)
#define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS 100
struct coap_addr_hash_t {
coap_address_t remote;
uint16_t lport;
coap_proto_t proto;
};
struct coap_session_t {
coap_proto_t proto;
coap_session_type_t type;
coap_session_state_t state;
unsigned ref;
size_t tls_overhead;
size_t mtu;
size_t csm_rcv_mtu;
coap_addr_hash_t addr_hash;
UT_hash_handle hh;
coap_addr_tuple_t addr_info;
int ifindex;
coap_socket_t sock;
#if COAP_SERVER_SUPPORT
coap_endpoint_t *endpoint;
#endif
coap_context_t *context;
void *tls;
uint16_t tx_mid;
uint8_t con_active;
uint8_t csm_block_supported;
coap_mid_t last_ping_mid;
coap_queue_t *delayqueue;
coap_lg_xmit_t *lg_xmit;
#if COAP_CLIENT_SUPPORT
coap_lg_crcv_t *lg_crcv;
#endif
#if COAP_SERVER_SUPPORT
coap_lg_srcv_t *lg_srcv;
#endif
size_t partial_write;
uint8_t read_header[8];
size_t partial_read;
coap_pdu_t *partial_pdu;
coap_tick_t last_rx_tx;
coap_tick_t last_tx_rst;
coap_tick_t last_ping;
coap_tick_t last_pong;
coap_tick_t csm_tx;
coap_dtls_cpsk_t cpsk_setup_data;
coap_bin_const_t *psk_identity;
coap_bin_const_t *psk_key;
coap_bin_const_t *psk_hint;
void *app;
coap_fixed_point_t ack_timeout;
coap_fixed_point_t ack_random_factor;
uint16_t max_retransmit;
uint16_t nstart;
coap_fixed_point_t default_leisure;
uint32_t probing_rate;
unsigned int dtls_timeout_count;
int dtls_event;
uint8_t csm_bert_rem_support;
uint8_t csm_bert_loc_support;
uint8_t block_mode;
uint8_t doing_first;
uint8_t proxy_session;
uint8_t delay_recursive;
uint8_t no_observe_cancel;
uint32_t tx_rtag;
uint64_t tx_token;
coap_bin_const_t *last_token;
coap_bin_const_t *echo;
coap_mid_t last_ack_mid;
coap_mid_t last_con_mid;
};
#if COAP_SERVER_SUPPORT
struct coap_endpoint_t {
struct coap_endpoint_t *next;
coap_context_t *context;
coap_proto_t proto;
uint16_t default_mtu;
coap_socket_t sock;
coap_address_t bind_addr;
coap_session_t *sessions;
};
#endif
void coap_session_send_csm(coap_session_t *session);
void coap_session_connected(coap_session_t *session);
int coap_session_refresh_psk_hint(coap_session_t *session,
const coap_bin_const_t *psk_hint);
int coap_session_refresh_psk_key(coap_session_t *session,
const coap_bin_const_t *psk_key);
int coap_session_refresh_psk_identity(coap_session_t *session,
const coap_bin_const_t *psk_identity);
#if COAP_SERVER_SUPPORT
coap_session_t *coap_new_server_session(
coap_context_t *ctx,
coap_endpoint_t *ep
);
#endif
ssize_t coap_session_send(coap_session_t *session,
const uint8_t *data, size_t datalen);
ssize_t coap_session_write(coap_session_t *session,
const uint8_t *data, size_t datalen);
ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu);
ssize_t
coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu,
coap_queue_t *node);
#if COAP_SERVER_SUPPORT
coap_session_t *coap_endpoint_get_session(coap_endpoint_t *endpoint,
const coap_packet_t *packet, coap_tick_t now);
#endif
size_t coap_session_max_pdu_rcv_size(const coap_session_t *session);
coap_session_t *coap_session_new_dtls_session(coap_session_t *session,
coap_tick_t now);
void coap_session_free(coap_session_t *session);
void coap_session_mfree(coap_session_t *session);
#define COAP_SESSION_REF(s) ((s)->ref
#define COAP_ACK_TIMEOUT(s) ((s)->ack_timeout)
#define COAP_ACK_RANDOM_FACTOR(s) ((s)->ack_random_factor)
#define COAP_MAX_RETRANSMIT(s) ((s)->max_retransmit)
#define COAP_NSTART(s) ((s)->nstart)
#define COAP_DEFAULT_LEISURE(s) ((s)->default_leisure)
#define COAP_PROBING_RATE(s) ((s)->probing_rate)
#define COAP_DEFAULT_LEISURE_TICKS(s) \
(COAP_DEFAULT_LEISURE(s).integer_part * COAP_TICKS_PER_SECOND + \
COAP_DEFAULT_LEISURE(s).fractional_part * COAP_TICKS_PER_SECOND / 1000)
#define COAP_MAX_TRANSMIT_SPAN(s) \
(((s)->ack_timeout.integer_part * 1000 + (s)->ack_timeout.fractional_part) * \
((1 << ((s)->max_retransmit)) -1) * \
((s)->ack_random_factor.integer_part * 1000 + \
(s)->ack_random_factor.fractional_part) \
/ 1000000)
#define COAP_MAX_TRANSMIT_WAIT(s) \
(((s)->ack_timeout.integer_part * 1000 + (s)->ack_timeout.fractional_part) * \
((1 << ((s)->max_retransmit + 1)) -1) * \
((s)->ack_random_factor.integer_part * 1000 + \
(s)->ack_random_factor.fractional_part) \
/ 1000000)
#define COAP_MAX_TRANSMIT_WAIT_TICKS(s) \
(COAP_MAX_TRANSMIT_WAIT(s) * COAP_TICKS_PER_SECOND)
#define COAP_PROCESSING_DELAY(s) \
(((s)->ack_timeout.integer_part * 1000 + (s)->ack_timeout.fractional_part + \
500) / 1000)
#define COAP_MAX_RTT(s) \
((2 * COAP_DEFAULT_MAX_LATENCY) + COAP_PROCESSING_DELAY(s))
#define COAP_EXCHANGE_LIFETIME(s) \
(COAP_MAX_TRANSMIT_SPAN(s) + (2 * COAP_DEFAULT_MAX_LATENCY) + \
COAP_PROCESSING_DELAY(s))
#define COAP_NON_LIFETIME(s) \
(COAP_MAX_TRANSMIT_SPAN(s) + COAP_DEFAULT_MAX_LATENCY)
#define SESSIONS_ADD(e, obj) \
HASH_ADD(hh, (e), addr_hash, sizeof((obj)->addr_hash), (obj))
#define SESSIONS_DELETE(e, obj) \
HASH_DELETE(hh, (e), (obj))
#define SESSIONS_ITER(e, el, rtmp) \
HASH_ITER(hh, (e), el, rtmp)
#define SESSIONS_ITER_SAFE(e, el, rtmp) \
for ((el) = (e); (el) && ((rtmp) = (el)->hh.next, 1); (el) = (rtmp))
#define SESSIONS_FIND(e, k, res) { \
HASH_FIND(hh, (e), &(k), sizeof(k), (res)); \
}
#endif