tmd/src/main.rs

135 lines
3.7 KiB
Rust

#![allow(incomplete_features)]
#![feature(const_generics)]
#![feature(never_type)]
mod net;
use std::io;
use std::net::IpAddr;
use tokio::net::{TcpListener, TcpStream};
#[tokio::main]
async fn main() -> io::Result<()> {
use clap::{load_yaml, App};
let yaml = load_yaml!("cli.yml");
let args = App::from_yaml(yaml).get_matches();
let host: IpAddr = args
.value_of("host")
.unwrap_or("::")
.parse()
.expect("Invalid host IP address.");
let port: u16 = args
.value_of("port")
.unwrap_or("25565")
.parse()
.expect("Port must be an integer between 1 an 65535.");
let listener = TcpListener::bind((host, port))
.await
.unwrap_or_else(|_| panic!("Failed to bind to {}:{}.", host, port));
listen(listener).await;
Ok(())
}
async fn listen(listener: TcpListener) {
loop {
let (socket, _) = match listener.accept().await {
Ok(x) => x,
Err(e) => {
eprintln!("Failed to accept client: {:?}", e);
continue;
},
};
tokio::spawn(accept_connection(socket));
}
}
async fn accept_connection(socket: TcpStream) -> Option<!> {
use crate::net::chat::Chat;
use crate::net::listener::*;
use crate::net::packet_stream::PacketStreamMaps;
use crate::net::protocol::state::play::*;
#[cfg(not(feature = "compression"))]
let compression_threshold = None;
#[cfg(feature = "compression")]
let compression_threshold = Some(64);
#[cfg(not(feature = "encryption"))]
let encryption_config = None;
#[cfg(feature = "encryption")]
let encryption_config = Some({
use rsa::RSAPrivateKey;
use std::fs::File;
use std::io::Read;
let mut public_key_bytes = Vec::new();
File::open("private/pub.der")
.expect("missing public key")
.read_to_end(&mut public_key_bytes)
.unwrap();
let mut private_key_bytes = Vec::new();
File::open("private/priv.der")
.expect("missing private key")
.read_to_end(&mut private_key_bytes)
.unwrap();
let private_key = RSAPrivateKey::from_pkcs1(&private_key_bytes).expect("Invalid private key.");
EncryptionConfig {
private_key,
public_key_bytes: public_key_bytes.into_boxed_slice(),
}
});
#[cfg(not(feature = "authentication"))]
let authentication_config = None;
#[cfg(feature = "authentication")]
let authentication_config = Some(AuthenticationConfig::default());
let config = ConnectionConfig {
enforce_host: Some(vec!["localhost".to_string().into_boxed_str()].into_boxed_slice()),
compression_threshold,
encryption_config,
authentication_config,
};
let (mut con, login_state) = setup_connection(&config, Box::new(socket), || {
use crate::net::protocol::state::status::{ResponseData, ResponsePlayers, ResponseVersion};
ResponseData {
version: ResponseVersion {
name: "1.16.1".to_string().into_boxed_str(),
protocol: 736,
},
players: ResponsePlayers {
max: 255,
online: 0,
sample: Vec::new(),
},
description: Chat {
text: "Hello, world!".to_string().into_boxed_str(),
},
favicon: None,
}
})
.await?;
eprintln!("Client logged in as: {:?}", login_state);
con.send(&Clientbound::Disconnect(Disconnect {
reason: Chat {
text: "Goodbye!".to_string().into_boxed_str(),
},
}))
.await
.ok()?;
None
}