use std::sync::RwLock;
use crate::crypto::{PublicKey, KeyPair};
use super::cookie::{CookiePair};
use super::csn::{CombinedSequencePair};
use super::state::{ServerHandshakeState, InitiatorHandshakeState, ResponderHandshakeState};
use super::types::{Identity, Address};
pub(crate) trait PeerContext {
fn identity(&self) -> Identity;
fn permanent_key(&self) -> Option<&PublicKey>;
fn session_key(&self) -> Option<&PublicKey>;
fn keypair(&self) -> Option<&KeyPair>;
fn csn_pair(&self) -> &RwLock<CombinedSequencePair>;
fn cookie_pair(&self) -> &CookiePair;
fn cookie_pair_mut(&mut self) -> &mut CookiePair;
}
#[derive(Debug)]
pub(crate) struct ServerContext {
handshake_state: ServerHandshakeState,
pub(crate) permanent_key: Option<PublicKey>,
pub(crate) session_key: Option<PublicKey>,
pub(crate) csn_pair: RwLock<CombinedSequencePair>,
pub(crate) cookie_pair: CookiePair,
}
impl ServerContext {
pub fn new() -> Self {
ServerContext {
handshake_state: ServerHandshakeState::New,
permanent_key: None,
session_key: None,
csn_pair: RwLock::new(CombinedSequencePair::new()),
cookie_pair: CookiePair::new(),
}
}
pub fn handshake_state(&self) -> ServerHandshakeState {
self.handshake_state
}
pub fn set_handshake_state(&mut self, new_state: ServerHandshakeState) {
trace!("Server handshake state transition: {:?} -> {:?}", self.handshake_state, new_state);
self.handshake_state = new_state;
}
}
impl PeerContext for ServerContext {
fn identity(&self) -> Identity {
Identity::Server
}
fn permanent_key(&self) -> Option<&PublicKey> {
self.permanent_key.as_ref()
}
fn session_key(&self) -> Option<&PublicKey> {
self.session_key.as_ref()
}
fn keypair(&self) -> Option<&KeyPair> {
None }
fn csn_pair(&self) -> &RwLock<CombinedSequencePair> {
&self.csn_pair
}
fn cookie_pair(&self) -> &CookiePair {
&self.cookie_pair
}
fn cookie_pair_mut(&mut self) -> &mut CookiePair {
&mut self.cookie_pair
}
}
#[derive(Debug)]
pub(crate) struct InitiatorContext {
handshake_state: InitiatorHandshakeState,
pub(crate) permanent_key: PublicKey,
pub(crate) session_key: Option<PublicKey>,
pub(crate) keypair: KeyPair,
pub(crate) csn_pair: RwLock<CombinedSequencePair>,
pub(crate) cookie_pair: CookiePair,
}
impl InitiatorContext {
pub fn new(permanent_key: PublicKey) -> Self {
InitiatorContext {
handshake_state: InitiatorHandshakeState::New,
permanent_key,
session_key: None,
keypair: KeyPair::new(),
csn_pair: RwLock::new(CombinedSequencePair::new()),
cookie_pair: CookiePair::new(),
}
}
pub fn handshake_state(&self) -> InitiatorHandshakeState {
self.handshake_state
}
pub fn set_handshake_state(&mut self, new_state: InitiatorHandshakeState) {
trace!("Initiator handshake state transition: {:?} -> {:?}", self.handshake_state, new_state);
self.handshake_state = new_state;
}
}
impl PeerContext for InitiatorContext {
fn identity(&self) -> Identity {
Identity::Initiator
}
fn permanent_key(&self) -> Option<&PublicKey> {
Some(&self.permanent_key)
}
fn session_key(&self) -> Option<&PublicKey> {
self.session_key.as_ref()
}
fn keypair(&self) -> Option<&KeyPair> {
Some(&self.keypair)
}
fn csn_pair(&self) -> &RwLock<CombinedSequencePair> {
&self.csn_pair
}
fn cookie_pair(&self) -> &CookiePair {
&self.cookie_pair
}
fn cookie_pair_mut(&mut self) -> &mut CookiePair {
&mut self.cookie_pair
}
}
#[derive(Debug)]
pub(crate) struct ResponderContext {
handshake_state: ResponderHandshakeState,
pub(crate) counter: u32,
pub(crate) address: Address,
pub(crate) permanent_key: Option<PublicKey>,
pub(crate) session_key: Option<PublicKey>,
pub(crate) keypair: KeyPair,
pub(crate) csn_pair: RwLock<CombinedSequencePair>,
pub(crate) cookie_pair: CookiePair,
}
impl ResponderContext {
pub fn new(address: Address, counter: u32) -> Self {
ResponderContext {
handshake_state: ResponderHandshakeState::New,
counter,
address,
permanent_key: None,
session_key: None,
keypair: KeyPair::new(),
csn_pair: RwLock::new(CombinedSequencePair::new()),
cookie_pair: CookiePair::new(),
}
}
pub fn handshake_state(&self) -> ResponderHandshakeState {
self.handshake_state
}
pub fn set_handshake_state(&mut self, new_state: ResponderHandshakeState) {
trace!("Responder handshake state transition: {:?} -> {:?}", self.handshake_state, new_state);
self.handshake_state = new_state;
}
}
impl PeerContext for ResponderContext {
fn identity(&self) -> Identity {
Identity::Responder(self.address.0)
}
fn permanent_key(&self) -> Option<&PublicKey> {
self.permanent_key.as_ref()
}
fn session_key(&self) -> Option<&PublicKey> {
self.session_key.as_ref()
}
fn keypair(&self) -> Option<&KeyPair> {
Some(&self.keypair)
}
fn csn_pair(&self) -> &RwLock<CombinedSequencePair> {
&self.csn_pair
}
fn cookie_pair(&self) -> &CookiePair {
&self.cookie_pair
}
fn cookie_pair_mut(&mut self) -> &mut CookiePair {
&mut self.cookie_pair
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn server_context_new() {
let ctx = ServerContext::new();
assert_eq!(ctx.identity(), Identity::Server);
assert_eq!(ctx.permanent_key(), None);
assert_eq!(ctx.session_key(), None);
}
}