mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
- replace anyhow with thiserror - implement own error types - Security: Begin to haarding Server, Prevent Crashes when Fail to receive/send Client Packet
204 lines
6.8 KiB
Rust
204 lines
6.8 KiB
Rust
use crate::{
|
|
protocol::{
|
|
client::{
|
|
config::{CFinishConfig, CKnownPacks, CRegistryData, Entry},
|
|
login::{CEncryptionRequest, CLoginSuccess},
|
|
status::{CPingResponse, CStatusResponse},
|
|
},
|
|
server::{
|
|
config::{SAcknowledgeFinishConfig, SClientInformation, SKnownPacks},
|
|
handshake::SHandShake,
|
|
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
|
|
status::{SPingRequest, SStatusRequest},
|
|
},
|
|
ConnectionState, KnownPack,
|
|
},
|
|
server::Server,
|
|
};
|
|
|
|
use super::{Client, PlayerConfig};
|
|
|
|
/// Processes incoming Packets from the Client to the Server
|
|
/// Implements the `Client` Packets, So everything before the Play state, then will use the `PlayerPacketProcessor`
|
|
pub trait ClientPacketProcessor {
|
|
// Handshake
|
|
fn handle_handshake(&mut self, server: &mut Server, handshake: SHandShake);
|
|
// Status
|
|
fn handle_status_request(&mut self, server: &mut Server, status_request: SStatusRequest);
|
|
fn handle_ping_request(&mut self, server: &mut Server, ping_request: SPingRequest);
|
|
// Login
|
|
fn handle_login_start(&mut self, server: &mut Server, login_start: SLoginStart);
|
|
fn handle_encryption_response(
|
|
&mut self,
|
|
server: &mut Server,
|
|
encryption_response: SEncryptionResponse,
|
|
);
|
|
fn handle_plugin_response(
|
|
&mut self,
|
|
server: &mut Server,
|
|
plugin_response: SLoginPluginResponse,
|
|
);
|
|
fn handle_login_acknowledged(
|
|
&mut self,
|
|
server: &mut Server,
|
|
login_acknowledged: SLoginAcknowledged,
|
|
);
|
|
// Config
|
|
fn handle_client_information(
|
|
&mut self,
|
|
server: &mut Server,
|
|
client_information: SClientInformation,
|
|
);
|
|
fn handle_known_packs(&mut self, server: &mut Server, config_acknowledged: SKnownPacks);
|
|
fn handle_config_acknowledged(
|
|
&mut self,
|
|
server: &mut Server,
|
|
config_acknowledged: SAcknowledgeFinishConfig,
|
|
);
|
|
}
|
|
|
|
impl ClientPacketProcessor for Client {
|
|
fn handle_handshake(&mut self, _server: &mut Server, handshake: SHandShake) {
|
|
// TODO set protocol version and check protocol version
|
|
self.connection_state = handshake.next_state;
|
|
dbg!("handshake");
|
|
}
|
|
|
|
fn handle_status_request(&mut self, server: &mut Server, _status_request: SStatusRequest) {
|
|
dbg!("sending status");
|
|
|
|
if let Ok(response) = serde_json::to_string(&server.status_response) {
|
|
self.send_packet(CStatusResponse::new(response))
|
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
|
} else {
|
|
log::error!("Failed to parse Status response to JSON")
|
|
}
|
|
}
|
|
|
|
fn handle_ping_request(&mut self, _server: &mut Server, ping_request: SPingRequest) {
|
|
dbg!("ping");
|
|
self.send_packet(CPingResponse::new(ping_request.payload))
|
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
|
self.close();
|
|
}
|
|
|
|
fn handle_login_start(&mut self, server: &mut Server, login_start: SLoginStart) {
|
|
dbg!("login start");
|
|
self.name = Some(login_start.name);
|
|
self.uuid = Some(login_start.uuid);
|
|
let verify_token: [u8; 4] = rand::random();
|
|
let public_key_der = &server.public_key_der;
|
|
let packet = CEncryptionRequest::new(
|
|
"",
|
|
public_key_der,
|
|
&verify_token,
|
|
false, // TODO
|
|
);
|
|
self.send_packet(packet)
|
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
|
}
|
|
|
|
fn handle_encryption_response(
|
|
&mut self,
|
|
server: &mut Server,
|
|
encryption_response: SEncryptionResponse,
|
|
) {
|
|
dbg!("encryption response");
|
|
self.enable_encryption(server, encryption_response.shared_secret)
|
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
|
|
|
if let Some(uuid) = self.uuid {
|
|
if let Some(name) = &self.name {
|
|
let packet = CLoginSuccess::new(uuid, name.clone(), 0, false);
|
|
self.send_packet(packet)
|
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
|
} else {
|
|
self.kick("Name is none");
|
|
}
|
|
} else {
|
|
self.kick("UUID is none");
|
|
}
|
|
}
|
|
|
|
fn handle_plugin_response(
|
|
&mut self,
|
|
_server: &mut Server,
|
|
_plugin_response: SLoginPluginResponse,
|
|
) {
|
|
}
|
|
|
|
fn handle_login_acknowledged(
|
|
&mut self,
|
|
_server: &mut Server,
|
|
_login_acknowledged: SLoginAcknowledged,
|
|
) {
|
|
self.connection_state = ConnectionState::Config;
|
|
Server::send_brand(self).unwrap_or_else(|e| self.kick(&e.to_string()));
|
|
// known data packs
|
|
self.send_packet(CKnownPacks::new(&[KnownPack {
|
|
namespace: "minecraft",
|
|
id: "core",
|
|
version: "1.21",
|
|
}]))
|
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
|
dbg!("login achnowlaged");
|
|
}
|
|
fn handle_client_information(
|
|
&mut self,
|
|
_server: &mut Server,
|
|
client_information: SClientInformation,
|
|
) {
|
|
self.config = Some(PlayerConfig {
|
|
locale: client_information.locale,
|
|
view_distance: client_information.view_distance,
|
|
chat_mode: client_information.chat_mode,
|
|
chat_colors: client_information.chat_colors,
|
|
skin_parts: client_information.skin_parts,
|
|
main_hand: client_information.main_hand,
|
|
text_filtering: client_information.text_filtering,
|
|
server_listing: client_information.server_listing,
|
|
});
|
|
}
|
|
|
|
fn handle_known_packs(&mut self, server: &mut Server, config_acknowledged: SKnownPacks) {
|
|
self.send_packet(CRegistryData::new(
|
|
"dimension_type",
|
|
&[
|
|
Entry {
|
|
entry_id: "minecraft:dimension_type",
|
|
has_data: true,
|
|
},
|
|
/* Entry {
|
|
entry_id: "minecraft:worldgen/biome".into(),
|
|
has_data: true,
|
|
},
|
|
Entry {
|
|
entry_id: "minecraft:chat_type".into(),
|
|
has_data: true,
|
|
},
|
|
Entry {
|
|
entry_id: "minecraft:damage_type".into(),
|
|
has_data: true,
|
|
}, */
|
|
],
|
|
))
|
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
|
|
|
// We are done with configuring
|
|
dbg!("finish config");
|
|
self.send_packet(CFinishConfig::new())
|
|
.unwrap_or_else(|e| self.kick(&e.to_string()));
|
|
}
|
|
|
|
fn handle_config_acknowledged(
|
|
&mut self,
|
|
server: &mut Server,
|
|
_config_acknowledged: SAcknowledgeFinishConfig,
|
|
) {
|
|
dbg!("config acknowledged");
|
|
self.connection_state = ConnectionState::Play;
|
|
// generate a player
|
|
server.spawn_player(self);
|
|
}
|
|
}
|