diff --git a/epp-client/src/config.rs b/epp-client/src/config.rs index d685779..8f0742b 100644 --- a/epp-client/src/config.rs +++ b/epp-client/src/config.rs @@ -1,3 +1,54 @@ +//! Config load module +//! +//! Loads the configuration and credentials for each registry connection from +//! the `$XDG_CONFIG_HOME/epp-client/epp-client.toml` file +//! +//! ## Usage +//! +//! The config is automatically loaded when the module is initialized +//! and is available through the `epp_client::config::CONFIG` variable +//! +//! ## Sample config +//! +//! ```toml +//! [registry.verisign] +//! host = 'epp.verisign-grs.com' +//! port = 700 +//! username = 'username' +//! password = 'password' +//! # service extensions +//! ext_uris = [] +//! +//! [registry.hexonet.tls_files] +//! # the full client certificate chain in PEM format +//! cert_chain = '/path/to/certificate/chain/pemfile' +//! # the RSA private key for your certificate +//! key = '/path/to/private/key/pemfile' +//! ``` +//! +//! ## Example +//! +//! ```rust +//! use epp_client::config::CONFIG; +//! +//! fn main() { +//! // Get configuration for the relevant registry section +//! let registry = CONFIG.registry("verisign").unwrap(); +//! +//! // Get EPP host name and port no. +//! let remote = registry.connection_details(); +//! +//! // Get username and password +//! let credentials = registry.credentials(); +//! +//! // Get EPP service extensions +//! let service_extensions = registry.ext_uris().unwrap(); +//! +//! // Get client certificate and private key +//! let tls = registry.tls_files().unwrap(); +//! } +//! ``` + use confy; use lazy_static::lazy_static; use rustls::{Certificate, PrivateKey}; diff --git a/epp-client/src/connection.rs b/epp-client/src/connection.rs index 2507c0d..f79d209 100644 --- a/epp-client/src/connection.rs +++ b/epp-client/src/connection.rs @@ -1,2 +1,5 @@ +//! Manages registry connections and reading/writing to them +//! and connects the EppClient instances to them + pub mod registry; pub mod client; diff --git a/epp-client/src/connection/client.rs b/epp-client/src/connection/client.rs index 3b2d1cf..c0ba848 100644 --- a/epp-client/src/connection/client.rs +++ b/epp-client/src/connection/client.rs @@ -1,3 +1,31 @@ +//! Manages sending/receiving EppObject request and responses to the registry connection +//! +//! ## Example +//! +//! ```rust +//! use epp_client::EppClient; +//! use epp_client::epp::{EppDomainCheck, EppDomainCheckResponse}; +//! +//! #[tokio::main] +//! async fn main() { +//! // Create an instance of EppClient, specifying the name of the registry as in +//! // the config file +//! let mut client = match EppClient::new("verisign").await { +//! Ok(client) => client, +//! Err(e) => panic!("Failed to create EppClient: {}", e) +//! }; +//! +//! // Make a EPP Hello call to the registry +//! let greeting = client.hello().await.unwrap(); +//! println!("{:?}", greeting); +//! +//! // Execute an EPP Command against the registry with distinct request and response objects +//! let domain_check = EppDomainCheck::new(vec!["eppdev.com", "eppdev.net"], "client-trid-12345"); +//! let response = client.transact::<_, EppDomainCheckResponse>(&domain_check).await.unwrap(); +//! println!("{:?}", response); +//! } +//! ``` + use futures::executor::block_on; use std::{error::Error, fmt::Debug}; // use std::time::SystemTime; @@ -49,6 +77,10 @@ async fn connect(registry: &'static str) -> Result> { Ok(client) } +/// Instances of the EppClient type are used to transact with the registry +/// An instance is first created, then various EPP request and response object +/// types are converted to EPP XML to be sent to the registry and the responses +/// from the registry are converted to local types pub struct EppClient { credentials: (String, String), ext_uris: Option>, @@ -65,6 +97,7 @@ pub struct EppClient { // } impl EppClient { + /// Fetches the username used in the registry connection pub fn username(&self) -> String { self.credentials.0.to_string() } @@ -74,6 +107,8 @@ impl EppClient { // self.client_tr_id_fn = Arc::new(func); // } + /// Creates a new EppClient object and does an EPP Login to a given registry to become ready + /// for subsequent transactions on this client instance pub async fn new(registry: &'static str) -> Result> { connect(registry).await } @@ -94,6 +129,7 @@ impl EppClient { Ok(client) } + /// Executes an EPP Hello call and return the response as an `EppGreeting` pub async fn hello(&mut self) -> Result> { let hello = EppHello::new(); let hello_xml = hello.serialize()?; @@ -103,6 +139,8 @@ impl EppClient { Ok(EppGreeting::deserialize(&response)?) } + /// Accepts an EPP request object to convert to a request to send to the registry. The response from the + /// registry is deserialized to response type E and returned. pub async fn transact(&mut self, request: &T) -> Result { let epp_xml = request.serialize()?; @@ -123,18 +161,23 @@ impl EppClient { } } + /// Accepts raw EPP XML and returns the raw EPP XML response to it. + /// Not recommended to use directly but sometimes can be useful for debugging pub async fn transact_xml(&mut self, xml: &str) -> Result> { self.connection.transact(&xml).await } + /// Return the greeting received on establishment of the connection in raw xml form pub fn xml_greeting(&self) -> String { return String::from(&self.connection.greeting) } + /// Return the greeting received on establishment of the connection as an `EppGreeting` instance pub fn greeting(&self) -> Result { EppGreeting::deserialize(&self.connection.greeting) } + /// Send the EPP Logout command to log out of the EPP session pub async fn logout(&mut self) -> Result { let client_tr_id = generate_client_tr_id(&self.credentials.0).unwrap(); let epp_logout = EppLogout::new(client_tr_id.as_str()); diff --git a/epp-client/src/connection/registry.rs b/epp-client/src/connection/registry.rs index 31f712a..8a93c9e 100644 --- a/epp-client/src/connection/registry.rs +++ b/epp-client/src/connection/registry.rs @@ -1,3 +1,5 @@ +//! Manages registry connections and reading/writing to them + use std::sync::Arc; use std::{str, u32}; use bytes::BytesMut; @@ -10,11 +12,13 @@ use tokio::{net::TcpStream, io::AsyncWriteExt, io::AsyncReadExt, io::split, io:: use crate::config::{EppClientConnection}; use crate::error; +/// Socket stream for the connection to the registry pub struct ConnectionStream { reader: ReadHalf>, writer: WriteHalf>, } +/// EPP Connection struct with some metadata for the connection pub struct EppConnection { registry: String, stream: ConnectionStream, @@ -22,6 +26,7 @@ pub struct EppConnection { } impl EppConnection { + /// Create an EppConnection instance with the stream to the registry pub async fn new( registry: String, mut stream: ConnectionStream) -> Result> { @@ -44,7 +49,7 @@ impl EppConnection { Ok(()) } - pub async fn send_epp_request(&mut self, content: &str) -> Result<(), Box> { + async fn send_epp_request(&mut self, content: &str) -> Result<(), Box> { let len = content.len(); let buf_size = len + 4; @@ -93,7 +98,7 @@ impl EppConnection { Ok(data) } - pub async fn get_epp_response(&mut self) -> Result> { + async fn get_epp_response(&mut self) -> Result> { let contents = self.read_epp_response().await?; let response = str::from_utf8(&contents)?.to_string(); @@ -101,6 +106,8 @@ impl EppConnection { Ok(response) } + /// Send an EPP XML request to the registry and return the response + /// receieved to the request pub async fn transact(&mut self, content: &str) -> Result> { self.send_epp_request(&content).await?; @@ -121,6 +128,8 @@ impl Drop for EppConnection { } } +/// Establish a TLS connection to a registry and return a ConnectionStream instance containing the +/// socket stream to read/write to the connection pub async fn epp_connect(registry_creds: &EppClientConnection) -> Result { let (host, port) = registry_creds.connection_details();