Solstice client.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

127 lines
3.2 KiB

use std::net::{SocketAddr, SocketAddrV4};
use anyhow::bail;
use solstice_proto::server::PeerAddressResponse;
use crate::context::Context;
use crate::message_handler::MessageHandler;
use crate::peer::PeerState;
#[derive(Debug, Default)]
pub struct PeerAddressResponseHandler;
impl MessageHandler for PeerAddressResponseHandler {
type Message = PeerAddressResponse;
fn run(
self,
context: &mut Context,
response: &PeerAddressResponse,
) -> anyhow::Result<()> {
match context.state.peers.peers.get_mut(&response.user_name) {
Some(state @ &mut PeerState::FetchingAddress) => {
*state = PeerState::Opening {
address: SocketAddr::V4(SocketAddrV4::new(
response.ip,
response.port,
)),
};
}
entry => bail!("unexpected peer state entry: {:?}", entry),
};
// TODO: try opening a connection to the peer. Queue an event that will be
// handled later if that fails.
//
// Question: should dispatcher_tx be added to Context? Otherwise, how would
// the asynchronous open task notify the context it is done? If we add it,
// then how does the dispatcher notice it should stop running?
Ok(())
}
fn name() -> String {
"PeerAddressResponseHandler".to_string()
}
}
#[cfg(test)]
mod tests {
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use solstice_proto::server::PeerAddressResponse;
use crate::context::{ContextBundle, ContextOptions};
use crate::message_handler::MessageHandler;
use crate::peer::PeerState;
use super::PeerAddressResponseHandler;
#[test]
fn run_missing_state() {
let mut options = ContextOptions::default();
options.initial_state.peers.peers.insert(
"aisha".to_string(),
PeerState::Opening {
address: "1.2.3.4:42".parse().unwrap(),
},
);
let mut bundle = ContextBundle::new(options);
let response = PeerAddressResponse {
user_name: "aisha".to_string(),
ip: Ipv4Addr::new(1, 2, 3, 4),
port: 42,
};
PeerAddressResponseHandler::default()
.run(&mut bundle.context, &response)
.unwrap_err();
}
#[test]
fn run_wrong_state() {
let mut bundle = ContextBundle::default();
let response = PeerAddressResponse {
user_name: "aisha".to_string(),
ip: Ipv4Addr::new(1, 2, 3, 4),
port: 42,
};
PeerAddressResponseHandler::default()
.run(&mut bundle.context, &response)
.unwrap_err();
}
#[test]
fn run_success() {
let mut options = ContextOptions::default();
options
.initial_state
.peers
.peers
.insert("aisha".to_string(), PeerState::FetchingAddress);
let mut bundle = ContextBundle::new(options);
let response = PeerAddressResponse {
user_name: "aisha".to_string(),
ip: Ipv4Addr::new(1, 2, 3, 4),
port: 42,
};
PeerAddressResponseHandler::default()
.run(&mut bundle.context, &response)
.unwrap();
match bundle.context.state.peers.peers.get("aisha") {
Some(PeerState::Opening { address }) => assert_eq!(
address,
&SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 42))
),
entry => panic!("unexpected peer state entry: {:?}", entry),
};
}
}