diff --git a/crates/service-rpc/src/auth.rs b/crates/service-rpc/src/auth.rs index e95e25c..8022dd7 100644 --- a/crates/service-rpc/src/auth.rs +++ b/crates/service-rpc/src/auth.rs @@ -3,25 +3,15 @@ use crate::game::AccountRef; use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct DeviceInfo { - #[serde(default)] pub udid: Option, - #[serde(default)] pub open_udid: Option, - #[serde(default)] pub device: Option, - #[serde(default)] pub os_version: Option, - #[serde(default)] pub android: bool, - #[serde(default)] pub preferred_language: String, - #[serde(default)] pub client_major_version: i32, - #[serde(default)] pub client_minor_version: i32, - #[serde(default)] pub client_build: i32, - #[serde(default)] pub resource_sha: Option, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] diff --git a/crates/service-rpc/src/error.rs b/crates/service-rpc/src/error.rs index 51beed8..571acb4 100644 --- a/crates/service-rpc/src/error.rs +++ b/crates/service-rpc/src/error.rs @@ -10,6 +10,8 @@ pub enum RpcError { FrameTooLarge { actual: usize, limit: usize }, #[error("peer closed the connection")] Closed, + #[error("peer stalled mid-frame")] + Timeout, #[error("service rejected the call: {0}")] Rejected(String), #[error("service is unavailable: {0}")] diff --git a/crates/service-rpc/src/server.rs b/crates/service-rpc/src/server.rs index 9ae30be..5afa1a5 100644 --- a/crates/service-rpc/src/server.rs +++ b/crates/service-rpc/src/server.rs @@ -2,8 +2,10 @@ use crate::error::{RpcError, RpcResult, WireError}; use serde::{de::DeserializeOwned, Serialize}; use std::sync::Arc; use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::time::{timeout, Duration}; use tokio::net::{TcpListener, TcpStream}; pub const MAX_FRAME_LEN: usize = 8 * 1024 * 1024; +pub const BODY_READ_TIMEOUT: Duration = Duration::from_secs(30); #[async_trait::async_trait] pub trait RpcService: Send + Sync + 'static { type Request: DeserializeOwned + Send; @@ -56,8 +58,11 @@ pub async fn read_frame(stream: &mut TcpStream) -> RpcResult> { }); } let mut payload = vec![0u8; length]; - stream.read_exact(&mut payload).await?; - Ok(payload) + match timeout(BODY_READ_TIMEOUT, stream.read_exact(&mut payload)).await { + Ok(Ok(_)) => Ok(payload), + Ok(Err(error)) => Err(error.into()), + Err(_) => Err(RpcError::Timeout), + } } pub async fn write_frame(stream: &mut TcpStream, payload: &[u8]) -> RpcResult<()> { if payload.len() > MAX_FRAME_LEN { diff --git a/crates/service-rpc/src/wire.rs b/crates/service-rpc/src/wire.rs index faa773f..0ab3a52 100644 --- a/crates/service-rpc/src/wire.rs +++ b/crates/service-rpc/src/wire.rs @@ -2,7 +2,6 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct WireMessage { pub message_type: u16, - #[serde(default)] pub message_version: u16, pub payload: Vec, }