rnp 0.1.146

A simple layer 4 ping tool for cloud.
Documentation
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::net::IpAddr;

#[derive(Debug, Serialize, Deserialize, PartialOrd, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub struct PingResultDto {
    pub utc_time: DateTime<Utc>,
    pub worker_id: u32,
    pub protocol: String,
    pub target_ip: IpAddr,
    pub target_port: u16,
    pub source_ip: IpAddr,
    pub source_port: u16,
    pub is_warmup: bool,
    pub is_succeeded: bool,
    pub rtt_in_ms: f64,
    pub is_timed_out: bool,
    pub preparation_error: String,
    pub ping_error: String,
    pub handshake_error: String,
    pub disconnect_error: String,
}

impl PingResultDto {
    pub fn to_console_log(&self) -> String {
        let warmup_sign = if self.is_warmup { " (warmup)" } else { "" };

        if self.is_timed_out {
            return format!(
                "Reaching {} {}:{} from {}:{}{} failed: Timed out, RTT = {:.2}ms",
                self.protocol, self.target_ip, self.target_port, self.source_ip, self.source_port, warmup_sign, self.rtt_in_ms,
            );
        }

        if !self.preparation_error.is_empty() {
            return format!(
                "Unable to perform ping to {} {}:{} from {}:{}{}, because failed preparing to ping: Error = {}",
                self.protocol, self.target_ip, self.target_port, self.source_ip, self.source_port, warmup_sign, self.preparation_error,
            );
        }

        if !self.ping_error.is_empty() {
            return format!(
                "Reaching {} {}:{} from {}:{}{} failed: {}",
                self.protocol, self.target_ip, self.target_port, self.source_ip, self.source_port, warmup_sign, self.ping_error,
            );
        }

        if !self.handshake_error.is_empty() {
            return format!(
                "Reaching {} {}:{} from {}:{}{} succeeded, but app handshake failed: RTT={:.2}ms, Error = {}",
                self.protocol, self.target_ip, self.target_port, self.source_ip, self.source_port, warmup_sign, self.rtt_in_ms, self.handshake_error,
            );
        }

        if !self.disconnect_error.is_empty() {
            return format!(
                "Reaching {} {}:{} from {}:{}{} succeeded, but disconnect failed: RTT={:.2}ms, Error = {}",
                self.protocol, self.target_ip, self.target_port, self.source_ip, self.source_port, warmup_sign, self.rtt_in_ms, self.disconnect_error,
            );
        }

        return format!(
            "Reaching {} {}:{} from {}:{}{} succeeded: RTT={:.2}ms",
            self.protocol, self.target_ip, self.target_port, self.source_ip, self.source_port, warmup_sign, self.rtt_in_ms,
        );
    }

    pub fn to_json_lite(&self) -> String {
        format!(
            "{{\"UtcTime\":\"{:?}\",\"WorkerId\":{},\"Protocol\":\"{}\",\"TargetIp\":\"{}\",\"TargetPort\":{},\"SourceIp\":\"{}\",\"SourcePort\":{},\"IsWarmup\":{},\"IsSucceeded\":{},\"RttInMs\":{:.2},\"IsTimedOut\":{},\"PreparationError\":\"{}\",\"PingError\":\"{}\",\"HandshakeError\":\"{}\",\"DisconnectError\":\"{}\"}}",
            self.utc_time,
            self.worker_id,
            self.protocol,
            self.target_ip,
            self.target_port,
            self.source_ip,
            self.source_port,
            self.is_warmup,
            self.is_succeeded,
            self.rtt_in_ms,
            self.is_timed_out,
            self.preparation_error,
            self.ping_error,
            self.handshake_error,
            self.disconnect_error,
        )
    }

    pub fn to_csv_lite(&self) -> String {
        format!(
            "{:?},{},{},{},{},{},{},{},{},{:.2},{},\"{}\",\"{}\",\"{}\",\"{}\"",
            self.utc_time,
            self.worker_id,
            self.protocol,
            self.target_ip,
            self.target_port,
            self.source_ip,
            self.source_port,
            self.is_warmup,
            self.is_succeeded,
            self.rtt_in_ms,
            self.is_timed_out,
            self.preparation_error,
            self.ping_error,
            self.handshake_error,
            self.disconnect_error,
        )
    }
}