From d3a9719a7f59602327f8afebe51c49a92d3319b6 Mon Sep 17 00:00:00 2001 From: yuudi Date: Sun, 19 Mar 2023 06:52:48 +0000 Subject: [PATCH] add "-t" option Signed-off-by: yuudi --- .devcontainer/devcontainer.json | 6 + .github/workflows/build.yml | 14 +- Cargo.lock | 261 +++++++++++++++++++++----------- Cargo.toml | 9 +- README.txt | 23 ++- src/main.rs | 115 ++++++++++---- 6 files changed, 297 insertions(+), 131 deletions(-) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..a32b44a --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,6 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node +{ + "name": "tcping", + "image": "mcr.microsoft.com/devcontainers/rust:1" +} \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4080afa..7cdac2e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -on: [ push, pull_request ] +on: [push, pull_request] name: Cross-compile @@ -10,11 +10,9 @@ jobs: fail-fast: false matrix: target: - - x86_64-unknown-linux-gnu - - i686-unknown-linux-gnu - - aarch64-unknown-linux-gnu - - mips-unknown-linux-gnu - - x86_64-pc-windows-gnu + - x86_64-unknown-linux-gnu # linux_x86-64 + - aarch64-unknown-linux-gnu # linux_arm64 + - x86_64-pc-windows-gnu # windows_x86-64 steps: - uses: actions/checkout@v2 @@ -28,11 +26,11 @@ jobs: with: use-cross: true command: build - args: --release --target=${{ matrix.target }} + args: --release --target=${{ matrix.target }} - uses: actions/upload-artifact@v2 with: name: target-${{ matrix.target }} path: | target/${{ matrix.target }}/release/tcping - target/${{ matrix.target }}/release/tcping.exe + target/${{ matrix.target }}/release/tcping.exe \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index efff88a..75013a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,52 +1,45 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] -name = "atty" -version = "0.2.14" +name = "bitflags" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] -name = "autocfg" -version = "1.0.1" +name = "bitflags" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d5dd14596c0e5b954530d0e6f1fd99b89c03e313aa2086e8da4303701a09e1cf" [[package]] -name = "bitflags" -version = "1.2.1" +name = "cc" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "clap" -version = "3.0.0-beta.2" +version = "4.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142" +checksum = "42dfd32784433290c51d92c438bb72ea5063797fc3cc9a21a8c4346bebbb2098" dependencies = [ - "atty", - "bitflags", + "bitflags 2.0.1", "clap_derive", - "indexmap", - "lazy_static", - "os_str_bytes", + "clap_lex", + "is-terminal", + "once_cell", "strsim", "termcolor", - "textwrap", - "unicode-width", - "vec_map", ] [[package]] name = "clap_derive" -version = "3.0.0-beta.2" +version = "4.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1" +checksum = "fddf67631444a3a3e3e5ac51c36a5e01335302de677bd78759eaa90ab1f46644" dependencies = [ "heck", "proc-macro-error", @@ -56,56 +49,93 @@ dependencies = [ ] [[package]] -name = "hashbrown" -version = "0.9.1" +name = "clap_lex" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" +dependencies = [ + "os_str_bytes", +] [[package]] -name = "heck" -version = "0.3.3" +name = "errno" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" dependencies = [ - "unicode-segmentation", + "errno-dragonfly", + "libc", + "winapi", ] [[package]] -name = "hermit-abi" -version = "0.1.18" +name = "errno-dragonfly" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ + "cc", "libc", ] [[package]] -name = "indexmap" -version = "1.6.2" +name = "heck" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "io-lifetimes" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd6da19f25979c7270e70fa95ab371ec3b701cd0eefc47667a09785b3c59155" dependencies = [ - "autocfg", - "hashbrown", + "hermit-abi", + "libc", + "windows-sys", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "is-terminal" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys", +] [[package]] name = "libc" -version = "0.2.96" +version = "0.2.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5600b4e6efc5421841a2138a6b082e07fe12f9aaa12783d50e5d13325b26b4fc" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "os_str_bytes" -version = "2.4.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "proc-macro-error" @@ -133,22 +163,36 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] +[[package]] +name = "rustix" +version = "0.36.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fe885c3a125aa45213b68cc1472a49880cb5923dc23f522ad2791b882228778" +dependencies = [ + "bitflags 1.2.1", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "strsim" version = "0.10.0" @@ -157,18 +201,18 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.72" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] name = "tcping" -version = "0.1.0" +version = "0.1.1" dependencies = [ "clap", ] @@ -183,43 +227,16 @@ dependencies = [ ] [[package]] -name = "textwrap" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "unicode-segmentation" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" - -[[package]] -name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - -[[package]] -name = "unicode-xid" -version = "0.2.2" +name = "unicode-ident" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "winapi" @@ -251,3 +268,69 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" diff --git a/Cargo.toml b/Cargo.toml index c5faab8..1540f3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,14 @@ authors = ["yuudi"] edition = "2018" name = "tcping" -version = "0.1.0" +version = "0.1.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = "3.0.0-beta.2" +clap = { version = "4", features = ["derive"] } + +[profile.release] +strip = true +lto = true +panic = "abort" diff --git a/README.txt b/README.txt index ebc3c11..6698238 100644 --- a/README.txt +++ b/README.txt @@ -4,17 +4,34 @@ tcping usage: tcping [] - tcping - tcping [arguments] arguments: -c, --count + -t, --forever -i, --interval -w, --timeout -4, --ipv4 -6, --ipv6 - \ No newline at end of file + +examples: + + tcping localhost + tcping localhost 80 + tcping localhost:80 + tcping -c 10 localhost + tcping -t localhost + tcping 127.0.0.1 + tcping 127.0.0.1 80 + tcping 127.0.0.1:80 + tcping [::1] + tcping [::1]:80 + tcping ::1 + ~~tcping ::1:80~~ (!won't work) + +build: + + cargo build --release \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 395b270..b09632b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,34 +1,44 @@ -use std::process; use std::error::Error; use std::io::ErrorKind; -use std::net::{SocketAddr, ToSocketAddrs}; use std::net::TcpStream; +use std::net::{SocketAddr, ToSocketAddrs}; +use std::process; use std::thread; use std::time::{Duration, SystemTime}; -use clap::Clap; -use std::convert::TryFrom; +use clap::Parser; -#[derive(Clap)] -#[clap(name = "tcping")] +#[derive(Parser)] +#[command()] struct Args { - #[clap(short = 'n', long, default_value = "4")] - count: u8, + /// Number of pings to send + #[arg(short = 'c', long, default_value = "4")] + count: u32, - #[clap(short, long, default_value = "1")] + /// Ping forever + #[arg(short = 't', long, default_value = "false", conflicts_with = "count")] + forever: bool, + + /// Interval between pings + #[arg(short, long, default_value = "1")] interval: f32, - #[clap(short = 'w', long, default_value = "2")] + /// Timeout for each ping + #[arg(short = 'w', long, default_value = "2")] timeout: f32, - #[clap(short = '4')] + /// Use IPv4 + #[arg(short = '4', conflicts_with = "ipv6")] ipv4: bool, - #[clap(short = '6')] + /// Use IPv6 + #[arg(short = '6')] ipv6: bool, + /// Hostname or IP address hostname: String, - #[clap(default_value = "80")] + /// Port number + #[arg(default_value = "80")] port: String, } @@ -63,6 +73,12 @@ fn main() { } }; let timeout_duration = Duration::from_secs_f32(args.timeout); + if args.forever { + loop { + handle_tcping(&socket, timeout_duration); + thread::sleep(Duration::from_secs_f32(args.interval)); + } + } for i in 0..args.count { handle_tcping(&socket, timeout_duration); if i != (args.count - 1) { @@ -71,30 +87,71 @@ fn main() { } } -fn solve_address(host: &str, port: &str, ip_version: IpAddrKind) -> Result> { - let mut address = host.to_owned(); - if !address.contains(':') { - address.push(':'); - address.push_str(port); +fn solve_address( + host: &str, + port: &str, + ip_version: IpAddrKind, +) -> Result> { + // check if host contains exactly one ":" + let mut colon_count = 0; + for c in host.chars() { + if c == ':' { + colon_count += 1; + if colon_count > 1 { + break; + } + } + } + + let (host_local, port_local) = if colon_count == 1 { + // split host and port + let position = host.find(':').unwrap(); + let h = &host[0..position]; + let p = &host[position + 1..]; + // let mut split = host.split(":"); + // let h = split.next().unwrap(); + // let p = split.next().unwrap(); + (h, p) + } else if host.contains("]:") { + let position = host.rfind(':').unwrap(); + let h = &host[1..position - 1]; // remove '[' and ']' + let p = &host[position + 1..]; + (h, p) + } else if host.len() >= 2 + && host.as_bytes()[0] == b'[' + && host.as_bytes()[host.len() - 1] == b']' + { + let h = &host[1..host.len() - 1]; + (h, port) + } else { + (host, port) }; - // Ok(address.to_socket_addrs()?.next().ok_or_else(Err(""))?) - for address in address.to_socket_addrs()? { - if (ip_version == IpAddrKind::IPv4) && address.is_ipv6() { continue; } - if (ip_version == IpAddrKind::IPv6) && address.is_ipv4() { continue; } - return Ok(address); + + let port_num: u16 = port_local.parse()?; + + for socket in (host_local, port_num).to_socket_addrs()? { + if (ip_version == IpAddrKind::IPv4) && socket.is_ipv6() { + continue; + } + if (ip_version == IpAddrKind::IPv6) && socket.is_ipv4() { + continue; + } + return Ok(socket); } - Err(Box::try_from("cannot resolve hostname").unwrap()) + Err(Box::new(std::io::Error::new( + ErrorKind::Other, + "cannot resolve hostname", + ))) } fn handle_tcping(sockaddr: &SocketAddr, timeout: Duration) { let sys_time = SystemTime::now(); let result = TcpStream::connect_timeout(sockaddr, timeout); - let duration = - SystemTime::now() - .duration_since(sys_time) - .unwrap() - .as_millis(); + let duration = SystemTime::now() + .duration_since(sys_time) + .unwrap() + .as_millis(); match result { Ok(_) => { println!("connected to {} {}ms", sockaddr, duration);