Skip to content

Commit

Permalink
Make Logging configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
Snowiiii committed Oct 11, 2024
1 parent 9ac4bdb commit bcbde20
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 15 deletions.
8 changes: 6 additions & 2 deletions pumpkin-config/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ use serde::{Deserialize, Serialize};
pub struct CommandsConfig {
/// Are commands from the Console accepted ?
pub use_console: bool,
// TODO: commands...
/// Should be commands from players be logged in console?
pub log_console: bool, // TODO: commands...
}

impl Default for CommandsConfig {
fn default() -> Self {
Self { use_console: true }
Self {
use_console: true,
log_console: true,
}
}
}
3 changes: 3 additions & 0 deletions pumpkin-config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use log::warn;
use logging::LoggingConfig;
use pumpkin_core::{Difficulty, GameMode};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

Expand All @@ -10,6 +11,7 @@ use std::{
};

pub mod auth;
pub mod logging;
pub mod proxy;
pub mod resource_pack;

Expand Down Expand Up @@ -46,6 +48,7 @@ pub struct AdvancedConfiguration {
pub commands: CommandsConfig,
pub rcon: RCONConfig,
pub pvp: PVPConfig,
pub logging: LoggingConfig,
}

#[derive(Serialize, Deserialize)]
Expand Down
40 changes: 40 additions & 0 deletions pumpkin-config/src/logging.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
pub struct LoggingConfig {
pub enabled: bool,
pub level: LevelFilter,
pub env: bool,
pub threads: bool,
pub color: bool,
pub timestamp: bool,
}

impl Default for LoggingConfig {
fn default() -> Self {
Self {
enabled: true,
level: LevelFilter::Info,
env: false,
threads: true,
color: true,
timestamp: true,
}
}
}

#[derive(Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum LevelFilter {
/// A level lower than all log levels.
Off,
/// Corresponds to the `Error` log level.
Error,
/// Corresponds to the `Warn` log level.
Warn,
/// Corresponds to the `Info` log level.
Info,
/// Corresponds to the `Debug` log level.
Debug,
/// Corresponds to the `Trace` log level.
Trace,
}
26 changes: 26 additions & 0 deletions pumpkin-config/src/rcon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,31 @@ pub struct RCONConfig {
/// The maximum number of concurrent RCON connections allowed.
/// If 0 there is no limit
pub max_connections: u32,
/// RCON Logging
pub logging: RCONLogging,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct RCONLogging {
/// Whether successful RCON logins should be logged.
pub log_logged_successfully: bool,
/// Whether failed RCON login attempts with incorrect passwords should be logged.
pub log_wrong_password: bool,
/// Whether all RCON commands, regardless of success or failure, should be logged.
pub log_commands: bool,
/// Whether RCON quit commands should be logged.
pub log_quit: bool,
}

impl Default for RCONLogging {
fn default() -> Self {
Self {
log_logged_successfully: true,
log_wrong_password: true,
log_commands: true,
log_quit: true,
}
}
}

impl Default for RCONConfig {
Expand All @@ -22,6 +47,7 @@ impl Default for RCONConfig {
address: SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 25575),
password: "".to_string(),
max_connections: 0,
logging: Default::default(),
}
}
}
2 changes: 1 addition & 1 deletion pumpkin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ base64 = "0.22.1"
png = "0.17.14"

# logging
simple_logger = "5.0.0"
simple_logger = { version = "5.0.0", features = ["threads"] }
log.workspace = true

# networking
Expand Down
7 changes: 7 additions & 0 deletions pumpkin/src/client/player_packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,13 @@ impl Player {
pub fn handle_chat_command(&self, server: &Arc<Server>, command: SChatCommand) {
let dispatcher = server.command_dispatcher.clone();
dispatcher.handle_command(&mut CommandSender::Player(self), server, &command.command);
if ADVANCED_CONFIG.commands.log_console {
log::info!(
"Player ({}): executed command /{}",
self.gameprofile.name,
command.command
);
}
}

pub fn handle_player_ground(&self, _server: &Arc<Server>, ground: SSetPlayerGround) {
Expand Down
38 changes: 34 additions & 4 deletions pumpkin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#[cfg(target_os = "wasi")]
compile_error!("Compiling for WASI targets is not supported!");

use log::LevelFilter;
use mio::net::TcpListener;
use mio::{Events, Interest, Poll, Token};

Expand All @@ -38,6 +39,38 @@ pub mod server;
pub mod util;
pub mod world;

fn init_logger() {
use pumpkin_config::ADVANCED_CONFIG;
if ADVANCED_CONFIG.logging.enabled {
let mut logger = simple_logger::SimpleLogger::new();

if !ADVANCED_CONFIG.logging.timestamp {
logger = logger.without_timestamps();
}

if ADVANCED_CONFIG.logging.env {
logger = logger.env();
}

logger = logger.with_level(convert_logger_filter(ADVANCED_CONFIG.logging.level));

logger = logger.with_colors(ADVANCED_CONFIG.logging.color);
logger = logger.with_threads(ADVANCED_CONFIG.logging.threads);
logger.init().unwrap()
}
}

fn convert_logger_filter(level: pumpkin_config::logging::LevelFilter) -> LevelFilter {
match level {
pumpkin_config::logging::LevelFilter::Off => LevelFilter::Off,
pumpkin_config::logging::LevelFilter::Error => LevelFilter::Error,
pumpkin_config::logging::LevelFilter::Warn => LevelFilter::Warn,
pumpkin_config::logging::LevelFilter::Info => LevelFilter::Info,
pumpkin_config::logging::LevelFilter::Debug => LevelFilter::Debug,
pumpkin_config::logging::LevelFilter::Trace => LevelFilter::Trace,
}
}

fn main() -> io::Result<()> {
use std::sync::Arc;

Expand All @@ -46,10 +79,7 @@ fn main() -> io::Result<()> {
use pumpkin_core::text::{color::NamedColor, TextComponent};
use rcon::RCONServer;

simple_logger::SimpleLogger::new()
.with_level(log::LevelFilter::Info)
.init()
.unwrap();
init_logger();

let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
Expand Down
32 changes: 24 additions & 8 deletions pumpkin/src/rcon/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{
collections::HashMap,
io::{self, Read, Write},
net::SocketAddr,
sync::Arc,
};

Expand All @@ -9,7 +10,7 @@ use mio::{
Events, Interest, Poll, Token,
};
use packet::{ClientboundPacket, Packet, PacketError, ServerboundPacket};
use pumpkin_config::RCONConfig;
use pumpkin_config::{RCONConfig, ADVANCED_CONFIG};
use thiserror::Error;

use crate::server::Server;
Expand Down Expand Up @@ -71,11 +72,9 @@ impl RCONServer {
return Err(e);
}
};
log::info!("Accepted connection from: {}", address);
if config.max_connections != 0
&& connections.len() >= config.max_connections as usize
{
log::warn!("Max RCON connections reached");
break;
}

Expand All @@ -87,7 +86,7 @@ impl RCONServer {
Interest::READABLE.add(Interest::WRITABLE),
)
.unwrap();
connections.insert(token, RCONClient::new(connection));
connections.insert(token, RCONClient::new(connection, address));
},

token => {
Expand All @@ -98,6 +97,13 @@ impl RCONServer {
};
if done {
if let Some(mut client) = connections.remove(&token) {
let config = &ADVANCED_CONFIG.rcon;
if config.logging.log_quit {
log::info!(
"RCON ({}): Client closed connection",
client.address
);
}
poll.registry().deregister(&mut client.connection)?;
}
}
Expand All @@ -116,15 +122,17 @@ impl RCONServer {

pub struct RCONClient {
connection: TcpStream,
address: SocketAddr,
logged_in: bool,
incoming: Vec<u8>,
closed: bool,
}

impl RCONClient {
pub const fn new(connection: TcpStream) -> Self {
pub const fn new(connection: TcpStream, address: SocketAddr) -> Self {
Self {
connection,
address,
logged_in: false,
incoming: Vec::new(),
closed: false,
Expand All @@ -147,7 +155,7 @@ impl RCONClient {
}
// If we get a close here, we might have a reply, which we still want to write.
let _ = self.poll(server, password).await.map_err(|e| {
log::error!("rcon error: {e}");
log::error!("RCON error: {e}");
self.closed = true;
});
}
Expand All @@ -161,16 +169,21 @@ impl RCONClient {
None => return Ok(()),
};

let config = &ADVANCED_CONFIG.rcon;
match packet.get_type() {
ServerboundPacket::Auth => {
let body = packet.get_body();
if !body.is_empty() && packet.get_body() == password {
self.send(ClientboundPacket::AuthResponse, packet.get_id(), "".into())
.await?;
log::info!("RCON Client logged in successfully");
if config.logging.log_logged_successfully {
log::info!("RCON ({}): Client logged in successfully", self.address);
}
self.logged_in = true;
} else {
log::warn!("RCON Client has tried wrong password");
if config.logging.log_wrong_password {
log::info!("RCON ({}): Client has tried wrong password", self.address);
}
self.send(ClientboundPacket::AuthResponse, -1, "".into())
.await?;
self.closed = true;
Expand All @@ -186,6 +199,9 @@ impl RCONClient {
packet.get_body(),
);
for line in output {
if config.logging.log_commands {
log::info!("RCON ({}): {}", self.address, line);
}
self.send(ClientboundPacket::Output, packet.get_id(), line)
.await?;
}
Expand Down

0 comments on commit bcbde20

Please sign in to comment.