From 0c9f9dbf0cec0b4808a5cd47a14ffa6c4fce49fd Mon Sep 17 00:00:00 2001 From: MeexReay Date: Sat, 3 May 2025 04:19:46 +0300 Subject: [PATCH] packet id constants --- src/server/mod.rs | 2 +- src/server/player/context.rs | 11 ++++- src/server/protocol.rs | 94 ++++++++++++++++++------------------ 3 files changed, 57 insertions(+), 50 deletions(-) diff --git a/src/server/mod.rs b/src/server/mod.rs index 2935fcd..b8d427d 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -17,7 +17,7 @@ pub mod protocol; // Ошибки сервера #[derive(Debug)] pub enum ServerError { - UnknownPacket(String), // Неизвестный пакет, в строке указана ситуация в которой он неизвестен + UnexpectedPacket, // Неожиданный пакет Protocol(ProtocolError), // Ошибка в протоколе при работе с rust_mc_proto ConnectionClosed, // Соединение закрыто, единственная ошибка которая не логируется у handle_connection SerTextComponent, // Ошибка при сериализации текст-компонента diff --git a/src/server/player/context.rs b/src/server/player/context.rs index b72c4ce..c4271c0 100644 --- a/src/server/player/context.rs +++ b/src/server/player/context.rs @@ -107,7 +107,7 @@ impl ClientContext { Ok(()) } - pub fn read_packet(self: &Arc) -> Result { + pub fn read_any_packet(self: &Arc) -> Result { let state = self.state(); let mut conn = self.conn.read().unwrap().try_clone()?; // так можно делать т.к сокет это просто поинтер @@ -127,6 +127,15 @@ impl ClientContext { } } + pub fn read_packet(self: &Arc, id: u8) -> Result { + let packet = self.read_any_packet()?; + if packet.id() != id { + Err(ServerError::UnexpectedPacket) + } else { + Ok(packet) + } + } + pub fn close(self: &Arc) { self.conn.write().unwrap().close(); } diff --git a/src/server/protocol.rs b/src/server/protocol.rs index 0423e69..a5a75ce 100644 --- a/src/server/protocol.rs +++ b/src/server/protocol.rs @@ -5,6 +5,23 @@ use rust_mc_proto::{DataReader, DataWriter, Packet}; use crate::{server::data::text_component::TextComponent, trigger_event}; +// Тут будут все айди пакетов + +pub const HANDSHAKE_ID: u8 = 0x00; +pub const STATUS_REQUEST_ID: u8 = 0x00; +pub const STATUS_RESPONSE_ID: u8 = 0x00; +pub const STATUS_PING_REQUEST_ID: u8 = 0x01; +pub const STATUS_PING_RESPONSE_ID: u8 = 0x01; +pub const LOGIN_START_ID: u8 = 0x00; +pub const LOGIN_SET_COMPRESSION_ID: u8 = 0x03; +pub const LOGIN_SUCCESS_ID: u8 = 0x02; +pub const LOGIN_ACKNOWLEDGED_ID: u8 = 0x03; +pub const CONFIGURATION_SERVERBOUND_PLUGIN_MESSAGE_ID: u8 = 0x02; +pub const CONFIGURATION_CLIENT_INFORMATION_ID: u8 = 0x00; +pub const CONFIGURATION_FINISH_ID: u8 = 0x03; +pub const CONFIGURATION_ACKNOWLEDGE_FINISH_ID: u8 = 0x03; + + #[derive(Debug, Clone)] pub enum ConnectionState { Handshake, @@ -21,11 +38,7 @@ pub fn handle_connection( // Получение пакетов производится через client.conn(), // ВАЖНО: не помещать сам client.conn() в переменные, // он должен сразу убиваться иначе соединение гдето задедлочится - let mut packet = client.read_packet()?; - - if packet.id() != 0x00 { - return Err(ServerError::UnknownPacket(format!("Неизвестный пакет рукопожатия"))); - } // Айди пакета не рукопожатное - выходим из функции + let mut packet = client.read_packet(HANDSHAKE_ID)?; let protocol_version = packet.read_varint()?; // Получаем версия протокола, может быть отрицательным если наш клиент дэбил let server_address = packet.read_string()?; // Получаем домен/адрес сервера к которому пытается подключиться клиент, например "play.example.com", а не айпи @@ -40,11 +53,11 @@ pub fn handle_connection( loop { // Чтение запроса - let packet = client.read_packet()?; + let mut packet = client.read_any_packet()?; match packet.id() { - 0x00 => { // Запрос статуса - let mut packet = Packet::empty(0x00); + STATUS_REQUEST_ID => { // Запрос статуса + let mut packet = Packet::empty(STATUS_RESPONSE_ID); // Дефолтный статус let mut status = "{ @@ -63,13 +76,16 @@ pub fn handle_connection( client.write_packet(&packet)?; }, - 0x01 => { // Пинг + STATUS_PING_REQUEST_ID => { // Пинг + // Раньше мы просто отправляли ему его-же пакет, но сейчас, + // С приходом к власти констант айди-пакетов, нам приходится делать такое непотребство + let timestamp = packet.read_long()?; + let mut packet = Packet::empty(STATUS_PING_RESPONSE_ID); + packet.write_long(timestamp)?; client.write_packet(&packet)?; - // Просто отправляем этот же пакет обратно - // ID такой-же, содержание тоже, так почему бы и нет? }, _ => { - return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при чтении запросов статуса"))); + return Err(ServerError::UnexpectedPacket); } } } @@ -78,7 +94,7 @@ pub fn handle_connection( client.set_state(ConnectionState::Login)?; // Мы находимся в режиме Login // Читаем пакет Login Start - let mut packet = client.read_packet()?; + let mut packet = client.read_packet(LOGIN_START_ID)?; let name = packet.read_string()?; let uuid = packet.read_uuid()?; @@ -91,52 +107,39 @@ pub fn handle_connection( // Отправляем пакет Set Compression если сжатие указано if let Some(threshold) = client.server.config.server.compression_threshold { - client.write_packet(&Packet::build(0x03, |p| p.write_usize_varint(threshold))?)?; + client.write_packet(&Packet::build(LOGIN_SET_COMPRESSION_ID, |p| p.write_usize_varint(threshold))?)?; client.set_compression(Some(threshold)); // Устанавливаем сжатие на соединении } // Отправка пакета Login Success - client.write_packet(&Packet::build(0x02, |p| { + client.write_packet(&Packet::build(LOGIN_SUCCESS_ID, |p| { p.write_uuid(&uuid)?; p.write_string(&name)?; p.write_varint(0) })?)?; - let packet = client.read_packet()?; - - if packet.id() != 0x03 { - return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при ожидании Login Acknowledged"))); - } + client.read_packet(LOGIN_ACKNOWLEDGED_ID)?; // Пакет Login Acknowledged client.set_state(ConnectionState::Configuration)?; // Мы перешли в режим Configuration // Получение бренда клиента из Serverbound Plugin Message // Identifier канала откуда берется бренд: minecraft:brand let brand = loop { - let mut packet = client.read_packet()?; + let mut packet = client.read_packet(CONFIGURATION_SERVERBOUND_PLUGIN_MESSAGE_ID)?; // Пакет Serverbound Plugin Message - if packet.id() == 0x02 { // Пакет Serverbound Plugin Message - let identifier = packet.read_string()?; + let identifier = packet.read_string()?; - let mut data = Vec::new(); - packet.get_mut().read_to_end(&mut data).unwrap(); + let mut data = Vec::new(); + packet.get_mut().read_to_end(&mut data).unwrap(); - if identifier == "minecraft:brand" { - break String::from_utf8_lossy(&data).to_string(); - } else { - trigger_event!(client, plugin_message, &identifier, &data); - } + if identifier == "minecraft:brand" { + break String::from_utf8_lossy(&data).to_string(); } else { - return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при ожидании Serverbound Plugin Message"))); - }; + trigger_event!(client, plugin_message, &identifier, &data); + } }; - let mut packet = client.read_packet()?; - - // Пакет Client Information - if packet.id() != 0x00 { - return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при ожидании Client Information"))); - } + let mut packet = client.read_packet(CONFIGURATION_CLIENT_INFORMATION_ID)?; // Пакет Client Information let locale = packet.read_string()?; // for example: en_us let view_distance = packet.read_signed_byte()?; // client-side render distance in chunks @@ -163,22 +166,17 @@ pub fn handle_connection( // TODO: Заюзать Listener'ы чтобы они подмешивали сюда чото - client.write_packet(&Packet::empty(0x03))?; - - let packet = client.read_packet()?; - - if packet.id() != 0x03 { - return Err(ServerError::UnknownPacket(format!("Неизвестный пакет при ожидании Acknowledge Finish Configuration"))); - } + client.write_packet(&Packet::empty(CONFIGURATION_FINISH_ID))?; + client.read_packet(CONFIGURATION_ACKNOWLEDGE_FINISH_ID)?; client.set_state(ConnectionState::Play)?; // Мы перешли в режим Play // Дальше работаем с режимом игры handle_play_state(client)?; }, - _ => { - return Err(ServerError::UnknownPacket(format!("Неизвестный NextState при рукопожатии"))); - } // Тип подключения не рукопожатный + _ => { // Тип подключения не рукопожатный + return Err(ServerError::UnexpectedPacket); + } } Ok(())