diff --git a/src/client.rs b/src/client.rs index ed70099..02824c1 100644 --- a/src/client.rs +++ b/src/client.rs @@ -11,7 +11,7 @@ pub use response::Response; use gio::{ prelude::{IOStreamExt, OutputStreamExt, SocketClientExt}, - Cancellable, NetworkAddress, SocketClient, SocketProtocol, TlsCertificate, + Cancellable, SocketClient, SocketProtocol, TlsCertificate, }; use glib::{Bytes, Priority, Uri}; @@ -49,7 +49,7 @@ impl Client { certificate: Option, callback: impl Fn(Result) + 'static, ) { - match network_address_for(&uri) { + match crate::gio::network_address::from_uri(&uri, DEFAULT_PORT) { Ok(network_address) => { self.socket.connect_async( &network_address.clone(), @@ -78,29 +78,13 @@ impl Client { }, ); } - Err(reason) => callback(Err(reason)), + Err(reason) => callback(Err(Error::NetworkAddress(reason))), }; } } // Private helpers -/// [SocketConnectable](https://docs.gtk.org/gio/iface.SocketConnectable.html) / -/// [SNI](https://geminiprotocol.net/docs/protocol-specification.gmi#server-name-indication) -fn network_address_for(uri: &Uri) -> Result { - Ok(NetworkAddress::new( - &match uri.host() { - Some(host) => host, - None => return Err(Error::Connectable(uri.to_string())), - }, - if uri.port().is_positive() { - uri.port() as u16 - } else { - DEFAULT_PORT - }, - )) -} - fn request_async( connection: Connection, query: String, diff --git a/src/client/error.rs b/src/client/error.rs index a9eb0ac..65771c0 100644 --- a/src/client/error.rs +++ b/src/client/error.rs @@ -2,11 +2,12 @@ use std::fmt::{Display, Formatter, Result}; #[derive(Debug)] pub enum Error { - Connectable(String), - Connection(super::connection::Error), Connect(glib::Error), + Connectable(String), + Connection(crate::client::connection::Error), + NetworkAddress(crate::gio::network_address::Error), Request(glib::Error), - Response(super::response::Error), + Response(crate::client::response::Error), Write(glib::Error), } @@ -22,6 +23,9 @@ impl Display for Error { Self::Connect(reason) => { write!(f, "Connect error: {reason}") } + Self::NetworkAddress(reason) => { + write!(f, "Network address error: {reason}") + } Self::Request(reason) => { write!(f, "Request error: {reason}") } diff --git a/src/gio.rs b/src/gio.rs index c20d929..8206018 100644 --- a/src/gio.rs +++ b/src/gio.rs @@ -1 +1,2 @@ pub mod memory_input_stream; +pub mod network_address; diff --git a/src/gio/network_address.rs b/src/gio/network_address.rs new file mode 100644 index 0000000..4869509 --- /dev/null +++ b/src/gio/network_address.rs @@ -0,0 +1,24 @@ +pub mod error; +pub use error::Error; + +use gio::NetworkAddress; +use glib::Uri; + +/// Create new valid [NetworkAddress](https://docs.gtk.org/gio/class.NetworkAddress.html) from [Uri](https://docs.gtk.org/glib/struct.Uri.html) +/// +/// Useful as: +/// * shared [SocketConnectable](https://docs.gtk.org/gio/iface.SocketConnectable.html) interface +/// * [SNI](https://geminiprotocol.net/docs/protocol-specification.gmi#server-name-indication) record for TLS connections +pub fn from_uri(uri: &Uri, default_port: u16) -> Result { + Ok(NetworkAddress::new( + &match uri.host() { + Some(host) => host, + None => return Err(Error::Host(uri.to_string())), + }, + if uri.port().is_positive() { + uri.port() as u16 + } else { + default_port + }, + )) +}