Cactus/net/mod.rs
1//! This module manages the TCP server and how/where the packets are managed/sent.
2pub mod packet;
3pub mod slp;
4
5use crate::net::packet::data_types::Uuid;
6use crate::net::packet::{data_types, utils};
7use bytes::{Buf, BytesMut};
8use log::{debug, error, info, warn};
9use packet::data_types::{CodecError, Encodable};
10use packet::{Packet, PacketError, Response};
11use std::cmp::min;
12use std::io;
13use std::net::Ipv4Addr;
14use std::sync::Arc;
15use thiserror::Error;
16use tokio::io::{AsyncReadExt, AsyncWriteExt};
17use tokio::net::TcpStream;
18use tokio::sync::Mutex;
19
20use std::sync::OnceLock;
21const DEFAULT_ADDR: &str = "0.0.0.0";
22static ADDRESS: OnceLock<Ipv4Addr> = OnceLock::new();
23
24fn address() -> &'static Ipv4Addr {
25 ADDRESS.get_or_init(|| {
26 crate::config::Settings::new()
27 .server_ip
28 .unwrap_or_else(|| DEFAULT_ADDR.parse().unwrap())
29 })
30}
31#[derive(Error, Debug)]
32pub enum NetError {
33 #[error("Connection closed: {0}")]
34 ConnectionClosed(String),
35
36 #[error("Failed to read from socket: {0}")]
37 Reading(String),
38
39 #[error("Failed to write to socket: {0}")]
40 Writing(String),
41
42 #[error("Failed to parse packet: {0}")]
43 Parsing(#[from] PacketError),
44
45 #[error("IO error: {0}")]
46 Io(#[from] io::Error),
47
48 #[error("Codec error: {0}")]
49 Codec(#[from] CodecError),
50
51 #[error("Unknown packet id: {0}")]
52 UnknownPacketId(String),
53}
54
55#[derive(Debug, Clone)]
56pub struct PlayerInfo {
57 pub uuid: Uuid,
58 pub name: String,
59 pub entity_id: i32,
60}
61
62/// Listens for every incoming TCP connection.
63pub async fn listen() -> Result<(), Box<dyn std::error::Error>> {
64 let config = crate::config::Settings::new();
65
66 let server_address = format!("{}:{}", address(), config.server_port);
67 let listener = tokio::net::TcpListener::bind(server_address).await?;
68
69 loop {
70 let (socket, addr) = listener.accept().await?;
71 tokio::spawn(async move {
72 if let Err(e) = handle_connection(socket).await {
73 log::warn!("Error handling connection from {addr}: {e}");
74 }
75 });
76 }
77}
78
79/// State of each connection. (e.g.: handshake, play, ...)
80#[derive(Debug, Clone, Copy)]
81enum ConnectionState {
82 Handshake,
83 Status,
84 Login,
85 Configuration,
86 Play,
87 Transfer,
88}
89
90impl Default for ConnectionState {
91 fn default() -> Self {
92 Self::Handshake
93 }
94}
95
96/// Object representing a TCP connection.
97struct Connection {
98 state: Arc<Mutex<ConnectionState>>,
99 socket: Arc<Mutex<TcpStream>>,
100 buffer: Mutex<BytesMut>,
101 player: Arc<Mutex<Option<PlayerInfo>>>,
102}
103
104impl Connection {
105 /// Base buffer size and the number of bytes we're trying to read from the socket.
106 const BUFFER_SIZE: usize = 512;
107
108 fn new(socket: TcpStream) -> Self {
109 Self {
110 state: Arc::new(Mutex::new(ConnectionState::default())),
111 socket: Arc::new(Mutex::new(socket)),
112 buffer: Mutex::new(BytesMut::with_capacity(Self::BUFFER_SIZE)),
113 player: Arc::new(Mutex::new(None)),
114 }
115 }
116
117 /// Get the current state of the connection
118 async fn get_state(&self) -> ConnectionState {
119 *self.state.lock().await
120 }
121
122 /// Change the state of the current Connection.
123 async fn set_state(&self, new_state: ConnectionState) {
124 debug!(
125 "Connection state: {:?} -> {:?}",
126 self.get_state().await,
127 new_state
128 );
129 *self.state.lock().await = new_state
130 }
131
132 /// Writes either a &[u8] to the socket.
133 ///
134 /// This function can take in `Packet`.
135 async fn write<T: AsRef<[u8]>>(&self, data: T) -> Result<(), NetError> {
136 let mut socket = self.socket.lock().await;
137 Ok(socket.write_all(data.as_ref()).await?)
138 }
139
140 /// Attempts to read a packet size (in bytes, in VarInt).
141 /// If yes, return size. (prepending the conn buffer)
142 /// If no, append bytes to connection buffer.
143 async fn wait_size(&self, bytes: &[u8]) -> Result<(usize, usize), ()> {
144 debug!("INTO WAIT_SIZE");
145 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
146 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
147 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
148 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
149 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
150 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
151 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
152 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
153 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
154 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
155 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
156 let mut buffer = self.buffer.lock().await;
157 let buffer_size: usize = buffer.len();
158 // OLDEST bytes first.
159 let read: Vec<u8> = buffer.iter().chain(bytes).copied().collect();
160 debug!("wait_size() buffer: {}", utils::get_dec_repr(&read));
161
162 match data_types::VarInt::from_bytes(read, ()) {
163 Ok(size) => {
164 debug!("Read VarInt from wait_size(): {}", size.get_value());
165 let s = usize::try_from(size.get_value()).map_err(|e| {
166 error!("Error while converting packet size into usize: {e}");
167 })?;
168 // Left-shift the buffers' items to account for this VarInt.
169 buffer.advance(min(buffer_size, size.size()));
170 Ok((s, size.size()))
171 }
172 Err(_) => {
173 //buffer.extend_from_slice(bytes);
174 Err(())
175 }
176 }
177 }
178 /// Wait for the number of bytes wait_size() spew.
179 /// If yes, return packet. (prepending the conn buffer)
180 /// If no, append bytes to connection buffer.
181 async fn wait_packet(&self, bytes: &[u8], size: usize, size_size: usize) -> Result<Packet, ()> {
182 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
183 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
184 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
185 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
186 // TODO: REWRITE THIS WITH ZERO COPY. INEFFICIENT!
187 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
188 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
189 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
190 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
191 // TODO: ADD CONCRETE ERRORS AND PROPAGATE;
192
193 let mut buffer = self.buffer.lock().await;
194 // Size of connection buffer.
195 let buffer_size: usize = buffer.len();
196
197 // OLDEST bytes first!
198 let read: Vec<u8> = buffer.iter().chain(bytes).copied().collect();
199
200 // Size of only the payload of the frame (ID + Data)
201 //let payload_size: usize = size - size_size;
202 // Size of ALL the frame.
203 let frame_size: usize = size + size_size;
204
205 // The concatenated [CONN BUFF + SOCK READ] is smaller than the frame.
206 if read.len() < frame_size {
207 buffer.extend_from_slice(bytes);
208 warn!("Frame size is bigger than cached data");
209 debug!("Cached data: {}", utils::get_dec_repr(&read));
210 debug!("Frame size: {}", frame_size);
211 Err(())
212 } else {
213 //if (size_size >= size) {
214 if 0 == size {
215 error!("Size is zero");
216 return Err(());
217 }
218
219 let frame = &read[..frame_size];
220 debug!("Cached data b4 advance: {}", utils::get_dec_repr(&buffer));
221 buffer.advance(min(frame_size, buffer_size));
222 debug!(
223 "Cached data after advance: {}",
224 utils::get_dec_repr(&buffer)
225 );
226 debug!("Frame: {frame:?}");
227 match Packet::new(frame) {
228 Ok(p) => {
229 if frame_size < read.len() {
230 debug!("Cached data b4 extend: {}", utils::get_dec_repr(&buffer));
231 buffer.extend_from_slice(&read[frame_size..]);
232 debug!("Cached data after extend: {}", utils::get_dec_repr(&buffer));
233 }
234 Ok(p)
235 }
236 Err(e) => {
237 error!("Error while making packet: {e}");
238 Err(())
239 }
240 }
241 }
242 }
243
244 /// TODO: CHECK & REWRITE
245 /// TODO: CHECK & REWRITE
246 /// TODO: CHECK & REWRITE
247 /// TODO: CHECK & REWRITE
248 /// TODO: CHECK & REWRITE
249 async fn read(&self) -> Result<Packet, NetError> {
250 let mut socket = self.socket.lock().await;
251
252 loop {
253 // Try to parse the VarInt length from the start of the connection buffer.
254 let (len_opt, len_len_opt) = {
255 let recv = self.buffer.lock().await;
256
257 if recv.is_empty() {
258 (None, None)
259 } else {
260 // Parse at most 5 bytes for the VarInt prefix.
261 let to_parse = recv.len().min(5);
262 match data_types::VarInt::from_bytes(recv[..to_parse].to_vec(), ()) {
263 Ok(v) => {
264 let len_usize = usize::try_from(v.get_value()).map_err(|_| {
265 NetError::Reading("Frame length does not fit in usize".to_string())
266 })?;
267 (Some(len_usize), Some(v.size()))
268 }
269 Err(_) => (None, None), // need more bytes for the length
270 }
271 }
272 };
273
274 if let (Some(len), Some(len_len)) = (len_opt, len_len_opt) {
275 if len == 0 {
276 return Err(NetError::Reading("Zero-length frame".to_string()));
277 }
278
279 let total = len_len + len;
280
281 // If we already have the full frame, split and parse.
282 if {
283 let recv = self.buffer.lock().await;
284 recv.len() >= total
285 } {
286 let mut recv = self.buffer.lock().await;
287 let frame = recv.split_to(total);
288 drop(recv);
289
290 return Packet::new(&frame).map_err(NetError::Parsing);
291 }
292 // else: we know the size but need more bytes; fall through to read.
293 }
294
295 // Read more bytes from the socket into the connection buffer.
296 let mut recv = self.buffer.lock().await;
297 let n = socket.read_buf(&mut *recv).await?;
298 if n == 0 {
299 return Err(NetError::ConnectionClosed("read 0 bytes".to_string()));
300 }
301 }
302 }
303 //
304 // /// Reads the socket for a full valid frame (packet).
305 // /// # Behavior
306 // /// - Maintains a per-connection buffer.
307 // ///
308 // /// Zeroth, if connection buffer not empty, read from it.
309 // ///
310 // /// First, wait for reading a **complete** packet length (VarInt).
311 // ///
312 // /// Second, waits for reading the complete frame, so it reads the parsed VarInt.
313 // ///
314 // /// Third, if there is more bytes than what we read as a first frame, we put that inside
315 // /// the connection buffer.
316 // ///
317 // /// Return the frame.
318 // async fn read(&self) -> Result<Packet, NetError> {
319 // // TODO: DROP TRIES AND ADD TIMEOUT!!
320 // // TODO: DROP TRIES AND ADD TIMEOUT!!
321 // // TODO: DROP TRIES AND ADD TIMEOUT!!
322 // // TODO: DROP TRIES AND ADD TIMEOUT!!
323 // // TODO: DROP TRIES AND ADD TIMEOUT!!
324 //
325 // let mut buffer = BytesMut::with_capacity(Self::BUFFER_SIZE);
326 // let mut socket = self.socket.lock().await;
327 //
328 // for try_count in 1..=Self::MAX_PACKET_TRIES {
329 // // 1) Try to parse the length (once).
330 // let size_res = Self::wait_size(self, &buffer).await;
331 // if size_res.is_err() {
332 // let n = socket.read_buf(&mut buffer).await?;
333 // if n == 0 { return Err(NetError::ConnectionClosed("read 0 bytes".into())); }
334 // continue;
335 // }
336 // let (size, size_len) = size_res.unwrap();
337 //
338 // // 2) Try to split the frame.
339 // if let Ok(pkt) = Self::wait_packet(self, &buffer, size, size_len).await {
340 // return Ok(pkt);
341 // }
342 //
343 // // 3) Need more bytes.
344 // let n = socket.read_buf(&mut buffer).await?;
345 // if n == 0 { return Err(NetError::ConnectionClosed("read 0 bytes".into())); }
346 // }
347 //
348 // return Err(NetError::Reading("Failed to delimit".to_string()));
349 //
350 //
351 //
352 // // Try to read a packet, up to MAX_PACKET_TRIES tries (basically socket reads).
353 // for try_count in 1..=Self::MAX_PACKET_TRIES {
354 // let is_conn_buf_empty: bool = { self.buffer.lock().await.is_empty() };
355 //
356 // if Self::wait_size(self, &buffer).await.is_err() {
357 // let n = socket.read_buf(&mut buffer).await?;
358 // if n == 0 { return Err(NetError::ConnectionClosed("read 0 bytes".into())); }
359 // continue;
360 // }
361 //
362 // // unwrap??
363 // let (size, size_len) = Self::wait_size(self, &buffer).await.unwrap();
364 //
365 // // 2) If we don't yet have size_len + size bytes, read more.
366 // if Self::wait_packet(self, &buffer, size, size_len).await.is_err() {
367 // let n = socket.read_buf(&mut buffer).await?;
368 // if n == 0 { return Err(NetError::ConnectionClosed("read 0 bytes".into())); }
369 // continue;
370 // }
371 //
372 // // 3) Now we have a full frame.
373 // let pkt = Self::wait_packet(self, &buffer, size, size_len).await.unwrap();
374 // return Ok(pkt);
375 //
376 // debug!("Try in read() to split a frame from stream");
377 // if is_conn_buf_empty {
378 // let read: usize = socket.read_buf(&mut buffer).await?;
379 // if read == 0 {
380 // warn!("Read zero bytes; connection should be closed.");
381 // return Err(NetError::ConnectionClosed("read 0 bytes".to_string()));
382 // }
383 // }
384 //
385 // debug!(
386 // "TCP buffer received ({}): {}",
387 // buffer.len(),
388 // crate::net::packet::utils::get_dec_repr(&buffer)
389 // );
390 // // VarInt Value / VarInt Size
391 // if let Ok(size_varint) = Self::wait_size(self, &buffer).await {
392 // debug!("Got packet with size: {}", size_varint.0);
393 // if let Ok(packet) =
394 // Self::wait_packet(self, &buffer, size_varint.0, size_varint.1).await
395 // {
396 // debug!("Split a packet: {packet:?}");
397 // return Ok(packet);
398 // } else {
399 // warn!(
400 // "Failed to delimit packet with current read bytes; try #{}/{}",
401 // try_count,
402 // Self::MAX_PACKET_TRIES
403 // );
404 // }
405 // } else {
406 // warn!(
407 // "Failed to delimit packet SIZE with current read bytes; try #{}/{}",
408 // try_count,
409 // Self::MAX_PACKET_TRIES
410 // );
411 // }
412 // }
413 //
414 // Err(NetError::Reading(
415 // "Failed to delimit packet in socket stream".to_string(),
416 // ))
417 // }
418
419 /// Tries to close the connection with the Minecraft client
420 async fn close(&self) -> Result<(), std::io::Error> {
421 info!("Connection closed: {}", self);
422 self.socket.lock().await.shutdown().await
423 }
424}
425
426use std::fmt;
427
428impl fmt::Display for Connection {
429 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
430 // Snapshot addresses without awaiting
431 let (local, peer) = match self.socket.try_lock() {
432 Ok(sock) => (sock.local_addr().ok(), sock.peer_addr().ok()),
433 Err(_) => (None, None), // couldn't lock right now
434 };
435
436 // Snapshot buffer length without awaiting
437 let buf_str = match self.buffer.try_lock() {
438 Ok(buf) => human_bytes(buf.len()),
439 Err(_) => "<locked>".to_string(),
440 };
441
442 write!(
443 f,
444 "conn({} -> {}, buf={})",
445 local.map(|a| a.to_string()).unwrap_or_else(|| "?".into()),
446 peer.map(|a| a.to_string()).unwrap_or_else(|| "?".into()),
447 buf_str
448 )
449 }
450}
451
452fn human_bytes(n: usize) -> String {
453 const KB: usize = 1024;
454 const MB: usize = KB * 1024;
455 const GB: usize = MB * 1024;
456 if n >= GB {
457 format!("{:.1}GiB", n as f64 / GB as f64)
458 } else if n >= MB {
459 format!("{:.1}MiB", n as f64 / MB as f64)
460 } else if n >= KB {
461 format!("{:.1}KiB", n as f64 / KB as f64)
462 } else {
463 format!("{n}B")
464 }
465}
466
467const IS_CRUEL: bool = true;
468
469/// Handles each connection. Receives every packet.
470async fn handle_connection(socket: TcpStream) -> Result<(), NetError> {
471 debug!("Handling new connection: {socket:?}");
472
473 let connection = Connection::new(socket);
474
475 #[cfg(debug_assertions)]
476 let mut packet_count: usize = 0;
477
478 loop {
479 debug!("handle_connection() loop");
480 // Read the socket and wait for a packet
481 let res = connection.read().await;
482 if res.is_err() && IS_CRUEL {
483 connection.close().await?;
484 }
485 let packet: Packet = res?;
486
487 #[cfg(debug_assertions)]
488 {
489 packet_count += 1;
490 debug!("Got packet #{}: {:?}", packet_count, packet);
491 }
492
493 let response: Response = handle_packet(&connection, packet).await?;
494
495 if let Some(packet) = response.get_packet() {
496 connection.write(packet).await?;
497 if response.does_close_conn() {
498 connection.close().await?;
499 return Ok(());
500 }
501 } else {
502 debug!("No response packet for this serverbound packet/state");
503 }
504 }
505}
506
507//async fn socket_transmitter
508
509/// This function returns an appropriate response given the input `buffer` packet data.
510async fn handle_packet(conn: &Connection, packet: Packet) -> Result<Response, NetError> {
511 debug!("{packet:?} / Conn. state: {:?}", conn.get_state().await);
512
513 // Dispatch packet depending on the current State.
514 match conn.get_state().await {
515 ConnectionState::Handshake => dispatch::handshaking(packet, conn).await,
516 ConnectionState::Status => dispatch::status(packet, conn).await,
517 ConnectionState::Login => dispatch::login(conn, packet).await,
518 ConnectionState::Configuration => dispatch::configuration(conn, packet).await,
519 ConnectionState::Play => dispatch::play(conn, packet).await,
520 ConnectionState::Transfer => dispatch::transfer(conn, packet).await,
521 }
522}
523
524/// The `dispatch` module contains functions that will change the state of the active `Connection`.
525/// Each function in `dispatch` corresponds not to a specific packet, but to a whole state.
526/// Each state has different packets, and a packet can be named the name but have different intent
527/// based on state.
528///
529/// # Example of state switch
530/// (Initial state: 'Handshake')
531/// We receive a Handshake packet, ID=0x00 with next_state(VarInt Enum) set to:
532/// 1: we switch the connection state to 'Status'.
533/// 2: we switch the connection state to 'Login'.
534/// 3: we switch the connection state to 'Transfer'.
535mod dispatch {
536 use std::borrow::Cow;
537
538 use super::*;
539 use crate::net::slp::ip_logger::ClientIpLoggerInfo;
540 use packet::packet_types::configuration::*;
541 use packet::packet_types::handshake::*;
542 use packet::packet_types::login::*;
543 use packet::packet_types::ClientboundPacket;
544 use packet::packet_types::EmptyPayloadPacket;
545 use packet::packet_types::GenericPacket;
546 use packet::{
547 data_types::{Encodable, VarInt},
548 Response,
549 };
550
551 /// https://minecraft.wiki/w/Java_Edition_protocol/Packets#Handshaking
552 pub async fn handshaking(packet: Packet, conn: &Connection) -> Result<Response, NetError> {
553 // Set state to Status
554 debug!("Handshake packet: {:?}", packet.get_full_packet());
555 conn.set_state(ConnectionState::Status).await;
556
557 debug!("Trying to create handshake packet...");
558 let handshake_packet: Handshake = packet.try_into()?;
559
560 match handshake_packet.next_state {
561 packet::packet_types::NextState::Status(_) => {
562 conn.set_state(ConnectionState::Status).await
563 }
564 packet::packet_types::NextState::Login(_) => {
565 conn.set_state(ConnectionState::Login).await
566 }
567 packet::packet_types::NextState::Transfer(_) => {
568 conn.set_state(ConnectionState::Transfer).await
569 }
570 packet::packet_types::NextState::Handshake(_) => {
571 return Err(NetError::Codec(CodecError::Decoding(
572 packet::data_types::DataType::Other(Cow::Borrowed("Handshake packet")),
573 packet::data_types::ErrorReason::UnknownValue(
574 "Got handshake next_state.".to_string(),
575 ),
576 )));
577 }
578 }
579
580 Ok(Response::new(None))
581 }
582
583 /// https://minecraft.wiki/w/Java_Edition_protocol/Packets#Status
584 pub async fn status(packet: Packet, conn: &Connection) -> Result<Response, NetError> {
585 match packet.get_id().get_value() {
586 0x00 => {
587 // Log IP if enabled.
588 if crate::consts::cactus::DO_LOG_IPS_SLP {
589 let info = ClientIpLoggerInfo {
590 ip: conn.socket.lock().await.peer_addr()?.to_string(),
591 };
592 slp::ip_logger::log_ip(info);
593 }
594
595 // Got Status Request
596 let status_resp_packet = slp::status_response()?;
597 let response = Response::new(Some(status_resp_packet));
598
599 Ok(response)
600 }
601 0x01 => {
602 // Got Ping Request (status)
603 let ping_request_packet = slp::ping_response(packet)?;
604 let response = Response::new(Some(ping_request_packet)).close_conn();
605
606 // We should close the connection after sending this packet.
607 // See the 7th step:
608 // https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol_FAQ#What_does_the_normal_status_ping_sequence_look_like?
609
610 Ok(response)
611 }
612 _ => {
613 warn!("Unknown packet ID, State: Status");
614 Err(NetError::UnknownPacketId(format!(
615 "unknown packet ID, State: Status, PacketId: {}",
616 packet.get_id().get_value()
617 )))
618 }
619 }
620 }
621
622 /// https://minecraft.wiki/w/Java_Edition_protocol/Packets#Login
623 pub async fn login(conn: &Connection, packet: Packet) -> Result<Response, NetError> {
624 match packet.get_id().get_value() {
625 0x00 => {
626 let login_start: LoginStart = packet.try_into()?;
627
628 let entity_id = 1;
629 *conn.player.lock().await = Some(PlayerInfo {
630 uuid: login_start.player_uuid.clone(),
631 name: login_start.name.get_value().clone(),
632 entity_id,
633 });
634 debug!("Got login Start packet: {login_start:#?}");
635
636 let args = (
637 login_start.player_uuid,
638 login_start.name,
639 VarInt::from_value(0)?, // No packs
640 Vec::new(),
641 );
642
643 let login_success: LoginSuccess = LoginSuccess::from_values(args)?;
644 Ok(Response::new(Some(login_success.get_packet().clone())))
645 }
646 0x03 => {
647 // Parse it just to be sure it's the Login Acknowledged packet.
648 let _login_success: LoginAcknowledged = packet.try_into()?;
649
650 // Switch the connection state to Configuration
651 conn.set_state(ConnectionState::Configuration).await;
652
653 // Don't respond anything
654 //Ok(Response::new(None))
655 //
656 // Respond with a Clientbound Known Packs packet
657 let args = (VarInt::from_value(0)?, Vec::new());
658 let clientbound_known_packs: Packet = ClientboundKnownPacks::from_values(args)?
659 .get_packet()
660 .clone();
661
662 Ok(Response::new(Some(clientbound_known_packs)))
663 }
664 _ => {
665 warn!("Unknown packet ID, State: Status");
666 Err(NetError::UnknownPacketId(format!(
667 "unknown packet ID, State: Status, PacketId: {}",
668 packet.get_id().get_value()
669 )))
670 }
671 }
672 }
673
674 /// https://minecraft.wiki/w/Java_Edition_protocol/Packets#Transfer
675 /// État non standard côté serveur (selon version/proxy). Par défaut: ignorer proprement.
676 pub async fn transfer(conn: &Connection, packet: Packet) -> Result<Response, NetError> {
677 warn!(
678 "Transfer state: ignoring packet id=0x{:02X} (len={}) from {}",
679 packet.get_id().get_value(),
680 packet.get_full_packet().len(),
681 conn
682 );
683
684 Ok(Response::new(None))
685 }
686
687 /// https://minecraft.wiki/w/Java_Edition_protocol/Packets#Configuration
688 pub async fn configuration(conn: &Connection, packet: Packet) -> Result<Response, NetError> {
689 match packet.get_id().get_value() {
690 0x00 => {
691 // TODO: Cookie Request packet
692 Ok(Response::new(None))
693 }
694 0x01 => {
695 // TODO: Clientbound Plugin Message packet
696 Ok(Response::new(None))
697 }
698 0x02 => {
699 // TODO: Disconnect packet
700 Ok(Response::new(None))
701 }
702 0x03 => {
703 let acknowledge_finish_configuration: FinishConfiguration = packet.try_into()?;
704 debug!(
705 "Got Acknowledge Finish Configuration: {acknowledge_finish_configuration:?}"
706 );
707
708 info!("{}", *crate::consts::messages::PLAY_PACKET_NOTIFIER);
709
710 conn.set_state(ConnectionState::Play).await;
711
712 // TODO: Send a 'Login (play)' packet
713 // TODO: Send a 'Login (play)' packet
714 // TODO: Send a 'Login (play)' packet
715 // TODO: Send a 'Login (play)' packet
716 // TODO: Send a 'Login (play)' packet
717 // TODO: Send a 'Login (play)' packet
718 // TODO: Send a 'Login (play)' packet
719 // TODO: Send a 'Login (play)' packet
720 // TODO: Send a 'Login (play)' packet
721 // TODO: Send a 'Login (play)' packet
722 // TODO: Send a 'Login (play)' packet
723 // TODO: Send a 'Login (play)' packet
724 // TODO: Send a 'Login (play)' packet
725 // TODO: Send a 'Login (play)' packet
726 //
727 // TO IMPLEMENT (for the 'Login (play)' packet):
728
729 // https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol#Type:Identifier
730
731 // https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol#Type:Long
732
733 // https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol#Type:Unsigned_Byte
734
735 // OK - https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol#Type:Byte
736
737 // https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol#Type:Position
738
739 // https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol#Type:Int
740
741 Ok(Response::new(None))
742 }
743 0x04 => {
744 // TODO: Clientbound Keep Alive packet
745 // TODO: Clientbound Keep Alive packet
746 // TODO: Clientbound Keep Alive packet
747 Ok(Response::new(None))
748 }
749 0x05 => {
750 // TODO: Ping packet
751 Ok(Response::new(None))
752 }
753 0x07 => {
754 let serverbound_known_packs: ServerboundKnownPacks = packet.try_into()?;
755 debug!("Got Serverbound Known Packs packet: {serverbound_known_packs:?}");
756
757 // Switch connection state to Play.
758 // NO! Why? We wait for the client to send an Ack first, fool!
759 //conn.set_state(ConnectionState::Play).await;
760
761 let finish_configuration = FinishConfiguration::new();
762 let finish_config_packet =
763 EmptyPayloadPacket::get_packet(&finish_configuration).clone();
764 Ok(Response::new(Some(finish_config_packet)))
765 }
766 // TODO: And a lot, lot more to follow
767
768 // 0x10 = 16. Last and sixteenth Configuration packet.
769 0x10 => {
770 // TODO: Server Links
771 Ok(Response::new(None))
772 }
773 _ => {
774 warn!("Unknown packet ID, State: Configuration");
775 Err(NetError::UnknownPacketId(format!(
776 "unknown packet ID, State: Configuration, PacketId: {}",
777 packet.get_id().get_value()
778 )))
779 }
780 }
781 }
782
783 /// https://minecraft.wiki/w/Java_Edition_protocol/Packets#Play
784 /// The largest state with over 60 different types of packets, the last one being 0x41 (65).
785 pub async fn play(conn: &Connection, packet: Packet) -> Result<Response, NetError> {
786 debug!("Inside play state");
787
788 match packet.get_id().get_value() {
789 _ => {
790 warn!("Unknown packet ID, State: Play");
791 Err(NetError::UnknownPacketId(format!(
792 "unknown packet ID, State: Play, PacketId: {}",
793 packet.get_id().get_value()
794 )))
795 }
796 }
797 }
798}