net_stream/
client.rs

1//! Client.
2
3mod actor;
4pub mod actor_handle;
5pub mod event;
6
7use crate::client::actor_handle::ActorHandle;
8use crate::client::event::Event;
9use crate::message_types::MessageTypes;
10use futures::channel::mpsc;
11use tokio::net::TcpStream;
12use tokio::net::UdpSocket;
13
14/// Error connecting to server
15#[derive(thiserror::Error, Debug)]
16pub enum ConnectError {
17    /// IO error.
18    #[error("IO Error")]
19    Io(#[from] ::std::io::Error),
20
21    /// Error resolving server host.
22    #[error("Unknown host {}", host)]
23    UnknownHost {
24        /// Host
25        host: String,
26    },
27}
28
29/// Client status
30///
31/// Returned from [actor_handle::ActorHandle::get_status].
32#[derive(Debug, Clone, PartialEq, Eq, Hash)]
33pub struct Status {
34    /// Time of most recently recieved UDP heartbeat from server.
35    pub latest_udp_heartbeat: Option<std::time::Instant>,
36}
37
38/// Connect.
39pub async fn connect<M: MessageTypes>(server_host: &str) -> Result<(ActorHandle<M>, futures::channel::mpsc::Receiver<Event<M>>), ConnectError> {
40    // Resolve host (DNS lookup)
41    log::info!("Resolving host {server_host}...");
42    let mut server_addr_iter = tokio::net::lookup_host(server_host).await?;
43    let server_addr = server_addr_iter.next().ok_or_else(|| ConnectError::UnknownHost {
44        host: server_host.to_owned(),
45    })?;
46    log::info!("OK: {server_host} resolved to {server_addr}");
47
48    log::info!("Connecting TCP stream...");
49    let tcp_stream = TcpStream::connect(&server_addr).await?;
50    log::info!("OK: Connected TCP stream");
51    log::info!("Getting TCP stream local address...");
52    let local_addr = tcp_stream.local_addr()?;
53    log::info!("OK: TCP stream local address {local_addr}");
54    log::info!("Binding UDP socket at {local_addr}...");
55    let udp_socket = UdpSocket::bind(local_addr).await?;
56    log::info!("OK: Bound UDP socket");
57    log::info!("Setting default destination for UDP socket...");
58    udp_socket.connect(&server_addr).await?;
59    log::info!("OK: Set default destination for UDP socket");
60
61    let (actor_msg_sender, actor_msg_receiver) = mpsc::channel::<actor::Message<M>>(32);
62    let (event_sender, event_receiver) = mpsc::channel::<Event<M>>(128);
63
64    let join_handle = tokio::spawn(actor::actor(actor_msg_receiver, event_sender, tcp_stream, udp_socket, server_addr));
65    let actor_handle = ActorHandle::new(join_handle, actor_msg_sender);
66
67    Ok((actor_handle, event_receiver))
68}