### Setup Dual-Output Logging with Tracing in Rust Source: https://context7.com/chungchandev/ccproxy/llms.txt Configures a tracing subscriber for CCProxy to output logs to both standard output (stdout) and rolling daily log files. Supports configurable log levels and formats (plain text or JSON) for each output. Requires the 'ccproxy' crate. ```rust use ccproxy::config::{CCProxyConfig, LogConfig, LogBaseConfig, LogFormat}; // Default logging configuration let log_config = LogConfig { stdout: LogBaseConfig { filter: "info".to_owned(), // trace, debug, info, warn, error format: LogFormat::Plain, // Plain or Json }, file: LogBaseConfig { filter: "debug".to_owned(), format: LogFormat::Json, }, }; // Initialize tracing subscriber let (subscriber, _guard) = log_config.tracing_subscriber()?; tracing::subscriber::set_global_default(subscriber) .expect("Failed to init tracing subscriber"); // Log messages will now go to both stdout and data/logs/*.log tracing::info!("Proxy server starting..."); tracing::debug!("Debug information for log files"); tracing::error!("Error messages appear everywhere"); // Log files are stored in data/logs/ with daily rotation // Example filename: 2024-01-15.log ``` -------------------------------- ### Implement Minecraft Query Protocol Handler in Rust Source: https://context7.com/chungchandev/ccproxy/llms.txt Shows how to implement the Minecraft Query Protocol using `QueryHandler` for server status requests. It covers handshake with challenge token authentication and supports both basic and full stat queries. The example includes setting up a fallback configuration and querying an upstream server directly, then processing the response. ```rust use ccproxy::network::query::QueryHandler; use ccproxy::config::ProxyQueryConfig; use std::net::SocketAddr; use std::time::Duration; // Create fallback query configuration let fallback_query = ProxyQueryConfig { motd: "My Server".to_owned(), game_type: "SMP".to_owned(), map: "Overworld".to_owned(), num_players: 10, max_players: 100, host_port: 19132, host_ip: "0.0.0.0".parse().unwrap(), version: "1.21.101".to_owned(), plugins: None, players: vec!["Player1".to_owned(), "Player2".to_owned()], }; // Initialize query handler let upstream_query_addr: SocketAddr = "127.0.0.1:19133".parse().unwrap(); let query_handler = QueryHandler::new(upstream_query_addr, &fallback_query); // Query an upstream server directly (static method) let response = QueryHandler::query( &upstream_query_addr, Duration::from_secs(5), // timeout 3, // retry count true, // full stat (true) or basic stat (false) ).await?; // Process query response match response.payload { QueryResponsePacketPayload::FullStat { k_v_section, players } => { println!("Server: {}", k_v_section.get("hostname").unwrap_or(&"Unknown".to_owned())); println!("Players online: {:?}", players); }, QueryResponsePacketPayload::BasicStat { motd, num_players, max_players, .. } => { println!("Server: {} ({}/{})", motd, num_players, max_players); }, _ => {} } ``` -------------------------------- ### Encode and Decode Minecraft Bedrock MOTD Strings in Rust Source: https://context7.com/chungchandev/ccproxy/llms.txt Demonstrates how to use the `BedrockMotd` struct to create, encode, and decode Minecraft Bedrock Edition MOTD strings. This involves handling server information like name, version, player counts, and game type. The `encode` method allows for optional GUID overriding, while `decode` can parse raw MOTD strings and override port information. ```rust use ccproxy::network::bedrock::{BedrockMotd, BedrockEdition, BedrockGametype}; // Create a custom MOTD let motd = BedrockMotd { edition: BedrockEdition::MCPE, server_name: "My Awesome Server".to_owned(), protocol_version: 827, version: "1.21.101".to_owned(), num_players: 5, max_players: 100, guid: 12345678, server_sub_name: "Powered by CCProxy".to_owned(), gametype: BedrockGametype::Survival, nintendo_limited: false, ipv4_port: Some(19132), ipv6_port: None, }; // Encode MOTD to string (optionally override GUID) let encoded = motd.encode(Some(87654321)); // Result: "MCPE;My Awesome Server;827;1.21.101;5;100;87654321;Powered by CCProxy;Survival;1;19132;" // Decode MOTD from upstream server response let raw_motd = "MCPE;Another Server;827;1.21.101;10;50;99999;SubName;Creative;1;19132;".to_owned(); let decoded = BedrockMotd::decode( raw_motd, None, // Keep original GUID Some(19132), // Override IPv4 port None, // No IPv6 port )?; println!("Server: {} ({}/{})", decoded.server_name, decoded.num_players, decoded.max_players); // Output: Server: Another Server (10/50) ``` -------------------------------- ### Custom Error Handling with CCProxyError in Rust Source: https://context7.com/chungchandev/ccproxy/llms.txt Illustrates CCProxy's custom error type, `CCProxyError`, which utilizes the `thiserror` crate for robust error management. This includes handling various error categories like I/O, configuration, networking, and protocol parsing. The example shows how to initialize the proxy and handle specific error variants. ```rust use ccproxy::error::{CCProxyError, CCProxyResult}; use ccproxy::config::CCProxyConfig; fn setup_proxy() -> CCProxyResult<()> { // Configuration errors are automatically converted let config = CCProxyConfig::init()?; // Handle specific error types match CCProxyConfig::init() { Ok(config) => { println!("Config loaded successfully"); Ok(()) }, Err(CCProxyError::Config { err }) => { eprintln!("Configuration error: {}", err); Err(CCProxyError::Config { err }) }, Err(CCProxyError::IO { err }) => { eprintln!("IO error (file not readable?): {}", err); Err(CCProxyError::IO { err }) }, Err(e) => { eprintln!("Unexpected error: {}", e); Err(e) } } } // Error types available: // - CCProxyError::IO { err } - I/O operations // - CCProxyError::Config { err } - Configuration parsing // - CCProxyError::RakNet { err } - RakNet networking // - CCProxyError::UpstreamMotdInvalid - Invalid upstream MOTD // - CCProxyError::MotdInvalid - MOTD parsing failure // - CCProxyError::QueryInvalid - Query protocol errors // - CCProxyError::QueryTimeout - Query request timeout // - CCProxyError::GracefulShutdown { err } - Shutdown handling // - CCProxyError::TracingAppenderRollingInit { err } - Log file init // - CCProxyError::TracingSubscriberParse { err } - Log filter parsing ``` -------------------------------- ### Running CCProxy Server Source: https://context7.com/chungchandev/ccproxy/llms.txt Demonstrates various methods to run the CCProxy server, including default configuration, Docker deployment, building from source, and using Nix. Ensure the necessary ports are exposed when using Docker. ```bash # Run with default configuration (auto-generated at data/config/config.yaml) ./ccproxy run # Run with Docker docker run -d \ --name ccproxy \ -p 19132:19132/udp \ -v ./data:/app/data \ ghcr.io/chungchandev/ccproxy:latest # Build from source and run cargo build --release ./target/release/ccproxy run # Run with Nix nix run . -- run ``` -------------------------------- ### Running CCProxy with Nix Source: https://github.com/chungchandev/ccproxy/blob/main/README.md This snippet shows how to build and run CCProxy using Nix, a powerful package manager. It demonstrates both building the release binary and running the proxy directly using Nix commands. ```sh nix build # or run directly nix run . -- run ``` -------------------------------- ### Initializing CCProxy Configuration in Rust Source: https://context7.com/chungchandev/ccproxy/llms.txt Illustrates how to initialize and access CCProxy configuration within a Rust application using the `CCProxyConfig::init()` function. This function handles loading configuration from YAML files and environment variables, and automatically generates a default config if none exists. It demonstrates accessing various configuration parameters. ```rust use ccproxy::config::CCProxyConfig; // Initialize configuration (loads from data/config/config.yaml and environment) let config = CCProxyConfig::init()?; // Access configuration values println!("Proxy address: {}", config.proxy.address); println!("Upstream address: {}", config.upstream.address); println!("Query address: {:?}", config.upstream.query_address); println!("PROXY protocol enabled: {}", config.upstream.proxy_protocol); // Access fallback MOTD settings println!("Fallback server name: {}", config.proxy.fallback_motd.server_name); println!("Max players: {}", config.proxy.fallback_motd.max_players); // Access logging configuration println!("Stdout log filter: {}", config.log.stdout.filter); ``` -------------------------------- ### Building CCProxy from Source (Rust) Source: https://github.com/chungchandev/ccproxy/blob/main/README.md This snippet demonstrates how to build CCProxy from its source code using Cargo, the Rust build system. It includes cloning the repository and running the build command. The resulting binary is placed in the `target/release/` directory. ```sh git clone https://github.com/chungchandev/ccproxy.git cd ccproxy cargo build --release ``` -------------------------------- ### Basic CCProxy Configuration (YAML) Source: https://github.com/chungchandev/ccproxy/blob/main/README.md This YAML configuration defines the logging, proxy, and upstream server settings for CCProxy. It specifies log levels, formats, proxy listen address, fallback MOTD and query responses, and the upstream server details. Environment variables can override these settings. ```yaml # Logging configuration log: # Stdout logging stdout: filter: "info" # Log level filter (trace, debug, info, warn, error) format: plain # Log format: "plain" or "json" # File logging (daily rolling files in data/logs/) file: filter: "info" format: plain # Proxy server configuration proxy: address: "0.0.0.0:19132" # Address the proxy listens on # Fallback MOTD shown when the upstream server is unreachable fallback_motd: edition: MCPE # MCPE (Bedrock) or MCEE (Education Edition) server_name: "CCProxy" protocol_version: 827 version: "1.21.101" num_players: 0 max_players: 100 server_sub_name: "CCProxy" gametype: Survival # Survival or Creative nintendo_limited: false ipv4_port: 19132 ipv6_port: null # Fallback Query Protocol response fallback_query: motd: "CCProxy" game_type: "SMP" map: "CCProxy" num_players: 0 max_players: 100 host_port: 19132 host_ip: "0.0.0.0" version: "1.21.101" # Upstream (backend) server configuration upstream: address: "127.0.0.1:19133" # Upstream Bedrock server address query_address: "127.0.0.1:19133" # Upstream Query Protocol address (null to disable) proxy_protocol: false # Enable HAProxy v2 PROXY protocol ``` -------------------------------- ### Docker Deployment for CCProxy Source: https://github.com/chungchandev/ccproxy/blob/main/README.md This snippet shows how to run CCProxy using Docker. It maps the default UDP port 19132 and mounts a local directory for data persistence. This is the recommended deployment method. ```sh docker run -d \ --name ccproxy \ -p 19132:19132/udp \ -v ./data:/app/data \ ghcr.io/chungchandev/ccproxy:latest ``` -------------------------------- ### Overriding CCProxy Configuration with Environment Variables Source: https://context7.com/chungchandev/ccproxy/llms.txt Shows how to override CCProxy's YAML configuration using environment variables. This method allows for dynamic configuration changes without modifying the config file directly. It supports nested keys using double underscores and also allows using a `.env` file. ```bash # Override upstream server address export CCPROXY__UPSTREAM__ADDRESS="192.168.1.100:19133" # Override proxy listening address export CCPROXY__PROXY__ADDRESS="0.0.0.0:25565" # Enable HAProxy v2 PROXY protocol export CCPROXY__UPSTREAM__PROXY_PROTOCOL=true # Set log level to debug export CCPROXY__LOG__STDOUT__FILTER="debug" # Use JSON logging format export CCPROXY__LOG__STDOUT__FORMAT="json" # Set custom data path export CCPROXY__DATA_PATH="/var/lib/ccproxy" # Using .env file cat > .env << 'EOF' CCPROXY__UPSTREAM__ADDRESS=192.168.1.100:19133 CCPROXY__PROXY__ADDRESS=0.0.0.0:19132 CCPROXY__UPSTREAM__PROXY_PROTOCOL=false CCPROXY__LOG__STDOUT__FILTER=info EOF ./ccproxy run ``` -------------------------------- ### Parse Upstream Query Data into ProxyQueryConfig in Rust Source: https://context7.com/chungchandev/ccproxy/llms.txt Parses key-value data and player lists received from upstream servers into the `ProxyQueryConfig` structure. This structure is used internally by CCProxy for managing and relaying server information to clients. Requires the 'ccproxy' crate and `std::collections::HashMap`. ```rust use ccproxy::config::ProxyQueryConfig; use std::collections::HashMap; // Simulate parsed query response from upstream let mut k_v_section = HashMap::new(); k_v_section.insert("hostname".to_owned(), "Upstream Server".to_owned()); k_v_section.insert("gametype".to_owned(), "SMP".to_owned()); k_v_section.insert("map".to_owned(), "world".to_owned()); k_v_section.insert("numplayers".to_owned(), "15".to_owned()); k_v_section.insert("maxplayers".to_owned(), "100".to_owned()); k_v_section.insert("hostport".to_owned(), "19133".to_owned()); k_v_section.insert("hostip".to_owned(), "192.168.1.10".to_owned()); k_v_section.insert("version".to_owned(), "1.21.101".to_owned()); let players = vec![ "Steve".to_owned(), "Alex".to_owned(), "Notch".to_owned(), ]; // Parse into ProxyQueryConfig let query_config = ProxyQueryConfig::from_kv_and_players(k_v_section, players)?; println!("Server: {} ({}/{})", query_config.motd, query_config.num_players, query_config.max_players ); // Output: Server: Upstream Server (15/100) println!("Players: {:?}", query_config.players); // Output: Players: ["Steve", "Alex", "Notch"] ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.