Add support for parallel connection checking

merge-requests/7/head
Anthony J. Martinez 2 years ago
parent fd632f856e
commit 9ef8eb7e68
  1. 13
      .gitignore
  2. 123
      Cargo.lock
  3. 7
      Cargo.toml
  4. 8
      README.md
  5. 106
      src/main.rs

13
.gitignore vendored

@ -0,0 +1,13 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
*.org

123
Cargo.lock generated

@ -42,29 +42,94 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "connchk"
version = "0.3.0"
version = "0.4.0"
dependencies = [
"rayon",
"reqwest",
"serde",
"serde_json",
"toml",
]
[[package]]
name = "const_fn"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
[[package]]
name = "crossbeam-channel"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
dependencies = [
"cfg-if 1.0.0",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
dependencies = [
"cfg-if 1.0.0",
"const_fn",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
dependencies = [
"autocfg",
"cfg-if 1.0.0",
"lazy_static",
]
[[package]]
name = "dtoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "encoding_rs"
version = "0.8.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
]
[[package]]
@ -341,7 +406,7 @@ version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
]
[[package]]
@ -356,6 +421,15 @@ version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "memoffset"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.16"
@ -378,7 +452,7 @@ version = "0.6.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"fuchsia-zircon",
"fuchsia-zircon-sys",
"iovec",
@ -409,7 +483,7 @@ version = "0.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"libc",
"winapi 0.3.9",
]
@ -498,6 +572,31 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
@ -575,6 +674,12 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sct"
version = "0.6.0"
@ -640,7 +745,7 @@ version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"libc",
"redox_syscall",
"winapi 0.3.9",
@ -734,7 +839,7 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"log",
"pin-project-lite",
"tracing-core",
@ -827,7 +932,7 @@ version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"serde",
"serde_json",
"wasm-bindgen-macro",
@ -854,7 +959,7 @@ version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"js-sys",
"wasm-bindgen",
"web-sys",

@ -1,12 +1,12 @@
[package]
name = "connchk"
version = "0.3.0"
version = "0.4.0"
authors = ["Anthony Martinez <anthony@ajmartinez.com>"]
edition = "2018"
license = "GPL-3.0+"
readme = "README.md"
homepage = "https://github.com/anthonyjmartinez/connchk"
repository = "https://github.com/anthonyjmartinez/connchk.git"
homepage = "https://gitlab.com/anthonyjmartinez/connchk"
repository = "https://gitlab.com/anthonyjmartinez/connchk.git"
description = "Cross-platform command-line network checking tool in Rust"
keywords = ["network", "CLI", "tools"]
categories = ["command-line-utilities"]
@ -18,6 +18,7 @@ reqwest = { version = "0.10", default-features = false, features = ["blocking",
toml = "0.5"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rayon = "1.5"
[profile.release]
lto = true

@ -76,20 +76,18 @@ Failed to connect to httpbin JSON endpoint - Error with:
The TOML structure of the configuration file maps on to JSON cleanly. Defining
JSON bodies should be as easy as `custom = { json = <Your JSON Here> }`. While
this was tested to a reasonable degree it's unlikely that every single possibility
has been explored, so if issues are encountered please [let it be known](https://github.com/anthonyjmartinez/connchk/issues/new/choose).
has been explored, so if issues are encountered please [let it be known](https://gitlab.com/anthonyjmartinez/connchk/-/issues).
### Major Changes
- v0.4.0
- Adds use of `rayon` to support parallel connection execution
- v0.3.0
- Adds support for JSON post bodies.
- Removes declaration of a "bad" status code. Custom tests define only the expected _good_ status code.
- v0.2.1 fixes error handling such that testing does not abort with the first failure
- v0.2.0 disabled the default `reqwest` features to move the package to use of `rustls` instead of `native-tls`
### TODO
- Asynchronous connection checking
### License
This project uses [GPL-3.0+](https://www.gnu.org/licenses/gpl-3.0.html).

@ -1,6 +1,6 @@
/*
connchk gives a status of reachability of plain tcp or http(s) endpoints from your machine
Copyright (C) 2020 Anthony Martinez
Copyright (C) 2020-2021 Anthony Martinez
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -16,17 +16,17 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*!
`connchk` is command-line network checking tool written in Rust. It aims
to provide a cross platform utility that can verify if your host can reach
targets defined in a TOML document.
*/
//!
//! `connchk` is command-line network checking tool written in Rust. It aims
//! to provide a cross platform utility that can verify if your host can reach
//! targets defined in a TOML document.
use std::boxed::Box;
use std::collections::HashMap;
use std::env;
use std::net::{Shutdown, TcpStream};
use rayon::prelude::*;
use reqwest::StatusCode;
use reqwest::blocking::{Client, Response};
use serde::Deserialize;
@ -34,10 +34,8 @@ use serde_json::Value;
use toml;
/**
Provides a deserialize target optional parameters for
custom HTTP(s) checks.
*/
/// Provides a deserialize target optional parameters for
/// custom HTTP(s) checks.
#[derive(Deserialize, Debug)]
struct HttpOptions {
params: Option<HashMap<String,String>>,
@ -45,10 +43,8 @@ struct HttpOptions {
ok: u16,
}
/**
Provides a deserialize target for general parameters
for HTTP(s) checks.
*/
/// Provides a deserialize target for general parameters
/// for HTTP(s) checks.
#[derive(Deserialize, Debug)]
struct HttpResource {
desc: String,
@ -57,11 +53,9 @@ struct HttpResource {
}
impl HttpResource {
/**
Checks an HTTP(s) endpoint's availability with a GET request.
Prints a success message if the status code is 200 OK, or
failure details in any other case.
*/
/// Checks an HTTP(s) endpoint's availability with a GET request.
/// Prints a success message if the status code is 200 OK, or
/// failure details in any other case.
fn check_basic(&self) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let resp = client.get(&self.addr).send()?;
@ -73,13 +67,11 @@ impl HttpResource {
}
}
/**
Checks an HTTP(s) endpoint's availability with a form POST request.
Values are defined in the `HttpOptions` struct.
Prints a success message if the status code is equal to the `ok` value,
or failure details when the status code is equaly to the `bad` value or
any other value/error.
*/
/// Checks an HTTP(s) endpoint's availability with a form POST request.
/// Values are defined in the `HttpOptions` struct.
/// Prints a success message if the status code is equal to the `ok` value,
/// or failure details when the status code is equaly to the `bad` value or
/// any other value/error.
fn check_custom(&self, options: &HttpOptions) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
@ -111,29 +103,23 @@ impl HttpResource {
}
}
/**
Provides a deserialize target for TCP checks
*/
/// Provides a deserialize target for TCP checks
#[derive(Deserialize, Debug)]
struct TcpResource {
desc: String,
addr: String,
}
/**
Provides a deserialize target for TOML configuration files
defining multiple `TcpResource` or `HttpResource` entities
*/
/// Provides a deserialize target for TOML configuration files
/// defining multiple `TcpResource` or `HttpResource` entities
#[derive(Debug, Deserialize)]
struct NetworkResources {
http: Option<Vec<HttpResource>>,
tcp: Option<Vec<TcpResource>>,
}
/**
Defines common behavior between `TcpResource` and `HttpResource`
structs
*/
/// Defines common behavior between `TcpResource` and `HttpResource`
/// structs
trait Checker {
/// Execute the connection check
fn check(&self) -> Result<(), Box<dyn std::error::Error>>;
@ -168,35 +154,39 @@ impl Checker for TcpResource {
}
impl NetworkResources {
/**
Checks all resources contained by a NetworkResources struct.
Any error messages will be printed to the console.
*/
fn check_resources(&self) {
NetworkResources::check_vec(&self.tcp);
NetworkResources::check_vec(&self.http);
/// Checks all resources contained by a NetworkResources struct.
/// Any error messages will be printed to the console.
fn check_resources(self) {
NetworkResources::check_tcp(self.tcp);
NetworkResources::check_http(self.http);
}
/**
Loops through all items present in a NetworkResources element.
*/
fn check_vec<T: Checker> (v: &Option<Vec<T>>) {
/// Loops through all items present in a NetworkResources.tcp element.
fn check_tcp(v: Option<Vec<TcpResource>>) {
if let Some(v) = v {
for element in v.iter() {
match element.check() {
v.par_iter()
.for_each(|el| match el.check() {
Ok(_) => (),
Err(e) => println!("Failed to connect to {} with:\n\t{:?}", element.description(), e)
}
}
Err(e) => println!("Failed to connect to {} with:\n\t{:?}", el.description(), e)
});
}
}
/// Loops through all items present in a NetworkResources.http element.
fn check_http(v: Option<Vec<HttpResource>>) {
if let Some(v) = v {
v.par_iter()
.for_each(|el| match el.check() {
Ok(_) => (),
Err(e) => println!("Failed to connect to {} with:\n\t{:?}", el.description(), e)
});
}
}
}
/**
Main entrypoint for connection validation. Once the TOML configuration
file has been deserialized all nested `TcpResource` and `HttpResource`
targets are checked.
*/
/// Main entrypoint for connection validation. Once the TOML configuration
/// file has been deserialized all nested `TcpResource` and `HttpResource`
/// targets are checked.
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {

Loading…
Cancel
Save