Skip to content

Commit

Permalink
Add socket timeout (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
ya7on authored Nov 24, 2021
1 parent f94cf60 commit 6febad9
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 11 deletions.
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,24 @@ To work with TCP, the `TcpStream` structure built into the `std::net` module is
## Example

```rust
use rcon::{AuthRequest, RCONClient, RCONError, RCONRequest};
use rcon::{AuthRequest, RCONClient, RCONConfig, RCONError, RCONRequest};

fn main() -> Result<(), RCONError> {
let server_url = "donkey-engine.host".to_string();

// Create new RCON client
let mut client = rcon::RCONClient::new(server_url)?;
let mut client = RCONClient::new(RCONConfig {
url: "donkey-engine.host".to_string(),
// Optional
read_timeout: Some(13),
write_timeout: Some(37),
})?;

// Auth request to RCON server (SERVERDATA_AUTH)
let auth_result = client.auth(AuthRequest::new("RCON_SECRET".to_string()))?;
let auth_result = client.auth(AuthRequest::new("rcon.password".to_string()))?;
assert!(auth_result.is_success());

// Execute command request to RCON server (SERVERDATA_EXECCOMMAND)
let version = client.execute(RCONRequest::new("VERSION".to_string()))?;
assert_eq!(version.body, "1.0.0");
let version = client.execute(RCONRequest::new("seed".to_string()))?;
assert_eq!(version.body, "Seed: [3257840388504953787]");

Ok(())
}
Expand Down
50 changes: 47 additions & 3 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ use crate::{AuthRequest, AuthResponse};
use bytes::BufMut;
use std::io::{Read, Write};
use std::net::TcpStream;
use std::time::Duration;

const DEFAULT_READ_TIMEOUT: u64 = 30;
const DEFAULT_WRITE_TIMEOUT: u64 = 30;

/// Configuration for RCON client
#[derive(Default)]
pub struct RCONConfig {
/// URL to server listening RCON
/// example: `0.0.0.0:25575` or `donkey-engine.host:1337`
pub url: String,
/// Timeout in secs for commands sending to server
/// Default: 30 secs
pub write_timeout: Option<u64>,
/// Timeout in secs for response waiting from server
/// Default: 30 secs
pub read_timeout: Option<u64>,
}

/// Simple RCON client
#[derive(Debug)]
Expand All @@ -15,11 +33,32 @@ pub struct RCONClient {
/// RCON client
impl RCONClient {
/// Create new connection
pub fn new(url: String) -> Result<Self, RCONError> {
let socket = TcpStream::connect(&url).map_err(|err| {
pub fn new(config: RCONConfig) -> Result<Self, RCONError> {
let socket = TcpStream::connect(&config.url).map_err(|err| {
RCONError::TcpConnectionError(format!("TCP connection error: {}", err))
})?;
Ok(Self { url, socket })

socket
.set_write_timeout(Some(Duration::new(
config.write_timeout.unwrap_or(DEFAULT_WRITE_TIMEOUT),
0,
)))
.map_err(|err| {
RCONError::TcpConnectionError(format!("Cannot set socket write_timeout: {}", err))
})?;
socket
.set_read_timeout(Some(Duration::new(
config.read_timeout.unwrap_or(DEFAULT_READ_TIMEOUT),
0,
)))
.map_err(|err| {
RCONError::TcpConnectionError(format!("Cannot set socket read_timeout: {}", err))
})?;

Ok(Self {
url: config.url,
socket,
})
}

/// Auth on game server
Expand Down Expand Up @@ -94,6 +133,11 @@ fn execute(
let response_body = String::from_utf8(response_body_buffer)
.map_err(|err| RCONError::TypeError(format!("TypeError {}", err)))?;

let mut terminating_nulls = [0u8; 2];
socket
.read_exact(&mut terminating_nulls)
.map_err(|err| RCONError::TcpConnectionError(format!("TCP response error {}", err)))?;

Ok(ExecuteResponse {
response_id,
response_type,
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ pub(crate) mod client;
pub(crate) mod errors;
pub(crate) mod types;

pub use client::RCONClient;
pub use client::{RCONClient, RCONConfig};
pub use errors::RCONError;
pub use types::{AuthRequest, AuthResponse, RCONRequest, RCONResponse};

0 comments on commit 6febad9

Please sign in to comment.