use super::Controller;
use crate::node::cookie::Cookie;
use crate::node::header::{Extensions, Header, MessageType};
use crate::node::messages::confirm_ack::ConfirmAck;
use crate::node::messages::confirm_req::ConfirmReq;
use crate::node::messages::frontier_req::FrontierReq;
use crate::node::messages::frontier_resp::FrontierResp;
use crate::node::messages::handshake::{Handshake, HandshakeQuery, HandshakeResponse};
use crate::node::messages::keepalive::Keepalive;
use crate::node::messages::publish::Publish;
use crate::node::messages::telemetry_ack::TelemetryAck;
use crate::node::messages::telemetry_req::TelemetryReq;
use crate::{Public, Seed, Signature};
use anyhow::Context;
use tracing::{debug, instrument, trace, warn};
impl Controller {
#[instrument(skip(self))]
pub async fn send_handshake(&mut self) -> anyhow::Result<()> {
trace!("Sending handshake");
self.send_header(MessageType::Handshake, *Extensions::new().query())
.await?;
let cookie = Cookie::random();
self.state
.lock()
.await
.set_cookie(self.peer_addr, cookie.clone())
.await?;
let handshake_query = HandshakeQuery::new(cookie);
self.send(&handshake_query).await?;
Ok(())
}
pub async fn handle_handshake(
&mut self,
header: &Header,
handshake: Handshake,
) -> anyhow::Result<()> {
enum ShouldRespond {
No,
Yes(Public, Signature),
}
let mut should_respond = ShouldRespond::No;
if header.ext().is_query() {
let query = handshake.query.expect("query is None but is_query is True");
let seed = Seed::random();
let private = seed.derive(0);
let public = private.to_public()?;
let signature = private.sign(query.cookie().as_bytes())?;
public
.verify(query.cookie().as_bytes(), &signature)
.context("Verify recv handshake signature")?;
should_respond = ShouldRespond::Yes(public, signature);
}
if header.ext().is_response() {
let response = handshake
.response
.expect("response is None but is_response is True");
let public = response.public;
let signature = response.signature;
let cookie = &self
.state
.lock()
.await
.cookie_for_socket_addr(&self.peer_addr)
.await?;
if cookie.is_none() {
warn!(
"Peer {:?} has no cookie. Can't verify handshake.",
self.peer_addr
);
return Ok(());
}
let cookie = cookie.as_ref().unwrap();
if self.validate_handshakes {
public
.verify(&cookie.as_bytes(), &signature)
.context("Invalid signature in handshake response")?;
}
}
if let ShouldRespond::Yes(public, signature) = should_respond {
let mut header = self.header;
header.reset(MessageType::Handshake, *Extensions::new().response());
self.send(&header).await?;
let response = HandshakeResponse::new(public, signature);
self.send(&response).await?;
}
Ok(())
}
pub async fn handle_keepalive(
&mut self,
_header: &Header,
keepalive: Keepalive,
) -> anyhow::Result<()> {
debug!("{:?}", keepalive);
Ok(())
}
pub async fn handle_telemetry_req(
&mut self,
_header: &Header,
_telemetry_req: TelemetryReq,
) -> anyhow::Result<()> {
Ok(())
}
pub async fn handle_telemetry_ack(
&mut self,
_header: &Header,
_telemetry_ack: TelemetryAck,
) -> anyhow::Result<()> {
Ok(())
}
pub async fn handle_publish(
&mut self,
_header: &Header,
_publish: Publish,
) -> anyhow::Result<()> {
Ok(())
}
pub async fn handle_confirm_req(
&mut self,
_header: &Header,
_confirm_req: ConfirmReq,
) -> anyhow::Result<()> {
Ok(())
}
pub async fn handle_confirm_ack(
&mut self,
_header: &Header,
_confirm_ack: ConfirmAck,
) -> anyhow::Result<()> {
Ok(())
}
pub async fn handle_frontier_req(
&mut self,
_header: &Header,
_frontier_req: FrontierReq,
) -> anyhow::Result<()> {
self.frontier_stream = true;
Ok(())
}
pub async fn handle_frontier_resp(
&mut self,
_frontier_resp: FrontierResp,
) -> anyhow::Result<()> {
Ok(())
}
}