// Copyright 2016 Matthew Collins // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #![allow(dead_code)] #![allow(non_camel_case_types)] use aes::Aes128; use cfb8::Cfb8; use cfb8::stream_cipher::{NewStreamCipher, StreamCipher}; use serde_json; #[cfg(not(target_arch = "wasm32"))] use reqwest; pub mod mojang; use crate::nbt; use crate::format; use std::fmt; use std::default; use std::net::TcpStream; use std::io; use std::io::{Write, Read}; use std::convert; use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; use flate2::read::{ZlibDecoder, ZlibEncoder}; use flate2::Compression; use std::time::{Instant, Duration}; use crate::shared::Position; pub const SUPPORTED_PROTOCOLS: [i32; 12] = [404, 451, 452, 340, 316, 315, 210, 109, 107, 74, 47, 5]; // TODO: switch to using thread_local storage?, see https://doc.rust-lang.org/std/macro.thread_local.html pub static mut CURRENT_PROTOCOL_VERSION: i32 = SUPPORTED_PROTOCOLS[0]; /// Helper macro for defining packets #[macro_export] macro_rules! state_packets { ($($state:ident $stateName:ident { $($dir:ident $dirName:ident { $( $(#[$attr:meta])* packet $name:ident { $($(#[$fattr:meta])*field $field:ident: $field_type:ty = $(when ($cond:expr))*, )+ } )* })+ })+) => { use crate::protocol::*; use std::io; #[derive(Debug)] pub enum Packet { $( $( $( $name($state::$dir::$name), )* )+ )+ } $( pub mod $state { $( pub mod $dir { #![allow(unused_imports)] use crate::protocol::*; use std::io; use crate::format; use crate::nbt; use crate::types; use crate::item; use crate::shared::Position; #[allow(non_upper_case_globals)] pub mod internal_ids { create_ids!(i32, $($name),*); } $( #[derive(Default, Debug)] $(#[$attr])* pub struct $name { $($(#[$fattr])* pub $field: $field_type),+, } impl PacketType for $name { fn packet_id(&self, version: i32) -> i32 { packet::versions::translate_internal_packet_id_for_version(version, State::$stateName, Direction::$dirName, internal_ids::$name, false) } fn write(self, buf: &mut W) -> Result<(), Error> { $( if true $(&& ($cond(&self)))* { self.$field.write_to(buf)?; } )+ Result::Ok(()) } } )* } )+ } )+ /// Returns the packet for the given state, direction and id after parsing the fields /// from the buffer. pub fn packet_by_id(version: i32, state: State, dir: Direction, id: i32, mut buf: &mut R) -> Result, Error> { match state { $( State::$stateName => { match dir { $( Direction::$dirName => { let internal_id = packet::versions::translate_internal_packet_id_for_version(version, state, dir, id, true); match internal_id { $( self::$state::$dir::internal_ids::$name => { use self::$state::$dir::$name; let mut packet : $name = $name::default(); $( if true $(&& ($cond(&packet)))* { packet.$field = Serializable::read_from(&mut buf)?; } )+ Result::Ok(Option::Some(Packet::$name(packet))) }, )* _ => Result::Ok(Option::None) } } )+ } } )+ } } } } #[macro_export] macro_rules! protocol_packet_ids { ($($state:ident $stateName:ident { $($dir:ident $dirName:ident { $( $(#[$attr:meta])* $id:expr => $name:ident )* })+ })+) => { use crate::protocol::*; pub fn translate_internal_packet_id(state: State, dir: Direction, id: i32, to_internal: bool) -> i32 { match state { $( State::$stateName => { match dir { $( Direction::$dirName => { if to_internal { match id { $( $id => crate::protocol::packet::$state::$dir::internal_ids::$name, )* _ => panic!("bad packet id 0x{:x} in {:?} {:?}", id, dir, state), } } else { match id { $( crate::protocol::packet::$state::$dir::internal_ids::$name => $id, )* _ => panic!("bad packet internal id 0x{:x} in {:?} {:?}", id, dir, state), } } } )* } } )* } } } } pub mod packet; pub mod versions; pub trait Serializable: Sized { fn read_from(buf: &mut R) -> Result; fn write_to(&self, buf: &mut W) -> Result<(), Error>; } impl Serializable for Vec { fn read_from(buf: &mut R) -> Result, Error> { let mut v = Vec::new(); buf.read_to_end(&mut v)?; Ok(v) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_all(&self[..]).map_err(|v| v.into()) } } impl Serializable for Option{ fn read_from(buf: &mut R) -> Result, Error> { let ty = buf.read_u8()?; if ty == 0 { Result::Ok(None) } else { let name = nbt::read_string(buf)?; let tag = nbt::Tag::read_from(buf)?; Result::Ok(Some(nbt::NamedTag(name, tag))) } } fn write_to(&self, buf: &mut W) -> Result<(), Error> { match *self { Some(ref val) => { buf.write_u8(10)?; nbt::write_string(buf, &val.0)?; val.1.write_to(buf)?; } None => buf.write_u8(0)?, } Result::Ok(()) } } impl Serializable for Option where T : Serializable { fn read_from(buf: &mut R) -> Result, Error> { Result::Ok(Some(T::read_from(buf)?)) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { if self.is_some() { self.as_ref().unwrap().write_to(buf)?; } Result::Ok(()) } } impl Serializable for String { fn read_from(buf: &mut R) -> Result { let len = VarInt::read_from(buf)?.0; debug_assert!(len >= 0, "Negative string length: {}", len); debug_assert!(len <= 65536, "String length too big: {}", len); let mut ret = String::new(); buf.take(len as u64).read_to_string(&mut ret)?; Result::Ok(ret) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { let bytes = self.as_bytes(); VarInt(bytes.len() as i32).write_to(buf)?; buf.write_all(bytes)?; Result::Ok(()) } } impl Serializable for format::Component { fn read_from(buf: &mut R) -> Result { let len = VarInt::read_from(buf)?.0; let mut ret = String::new(); buf.take(len as u64).read_to_string(&mut ret)?; let val: serde_json::Value = serde_json::from_str(&ret[..]).unwrap(); Result::Ok(Self::from_value(&val)) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { let val = serde_json::to_string(&self.to_value()).unwrap(); let bytes = val.as_bytes(); VarInt(bytes.len() as i32).write_to(buf)?; buf.write_all(bytes)?; Result::Ok(()) } } impl Serializable for () { fn read_from(_: &mut R) -> Result<(), Error> { Result::Ok(()) } fn write_to(&self, _: &mut W) -> Result<(), Error> { Result::Ok(()) } } impl Serializable for bool { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_u8()? != 0) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_u8(if *self { 1 } else { 0 })?; Result::Ok(()) } } impl Serializable for i8 { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_i8()?) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_i8(*self)?; Result::Ok(()) } } impl Serializable for i16 { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_i16::()?) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_i16::(*self)?; Result::Ok(()) } } impl Serializable for i32 { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_i32::()?) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_i32::(*self)?; Result::Ok(()) } } impl Serializable for i64 { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_i64::()?) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_i64::(*self)?; Result::Ok(()) } } impl Serializable for u8 { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_u8()?) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_u8(*self)?; Result::Ok(()) } } impl Serializable for u16 { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_u16::()?) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_u16::(*self)?; Result::Ok(()) } } impl Serializable for u64 { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_u64::()?) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_u64::(*self)?; Result::Ok(()) } } impl Serializable for f32 { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_f32::()?) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_f32::(*self)?; Result::Ok(()) } } impl Serializable for f64 { fn read_from(buf: &mut R) -> Result { Result::Ok(buf.read_f64::()?) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_f64::(*self)?; Result::Ok(()) } } #[derive(Debug, PartialEq, Eq, Hash, Clone)] pub struct UUID(u64, u64); impl UUID { pub fn from_str(s: &str) -> UUID { use hex; // TODO: Panics aren't the best idea here if s.len() != 36 { panic!("Invalid UUID format"); } let mut parts = hex::decode(&s[..8]).unwrap(); parts.extend_from_slice(&hex::decode(&s[9..13]).unwrap()); parts.extend_from_slice(&hex::decode(&s[14..18]).unwrap()); parts.extend_from_slice(&hex::decode(&s[19..23]).unwrap()); parts.extend_from_slice(&hex::decode(&s[24..36]).unwrap()); let mut high = 0u64; let mut low = 0u64; for i in 0 .. 8 { high |= (parts[i] as u64) << (56 - i*8); low |= (parts[i + 8] as u64) << (56 - i*8); } UUID(high, low) } } impl Default for UUID { fn default() -> Self { UUID(0, 0) } } impl Serializable for UUID { fn read_from(buf: &mut R) -> Result { Result::Ok(UUID(buf.read_u64::()?, buf.read_u64::()?)) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { buf.write_u64::(self.0)?; buf.write_u64::(self.1)?; Result::Ok(()) } } pub trait Lengthable : Serializable + Copy + Default { fn into(self) -> usize; fn from(_: usize) -> Self; } pub struct LenPrefixed { len: L, pub data: Vec, } impl LenPrefixed { pub fn new(data: Vec) -> LenPrefixed { LenPrefixed { len: Default::default(), data, } } } impl Serializable for LenPrefixed { fn read_from(buf: &mut R) -> Result, Error> { let len_data: L = Serializable::read_from(buf)?; let len: usize = len_data.into(); let mut data: Vec = Vec::with_capacity(len); for _ in 0..len { data.push(Serializable::read_from(buf)?); } Result::Ok(LenPrefixed { len: len_data, data, }) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { let len_data: L = L::from(self.data.len()); len_data.write_to(buf)?; let data = &self.data; for val in data { val.write_to(buf)?; } Result::Ok(()) } } impl Default for LenPrefixed { fn default() -> Self { LenPrefixed { len: default::Default::default(), data: default::Default::default(), } } } impl fmt::Debug for LenPrefixed { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.data.fmt(f) } } // Optimization pub struct LenPrefixedBytes { len: L, pub data: Vec, } impl LenPrefixedBytes { pub fn new(data: Vec) -> LenPrefixedBytes { LenPrefixedBytes { len: Default::default(), data, } } } impl Serializable for LenPrefixedBytes { fn read_from(buf: &mut R) -> Result, Error> { let len_data: L = Serializable::read_from(buf)?; let len: usize = len_data.into(); let mut data: Vec = Vec::with_capacity(len); buf.take(len as u64).read_to_end(&mut data)?; Result::Ok(LenPrefixedBytes { len: len_data, data, }) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { let len_data: L = L::from(self.data.len()); len_data.write_to(buf)?; buf.write_all(&self.data[..])?; Result::Ok(()) } } impl Default for LenPrefixedBytes { fn default() -> Self { LenPrefixedBytes { len: default::Default::default(), data: default::Default::default(), } } } impl fmt::Debug for LenPrefixedBytes { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.data.fmt(f) } } impl Lengthable for bool { fn into(self) -> usize { if self { 1 } else { 0 } } fn from(u: usize) -> bool { u != 0 } } impl Lengthable for u8 { fn into(self) -> usize { self as usize } fn from(u: usize) -> u8 { u as u8 } } impl Lengthable for i16 { fn into(self) -> usize { self as usize } fn from(u: usize) -> i16 { u as i16 } } impl Lengthable for i32 { fn into(self) -> usize { self as usize } fn from(u: usize) -> i32 { u as i32 } } /// `VarInt` have a variable size (between 1 and 5 bytes) when encoded based /// on the size of the number #[derive(Clone, Copy)] pub struct VarInt(pub i32); impl Lengthable for VarInt { fn into(self) -> usize { self.0 as usize } fn from(u: usize) -> VarInt { VarInt(u as i32) } } impl Serializable for VarInt { /// Decodes a `VarInt` from the Reader fn read_from(buf: &mut R) -> Result { const PART : u32 = 0x7F; let mut size = 0; let mut val = 0u32; loop { let b = buf.read_u8()? as u32; val |= (b & PART) << (size * 7); size += 1; if size > 5 { return Result::Err(Error::Err("VarInt too big".to_owned())); } if (b & 0x80) == 0 { break } } Result::Ok(VarInt(val as i32)) } /// Encodes a `VarInt` into the Writer fn write_to(&self, buf: &mut W) -> Result<(), Error> { const PART : u32 = 0x7F; let mut val = self.0 as u32; loop { if (val & !PART) == 0 { buf.write_u8(val as u8)?; return Result::Ok(()); } buf.write_u8(((val & PART) | 0x80) as u8)?; val >>= 7; } } } impl default::Default for VarInt { fn default() -> VarInt { VarInt(0) } } impl fmt::Debug for VarInt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) } } /// `VarLong` have a variable size (between 1 and 10 bytes) when encoded based /// on the size of the number #[derive(Clone, Copy)] pub struct VarLong(pub i64); impl Lengthable for VarLong { fn into(self) -> usize { self.0 as usize } fn from(u: usize) -> VarLong { VarLong(u as i64) } } impl Serializable for VarLong { /// Decodes a `VarLong` from the Reader fn read_from(buf: &mut R) -> Result { const PART : u64 = 0x7F; let mut size = 0; let mut val = 0u64; loop { let b = buf.read_u8()? as u64; val |= (b & PART) << (size * 7); size += 1; if size > 10 { return Result::Err(Error::Err("VarLong too big".to_owned())); } if (b & 0x80) == 0 { break } } Result::Ok(VarLong(val as i64)) } /// Encodes a `VarLong` into the Writer fn write_to(&self, buf: &mut W) -> Result<(), Error> { const PART : u64 = 0x7F; let mut val = self.0 as u64; loop { if (val & !PART) == 0 { buf.write_u8(val as u8)?; return Result::Ok(()); } buf.write_u8(((val & PART) | 0x80) as u8)?; val >>= 7; } } } impl default::Default for VarLong { fn default() -> VarLong { VarLong(0) } } impl fmt::Debug for VarLong { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) } } impl Serializable for Position { fn read_from(buf: &mut R) -> Result { let pos = buf.read_u64::()?; Ok(Position::new( ((pos as i64) >> 38) as i32, (((pos as i64) >> 26) & 0xFFF) as i32, ((pos as i64) << 38 >> 38) as i32 )) } fn write_to(&self, buf: &mut W) -> Result<(), Error> { let pos = (((self.x as u64) & 0x3FFFFFF) << 38) | (((self.y as u64) & 0xFFF) << 26) | ((self.z as u64) & 0x3FFFFFF); buf.write_u64::(pos)?; Result::Ok(()) } } /// Direction is used to define whether packets are going to the /// server or the client. #[derive(Clone, Copy, Debug)] pub enum Direction { Serverbound, Clientbound, } /// The protocol has multiple 'sub-protocols' or states which control which /// packet an id points to. #[derive(Clone, Copy, Debug)] pub enum State { Handshaking, Play, Status, Login, } /// Return for any protocol related error. #[derive(Debug)] pub enum Error { Err(String), Disconnect(format::Component), IOError(io::Error), Json(serde_json::Error), #[cfg(not(target_arch = "wasm32"))] Reqwest(reqwest::Error), } impl convert::From for Error { fn from(e: io::Error) -> Error { Error::IOError(e) } } impl convert::From for Error { fn from(e: serde_json::Error) -> Error { Error::Json(e) } } #[cfg(not(target_arch = "wasm32"))] impl convert::From for Error { fn from(e: reqwest::Error) -> Error { Error::Reqwest(e) } } impl ::std::error::Error for Error { fn description(&self) -> &str { match *self { Error::Err(ref val) => &val[..], Error::Disconnect(_) => "Disconnect", Error::IOError(ref e) => e.description(), Error::Json(ref e) => e.description(), #[cfg(not(target_arch = "wasm32"))] Error::Reqwest(ref e) => e.description(), } } } impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match *self { Error::Err(ref val) => write!(f, "protocol error: {}", val), Error::Disconnect(ref val) => write!(f, "{}", val), Error::IOError(ref e) => e.fmt(f), Error::Json(ref e) => e.fmt(f), #[cfg(not(target_arch = "wasm32"))] Error::Reqwest(ref e) => e.fmt(f), } } } type Aes128Cfb = Cfb8; pub struct Conn { stream: TcpStream, pub host: String, pub port: u16, direction: Direction, pub protocol_version: i32, pub state: State, cipher: Option, compression_threshold: i32, compression_read: Option>>>, compression_write: Option>>>, } impl Conn { pub fn new(target: &str, protocol_version: i32) -> Result { unsafe { CURRENT_PROTOCOL_VERSION = protocol_version; } // TODO SRV record support let mut parts = target.split(':').collect::>(); let address = if parts.len() == 1 { parts.push("25565"); format!("{}:25565", parts[0]) } else { format!("{}:{}", parts[0], parts[1]) }; let stream = TcpStream::connect(&*address)?; Result::Ok(Conn { stream, host: parts[0].to_owned(), port: parts[1].parse().unwrap(), direction: Direction::Serverbound, state: State::Handshaking, protocol_version, cipher: Option::None, compression_threshold: -1, compression_read: Option::None, compression_write: Option::None, }) } pub fn write_packet(&mut self, packet: T) -> Result<(), Error> { let mut buf = Vec::new(); VarInt(packet.packet_id(self.protocol_version)).write_to(&mut buf)?; packet.write(&mut buf)?; let mut extra = if self.compression_threshold >= 0 { 1 } else { 0 }; if self.compression_threshold >= 0 && buf.len() as i32 > self.compression_threshold { if self.compression_write.is_none() { self.compression_write = Some(ZlibEncoder::new(io::Cursor::new(Vec::new()), Compression::default())); } extra = 0; let uncompressed_size = buf.len(); let mut new = Vec::new(); VarInt(uncompressed_size as i32).write_to(&mut new)?; let write = self.compression_write.as_mut().unwrap(); write.reset(io::Cursor::new(buf)); write.read_to_end(&mut new)?; buf = new; } VarInt(buf.len() as i32 + extra).write_to(self)?; if self.compression_threshold >= 0 && extra == 1 { VarInt(0).write_to(self)?; } self.write_all(&buf)?; Result::Ok(()) } pub fn read_packet(&mut self) -> Result { let len = VarInt::read_from(self)?.0 as usize; let mut ibuf = vec![0; len]; self.read_exact(&mut ibuf)?; let mut buf = io::Cursor::new(ibuf); if self.compression_threshold >= 0 { if self.compression_read.is_none() { self.compression_read = Some(ZlibDecoder::new(io::Cursor::new(Vec::new()))); } let uncompressed_size = VarInt::read_from(&mut buf)?.0; if uncompressed_size != 0 { let mut new = Vec::with_capacity(uncompressed_size as usize); { let reader = self.compression_read.as_mut().unwrap(); reader.reset(buf); reader.read_to_end(&mut new)?; } buf = io::Cursor::new(new); } } let id = VarInt::read_from(&mut buf)?.0; let dir = match self.direction { Direction::Clientbound => Direction::Serverbound, Direction::Serverbound => Direction::Clientbound, }; let packet = packet::packet_by_id(self.protocol_version, self.state, dir, id, &mut buf)?; match packet { Some(val) => { let pos = buf.position() as usize; let ibuf = buf.into_inner(); if ibuf.len() != pos { return Result::Err(Error::Err(format!("Failed to read all of packet 0x{:X}, \ had {} bytes left", id, ibuf.len() - pos))) } Result::Ok(val) } None => Result::Err(Error::Err("missing packet".to_owned())), } } pub fn enable_encyption(&mut self, key: &[u8], _decrypt: bool) { let cipher = Aes128Cfb::new_var(key, key).unwrap(); self.cipher = Option::Some(cipher); } pub fn set_compresssion(&mut self, threshold: i32) { self.compression_threshold = threshold; } pub fn do_status(mut self) -> Result<(Status, Duration), Error> { use serde_json::Value; use self::packet::status::serverbound::*; use self::packet::handshake::serverbound::Handshake; use self::packet::Packet; let host = self.host.clone(); let port = self.port; self.write_packet(Handshake { protocol_version: VarInt(self.protocol_version), host, port, next: VarInt(1), })?; self.state = State::Status; self.write_packet(StatusRequest { empty: () })?; let status = if let Packet::StatusResponse(res) = self.read_packet()? { res.status } else { return Err(Error::Err("Wrong packet".to_owned())); }; let start = Instant::now(); self.write_packet(StatusPing { ping: 42 })?; if let Packet::StatusPong(_) = self.read_packet()? { } else { return Err(Error::Err("Wrong packet".to_owned())); }; let ping = start.elapsed(); let val: Value = match serde_json::from_str(&status) { Ok(val) => val, Err(_) => return Err(Error::Err("Json parse error".to_owned())), }; let invalid_status = || Error::Err("Invalid status".to_owned()); let version = val.get("version").ok_or(invalid_status())?; let players = val.get("players").ok_or(invalid_status())?; Ok((Status { version: StatusVersion { name: version.get("name").and_then(Value::as_str).ok_or(invalid_status())? .to_owned(), protocol: version.get("protocol") .and_then(Value::as_i64) .ok_or(invalid_status())? as i32, }, players: StatusPlayers { max: players.get("max") .and_then(Value::as_i64) .ok_or(invalid_status())? as i32, online: players.get("online") .and_then(Value::as_i64) .ok_or(invalid_status())? as i32, sample: Vec::new(), /* TODO */ }, description: format::Component::from_value(val.get("description") .ok_or(invalid_status())?), favicon: val.get("favicon").and_then(Value::as_str).map(|v| v.to_owned()), }, ping)) } } #[derive(Debug)] pub struct Status { pub version: StatusVersion, pub players: StatusPlayers, pub description: format::Component, pub favicon: Option, } #[derive(Debug)] pub struct StatusVersion { pub name: String, pub protocol: i32, } #[derive(Debug)] pub struct StatusPlayers { pub max: i32, pub online: i32, pub sample: Vec, } #[derive(Debug)] pub struct StatusPlayer { name: String, id: String, } impl Read for Conn { fn read(&mut self, buf: &mut [u8]) -> io::Result { match self.cipher.as_mut() { Option::None => self.stream.read(buf), Option::Some(cipher) => { let ret = self.stream.read(buf)?; cipher.decrypt(&mut buf[..ret]); Ok(ret) } } } } impl Write for Conn { fn write(&mut self, buf: &[u8]) -> io::Result { match self.cipher.as_mut() { Option::None => self.stream.write(buf), Option::Some(cipher) => { // TODO: avoid copying, but trait requires non-mutable buf let mut data = vec![0; buf.len()]; for i in 0..buf.len() { data[i] = buf[i]; } cipher.encrypt(&mut data); self.stream.write_all(&data)?; Ok(buf.len()) } } } fn flush(&mut self) -> io::Result<()> { self.stream.flush() } } impl Clone for Conn { fn clone(&self) -> Self { Conn { stream: self.stream.try_clone().unwrap(), host: self.host.clone(), port: self.port, direction: self.direction, state: self.state, protocol_version: self.protocol_version, cipher: Option::None, compression_threshold: self.compression_threshold, compression_read: Option::None, compression_write: Option::None, } } } pub trait PacketType { fn packet_id(&self, protocol_version: i32) -> i32; fn write(self, buf: &mut W) -> Result<(), Error>; }