GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — feather/tools/proxy/src/main.rs at main · ByteCoding/feather Expand file tree/ Copy pathmain.rsMore file actions 218 lines (188 loc) · 7.27 KB / Copy pathmain.rsFile metadata and controls218 lines (188 loc) · 7.27 KB 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 use std::net::{SocketAddr, TcpListener, TcpStream}; use anyhow::{bail, Context}; use argh::FromArgs; use async_executor::Executor; use async_io::{block_on, Async}; use either::Either; use feather_protocol::{ packets::client::HandshakeState, ClientHandshakePacket, ClientPacket, ClientPacketCodec, ProtocolState, ServerLoginPacket, ServerPacket, ServerPacketCodec, }; use futures_lite::FutureExt; use futures_lite::{AsyncReadExt, AsyncWriteExt}; use simple_logger::SimpleLogger; /// A proxy for debugging and inspecting the Minecraft protocol. #[derive(Debug, FromArgs)] struct Args { /// the port to listen on. Must be different from /// the vanilla server's port. #[argh(option, short = 'p')] port: u16, /// the port of the server to proxy to. #[argh(option, short = 's')] server_port: u16, } fn main() -> anyhow::Result<()> { SimpleLogger::new() .with_level(log::LevelFilter::Debug) .init() .unwrap(); let args: Args = argh::from_env(); let addr = format!("127.0.0.1:{}", args.port); let listener = TcpListener::bind(&addr) .with_context(|| format!("failed to bind to port {}", args.port))?; let mut listener = Async::new(listener)?; log::info!("Listening on {}", addr); let executor = Executor::new(); block_on(executor.run(async { accept_connections(&executor, &mut listener, args.server_port).await; })); Ok(()) } async fn accept_connections( executor: &Executor<'static>, listener: &mut Async<TcpListener>, server_port: u16, ) { loop { let (stream, addr) = match listener.accept().await { Ok(con) => con, Err(e) => { log::error!("Failed to accept connection: {}", e); continue; } }; log::info!("Accepting connection from {}", addr); executor .spawn(async move { if let Err(e) = handle_connection(stream, server_port).await { log::error!("Connection dropped: {:?}", e); } }) .detach(); } } struct Connection { /// The client's username. username: String, client_buffer: [u8; 256], client_codec: ClientPacketCodec, client: Async<TcpStream>, server_buffer: [u8; 256], server_codec: ServerPacketCodec, server: Async<TcpStream>, } impl Connection { fn set_state(&mut self, state: ProtocolState) { log::info!("{}: switching to state {:?}", self.username, state); self.client_codec.set_state(state); self.server_codec.set_state(state); } } const MAX_PACKET_DISPLAY: usize = 4000; async fn handle_connection(client: Async<TcpStream>, server_port: u16) -> anyhow::Result<()> { let server = Async::<TcpStream>::connect(format!("127.0.0.1:{}", server_port).parse::<SocketAddr>()?) .await .with_context(|| format!("failed to connect to server at localhost:{}", server_port))?; let mut connection = Connection { username: String::from("<unknown>"), client_buffer: [0; 256], client_codec: ClientPacketCodec::new(), client, server_buffer: [0; 256], server_codec: ServerPacketCodec::new(), server, }; let mut buffer = Vec::new(); loop { let client = &mut connection.client; let client_buffer = &mut connection.client_buffer; let server = &mut connection.server; let server_buffer = &mut connection.server_buffer; // Attempt to read data from either the server or the client. let recv_client = async { Either::Left(client.read(client_buffer).await) }; let recv_server = async { Either::Right(server.read(server_buffer).await) }; match recv_client.race(recv_server).await { Either::Left(client) => { let mut bytes_read = client?; if bytes_read == 0 { bail!("disconnected from client"); } while let Some(packet) = connection .client_codec .decode(&connection.client_buffer[..bytes_read]) .context("failed to decode client packet")? { bytes_read = 0; let mut packet_str = format!("{:?}", packet); if packet_str.len() > MAX_PACKET_DISPLAY { packet_str = format!("{} <snip>", &packet_str[..MAX_PACKET_DISPLAY]); } log::info!("client @ {}: {}", connection.username, packet_str); // Attempt to detect state switches. if let ClientPacket::Handshake(packet) = &packet { let state = match packet { ClientHandshakePacket::Handshake(packet) => match packet.next_state { HandshakeState::Login => ProtocolState::Login, HandshakeState::Status => ProtocolState::Status, }, }; connection.set_state(state) } // Forward the packet to the server. connection.client_codec.encode(&packet, &mut buffer); connection.server.write_all(&buffer).await?; buffer.clear(); } } Either::Right(server) => { let mut bytes_read = server?; if bytes_read == 9 { bail!("disconnected from server"); } while let Some(packet) = connection .server_codec .decode(&connection.server_buffer[..bytes_read]) .context("failed to decode server packet")? { bytes_read = 0; let mut packet_str = format!("{:?}", packet); if packet_str.len() > MAX_PACKET_DISPLAY { packet_str = format!("{} <snip>", &packet_str[..MAX_PACKET_DISPLAY]); } log::info!("server @ {}: {}", connection.username, packet_str); // Attempt to detect state switches. if let ServerPacket::Login(ServerLoginPacket::LoginSuccess(packet)) = &packet { connection.username = packet.username.clone(); connection.set_state(ProtocolState::Play); } // Forward the packet to the client. connection.server_codec.encode(&packet, &mut buffer); connection.client.write_all(&buffer).await?; buffer.clear(); } } } } } #[cfg(test)] mod tests { use super::*; #[test] fn parse_cli_args() { let args = Args::from_args(&["minecraft-proxy"], &["-p", "25565", "-s", "25566"]).unwrap(); assert_eq!(args.port, 25565); assert_eq!(args.server_port, 25566); } #[test] fn parse_cli_args_long_port() { let args = Args::from_args( &["minecraft-proxy"], &["--port", "25565", "--server-port", "25566"], ) .unwrap(); assert_eq!(args.port, 25565); assert_eq!(args.server_port, 25566); } } |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |