use std::net::SocketAddr; use bytes::Bytes; use lanspread_db::db::{Game, GameFileDescription}; use serde::{Deserialize, Serialize}; pub const PROTOCOL_VERSION: u32 = 3; pub use lanspread_db::db::Availability; #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] pub struct GameSummary { pub id: String, pub name: String, pub size: u64, pub downloaded: bool, pub installed: bool, pub eti_version: Option, pub manifest_hash: u64, pub availability: Availability, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Hello { pub peer_id: String, pub proto_ver: u32, pub listen_addr: Option, pub library_rev: u64, pub library_digest: u64, pub features: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct HelloAck { pub peer_id: String, pub proto_ver: u32, pub listen_addr: Option, pub library_rev: u64, pub library_digest: u64, pub features: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct LibrarySummary { pub library_rev: u64, pub library_digest: u64, pub game_count: usize, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct LibrarySnapshot { pub library_rev: u64, pub games: Vec, } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct LibraryDelta { pub from_rev: u64, pub to_rev: u64, pub added: Vec, pub updated: Vec, pub removed: Vec, } #[derive(Debug, Serialize, Deserialize)] pub enum Request { Ping, ListGames, GetGame { id: String, }, GetGameFileData(GameFileDescription), GetGameFileChunk { game_id: String, relative_path: String, offset: u64, length: u64, }, Hello(Hello), LibrarySummary { peer_id: String, summary: LibrarySummary, }, LibrarySnapshot { peer_id: String, snapshot: LibrarySnapshot, }, LibraryDelta { peer_id: String, delta: LibraryDelta, }, Goodbye { peer_id: String, }, Invalid(Bytes, String), } #[derive(Clone, Debug, Serialize, Deserialize)] pub enum Response { Pong, ListGames(Vec), GetGame { id: String, file_descriptions: Vec, }, HelloAck(HelloAck), GameNotFound(String), InvalidRequest(Bytes, String), EncodingError(String), DecodingError(Bytes, String), InternalPeerError(String), } // Add Message trait pub trait Message { fn decode(bytes: Bytes) -> Self; fn encode(&self) -> Bytes; } // Implement for Request impl Message for Request { fn decode(bytes: Bytes) -> Self { match serde_json::from_slice(&bytes) { Ok(t) => t, Err(e) => { tracing::error!(?e, "Request decoding error"); Request::Invalid(bytes, e.to_string()) } } } fn encode(&self) -> Bytes { match serde_json::to_vec(self) { Ok(s) => Bytes::from(s), Err(e) => { tracing::error!(?e, "Request encoding error"); Bytes::from(format!(r#"{{"error": "encoding error: {e}"}}"#)) } } } } // Implement for Response impl Message for Response { fn decode(bytes: Bytes) -> Self { match serde_json::from_slice(&bytes) { Ok(t) => t, Err(e) => { tracing::error!(?e, "Response decoding error"); Response::DecodingError(bytes, e.to_string()) } } } fn encode(&self) -> Bytes { match serde_json::to_vec(self) { Ok(s) => Bytes::from(s), Err(e) => { tracing::error!(?e, "Response encoding error"); Bytes::from(format!(r#"{{"error": "encoding error: {e}"}}"#)) } } } }