#ifndef _DTLS_PEER_H_
#define _DTLS_PEER_H_
#include <sys/types.h>
#include "tinydtls.h"
#include "global.h"
#include "session.h"
#include "state.h"
#include "crypto.h"
#ifndef DTLS_PEERS_NOHASH
#include "uthash.h"
#endif
typedef enum { DTLS_CLIENT=0, DTLS_SERVER } dtls_peer_type;
typedef struct dtls_peer_t {
#ifdef DTLS_PEERS_NOHASH
struct dtls_peer_t *next;
#else
UT_hash_handle hh;
#endif
session_t session;
dtls_peer_type role;
dtls_state_t state;
int16_t optional_handshake_message;
dtls_security_parameters_t *security_params[2];
dtls_handshake_parameters_t *handshake_params;
} dtls_peer_t;
typedef struct dtls_ephemeral_peer_t {
session_t *session;
uint64_t rseq;
uint16_t mseq;
} dtls_ephemeral_peer_t;
static inline dtls_security_parameters_t *dtls_security_params_epoch(dtls_peer_t *peer, uint16_t epoch)
{
if (peer->security_params[0] && peer->security_params[0]->epoch == epoch) {
return peer->security_params[0];
} else if (peer->security_params[1] && peer->security_params[1]->epoch == epoch) {
return peer->security_params[1];
} else {
return NULL;
}
}
static inline dtls_security_parameters_t *dtls_security_params_read_epoch(dtls_peer_t *peer, uint16_t epoch)
{
if (peer->handshake_params) {
if (peer->handshake_params->hs_state.read_epoch == epoch) {
return dtls_security_params_epoch(peer, epoch);
}
} else if (peer->security_params[0] && peer->security_params[0]->epoch == epoch) {
return peer->security_params[0];
}
return NULL;
}
static inline dtls_security_parameters_t *dtls_security_params(dtls_peer_t *peer)
{
return peer->security_params[0];
}
static inline dtls_security_parameters_t *dtls_security_params_next(dtls_peer_t *peer)
{
if (peer->security_params[1])
dtls_security_free(peer->security_params[1]);
peer->security_params[1] = dtls_security_new();
if (!peer->security_params[1]) {
return NULL;
}
peer->security_params[1]->epoch = peer->security_params[0]->epoch + 1;
return peer->security_params[1];
}
static inline void dtls_security_params_free_other(dtls_peer_t *peer)
{
dtls_security_parameters_t * security0 = peer->security_params[0];
dtls_security_parameters_t * security1 = peer->security_params[1];
if (!security0 || !security1 || security0->epoch < security1->epoch)
return;
dtls_security_free(security1);
peer->security_params[1] = NULL;
}
static inline void dtls_security_params_switch(dtls_peer_t *peer)
{
dtls_security_parameters_t * security = peer->security_params[1];
peer->security_params[1] = peer->security_params[0];
peer->security_params[0] = security;
}
void peer_init(void);
dtls_peer_t *dtls_new_peer(const session_t *session);
void dtls_free_peer(dtls_peer_t *peer);
static inline dtls_state_t dtls_peer_state(const dtls_peer_t *peer) {
return peer->state;
}
static inline int dtls_peer_is_connected(const dtls_peer_t *peer) {
return peer->state == DTLS_STATE_CONNECTED;
}
#endif