Pre serde-delete
Dieser Commit ist enthalten in:
Ursprung
b48c214318
Commit
00befafc33
39
Cargo.lock
generiert
39
Cargo.lock
generiert
@ -11,6 +11,8 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tokio-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -31,6 +33,18 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
@ -297,6 +311,31 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-stream"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-util"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "64910e1b9c1901aaf5375561e35b9c057d95ff41a44ede043a03e09279eabaf1"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"log",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
|
@ -6,7 +6,9 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.15", features = ["full"] }
|
tokio = { version = "1.15", features = ["full"] }
|
||||||
|
tokio-util = { version = "0.7", features = ["codec"] }
|
||||||
|
tokio-stream = "0.1"
|
||||||
serde = { version = "1.0", features = ["derive", "std"] }
|
serde = { version = "1.0", features = ["derive", "std"] }
|
||||||
bytes = "1.1"
|
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
bytes = "1.1"
|
||||||
lixcraft-derive = { path = "lixcraft-derive" }
|
lixcraft-derive = { path = "lixcraft-derive" }
|
@ -1,55 +1,91 @@
|
|||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use syn::{Data, DeriveInput, parse_macro_input};
|
use syn::{Data, DeriveInput, Fields, parse_macro_input};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
#[proc_macro_derive(Wrapper)]
|
macro_rules! iter_named_fields {
|
||||||
pub fn derive_wrapper(input: TokenStream) -> TokenStream {
|
($f:expr, $m:expr, $r:expr) => {
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
$f.iter().map(|field| {
|
||||||
|
let ty = &field.ty;
|
||||||
let ident = &input.ident;
|
let ident = &field.ident.as_ref().unwrap();
|
||||||
|
$m(ty, ident)
|
||||||
match &input.data {
|
}).reduce($r).unwrap_or_default()
|
||||||
Data::Struct(s) => {
|
|
||||||
if s.fields.len() != 1 {
|
|
||||||
panic!("#[derive(Wrapper)] only usable with one value")
|
|
||||||
}
|
|
||||||
for field in s.fields.iter() {
|
|
||||||
if field.ident.is_some() {
|
|
||||||
panic!("#[derive(Wrapper)] only usable on newtype structs")
|
|
||||||
}
|
|
||||||
|
|
||||||
let field_type = &field.ty;
|
|
||||||
let output = quote!{
|
|
||||||
impl From<#ident> for #field_type {
|
|
||||||
fn from(v: #ident) -> Self {
|
|
||||||
v.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for #ident {
|
|
||||||
type Target = #field_type;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl DerefMut for #ident {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<#field_type> for #ident {
|
|
||||||
fn from(v: #field_type) -> Self {
|
|
||||||
#ident(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return output.into();
|
|
||||||
}
|
|
||||||
panic!("Unreachable")
|
|
||||||
},
|
|
||||||
_ => panic!("#[derive(Wrapper)] only usable on structs")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
macro_rules! iter_unnamed_fields {
|
||||||
|
($f:expr, $m:expr, $r:expr) => {
|
||||||
|
$f.iter().enumerate().map(|(id, field)| {
|
||||||
|
let ty = &field.ty;
|
||||||
|
$m(ty, id)
|
||||||
|
}).reduce($r).unwrap_or_default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_serializable {
|
||||||
|
($struct_ident:expr, $size:expr, $serialize:expr, $deserialize:expr) => {
|
||||||
|
{
|
||||||
|
let struct_ident = $struct_ident;
|
||||||
|
let mut size = $size;
|
||||||
|
if size.is_empty() {
|
||||||
|
size = quote!{ 0 }
|
||||||
|
}
|
||||||
|
let serialize = $serialize;
|
||||||
|
let deserialize = $deserialize;
|
||||||
|
quote!{
|
||||||
|
impl JavaSerializable for #struct_ident {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
#size
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut bytes::BytesMut) {
|
||||||
|
#serialize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut bytes::Bytes) -> Result<Self, crate::serde::JavaDeserError> {
|
||||||
|
Ok(#deserialize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(JavaSerializable)]
|
||||||
|
pub fn derive_serializable(input: TokenStream) -> TokenStream {
|
||||||
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
|
let struct_ident = &input.ident;
|
||||||
|
|
||||||
|
let s = match &input.data {
|
||||||
|
Data::Struct(s) => s,
|
||||||
|
_ => panic!("#[derive(JavaSerializable)] currently only usable on structs")
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = match &s.fields {
|
||||||
|
Fields::Named(named) => {
|
||||||
|
let fields = &named.named;
|
||||||
|
fields.iter().map(|field| {
|
||||||
|
let ty = &field.ty;
|
||||||
|
let ident = &field.ident.as_ref().unwrap();
|
||||||
|
quote!{ #ident: #ty::deserialize(buf)? }
|
||||||
|
}).reduce(|a, b| quote!{ #a, #b }).unwrap_or_default();
|
||||||
|
let (size_in_bytes, serialize, deserialize) = (
|
||||||
|
iter_named_fields!(fields, |_, ident| quote!{ self.#ident.size_in_bytes() }, |a, b| quote!{ #a + #b }),
|
||||||
|
iter_named_fields!(fields, |_, ident| quote!{ self.#ident.serialize(buf); }, |a, b| quote!{ #a #b }),
|
||||||
|
iter_named_fields!(fields, |ty, ident| quote!{ #ident: #ty::deserialize(buf)? }, |a, b| quote!{ #a, #b })
|
||||||
|
);
|
||||||
|
impl_serializable!(struct_ident, size_in_bytes, serialize, quote! { #struct_ident {#deserialize} })
|
||||||
|
},
|
||||||
|
Fields::Unnamed(unnamed) => {
|
||||||
|
let fields = &unnamed.unnamed;
|
||||||
|
let (size_in_bytes, serialize, deserialize) = (
|
||||||
|
iter_unnamed_fields!(fields, |_, ident| quote!{ self.#ident.size_in_bytes() }, |a, b| quote!{ #a + #b }),
|
||||||
|
iter_unnamed_fields!(fields, |_, ident| quote!{ self.#ident.serialize(buf); }, |a, b| quote!{ #a #b }),
|
||||||
|
iter_unnamed_fields!(fields, |ty, _| quote!{ #ty::deserialize(buf)? }, |a, b| quote!{ #a, #b })
|
||||||
|
);
|
||||||
|
impl_serializable!(struct_ident, size_in_bytes, serialize, quote! { #struct_ident (#deserialize) })
|
||||||
|
},
|
||||||
|
Fields::Unit => impl_serializable!(struct_ident, quote! { 0 }, quote! {}, quote! { #struct_ident {} })
|
||||||
|
}.into();
|
||||||
|
println!("{}", result);
|
||||||
|
result
|
||||||
|
}
|
134
src/datatypes.rs
134
src/datatypes.rs
@ -1,6 +1,7 @@
|
|||||||
|
use std::fmt::{Formatter, Write};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use serde::de::Error;
|
use serde::de::{EnumAccess, Error, MapAccess, SeqAccess, Visitor};
|
||||||
use lixcraft_derive::Wrapper;
|
use lixcraft_derive::Wrapper;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Wrapper)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Wrapper)]
|
||||||
@ -21,12 +22,14 @@ impl From<usize> for VarInt {
|
|||||||
impl Serialize for VarInt {
|
impl Serialize for VarInt {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
||||||
let mut v = self.0 as u32;
|
let mut v = self.0 as u32;
|
||||||
|
let mut result = Vec::with_capacity(5);
|
||||||
loop {
|
loop {
|
||||||
if v & 0x80 == 0 {
|
if v & 0x80 == 0 {
|
||||||
return serializer.serialize_u8(v as u8);
|
result.push(v as u8);
|
||||||
|
return serializer.serialize_bytes(&result);
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer.serialize_u8((v as u8 & 0x7f) | 0x80)?;
|
result.push((v as u8 & 0x7f) | 0x80);
|
||||||
v >>= 7;
|
v >>= 7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +40,7 @@ impl<'de> Deserialize<'de> for VarInt {
|
|||||||
let mut num_read = 0;
|
let mut num_read = 0;
|
||||||
let mut result = 0;
|
let mut result = 0;
|
||||||
loop {
|
loop {
|
||||||
let read = u8::deserialize(deserializer)?;
|
let read = (&mut *deserializer).deserialize_u8(VarIntVisitor{})?;
|
||||||
let value = i32::from(read & 0b0111_1111);
|
let value = i32::from(read & 0b0111_1111);
|
||||||
result |= value.overflowing_shl(7 * num_read).0;
|
result |= value.overflowing_shl(7 * num_read).0;
|
||||||
|
|
||||||
@ -81,35 +84,35 @@ impl<'de> Deserialize<'de> for NextState {
|
|||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct StatusResponseVersion {
|
pub struct StatusResponseVersion {
|
||||||
name: String,
|
pub name: String,
|
||||||
protocol: i32
|
pub protocol: i32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct StatusResponseSample {
|
pub struct StatusResponseSample {
|
||||||
name: String,
|
pub name: String,
|
||||||
id: String
|
pub id: String
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct StatusResponsePlayers {
|
pub struct StatusResponsePlayers {
|
||||||
max: i32,
|
pub max: i32,
|
||||||
online: i32,
|
pub online: i32,
|
||||||
sample: Vec<StatusResponseSample>
|
pub sample: Vec<StatusResponseSample>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct StatusResponseDescription {
|
pub struct StatusResponseDescription {
|
||||||
text: String
|
pub text: String
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StatusResponse {
|
pub struct StatusResponse {
|
||||||
version: StatusResponseVersion,
|
pub version: StatusResponseVersion,
|
||||||
players: StatusResponsePlayers,
|
pub players: StatusResponsePlayers,
|
||||||
description: StatusResponseDescription,
|
pub description: StatusResponseDescription,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
favicon: Option<String>
|
pub favicon: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for StatusResponse {
|
impl Serialize for StatusResponse {
|
||||||
@ -132,3 +135,102 @@ impl<'de> Deserialize<'de> for StatusResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
//TODO: Serialize, Deserialize
|
||||||
|
pub enum Font {
|
||||||
|
Uniform, //minecraft:uniform
|
||||||
|
Alt, //minecraft:alt
|
||||||
|
Default //minecraft:default
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum ClickEventAction {
|
||||||
|
open_url,
|
||||||
|
run_command,
|
||||||
|
suggest_command,
|
||||||
|
change_page,
|
||||||
|
copy_to_clipboard
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ClickEvent {
|
||||||
|
action: ClickEventAction,
|
||||||
|
value: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum HoverEventAction {
|
||||||
|
show_text,
|
||||||
|
show_item,
|
||||||
|
show_entity
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct HoverEvent {
|
||||||
|
action: HoverEventAction,
|
||||||
|
value: String //or Chat (Recursion!)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct SharedChat {
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
bold: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
italic: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
underlined: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
strikethrough: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
obfuscated: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
font: Font,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
color: String, //TODO Color code, format code or hex code
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
insertion: String,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
clickEvent: ClickEvent,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
hoverEvent: HoverEvent,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
extra: Vec<Chat>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Score {
|
||||||
|
name: String, //Or UUID
|
||||||
|
objective: String,
|
||||||
|
value: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
//TODO: Serialize, Deserialize
|
||||||
|
pub enum Chat {
|
||||||
|
StringComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
text: String
|
||||||
|
},
|
||||||
|
TranslationComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
translate: String //TODO Special strings
|
||||||
|
},
|
||||||
|
KeybindComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
keybind: String
|
||||||
|
},
|
||||||
|
ScoreComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
score: Score
|
||||||
|
},
|
||||||
|
SelectorComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
selector: String //TODO ominous
|
||||||
|
}
|
||||||
|
}
|
@ -30,6 +30,10 @@ pub struct JavaDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl JavaDeserializer {
|
impl JavaDeserializer {
|
||||||
|
pub fn from_bytes<'a, T: Deserialize<'a>>(data: Bytes) -> Result<T, JavaDeserError> {
|
||||||
|
let mut deserializer = JavaDeserializer{input : data };
|
||||||
|
T::deserialize(&mut deserializer)
|
||||||
|
}
|
||||||
|
|
||||||
fn assert_remaining(&self, size: usize) -> Result<(), JavaDeserError> {
|
fn assert_remaining(&self, size: usize) -> Result<(), JavaDeserError> {
|
||||||
match self.input.remaining() >= size {
|
match self.input.remaining() >= size {
|
||||||
@ -114,7 +118,7 @@ impl<'a, 'de> Deserializer<'de> for &'a mut JavaDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
||||||
let size = VarInt::deserialize(self)?;
|
let size = VarInt::deserialize(&mut *self)?;
|
||||||
if *size > 32767 {
|
if *size > 32767 {
|
||||||
return Err(JavaDeserError::InvalidValue)
|
return Err(JavaDeserError::InvalidValue)
|
||||||
}
|
}
|
||||||
@ -151,12 +155,12 @@ impl<'a, 'de> Deserializer<'de> for &'a mut JavaDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
||||||
let size = VarInt::deserialize(self)?;
|
let size = VarInt::deserialize(&mut *self)?;
|
||||||
visitor.visit_seq(LengthPrefixedSeq { de: self, remaining: usize::from(size) })
|
visitor.visit_seq(KnownLengthSeq { de: self, remaining: usize::from(size) })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
||||||
panic!("Tuple not deserializable in Java protocol")
|
visitor.visit_seq(KnownLengthSeq { de: self, remaining: len })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize_tuple_struct<V>(self, name: &'static str, len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
fn deserialize_tuple_struct<V>(self, name: &'static str, len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
||||||
@ -184,12 +188,12 @@ impl<'a, 'de> Deserializer<'de> for &'a mut JavaDeserializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LengthPrefixedSeq<'a> {
|
struct KnownLengthSeq<'a> {
|
||||||
de: &'a mut JavaDeserializer,
|
de: &'a mut JavaDeserializer,
|
||||||
remaining: usize
|
remaining: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, 'a> SeqAccess<'de> for LengthPrefixedSeq<'a> {
|
impl<'de, 'a> SeqAccess<'de> for KnownLengthSeq<'a> {
|
||||||
type Error = <&'a mut JavaDeserializer as Deserializer<'de>>::Error;
|
type Error = <&'a mut JavaDeserializer as Deserializer<'de>>::Error;
|
||||||
|
|
||||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> where T: DeserializeSeed<'de> {
|
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> where T: DeserializeSeed<'de> {
|
||||||
@ -197,7 +201,7 @@ impl<'de, 'a> SeqAccess<'de> for LengthPrefixedSeq<'a> {
|
|||||||
0 => Ok(None),
|
0 => Ok(None),
|
||||||
_ => {
|
_ => {
|
||||||
self.remaining -= 1;
|
self.remaining -= 1;
|
||||||
seed.deserialize(self.de).map(Some)
|
seed.deserialize(&mut *self.de).map(Some)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
94
src/main.rs
94
src/main.rs
@ -1,103 +1,11 @@
|
|||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
mod serializer;
|
pub mod serde;
|
||||||
mod datatypes;
|
|
||||||
mod deserializer;
|
|
||||||
mod packets;
|
mod packets;
|
||||||
|
|
||||||
use tokio::io::{AsyncRead};
|
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
|
||||||
use async_trait::async_trait;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let listen_addr = String::from("127.0.0.1:25565");
|
|
||||||
|
|
||||||
println!("Listening on: {}", listen_addr);
|
|
||||||
|
|
||||||
let listener = TcpListener::bind(listen_addr).await?;
|
|
||||||
|
|
||||||
while let Ok((inbound, addr)) = listener.accept().await {
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub struct Stoppable {
|
|
||||||
interruptor: tokio::sync::oneshot::Receiver<bool>,
|
|
||||||
interrupted: tokio::sync::oneshot::Sender<bool>
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Stopper {
|
|
||||||
interruptable: tokio::sync::oneshot::Sender<bool>,
|
|
||||||
interrupted: tokio::sync::oneshot::Receiver<bool>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Stopper {
|
|
||||||
pub fn new() -> (Stopper, Stoppable) {
|
|
||||||
let (interruptable, interruptor) = tokio::sync::oneshot::channel();
|
|
||||||
let (interrupted_s, interrupted_r) = tokio::sync::oneshot::channel();
|
|
||||||
|
|
||||||
(Stopper {interruptable, interrupted: interrupted_r}, Stoppable {interruptor, interrupted: interrupted_s})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn stop(&mut self) {
|
|
||||||
if self.interruptable.is_closed() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.interruptable.send(true).unwrap_or_default();
|
|
||||||
self.interrupted.await.expect_err("Send on Stopper.interrupted occured");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait InputStream {}
|
|
||||||
pub trait OutputStream {}
|
|
||||||
|
|
||||||
pub struct StoppableAsyncRead<T: AsyncRead> {
|
|
||||||
inner: T,
|
|
||||||
stoppable: Stoppable
|
|
||||||
}
|
|
||||||
|
|
||||||
impl <T: AsyncRead> StoppableAsyncRead<T> {
|
|
||||||
pub fn new(inner: T, stoppable: Stoppable) -> StoppableAsyncRead<T> {
|
|
||||||
StoppableAsyncRead { inner, stoppable }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unwrap(self) -> T {
|
|
||||||
self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl <T: AsyncRead> InputStream for StoppableAsyncRead<T> {}
|
|
||||||
|
|
||||||
impl OutputStream for OwnedWriteHalf {}
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
pub trait Reader<T: InputStream> {
|
|
||||||
async fn run(self, stream: T, connection: Arc<Connection>);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Connection {
|
|
||||||
writer: Box<parking_lot::Mutex<dyn OutputStream>>,
|
|
||||||
stopper: Stopper
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Connection {
|
|
||||||
pub fn new<T: 'static + Reader<StoppableAsyncRead<OwnedReadHalf>>>(stream: TcpStream, reader: T) -> Arc<Connection> {
|
|
||||||
let (read, write) = stream.into_split();
|
|
||||||
let (stopper, stoppable) = Stopper::new();
|
|
||||||
|
|
||||||
let connection = Arc::new(Connection {
|
|
||||||
writer: Box::new(parking_lot::Mutex::new(write)),
|
|
||||||
stopper
|
|
||||||
});
|
|
||||||
|
|
||||||
tokio::spawn(reader.run(StoppableAsyncRead::new(read, stoppable), connection.clone()));
|
|
||||||
|
|
||||||
connection
|
|
||||||
}
|
|
||||||
}
|
|
128
src/oldmain.rs
Normale Datei
128
src/oldmain.rs
Normale Datei
@ -0,0 +1,128 @@
|
|||||||
|
use tokio::io;
|
||||||
|
use tokio::io::{AsyncRead, AsyncWriteExt};
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
|
||||||
|
use futures::FutureExt;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let listen_addr = String::from("127.0.0.1:25565");
|
||||||
|
let server_addr = String::from("steamwar.de:25565");
|
||||||
|
|
||||||
|
println!("Listening on: {}", listen_addr);
|
||||||
|
println!("Proxying to: {}", server_addr);
|
||||||
|
|
||||||
|
let listener = TcpListener::bind(listen_addr).await?;
|
||||||
|
|
||||||
|
while let Ok((inbound, _)) = listener.accept().await {
|
||||||
|
let transfer = transfer(inbound, server_addr.clone()).map(|r| {
|
||||||
|
if let Err(e) = r {
|
||||||
|
println!("Failed to transfer; error={}", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tokio::spawn(transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stoppable {
|
||||||
|
interruptor: tokio::sync::oneshot::Receiver<bool>,
|
||||||
|
interrupted: tokio::sync::oneshot::Sender<bool>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stopper {
|
||||||
|
interruptable: tokio::sync::oneshot::Sender<bool>,
|
||||||
|
interrupted: tokio::sync::oneshot::Receiver<bool>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stopper {
|
||||||
|
pub fn new() -> (Stopper, Stoppable) {
|
||||||
|
let (interruptable, interruptor) = tokio::sync::oneshot::channel();
|
||||||
|
let (interrupted_s, interrupted_r) = tokio::sync::oneshot::channel();
|
||||||
|
|
||||||
|
(Stopper {interruptable, interrupted: interrupted_r}, Stoppable {interruptor, interrupted: interrupted_s})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn stop(&mut self) {
|
||||||
|
if self.interruptable.is_closed() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.interruptable.send(true).unwrap_or_default();
|
||||||
|
self.interrupted.await.expect_err("Send on Stopper.interrupted occured");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait InputStream {}
|
||||||
|
pub trait OutputStream {}
|
||||||
|
|
||||||
|
pub struct StoppableAsyncRead<T: AsyncRead> {
|
||||||
|
inner: T,
|
||||||
|
stoppable: Stoppable
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T: AsyncRead> StoppableAsyncRead<T> {
|
||||||
|
pub fn new(inner: T, stoppable: Stoppable) -> StoppableAsyncRead<T> {
|
||||||
|
StoppableAsyncRead { inner, stoppable }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unwrap(self) -> T {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T: AsyncRead> InputStream for StoppableAsyncRead<T> {}
|
||||||
|
|
||||||
|
impl OutputStream for OwnedWriteHalf {}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait Reader<T: InputStream> {
|
||||||
|
async fn run(self, stream: T, connection: Arc<Connection>);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Connection {
|
||||||
|
writer: Box<parking_lot::Mutex<dyn OutputStream>>,
|
||||||
|
stopper: Stopper
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Connection {
|
||||||
|
pub fn new<T: 'static + Reader<StoppableAsyncRead<OwnedReadHalf>>>(stream: TcpStream, reader: T) -> Arc<Connection> {
|
||||||
|
let (read, write) = stream.into_split();
|
||||||
|
let (stopper, stoppable) = Stopper::new();
|
||||||
|
|
||||||
|
let connection = Arc::new(Connection {
|
||||||
|
writer: Box::new(parking_lot::Mutex::new(write)),
|
||||||
|
stopper
|
||||||
|
});
|
||||||
|
|
||||||
|
tokio::spawn(reader.run(StoppableAsyncRead::new(read, stoppable), connection.clone()));
|
||||||
|
|
||||||
|
connection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn transfer(mut inbound: TcpStream, proxy_addr: String) -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut outbound = TcpStream::connect(proxy_addr).await?;
|
||||||
|
|
||||||
|
let (mut ri, mut wi) = inbound.split();
|
||||||
|
let (mut ro, mut wo) = outbound.split();
|
||||||
|
|
||||||
|
let client_to_server = async {
|
||||||
|
io::copy(&mut ri, &mut wo).await?;
|
||||||
|
wo.shutdown().await
|
||||||
|
};
|
||||||
|
|
||||||
|
let server_to_client = async {
|
||||||
|
io::copy(&mut ro, &mut wi).await?;
|
||||||
|
wi.shutdown().await
|
||||||
|
};
|
||||||
|
|
||||||
|
tokio::try_join!(client_to_server, server_to_client)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
114
src/packets.rs
114
src/packets.rs
@ -1,31 +1,111 @@
|
|||||||
mod handshake {
|
pub mod handshake {
|
||||||
use serde::{Serialize, Deserialize};
|
use crate::serde::{VarInt, JavaSerializable, NextState};
|
||||||
use crate::datatypes::{NextState, VarInt};
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct HandshakePacket {
|
pub struct HandshakePacket {
|
||||||
protocol_version: VarInt,
|
pub protocol_version: VarInt,
|
||||||
server_address: String,
|
pub server_address: String,
|
||||||
server_port: u16,
|
pub server_port: u16,
|
||||||
next_state: NextState
|
pub next_state: NextState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod status {
|
pub mod status {
|
||||||
use serde::{Serialize, Deserialize};
|
use crate::serde::{JavaSerializable, StatusResponse};
|
||||||
use crate::datatypes::StatusResponse;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct RequestPacket {}
|
pub struct RequestPacket{}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct ResponsePacket {
|
pub struct ResponsePacket {
|
||||||
response: StatusResponse
|
pub response: StatusResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct PingPacket {
|
pub struct PingPacket {
|
||||||
payload: u64
|
pub payload: i64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod login {
|
||||||
|
use bytes::{BufMut, Bytes, BytesMut};
|
||||||
|
use crate::serde::{VarInt, JavaSerializable, Chat, JavaDeserError};
|
||||||
|
|
||||||
|
#[derive(JavaSerializable, Debug)]
|
||||||
|
pub struct DisconnectPacket{
|
||||||
|
reason: Chat
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JavaSerializable, Debug)]
|
||||||
|
pub struct EncryptionRequestPacket {
|
||||||
|
server_id: String,
|
||||||
|
public_key: Vec::<u8>,
|
||||||
|
verify_token: Vec::<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JavaSerializable, Debug)]
|
||||||
|
pub struct LoginSuccessPacket {
|
||||||
|
uuid: String, //TODO: UUID
|
||||||
|
username: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JavaSerializable, Debug)]
|
||||||
|
pub struct SetCompressionPacket {
|
||||||
|
threshold: VarInt
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JavaSerializable, Debug)]
|
||||||
|
pub struct PluginRequestPacket {
|
||||||
|
message_id: VarInt,
|
||||||
|
channel: String, //TODO: Identifier
|
||||||
|
data: Vec::<u8> //TODO: Length inferred by packet length
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JavaSerializable, Debug)]
|
||||||
|
pub struct LoginStartPacket {
|
||||||
|
name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JavaSerializable, Debug)]
|
||||||
|
pub struct EncryptionResponsePacket {
|
||||||
|
shared_secret: Vec::<u8>,
|
||||||
|
verify_token: Vec::<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum PluginResponseSuccessful {
|
||||||
|
Successful(Vec<u8>),
|
||||||
|
Failed
|
||||||
|
}
|
||||||
|
impl JavaSerializable for PluginResponseSuccessful {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
PluginResponseSuccessful::Successful(v) => true.size_in_bytes() + v.len(),
|
||||||
|
PluginResponseSuccessful::Failed => false.size_in_bytes()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
match self {
|
||||||
|
PluginResponseSuccessful::Successful(v) => {
|
||||||
|
true.serialize(buf);
|
||||||
|
buf.put_slice(v.as_slice())
|
||||||
|
}
|
||||||
|
PluginResponseSuccessful::Failed => false.serialize(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
match bool::deserialize(buf)? {
|
||||||
|
true => Ok(PluginResponseSuccessful::Successful(buf.to_vec())),
|
||||||
|
false => Ok(PluginResponseSuccessful::Failed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JavaSerializable, Debug)]
|
||||||
|
pub struct PluginResponsePacket {
|
||||||
|
message_id: VarInt,
|
||||||
|
data: PluginResponseSuccessful
|
||||||
|
}
|
||||||
|
}
|
||||||
|
431
src/serde.rs
Normale Datei
431
src/serde.rs
Normale Datei
@ -0,0 +1,431 @@
|
|||||||
|
use std::ops::{DerefMut, Deref};
|
||||||
|
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||||
|
use crate::serde::JavaDeserError::{InvalidValue, MissingBytes};
|
||||||
|
|
||||||
|
pub use lixcraft_derive::JavaSerializable;
|
||||||
|
|
||||||
|
pub enum JavaDeserError {
|
||||||
|
InvalidValue,
|
||||||
|
MissingBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait JavaSerializable: Sized {
|
||||||
|
fn size_in_bytes(&self) -> usize;
|
||||||
|
fn serialize(&self, buf: &mut BytesMut);
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError>; // where Self: Sized
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JavaSerializable for bool {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
match *self {
|
||||||
|
true => buf.put_u8(1),
|
||||||
|
false => buf.put_u8(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
match buf.len() > 0 {
|
||||||
|
true => match buf.get_u8() {
|
||||||
|
0 => Ok(false),
|
||||||
|
1 => Ok(true),
|
||||||
|
_ => Err(InvalidValue)
|
||||||
|
},
|
||||||
|
false => Err(MissingBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! save_get {
|
||||||
|
($s:expr, $b:expr, $g:ident) => {
|
||||||
|
match $b.len() >= $s {
|
||||||
|
true => Ok($b.$g()),
|
||||||
|
false => Err(MissingBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_num {
|
||||||
|
($t:ty, $s:expr, $p:ident, $g:ident) => {
|
||||||
|
impl JavaSerializable for $t {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
$s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
buf.$p(*self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
save_get!($s, buf, $g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_num!(i8, 1, put_i8, get_i8);
|
||||||
|
impl_num!(u8, 1, put_u8, get_u8);
|
||||||
|
impl_num!(i16, 2, put_i16, get_i16);
|
||||||
|
impl_num!(u16, 2, put_u16, get_u16);
|
||||||
|
impl_num!(i32, 4, put_i32, get_i32);
|
||||||
|
impl_num!(i64, 8, put_i64, get_i64);
|
||||||
|
impl_num!(f32, 4, put_f32, get_f32);
|
||||||
|
impl_num!(f64, 8, put_f64, get_f64);
|
||||||
|
|
||||||
|
macro_rules! impl_wrapper {
|
||||||
|
($t:ty, $f:ty, $c:expr) => {
|
||||||
|
impl From<$t> for $f {
|
||||||
|
fn from(v: $t) -> Self {
|
||||||
|
v.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for $t {
|
||||||
|
type Target = $f;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl DerefMut for $t {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<$f> for $t {
|
||||||
|
fn from(v: $f) -> Self {
|
||||||
|
$c(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct VarInt(pub i32);
|
||||||
|
impl_wrapper!(VarInt, i32, VarInt);
|
||||||
|
|
||||||
|
impl From<VarInt> for usize {
|
||||||
|
fn from(v: VarInt) -> Self {
|
||||||
|
v.0 as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<usize> for VarInt {
|
||||||
|
fn from(v: usize) -> Self {
|
||||||
|
VarInt(v as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_varnum_ser {
|
||||||
|
($u:ty, $v:expr, $b:expr) => {
|
||||||
|
{
|
||||||
|
let mut v = $v as $u;
|
||||||
|
loop {
|
||||||
|
if v & 0x80 == 0 {
|
||||||
|
$b.put_u8(v as u8);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$b.put_u8((v as u8 & 0x7f) | 0x80);
|
||||||
|
v >>= 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_varnum_de {
|
||||||
|
($t:ty, $r:expr, $b:expr, $m:expr) => {
|
||||||
|
let mut num_read = 0;
|
||||||
|
loop {
|
||||||
|
let read = save_get!(1, $b, get_u8)?;
|
||||||
|
let value = <$t>::from(read & 0x7f);
|
||||||
|
$r |= value.overflowing_shl(7 * num_read).0;
|
||||||
|
|
||||||
|
num_read += 1;
|
||||||
|
|
||||||
|
if num_read > $m {
|
||||||
|
return Err(InvalidValue);
|
||||||
|
}
|
||||||
|
if read & 0x80 == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JavaSerializable for VarInt {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
match **self {
|
||||||
|
0..=127 => 1,
|
||||||
|
128..=16383 => 2,
|
||||||
|
16384..=2097151 => 3,
|
||||||
|
2097152..=268435455 => 4,
|
||||||
|
_ => 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
impl_varnum_ser!(u32, **self, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
let mut result = 0;
|
||||||
|
impl_varnum_de!(i32, result, buf, 5);
|
||||||
|
Ok(VarInt(result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct VarLong(pub i64);
|
||||||
|
impl_wrapper!(VarLong, i64, VarLong);
|
||||||
|
|
||||||
|
impl JavaSerializable for VarLong {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
match **self {
|
||||||
|
0..=127 => 1,
|
||||||
|
128..=16383 => 2,
|
||||||
|
16384..=2097151 => 3,
|
||||||
|
2097152..=268435455 => 4,
|
||||||
|
268435456..=34359738367 => 5,
|
||||||
|
34359738368..=4398046511103 => 6,
|
||||||
|
4398046511104..=562949953421311 => 7,
|
||||||
|
562949953421312..=72057594037927935 => 8,
|
||||||
|
72057594037927936..=9223372036854775807 => 9,
|
||||||
|
_ => 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
impl_varnum_ser!(u64, **self, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
let mut result = 0;
|
||||||
|
impl_varnum_de!(i64, result, buf, 10);
|
||||||
|
Ok(VarLong(result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JavaSerializable for String {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
VarInt(self.len() as i32).size_in_bytes() + self.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
VarInt(self.len() as i32).serialize(buf);
|
||||||
|
buf.put_slice(self.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
let len = VarInt::deserialize(buf)?;
|
||||||
|
Ok(String::from_utf8(buf.split_to(usize::from(len)).to_vec()).map_err(|_| InvalidValue)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: JavaSerializable> JavaSerializable for Vec<T> {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
VarInt(self.len() as i32).size_in_bytes() + self.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
VarInt(self.len() as i32).serialize(buf);
|
||||||
|
for i in self.iter() {
|
||||||
|
i.serialize(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
let len = VarInt::deserialize(buf)?;
|
||||||
|
let mut result = Vec::with_capacity(usize::from(len));
|
||||||
|
for _ in 0..*len {
|
||||||
|
result.push(T::deserialize(buf)?)
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum NextState {
|
||||||
|
Status,
|
||||||
|
Login
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JavaSerializable for NextState {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
VarInt::from(match self {
|
||||||
|
NextState::Status => 1,
|
||||||
|
NextState::Login => 2
|
||||||
|
}).serialize(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
match VarInt::deserialize(buf)? {
|
||||||
|
VarInt(1) => Ok(NextState::Status),
|
||||||
|
VarInt(2) => Ok(NextState::Login),
|
||||||
|
_ => Err(InvalidValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct StatusResponseVersion {
|
||||||
|
pub name: String,
|
||||||
|
pub protocol: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct StatusResponseSample {
|
||||||
|
pub name: String,
|
||||||
|
pub id: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct StatusResponsePlayers {
|
||||||
|
pub max: i32,
|
||||||
|
pub online: i32,
|
||||||
|
pub sample: Vec<StatusResponseSample>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct StatusResponseDescription {
|
||||||
|
pub text: String
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_json {
|
||||||
|
($t:ty) => {
|
||||||
|
impl JavaSerializable for $t {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
serde_json::to_string(self).unwrap().size_in_bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
serde_json::to_string(self).unwrap().serialize(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
match serde_json::from_str(&String::deserialize(buf)?) {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(_) => Err(InvalidValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct StatusResponse {
|
||||||
|
pub version: StatusResponseVersion,
|
||||||
|
pub players: StatusResponsePlayers,
|
||||||
|
pub description: StatusResponseDescription,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub favicon: Option<String>
|
||||||
|
}
|
||||||
|
impl_json!(StatusResponse);
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
//TODO: Serialize, Deserialize
|
||||||
|
pub enum Font {
|
||||||
|
Uniform, //minecraft:uniform
|
||||||
|
Alt, //minecraft:alt
|
||||||
|
Default //minecraft:default
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub enum ClickEventAction {
|
||||||
|
open_url,
|
||||||
|
run_command,
|
||||||
|
suggest_command,
|
||||||
|
change_page,
|
||||||
|
copy_to_clipboard
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct ClickEvent {
|
||||||
|
action: ClickEventAction,
|
||||||
|
value: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub enum HoverEventAction {
|
||||||
|
show_text,
|
||||||
|
show_item,
|
||||||
|
show_entity
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct HoverEvent {
|
||||||
|
action: HoverEventAction,
|
||||||
|
value: String //or Chat (Recursion!)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct SharedChat {
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
bold: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
italic: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
underlined: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
strikethrough: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
obfuscated: bool,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
font: Font,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
color: String, //TODO Color code, format code or hex code
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
insertion: String,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
clickEvent: ClickEvent,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
hoverEvent: HoverEvent,
|
||||||
|
//#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
extra: Vec<Chat>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct Score {
|
||||||
|
name: String, //Or UUID
|
||||||
|
objective: String,
|
||||||
|
value: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub enum Chat {
|
||||||
|
StringComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
text: String
|
||||||
|
},
|
||||||
|
TranslationComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
translate: String //TODO Special strings
|
||||||
|
},
|
||||||
|
KeybindComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
keybind: String
|
||||||
|
},
|
||||||
|
ScoreComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
score: Score
|
||||||
|
},
|
||||||
|
SelectorComponent {
|
||||||
|
#[serde(flatten)]
|
||||||
|
options: SharedChat,
|
||||||
|
selector: String //TODO ominous
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl_json!(Chat);
|
127
src/serdemain.rs
Normale Datei
127
src/serdemain.rs
Normale Datei
@ -0,0 +1,127 @@
|
|||||||
|
extern crate core;
|
||||||
|
|
||||||
|
mod serializer;
|
||||||
|
mod datatypes;
|
||||||
|
mod deserializer;
|
||||||
|
mod packets;
|
||||||
|
mod ser;
|
||||||
|
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tokio_stream::StreamExt;
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
use std::io::ErrorKind;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||||
|
use tokio_util::codec::{Decoder, Encoder, Framed};
|
||||||
|
use crate::datatypes::VarInt;
|
||||||
|
use crate::deserializer::JavaDeserializer;
|
||||||
|
use crate::packets::handshake::HandshakePacket;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let listen_addr = String::from("127.0.0.1:25565");
|
||||||
|
|
||||||
|
println!("Listening on: {}", listen_addr);
|
||||||
|
|
||||||
|
let listener = TcpListener::bind(listen_addr).await?;
|
||||||
|
|
||||||
|
while let Ok((inbound, addr)) = listener.accept().await {
|
||||||
|
tokio::spawn(async move {process_initial(inbound, addr)});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn process_initial(stream: TcpStream, addr: SocketAddr) {
|
||||||
|
let mut framed = Framed::new(stream, LengthPrefixedFrame {});
|
||||||
|
match framed.next().await {
|
||||||
|
Some(Ok(buf)) => {
|
||||||
|
match JavaDeserializer::from_bytes(buf.freeze()) {
|
||||||
|
Ok(v) => {
|
||||||
|
let v: HandshakePacket = v;
|
||||||
|
println!("{:?}", v);
|
||||||
|
},
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None | Some(Err(_)) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum VarIntReadError {
|
||||||
|
BytesMissing,
|
||||||
|
InvalidData
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LengthPrefixedFrame {}//TODO: Max expected length
|
||||||
|
|
||||||
|
impl LengthPrefixedFrame {
|
||||||
|
fn try_read_var_int(src: &mut BytesMut) -> Result<(VarInt, usize), VarIntReadError> {
|
||||||
|
let src = src.chunk();
|
||||||
|
let mut num_read = 0;
|
||||||
|
let mut result = 0;
|
||||||
|
loop {
|
||||||
|
if src.len() <= num_read {
|
||||||
|
return Err(VarIntReadError::BytesMissing)
|
||||||
|
}
|
||||||
|
let read = src[num_read];
|
||||||
|
let value = i32::from(read & 0b0111_1111);
|
||||||
|
result |= value.overflowing_shl((7 * num_read) as u32).0;
|
||||||
|
|
||||||
|
num_read += 1;
|
||||||
|
|
||||||
|
if num_read > 5 {
|
||||||
|
return Err(VarIntReadError::InvalidData);
|
||||||
|
}
|
||||||
|
if read & 0b1000_0000 == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((VarInt(result), num_read))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decoder for LengthPrefixedFrame {
|
||||||
|
type Item = BytesMut;
|
||||||
|
type Error = tokio::io::Error;
|
||||||
|
|
||||||
|
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||||
|
match LengthPrefixedFrame::try_read_var_int(src) {
|
||||||
|
Ok((length, prefix_length)) => {
|
||||||
|
let total_length = prefix_length + usize::from(length);
|
||||||
|
|
||||||
|
if src.len() >= total_length {
|
||||||
|
src.advance(prefix_length);
|
||||||
|
Ok(Some(src.split_to(usize::from(length))))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(VarIntReadError::BytesMissing) => Ok(None),
|
||||||
|
Err(VarIntReadError::InvalidData) => Err(tokio::io::Error::from(ErrorKind::InvalidData))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Encoder<Bytes> for LengthPrefixedFrame {
|
||||||
|
type Error = tokio::io::Error;
|
||||||
|
|
||||||
|
fn encode(&mut self, data: Bytes, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||||
|
dst.reserve(5 + data.len());
|
||||||
|
|
||||||
|
let mut v = data.len();
|
||||||
|
loop {
|
||||||
|
if v & 0x80 == 0 {
|
||||||
|
dst.put_u8(v as u8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst.put_u8((v as u8 & 0x7f) | 0x80);
|
||||||
|
v >>= 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst.put_slice(&data);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -113,7 +113,7 @@ impl<'a> Serializer for &'a mut JavaSerializer {
|
|||||||
|
|
||||||
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
|
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
|
||||||
let v = v.as_bytes();
|
let v = v.as_bytes();
|
||||||
VarInt::serialize(&VarInt::from(v.len()), self)?;
|
VarInt::serialize(&VarInt::from(v.len()), &mut *self)?;
|
||||||
self.serialize_bytes(v)
|
self.serialize_bytes(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ impl<'a> Serializer for &'a mut JavaSerializer {
|
|||||||
|
|
||||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
||||||
match len {
|
match len {
|
||||||
Some(v) => VarInt::from(v).serialize(self)?,
|
Some(v) => VarInt::from(v).serialize(&mut *self)?,
|
||||||
None => ()
|
None => ()
|
||||||
}
|
}
|
||||||
Ok(self)
|
Ok(self)
|
||||||
@ -191,7 +191,7 @@ impl<'a> SerializeSeq for &'a mut JavaSerializer {
|
|||||||
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
||||||
value.serialize(*self)
|
value.serialize(&mut **self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||||
@ -204,7 +204,7 @@ impl<'a> SerializeStruct for &'a mut JavaSerializer {
|
|||||||
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
||||||
value.serialize(*self)
|
value.serialize(&mut **self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
fn end(self) -> Result<Self::Ok, Self::Error> {
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren