fingers

Finger client library in Rust
Log | Files | Refs | README | LICENSE

commit 24834f39517ac9a2c3e16cc1c981b1cdbdbf11d8
parent 1a01a43d9f9e239a61832652d09105073c394e6f
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Wed,  1 Dec 2021 22:16:32 -0800

Fix comments, add timeout

Diffstat:
MCargo.lock | 2+-
MCargo.toml | 2+-
Msrc/lib.rs | 38+++++++++++++++++++++++++-------------
3 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -4,4 +4,4 @@ version = 3 [[package]] name = "fingers" -version = "0.1.0" +version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fingers" -version = "0.1.0" +version = "0.1.1" edition = "2018" license = "0BSD" readme = "README" diff --git a/src/lib.rs b/src/lib.rs @@ -1,17 +1,19 @@ +//! A finger client library +//! See https://datatracker.ietf.org/doc/html/rfc1288 +//! Be mature. +//! +//! Inspired by Elif Batuman's "The Idiot" +//! https://datatracker.ietf.org/doc/html/draft-ietf-uri-url-finger-02 + use std::io::prelude::*; use std::net::{TcpStream, ToSocketAddrs}; use std::str; -/// A finger client library -/// See https://datatracker.ietf.org/doc/html/rfc1288 -/// Be mature. -/// -/// Inspired by Elif Batuman's "The Idiot" -/// https://datatracker.ietf.org/doc/html/draft-ietf-uri-url-finger-02 - +use std::time::{Duration, Instant}; #[derive(Debug)] pub enum Error { InvalidFingerURL, HostError, + Timeout, IoError(std::io::Error), Utf8Error(str::Utf8Error), } @@ -31,9 +33,8 @@ impl From<std::io::Error> for Error { pub struct Request { query: String, host: String, - // TODO - // timeout: Option<u64>, // seconds - // max_response_len: Option<u64>, + timeout: Option<u64>, // seconds + // max_response_len: Option<u64>, } /// From the draft spec: @@ -62,7 +63,7 @@ pub fn finger(query: &str, host: &str) -> Request { Request { query: q.to_owned(), host: host.to_owned(), - // timeout: Some(3), + timeout: Some(10), // max_response_len: Some(1024 * 10), // 10KB } } @@ -76,9 +77,20 @@ impl Request { dest = self.host; } let server = dest.to_socket_addrs()?.next().ok_or(Error::HostError)?; - let mut stream = TcpStream::connect(&server)?; - + let timeout = Duration::from_secs(self.timeout.unwrap()); + let start = Instant::now(); + let mut stream = TcpStream::connect_timeout(&server, timeout)?; + // TODO improve timeout code + if start + timeout < Instant::now() { + return Err(Error::Timeout); // TODO make timeout errors consistent + } + stream.set_write_timeout(Some((start + timeout) - Instant::now()))?; stream.write(self.query.as_bytes())?; + if start + timeout < Instant::now() { + return Err(Error::Timeout); + } + stream.set_read_timeout(Some((start + timeout) - Instant::now()))?; + let mut line: Vec<u8> = vec![]; stream.read_to_end(&mut line)?;