Login complete

This commit is contained in:
Garen Tyler 2022-04-19 09:09:30 -06:00
parent 144ebbba1d
commit 4d928973a6
No known key found for this signature in database
GPG Key ID: E3BF83D66394FD92
4 changed files with 117 additions and 7 deletions

View File

@ -98,6 +98,7 @@ pub mod prelude {
pub use log::*;
pub use serde::{Deserialize, Serialize};
pub use serde_json::json;
pub use uuid::Uuid;
pub type JSON = serde_json::Value;
pub type NBT = fastnbt::Value;
pub use std::collections::VecDeque;

View File

@ -77,6 +77,8 @@ impl NetworkClient {
Ok(())
}
pub async fn send_packet(&mut self, packet: Packet) -> Result<(), tokio::io::Error> {
trace!("NetworkClient.send_packet()");
debug!("Sending packet {:?} to client {}", packet, self.id);
let bytes = packet.serialize();
self.stream.write(&bytes).await?;
Ok(())
@ -90,7 +92,12 @@ impl NetworkClient {
let _ = self.read_data().await;
let _ = self.read_packet();
}
pub fn disconnect(&mut self) {
pub async fn disconnect(&mut self, reason: Option<JSON>) {
if let Some(reason) = reason {
if self.state == NetworkClientState::Login {
let _ = self.send_packet(Packet::CL00Disconnect { reason }).await;
}
}
self.state = NetworkClientState::Disconnected;
}
}

View File

@ -26,7 +26,40 @@ pub enum Packet {
SS01Ping {
payload: i64,
},
// Login
CL00Disconnect {
reason: JSON,
},
CL01EncryptionRequest {
server_id: String,
public_key: Vec<u8>,
verify_token: Vec<u8>,
},
CL02LoginSuccess {
uuid: u128,
username: String,
},
CL03SetCompression {
threshold: usize,
},
CL04LoginPluginRequest {
message_id: i32,
channel: String,
data: Vec<u8>,
},
SL00LoginStart {
username: String,
},
SL01EncryptionResponse {
shared_secret: Vec<u8>,
verify_token: Vec<u8>,
},
SL02LoginPluginResponse {
message_id: i32,
successful: bool,
data: Option<Vec<u8>>,
},
// Play
}
impl Packet {
@ -90,7 +123,46 @@ impl Packet {
}
_ => Err(ParseError::InvalidData),
},
Login => unimplemented!("Parse Login packet"),
Login => match id {
0x00 => {
if serverbound {
let (username, offset_delta) = parse_string(&data[offset..])?;
offset += offset_delta;
Ok((SL00LoginStart { username }, offset))
} else {
unimplemented!("Parse CL00Disconnect")
}
}
0x01 => {
if serverbound {
unimplemented!("Parse SL01EncryptionResponse")
} else {
unimplemented!("Parse CL01EncryptionRequest")
}
}
0x02 => {
if serverbound {
unimplemented!("Parse SL02LoginPluginResponse")
} else {
unimplemented!("Parse CL02LoginSuccess")
}
}
0x03 => {
if serverbound {
Err(ParseError::InvalidData)
} else {
unimplemented!("Parse CL03SetCompression")
}
}
0x04 => {
if serverbound {
Err(ParseError::InvalidData)
} else {
unimplemented!("Parse CL04LoginPluginRequest")
}
}
_ => Err(ParseError::InvalidData),
},
Play => unimplemented!("Parse Play packet"),
}
}
@ -105,7 +177,7 @@ impl Packet {
description,
} => (
0x00,
serialize_json(serde_json::json!({
serialize_json(json!({
"version": {
"name": version_name,
"protocol": protocol_version,
@ -120,7 +192,17 @@ impl Packet {
})),
),
CS01Pong { payload } => (0x01, serialize_long(*payload).to_vec()),
_ => unimplemented!(),
CL00Disconnect { reason } => (0x00, serialize_json(reason.clone())),
// CL01EncryptionRequest
CL02LoginSuccess { uuid, username } => (0x02, {
let mut out = vec![];
out.extend(uuid.to_be_bytes());
out.extend(serialize_string(username));
out
}),
// CL03SetCompression
// CL04LoginPluginRequest
_ => unimplemented!("Serializing unknown packet"),
};
let mut id_and_body = serialize_varint(id as i32);
id_and_body.append(&mut body);

View File

@ -93,7 +93,6 @@ impl Server {
current_players += 1;
}
}
// TODO: Make this count the number in the play state.
let client = &mut self.clients[client_index];
match packet {
SH00Handshake {
@ -107,7 +106,7 @@ impl Server {
"Disconnecting client {} for mismatched protocols: {} (expected {})",
client.id, protocol_version, PROTOCOL_VERSION
);
client.disconnect();
client.disconnect(None).await;
return Err(());
}
client.state = next_state;
@ -128,7 +127,28 @@ impl Server {
SS01Ping { payload } => {
let _ = client.send_packet(CS01Pong { payload }).await;
debug!("Disconnecting client {}, SLP completed", client.id);
client.disconnect();
client.disconnect(None).await;
}
SL00LoginStart { username } => {
debug!(
"Client {} is connecting with username {}",
client.id, username
);
if current_players >= CONFIG.max_players {
client
.disconnect(Some(json!({ "text": "Server full!" })))
.await;
}
// TODO: Authentication
// TODO: Encryption
// TODO: Compression
let _ = client
.send_packet(CL02LoginSuccess {
uuid: client.id,
username,
})
.await;
client.state = NetworkClientState::Play;
}
_ => unimplemented!("Handling unknown packet"),
}