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.

95 lines
2.2 KiB

//! Information about a connected client
use std::fmt;
use std::io::{BufRead, BufReader, BufWriter, ErrorKind, Write};
use std::net::{Shutdown, SocketAddr};
use log::error;
use mio::net::TcpStream;
use mio::Token;
use crate::result::RudeResult;
use crate::state::*;
use crate::try_log;
/// `Client` struct for storing information about a connected client, also
/// a few helper functions for communicating with the client.
#[derive(Debug)]
pub struct Client {
/// TCP socket
pub socket: TcpStream,
/// Identifier token
pub token: Token,
/// IP information
pub addr: SocketAddr,
/// Client's play state
pub state: State,
}
impl fmt::Display for Client {
/// Only need the ip and port to be printed.
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.addr.ip(), self.addr.port())
}
}
impl Into<String> for Client {
/// Convert the ip and port into a string.
fn into(self) -> String {
format!("{}:{}", self.addr.ip(), self.addr.port())
}
}
impl Client {
/// Read a message from the client
pub fn read(&self) -> RudeResult<String> {
let reader = BufReader::new(&self.socket);
let mut buf = String::new();
for line in reader.lines() {
match line {
Ok(line) => buf += &line,
Err(e) => match e.kind() {
ErrorKind::WouldBlock => break,
_ => return Err(e.into()),
},
}
}
Ok(buf)
}
/// Send a string to the client.
pub fn send_without_prompt<T: Into<String>>(&mut self, message: T) {
let message = message.into();
let mut writer = BufWriter::new(&self.socket);
if let Err(e) = writer.write_all(message.as_bytes()) {
error!("Unable to send message to client ({:?}): {}", self, e);
}
}
/// Send a string to the client, followed by a prompt.
pub fn send_with_prompt<T: Into<String>>(&mut self, message: T) {
let message = message.into() + self.prompt();
let mut writer = BufWriter::new(&self.socket);
if let Err(e) = writer.write_all(message.as_bytes()) {
error!("Unable to send message to client ({:?}): {}", self, e);
}
}
fn prompt(&self) -> &str {
"\n> "
}
pub fn close(&self) -> RudeResult<()> {
Ok(try_log!(
self.socket.shutdown(Shutdown::Both),
"Unable to close socket"
))
}
}