// Copyright Marcus Del Favero 2025
// Licensed under the GNU AGPLv3 with an exception, see `README.md` for details
/**
 * Module used for handling discovering game servers on the LAN.
 *
 * This uses SERP Discover just like online server discovery, but the discovery
 * servers are unknown rather than being built-in or manually configured. To
 * find the address of any discovery servers, and the corresponding game servers
 * hosted, the client sends out UDP datagrams to multiple broadcast and
 * multicast addresses on the local network. Any listening discovery server
 * would send back a response confirming its existence and more information used
 * in the next phase.
 *
 * The discovery message broadcast by the client is:
 * 	1. Magic number of `DISCOVER_MAGIC_NUMBER`.
 * 	2. vu30 (see `net/serp/vu30.rs`) for the LAN discovery protocol version
 * 	   (equal to 1).
 *
 * The client sends this message to the server as a UDP datagram. The server,
 * listening on UDP port `SERVER_PORT` (right now 4081), responds to these
 * messages by sending a unicast UDP datagram back to the client. If the LAN
 * discovery protocol version (of 1) the server supports is newer than the
 * client's version sent, the datagram is ignored. This is because the version
 * number the client sends is their latest version they support, so the client
 * won't understand the message. If the client has sent a LAN discovery message
 * of a newer version, the server sends back a response in the possibility the
 * client understands it.
 *
 * This response back to the client is:
 * 	1. Magic number of `RESPONSE_MAGIC_NUMBER`.
 * 	2. vu30 for the LAN discovery protocol version (equal to 1).
 * 	3. 64 bits of the server id. The server id is chosen randomly when the LAN
 * 	   discovery server starts and is used to allow the client to identify
 * 	   when multiple IP addresses belong to the same discovery server.
 * 	4. 16 bits for the game port number, in little-endian.
 *
 * If the magic numbers don't match in either case, the datagram is dropped.
 *
 * If there is additional data at the end of the discovery message, the datagram
 * is dropped as it is invalid. An exception is if the client protocol version
 * is newer than supported, as that might be valid in the future.
 *
 * If there is additional data at the end of the response message, the datagram
 * is dropped.
 *
 * Security note: It is possible for a malicious server on the local network to
 * hide the results from a legitimate discovery server. This would be done by
 * sending back LAN discovery responses with the same server id as the real
 * server. This means that if the client receives the SERP Discover response
 * from the malicious server first, those game servers would be presented while
 * the game servers on the actual server would be hidden.
 *
 * The consequences of this aren't that concerning, as the local network being
 * trusted is a reasonably fair assumption to make, and connecting to a game
 * server different from the one expected is just an annoyance (as the client is
 * designed to never trust the server in the same way the server never trusts
 * the client).
 */
#[cfg(feature = "client")] pub mod client;
pub mod server;

use super::server::PORT;
use super::serp::vu30::Vu30;

const PROTOCOL_VERSION: Vu30 = Vu30::from_u8(1);
const DISCOVER_MAGIC_NUMBER: &[u8] = b"spsh-discover";
const RESPONSE_MAGIC_NUMBER: &[u8] = b"spsh-response";

/*
 * Port for the server to listen on, and the preferred port for the client to
 * listen on. These are both UDP.
 *
 * The purpose of having the client listen on a preferred port is so a firewall
 * rule on the client can be specified to allow incoming traffic for LAN
 * discovery, rather than requiring the firewall to allow all ports.
 */
const SERVER_PORT: u16 = PORT + 1;
#[cfg(feature = "client")] const CLIENT_PORT: u16 = PORT + 2;

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg(feature = "client")]
pub struct ServerId(u64);
