|
|
|
@ -1,6 +1,7 @@ |
|
|
|
//! A client interface for remote servers.
|
|
|
|
|
|
|
|
use std::io;
|
|
|
|
use std::net::Ipv4Addr;
|
|
|
|
|
|
|
|
use log::{debug, info};
|
|
|
|
use thiserror::Error;
|
|
|
|
@ -20,6 +21,15 @@ pub struct Client { |
|
|
|
version: Version,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Contents of a successful login response.
|
|
|
|
pub struct LoginInfo {
|
|
|
|
/// The server's message of the day.
|
|
|
|
pub motd: String,
|
|
|
|
|
|
|
|
/// Our public IP address, as observed by the server.
|
|
|
|
pub public_ip: Ipv4Addr,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An error that arose while logging in to a remote server.
|
|
|
|
#[derive(Debug, Error)]
|
|
|
|
pub enum ClientLoginError {
|
|
|
|
@ -63,7 +73,7 @@ impl Client { |
|
|
|
pub async fn login(
|
|
|
|
mut self,
|
|
|
|
credentials: Credentials,
|
|
|
|
) -> Result<ClientWorker, ClientLoginError> {
|
|
|
|
) -> Result<(LoginInfo, ClientWorker), ClientLoginError> {
|
|
|
|
let login_request = credentials.into_login_request(self.version);
|
|
|
|
debug!("Sending login request: {:?}", login_request);
|
|
|
|
self
|
|
|
|
@ -94,7 +104,12 @@ impl Client { |
|
|
|
info!("Login: Public IP address: {}", ip);
|
|
|
|
info!("Login: Password MD5: {:?}", password_md5_opt);
|
|
|
|
|
|
|
|
Ok(Worker::from_parts(self.reader, self.writer))
|
|
|
|
let info = LoginInfo {
|
|
|
|
motd,
|
|
|
|
public_ip: ip,
|
|
|
|
};
|
|
|
|
let worker = Worker::from_parts(self.reader, self.writer);
|
|
|
|
Ok((info, worker))
|
|
|
|
}
|
|
|
|
ServerResponse::LoginResponse(LoginResponse::LoginFail { reason }) => {
|
|
|
|
Err(ClientLoginError::LoginFailed(reason, self))
|
|
|
|
@ -190,7 +205,7 @@ mod tests { |
|
|
|
.await
|
|
|
|
.expect("connecting");
|
|
|
|
|
|
|
|
let mut worker = Client::new(stream)
|
|
|
|
let (_, mut worker) = Client::new(stream)
|
|
|
|
.login(credentials())
|
|
|
|
.await
|
|
|
|
.expect("logging in");
|
|
|
|
|