mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
More Bedrock work
This commit is contained in:
62
pumpkin-protocol/src/bedrock/ack.rs
Normal file
62
pumpkin-protocol/src/bedrock/ack.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use pumpkin_macros::packet;
|
||||
|
||||
use crate::{ClientPacket, codec::u24::U24, ser::NetworkWriteExt};
|
||||
|
||||
#[packet(0xC0)]
|
||||
pub struct Ack {
|
||||
sequences: Vec<u32>,
|
||||
}
|
||||
|
||||
impl Ack {
|
||||
pub fn new(sequences: Vec<u32>) -> Self {
|
||||
Self { sequences }
|
||||
}
|
||||
}
|
||||
|
||||
impl Ack {
|
||||
fn write_range(
|
||||
start: u32,
|
||||
end: u32,
|
||||
mut write: impl std::io::Write,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
if start == end {
|
||||
write.write_u8_be(1)?;
|
||||
U24::encode(&U24(start), &mut write)?;
|
||||
} else {
|
||||
write.write_u8_be(0)?;
|
||||
U24::encode(&U24(start), &mut write)?;
|
||||
U24::encode(&U24(end), &mut write)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for Ack {
|
||||
fn write_packet_data(
|
||||
&self,
|
||||
mut write: impl std::io::Write,
|
||||
) -> Result<(), crate::ser::WritingError> {
|
||||
let mut buffer = Vec::new();
|
||||
let mut count = 0;
|
||||
|
||||
let mut start = self.sequences[0];
|
||||
let mut end = start;
|
||||
for seq in self.sequences.clone() {
|
||||
if seq == end + 1 {
|
||||
end = seq
|
||||
} else {
|
||||
Self::write_range(start, end, &mut buffer)?;
|
||||
count += 1;
|
||||
start = seq;
|
||||
end = seq;
|
||||
}
|
||||
}
|
||||
Self::write_range(start, end, &mut buffer)?;
|
||||
count += 1;
|
||||
|
||||
write.write_u16_be(count)?;
|
||||
write.write_slice(&buffer)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
pub mod connection;
|
||||
pub mod open_connection;
|
||||
pub mod unconnected_pong;
|
||||
pub mod raknet;
|
||||
|
||||
34
pumpkin-protocol/src/bedrock/client/raknet/connection.rs
Normal file
34
pumpkin-protocol/src/bedrock/client/raknet/connection.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use crate::ser::network_serialize_no_prefix;
|
||||
use pumpkin_macros::packet;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::codec::socket_address::SocketAddress;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[packet(0x10)]
|
||||
pub struct CConnectionRequestAccepted {
|
||||
client_address: SocketAddress,
|
||||
system_index: u16,
|
||||
#[serde(serialize_with = "network_serialize_no_prefix")]
|
||||
system_addresses: Vec<SocketAddress>,
|
||||
requested_timestamp: u64,
|
||||
timestamp: u64,
|
||||
}
|
||||
|
||||
impl CConnectionRequestAccepted {
|
||||
pub fn new(
|
||||
client_address: SocketAddress,
|
||||
system_index: u16,
|
||||
system_addresses: Vec<SocketAddress>,
|
||||
requested_timestamp: u64,
|
||||
timestamp: u64,
|
||||
) -> Self {
|
||||
Self {
|
||||
client_address,
|
||||
system_index,
|
||||
system_addresses,
|
||||
requested_timestamp,
|
||||
timestamp,
|
||||
}
|
||||
}
|
||||
}
|
||||
3
pumpkin-protocol/src/bedrock/client/raknet/mod.rs
Normal file
3
pumpkin-protocol/src/bedrock/client/raknet/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod connection;
|
||||
pub mod open_connection;
|
||||
pub mod unconnected_pong;
|
||||
@@ -28,6 +28,7 @@ impl COpenConnectionReply1 {
|
||||
#[derive(Serialize)]
|
||||
#[packet(0x08)]
|
||||
pub struct COpenConnectionReply2 {
|
||||
magic: [u8; 16],
|
||||
server_guid: u64,
|
||||
client_address: SocketAddress,
|
||||
mtu: u16,
|
||||
@@ -37,6 +38,7 @@ pub struct COpenConnectionReply2 {
|
||||
impl COpenConnectionReply2 {
|
||||
pub fn new(server_guid: u64, client_address: SocketAddress, mtu: u16, security: bool) -> Self {
|
||||
Self {
|
||||
magic: RAKNET_MAGIC,
|
||||
server_guid,
|
||||
client_address,
|
||||
mtu,
|
||||
131
pumpkin-protocol/src/bedrock/frame_set.rs
Normal file
131
pumpkin-protocol/src/bedrock/frame_set.rs
Normal file
@@ -0,0 +1,131 @@
|
||||
use std::io::Write;
|
||||
|
||||
use bytes::Bytes;
|
||||
use pumpkin_macros::packet;
|
||||
|
||||
use crate::bedrock::{RAKNET_SPLIT, RakReliability};
|
||||
use crate::codec::u24::U24;
|
||||
use crate::ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError};
|
||||
use crate::{ClientPacket, ServerPacket};
|
||||
|
||||
#[packet[0x80]]
|
||||
pub struct FrameSet {
|
||||
pub sequence: U24,
|
||||
pub frames: Vec<Frame>,
|
||||
}
|
||||
|
||||
impl ServerPacket for FrameSet {
|
||||
fn read(mut read: impl std::io::Read) -> Result<Self, ReadingError> {
|
||||
Ok(Self {
|
||||
sequence: read.get_u24()?,
|
||||
frames: Frame::read(read)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientPacket for FrameSet {
|
||||
fn write_packet_data(&self, mut write: impl Write) -> Result<(), WritingError> {
|
||||
write.write_u24_be(self.sequence)?;
|
||||
for frame in &self.frames {
|
||||
frame.write(&mut write)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Frame {
|
||||
pub reliability: RakReliability,
|
||||
pub payload: Bytes,
|
||||
pub reliable_index: u32,
|
||||
pub sequence_index: u32,
|
||||
pub order_index: u32,
|
||||
pub order_channel: u8,
|
||||
pub split_size: u32,
|
||||
pub split_id: u16,
|
||||
pub split_index: u32,
|
||||
}
|
||||
|
||||
impl Frame {
|
||||
pub fn read(mut read: impl std::io::Read) -> Result<Vec<Self>, crate::ser::ReadingError> {
|
||||
let mut frames = Vec::new();
|
||||
|
||||
while let Ok(header) = read.get_u8_be() {
|
||||
let reliability_id = (header & 0xE0) >> 5;
|
||||
let reliability = match RakReliability::from_id(reliability_id) {
|
||||
Some(reliability) => reliability,
|
||||
None => {
|
||||
return Err(ReadingError::Message(format!(
|
||||
"Invalid RakReliability {reliability_id}"
|
||||
)));
|
||||
}
|
||||
};
|
||||
let split = (header & RAKNET_SPLIT) != 0;
|
||||
let length = (read.get_u16_be()? as f32 / 8.0).ceil();
|
||||
|
||||
let reliable_index = if reliability.is_reliable() {
|
||||
read.get_u24()?.0
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let sequence_index = if reliability.is_sequenced() {
|
||||
read.get_u24()?.0
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let (order_index, order_channel) = if reliability.is_ordered() {
|
||||
(read.get_u24()?.0, read.get_u8_be()?)
|
||||
} else {
|
||||
(0, 0)
|
||||
};
|
||||
let (split_size, split_id, split_index) = if split {
|
||||
(read.get_u32_be()?, read.get_u16_be()?, read.get_u32_be()?)
|
||||
} else {
|
||||
(0, 0, 0)
|
||||
};
|
||||
let payload = read.read_boxed_slice(length as usize)?;
|
||||
frames.push(Self {
|
||||
reliability,
|
||||
payload: payload.into(),
|
||||
reliable_index,
|
||||
sequence_index,
|
||||
order_index,
|
||||
order_channel,
|
||||
split_size,
|
||||
split_id,
|
||||
split_index,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(frames)
|
||||
}
|
||||
|
||||
fn write(&self, mut write: impl Write) -> Result<(), WritingError> {
|
||||
let is_split = self.split_size > 0;
|
||||
write.write_u8_be(
|
||||
(self.reliability.to_id() >> 5) & if is_split { RAKNET_SPLIT } else { 0 },
|
||||
)?;
|
||||
write.write_u16_be((self.payload.len() >> 3) as u16)?;
|
||||
if self.reliability.is_reliable() {
|
||||
write.write_u24_be(U24(self.reliable_index))?;
|
||||
}
|
||||
if self.reliability.is_sequenced() {
|
||||
write.write_u24_be(U24(self.sequence_index))?;
|
||||
}
|
||||
if self.reliability.is_ordered() {
|
||||
write.write_u24_be(U24(self.order_index))?;
|
||||
write.write_u8_be(self.order_channel)?;
|
||||
}
|
||||
if is_split {
|
||||
write.write_u32_be(self.split_size)?;
|
||||
write.write_u16_be(self.split_id)?;
|
||||
write.write_u32_be(self.split_index)?;
|
||||
}
|
||||
|
||||
write.write_slice(&self.payload).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
pub mod ack;
|
||||
pub mod client;
|
||||
pub mod frame_set;
|
||||
pub mod packet_decoder;
|
||||
pub mod packet_encoder;
|
||||
pub mod server;
|
||||
@@ -6,3 +8,85 @@ pub mod server;
|
||||
pub const RAKNET_MAGIC: [u8; 16] = [
|
||||
0x00, 0xff, 0xff, 0x0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfd, 0xfd, 0x12, 0x34, 0x56, 0x78,
|
||||
];
|
||||
|
||||
pub const RAKNET_VALID: u8 = 0x80;
|
||||
pub const RAKNET_ACK: u8 = 0xC0;
|
||||
pub const RAKNET_NACK: u8 = 0xA0;
|
||||
pub const RAKNET_SPLIT: u8 = 0x10;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
|
||||
pub enum RakReliability {
|
||||
Unreliable,
|
||||
UnreliableSequenced,
|
||||
Reliable,
|
||||
#[default]
|
||||
ReliableOrdered,
|
||||
ReliableSequenced,
|
||||
UnreliableWithAckReceipt,
|
||||
ReliableWithAckReceipt,
|
||||
ReliableOrderedWithAckReceipt,
|
||||
}
|
||||
|
||||
impl RakReliability {
|
||||
pub fn is_reliable(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
RakReliability::Reliable
|
||||
| RakReliability::ReliableOrdered
|
||||
| RakReliability::ReliableSequenced
|
||||
| RakReliability::ReliableWithAckReceipt
|
||||
| RakReliability::ReliableOrderedWithAckReceipt
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_sequenced(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
RakReliability::ReliableSequenced | RakReliability::UnreliableSequenced
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_ordered(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
RakReliability::UnreliableSequenced
|
||||
| RakReliability::ReliableOrdered
|
||||
| RakReliability::ReliableSequenced
|
||||
| RakReliability::ReliableOrderedWithAckReceipt
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_order_exclusive(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
RakReliability::ReliableOrdered | RakReliability::ReliableOrderedWithAckReceipt
|
||||
)
|
||||
}
|
||||
|
||||
pub fn from_id(id: u8) -> Option<Self> {
|
||||
match id {
|
||||
0 => Some(RakReliability::Unreliable),
|
||||
1 => Some(RakReliability::UnreliableSequenced),
|
||||
2 => Some(RakReliability::Reliable),
|
||||
3 => Some(RakReliability::ReliableOrdered),
|
||||
4 => Some(RakReliability::ReliableSequenced),
|
||||
5 => Some(RakReliability::UnreliableWithAckReceipt),
|
||||
6 => Some(RakReliability::ReliableWithAckReceipt),
|
||||
7 => Some(RakReliability::ReliableOrderedWithAckReceipt),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_id(&self) -> u8 {
|
||||
match self {
|
||||
RakReliability::Unreliable => 0,
|
||||
RakReliability::UnreliableSequenced => 1,
|
||||
RakReliability::Reliable => 2,
|
||||
RakReliability::ReliableOrdered => 3,
|
||||
RakReliability::ReliableSequenced => 4,
|
||||
RakReliability::UnreliableWithAckReceipt => 5,
|
||||
RakReliability::ReliableWithAckReceipt => 6,
|
||||
RakReliability::ReliableOrderedWithAckReceipt => 7,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::io::Cursor;
|
||||
|
||||
use async_compression::tokio::bufread::ZlibDecoder;
|
||||
use bytes::Buf;
|
||||
use bytes::Bytes;
|
||||
use tokio::io::{AsyncRead, AsyncReadExt, BufReader};
|
||||
|
||||
use crate::{Aes128Cfb8Dec, CompressionThreshold, PacketDecodeError, RawPacket, StreamDecryptor};
|
||||
use crate::{Aes128Cfb8Dec, CompressionThreshold, PacketDecodeError, StreamDecryptor};
|
||||
|
||||
// decrypt -> decompress -> raw
|
||||
pub enum DecompressionReader<R: AsyncRead + Unpin> {
|
||||
@@ -97,26 +97,16 @@ impl UDPNetworkDecoder {
|
||||
// take_mut::take(&mut self.reader, |decoder| decoder.upgrade(cipher));
|
||||
}
|
||||
|
||||
pub async fn get_raw_packet(
|
||||
pub async fn get_packet_payload(
|
||||
&mut self,
|
||||
mut reader: Cursor<Vec<u8>>,
|
||||
) -> Result<RawPacket, PacketDecodeError> {
|
||||
// TODO: Serde is sync so we need to write to a buffer here :(
|
||||
// Is there a way to deserialize in an asynchronous manner?
|
||||
|
||||
let packet_id = reader
|
||||
.try_get_u8()
|
||||
.map_err(|_| PacketDecodeError::DecodeID)?;
|
||||
|
||||
) -> Result<Bytes, PacketDecodeError> {
|
||||
let mut payload = Vec::new();
|
||||
reader
|
||||
.read_to_end(&mut payload)
|
||||
.await
|
||||
.map_err(|err| PacketDecodeError::FailedDecompression(err.to_string()))?;
|
||||
|
||||
Ok(RawPacket {
|
||||
id: packet_id as i32,
|
||||
payload: payload.into(),
|
||||
})
|
||||
Ok(payload.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
use pumpkin_macros::packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[packet(0x09)]
|
||||
pub struct SConnectionRequest {
|
||||
pub client_guid: u64,
|
||||
pub time: u64,
|
||||
pub security: bool,
|
||||
}
|
||||
@@ -1,3 +1 @@
|
||||
pub mod connection;
|
||||
pub mod open_connection;
|
||||
pub mod unconnected_ping;
|
||||
pub mod raknet;
|
||||
|
||||
25
pumpkin-protocol/src/bedrock/server/raknet/connection.rs
Normal file
25
pumpkin-protocol/src/bedrock/server/raknet/connection.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use pumpkin_macros::packet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::codec::socket_address::SocketAddress;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[packet(0x09)]
|
||||
pub struct SConnectionRequest {
|
||||
pub client_guid: u64,
|
||||
pub time: u64,
|
||||
pub security: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[packet(0x13)]
|
||||
pub struct SNewIncomingConnection {
|
||||
pub server_address: SocketAddress,
|
||||
pub internal_address: SocketAddress,
|
||||
pub ping_time: u64,
|
||||
pub pong_time: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[packet(0x15)]
|
||||
pub struct SDisconnect;
|
||||
3
pumpkin-protocol/src/bedrock/server/raknet/mod.rs
Normal file
3
pumpkin-protocol/src/bedrock/server/raknet/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod connection;
|
||||
pub mod open_connection;
|
||||
pub mod unconnected_ping;
|
||||
@@ -2,5 +2,6 @@ pub mod ascii_string;
|
||||
pub mod bit_set;
|
||||
pub mod item_stack_seralizer;
|
||||
pub mod socket_address;
|
||||
pub mod u24;
|
||||
pub mod var_int;
|
||||
pub mod var_long;
|
||||
|
||||
64
pumpkin-protocol/src/codec/u24.rs
Normal file
64
pumpkin-protocol/src/codec/u24.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use crate::ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError};
|
||||
use serde::{
|
||||
Deserialize,
|
||||
de::{self, SeqAccess},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct U24(pub u32);
|
||||
|
||||
impl U24 {
|
||||
pub fn decode(read: &mut impl Read) -> Result<Self, ReadingError> {
|
||||
let a = read.get_u8_le()?;
|
||||
let b = read.get_u8_le()?;
|
||||
let c = read.get_u8_le()?;
|
||||
Ok(U24(u32::from_le_bytes([a, b, c, 0])))
|
||||
}
|
||||
|
||||
pub fn encode(&self, write: &mut impl Write) -> Result<(), WritingError> {
|
||||
let data = self.0 & 0xFFFFFF; // Get the internal u32 value
|
||||
write.write_u8_be((data & 0xFF) as u8)?;
|
||||
write.write_u8_be(((data >> 8) & 0xFF) as u8)?;
|
||||
write.write_u8_be(((data >> 16) & 0xFF) as u8)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for U24 {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
struct Visitor;
|
||||
impl<'de> de::Visitor<'de> for Visitor {
|
||||
type Value = U24;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a valid u24")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut data: u32 = 0;
|
||||
|
||||
// Read the first byte (LSB)
|
||||
data |= seq.next_element::<u8>()?.unwrap() as u32;
|
||||
|
||||
// Read the second byte and shift it by 8 bits
|
||||
data |= (seq.next_element::<u8>()?.unwrap() as u32) << 8;
|
||||
|
||||
// Read the third next_element and shift it by 16 bits
|
||||
data |= (seq.next_element::<u8>()?.unwrap() as u32) << 16;
|
||||
|
||||
// Mask to ensure only the lower 24 bits are kept
|
||||
Ok(U24(data & 0xFFFFFF))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_seq(Visitor)
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ use std::io::{Read, Write};
|
||||
|
||||
use crate::{
|
||||
FixedBitSet,
|
||||
codec::{bit_set::BitSet, var_int::VarInt, var_long::VarLong},
|
||||
codec::{bit_set::BitSet, u24::U24, var_int::VarInt, var_long::VarLong},
|
||||
};
|
||||
|
||||
pub mod deserializer;
|
||||
@@ -48,6 +48,8 @@ pub enum WritingError {
|
||||
pub trait NetworkReadExt {
|
||||
fn get_i8_be(&mut self) -> Result<i8, ReadingError>;
|
||||
fn get_u8_be(&mut self) -> Result<u8, ReadingError>;
|
||||
fn get_u8_le(&mut self) -> Result<u8, ReadingError>;
|
||||
|
||||
fn get_i16_be(&mut self) -> Result<i16, ReadingError>;
|
||||
fn get_u16_be(&mut self) -> Result<u16, ReadingError>;
|
||||
fn get_i32_be(&mut self) -> Result<i32, ReadingError>;
|
||||
@@ -63,6 +65,7 @@ pub trait NetworkReadExt {
|
||||
fn read_remaining_to_boxed_slice(&mut self, bound: usize) -> Result<Box<[u8]>, ReadingError>;
|
||||
|
||||
fn get_bool(&mut self) -> Result<bool, ReadingError>;
|
||||
fn get_u24(&mut self) -> Result<U24, ReadingError>;
|
||||
fn get_var_int(&mut self) -> Result<VarInt, ReadingError>;
|
||||
fn get_var_long(&mut self) -> Result<VarLong, ReadingError>;
|
||||
fn get_string_bounded(&mut self, bound: usize) -> Result<String, ReadingError>;
|
||||
@@ -100,6 +103,14 @@ impl<R: Read> NetworkReadExt for R {
|
||||
Ok(u8::from_be_bytes(buf))
|
||||
}
|
||||
|
||||
fn get_u8_le(&mut self) -> Result<u8, ReadingError> {
|
||||
let mut buf = [0u8];
|
||||
self.read_exact(&mut buf)
|
||||
.map_err(|err| ReadingError::Incomplete(err.to_string()))?;
|
||||
|
||||
Ok(u8::from_le_bytes(buf))
|
||||
}
|
||||
|
||||
fn get_i16_be(&mut self) -> Result<i16, ReadingError> {
|
||||
let mut buf = [0u8; 2];
|
||||
self.read_exact(&mut buf)
|
||||
@@ -116,6 +127,10 @@ impl<R: Read> NetworkReadExt for R {
|
||||
Ok(u16::from_be_bytes(buf))
|
||||
}
|
||||
|
||||
fn get_u24(&mut self) -> Result<U24, ReadingError> {
|
||||
U24::decode(self)
|
||||
}
|
||||
|
||||
fn get_i32_be(&mut self) -> Result<i32, ReadingError> {
|
||||
let mut buf = [0u8; 4];
|
||||
self.read_exact(&mut buf)
|
||||
@@ -289,6 +304,7 @@ pub trait NetworkWriteExt {
|
||||
fn write_u8_be(&mut self, data: u8) -> Result<(), WritingError>;
|
||||
fn write_i16_be(&mut self, data: i16) -> Result<(), WritingError>;
|
||||
fn write_u16_be(&mut self, data: u16) -> Result<(), WritingError>;
|
||||
fn write_u24_be(&mut self, data: U24) -> Result<(), WritingError>;
|
||||
fn write_i32_be(&mut self, data: i32) -> Result<(), WritingError>;
|
||||
fn write_u32_be(&mut self, data: u32) -> Result<(), WritingError>;
|
||||
fn write_i64_be(&mut self, data: i64) -> Result<(), WritingError>;
|
||||
@@ -371,6 +387,10 @@ impl<W: Write> NetworkWriteExt for W {
|
||||
.map_err(WritingError::IoError)
|
||||
}
|
||||
|
||||
fn write_u24_be(&mut self, data: U24) -> Result<(), WritingError> {
|
||||
data.encode(self)
|
||||
}
|
||||
|
||||
fn write_i32_be(&mut self, data: i32) -> Result<(), WritingError> {
|
||||
self.write_all(&data.to_be_bytes())
|
||||
.map_err(WritingError::IoError)
|
||||
|
||||
34
pumpkin/src/net/bedrock/connection.rs
Normal file
34
pumpkin/src/net/bedrock/connection.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use std::{net::SocketAddr, time::UNIX_EPOCH};
|
||||
|
||||
use pumpkin_protocol::{
|
||||
bedrock::{
|
||||
RakReliability, client::raknet::connection::CConnectionRequestAccepted,
|
||||
server::raknet::connection::SConnectionRequest,
|
||||
},
|
||||
codec::socket_address::SocketAddress,
|
||||
};
|
||||
|
||||
use crate::net::{Client, bedrock::BedrockClientPlatform};
|
||||
|
||||
impl Client {
|
||||
pub async fn handle_connection_request(
|
||||
&self,
|
||||
bedrock: &BedrockClientPlatform,
|
||||
packet: SConnectionRequest,
|
||||
) {
|
||||
dbg!("send connection accepted");
|
||||
bedrock
|
||||
.send_framed_packet(
|
||||
self,
|
||||
&CConnectionRequestAccepted::new(
|
||||
SocketAddress(*self.address.lock().await),
|
||||
0,
|
||||
vec![],
|
||||
packet.time,
|
||||
UNIX_EPOCH.elapsed().unwrap().as_millis() as u64,
|
||||
),
|
||||
RakReliability::Unreliable,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,34 @@
|
||||
use std::{
|
||||
io::{Cursor, Write},
|
||||
sync::Arc,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicU32, Ordering},
|
||||
},
|
||||
};
|
||||
|
||||
use bytes::Bytes;
|
||||
use pumpkin_protocol::{
|
||||
ClientPacket, PacketDecodeError, PacketEncodeError, RawPacket, ServerPacket,
|
||||
ClientPacket, PacketDecodeError, PacketEncodeError, ServerPacket,
|
||||
bedrock::{
|
||||
RAKNET_ACK, RAKNET_NACK, RAKNET_VALID, RakReliability,
|
||||
ack::Ack,
|
||||
frame_set::{Frame, FrameSet},
|
||||
packet_decoder::UDPNetworkDecoder,
|
||||
packet_encoder::UDPNetworkEncoder,
|
||||
server::{
|
||||
server::raknet::{
|
||||
connection::{SConnectionRequest, SDisconnect},
|
||||
open_connection::{SOpenConnectionRequest1, SOpenConnectionRequest2},
|
||||
unconnected_ping::SUnconnectedPing,
|
||||
},
|
||||
},
|
||||
codec::u24::U24,
|
||||
packet::Packet,
|
||||
ser::{NetworkWriteExt, ReadingError, WritingError},
|
||||
ser::{NetworkReadExt, NetworkWriteExt, ReadingError, WritingError},
|
||||
};
|
||||
use std::net::SocketAddr;
|
||||
use tokio::{net::UdpSocket, sync::Mutex};
|
||||
|
||||
pub mod connection;
|
||||
pub mod open_connection;
|
||||
pub mod unconnected;
|
||||
|
||||
@@ -33,6 +42,10 @@ pub struct BedrockClientPlatform {
|
||||
network_writer: Arc<Mutex<UDPNetworkEncoder>>,
|
||||
/// The packet decoder for incoming packets.
|
||||
network_reader: Mutex<UDPNetworkDecoder>,
|
||||
|
||||
use_frame_sets: AtomicBool,
|
||||
output_sequence: AtomicU32,
|
||||
output_reliable_index: AtomicU32,
|
||||
}
|
||||
|
||||
impl BedrockClientPlatform {
|
||||
@@ -43,19 +56,18 @@ impl BedrockClientPlatform {
|
||||
addr,
|
||||
network_writer: Arc::new(Mutex::new(UDPNetworkEncoder::new())),
|
||||
network_reader: Mutex::new(UDPNetworkDecoder::new()),
|
||||
use_frame_sets: AtomicBool::new(false),
|
||||
output_sequence: AtomicU32::new(0),
|
||||
output_reliable_index: AtomicU32::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn process_packet(&self, client: &Client, server: &Server, packet: Cursor<Vec<u8>>) {
|
||||
let packet = self.get_packet(client, packet).await;
|
||||
let packet = self.get_packet_payload(client, packet).await;
|
||||
if let Some(packet) = packet {
|
||||
if let Err(error) = Self::handle_packet(client, server, &packet).await {
|
||||
if let Err(error) = self.handle_packet_payload(client, server, packet).await {
|
||||
let _text = format!("Error while reading incoming packet {error}");
|
||||
log::error!(
|
||||
"Failed to read incoming packet with id {}: {}",
|
||||
packet.id,
|
||||
error
|
||||
);
|
||||
log::error!("Failed to read incoming packet with : {error}");
|
||||
//self.kick(TextComponent::text(text)).await;
|
||||
}
|
||||
}
|
||||
@@ -78,12 +90,34 @@ impl BedrockClientPlatform {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn send_packet_now(&self, client: &Client, packet: Vec<u8>) {
|
||||
pub async fn send_framed_packet<P: ClientPacket>(
|
||||
&self,
|
||||
client: &Client,
|
||||
packet: &P,
|
||||
reliability: RakReliability,
|
||||
) {
|
||||
let mut packet_buf = Vec::new();
|
||||
let writer = &mut packet_buf;
|
||||
Self::write_packet(packet, writer).unwrap();
|
||||
let frame = Frame {
|
||||
payload: packet_buf.into(),
|
||||
reliability,
|
||||
reliable_index: self.output_reliable_index.fetch_add(1, Ordering::Relaxed),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// TODO: this is really bad, batch this
|
||||
let frame_set = FrameSet {
|
||||
sequence: U24(self.output_sequence.fetch_add(1, Ordering::Relaxed)),
|
||||
frames: vec![frame],
|
||||
};
|
||||
let mut packet_buf = Vec::new();
|
||||
Self::write_packet(&frame_set, &mut packet_buf).unwrap();
|
||||
if let Err(err) = self
|
||||
.network_writer
|
||||
.lock()
|
||||
.await
|
||||
.write_packet(packet.into(), self.addr, &self.socket)
|
||||
.write_packet(packet_buf.into(), self.addr, &self.socket)
|
||||
.await
|
||||
{
|
||||
// It is expected that the packet will fail if we are closed
|
||||
@@ -96,13 +130,124 @@ impl BedrockClientPlatform {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_packet(
|
||||
pub async fn send_packet_now(&self, client: &Client, packet: Vec<u8>) {
|
||||
if !self.use_frame_sets.load(Ordering::Relaxed) {
|
||||
// Sent the packet directly
|
||||
if let Err(err) = self
|
||||
.network_writer
|
||||
.lock()
|
||||
.await
|
||||
.write_packet(packet.into(), self.addr, &self.socket)
|
||||
.await
|
||||
{
|
||||
// It is expected that the packet will fail if we are closed
|
||||
if !client.closed.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
log::warn!("Failed to send packet to client {}: {}", client.id, err);
|
||||
// We now need to close the connection to the client since the stream is in an
|
||||
// unknown state
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_packet_payload(
|
||||
&self,
|
||||
client: &Client,
|
||||
server: &Server,
|
||||
packet: &RawPacket,
|
||||
packet: Bytes,
|
||||
) -> Result<(), ReadingError> {
|
||||
let payload = &packet.payload[..];
|
||||
match packet.id {
|
||||
let mut payload = &packet[..];
|
||||
|
||||
let Ok(id) = payload.get_u8_be() else {
|
||||
return Err(ReadingError::CleanEOF(String::new()));
|
||||
};
|
||||
|
||||
let is_valid = id & RAKNET_VALID == RAKNET_VALID;
|
||||
if !is_valid {
|
||||
// Offline packets just have Packet ID + Payload
|
||||
return Self::handle_offline_packet(client, server, i32::from(id), payload).await;
|
||||
}
|
||||
self.use_frame_sets.store(true, Ordering::Relaxed);
|
||||
let header = id;
|
||||
|
||||
match header {
|
||||
RAKNET_ACK => {
|
||||
dbg!("received ack");
|
||||
}
|
||||
RAKNET_NACK => {
|
||||
dbg!("received non ack");
|
||||
}
|
||||
0x80..0x8d => {
|
||||
self.handle_frame_set(client, server, FrameSet::read(payload)?)
|
||||
.await;
|
||||
}
|
||||
_ => {
|
||||
log::warn!("Received unknown online packet {header}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_frame_set(&self, client: &Client, server: &Server, frame_set: FrameSet) {
|
||||
// TODO: this is bad
|
||||
client
|
||||
.send_packet_now(&Ack::new(vec![frame_set.sequence.0]))
|
||||
.await;
|
||||
// TODO
|
||||
for frame in frame_set.frames {
|
||||
self.handle_frame(client, server, &frame).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_frame(
|
||||
&self,
|
||||
client: &Client,
|
||||
server: &Server,
|
||||
frame: &Frame,
|
||||
) -> Result<(), ReadingError> {
|
||||
if frame.split_size > 0 {
|
||||
dbg!("oh no, frame is split, TODO");
|
||||
}
|
||||
dbg!(frame.reliability);
|
||||
|
||||
let mut payload = &frame.payload[..];
|
||||
let id = payload.get_u8_be()?;
|
||||
self.handle_packet(client, server, i32::from(id), payload)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn handle_packet(
|
||||
&self,
|
||||
client: &Client,
|
||||
_server: &Server,
|
||||
packet_id: i32,
|
||||
payload: &[u8],
|
||||
) -> Result<(), ReadingError> {
|
||||
match packet_id {
|
||||
SConnectionRequest::PACKET_ID => {
|
||||
client
|
||||
.handle_connection_request(self, SConnectionRequest::read(payload)?)
|
||||
.await;
|
||||
}
|
||||
SDisconnect::PACKET_ID => {
|
||||
dbg!("Bedrock client disconnected");
|
||||
client.close();
|
||||
}
|
||||
_ => {
|
||||
log::warn!("Received Online online packet {packet_id}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_offline_packet(
|
||||
client: &Client,
|
||||
server: &Server,
|
||||
packet_id: i32,
|
||||
payload: &[u8],
|
||||
) -> Result<(), ReadingError> {
|
||||
match packet_id {
|
||||
SUnconnectedPing::PACKET_ID => {
|
||||
client
|
||||
.handle_unconnected_ping(server, SUnconnectedPing::read(payload)?)
|
||||
@@ -119,20 +264,24 @@ impl BedrockClientPlatform {
|
||||
.await;
|
||||
}
|
||||
_ => {
|
||||
log::error!("Failed to handle bedrock client packet id {}", packet.id);
|
||||
log::error!("Failed to handle bedrock client packet id {packet_id}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_packet(&self, client: &Client, packet: Cursor<Vec<u8>>) -> Option<RawPacket> {
|
||||
pub async fn get_packet_payload(
|
||||
&self,
|
||||
client: &Client,
|
||||
packet: Cursor<Vec<u8>>,
|
||||
) -> Option<Bytes> {
|
||||
let mut network_reader = self.network_reader.lock().await;
|
||||
tokio::select! {
|
||||
() = client.await_close_interrupt() => {
|
||||
log::debug!("Canceling player packet processing");
|
||||
None
|
||||
},
|
||||
packet_result = network_reader.get_raw_packet(packet) => {
|
||||
packet_result = network_reader.get_packet_payload(packet) => {
|
||||
match packet_result {
|
||||
Ok(packet) => Some(packet),
|
||||
Err(err) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use pumpkin_protocol::{
|
||||
bedrock::{
|
||||
client::open_connection::{COpenConnectionReply1, COpenConnectionReply2},
|
||||
server::open_connection::{SOpenConnectionRequest1, SOpenConnectionRequest2},
|
||||
client::raknet::open_connection::{COpenConnectionReply1, COpenConnectionReply2},
|
||||
server::raknet::open_connection::{SOpenConnectionRequest1, SOpenConnectionRequest2},
|
||||
},
|
||||
codec::socket_address::SocketAddress,
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use pumpkin_config::BASIC_CONFIG;
|
||||
use pumpkin_protocol::{
|
||||
bedrock::{
|
||||
client::unconnected_pong::{CUnconnectedPong, ServerInfo},
|
||||
server::unconnected_ping::SUnconnectedPing,
|
||||
client::raknet::unconnected_pong::{CUnconnectedPong, ServerInfo},
|
||||
server::raknet::unconnected_ping::SUnconnectedPing,
|
||||
},
|
||||
codec::ascii_string::AsciiString,
|
||||
};
|
||||
@@ -14,8 +14,8 @@ impl Client {
|
||||
let motd_string = ServerInfo {
|
||||
edition: "MCPE",
|
||||
motd_line_1: &BASIC_CONFIG.motd,
|
||||
protocol_version: 527,
|
||||
version_name: "1.19.1",
|
||||
protocol_version: 818,
|
||||
version_name: "1.21.90",
|
||||
player_count: 1,
|
||||
max_player_count: BASIC_CONFIG.max_players,
|
||||
server_unique_id: server.server_guid,
|
||||
|
||||
Reference in New Issue
Block a user