2020-12-24 15:48:50 -05:00
|
|
|
// Copyright 2020 Jeremy Wall
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2021-01-05 20:33:11 -05:00
|
|
|
use std::sync::{Arc, RwLock};
|
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
use crate::util;
|
|
|
|
|
2020-12-24 23:19:05 -05:00
|
|
|
use ekko::{Ekko, EkkoResponse};
|
|
|
|
use gflags;
|
|
|
|
use log::{error, info};
|
|
|
|
use prometheus::{CounterVec, IntGaugeVec};
|
2020-12-24 15:48:50 -05:00
|
|
|
|
2020-12-24 23:19:05 -05:00
|
|
|
gflags::define! {
|
2020-12-24 23:28:30 -05:00
|
|
|
/// The size in bytes of the ping requests.
|
2020-12-24 23:19:05 -05:00
|
|
|
--pingPayload = "durnitisp"
|
|
|
|
}
|
2020-12-24 15:48:50 -05:00
|
|
|
|
|
|
|
gflags::define! {
|
2020-12-24 23:28:30 -05:00
|
|
|
/// The size in bytes of the ping requests.
|
2020-12-24 23:19:05 -05:00
|
|
|
--pingTTL: u32 = 113
|
2020-12-24 15:48:50 -05:00
|
|
|
}
|
|
|
|
|
2020-12-24 23:19:05 -05:00
|
|
|
gflags::define! {
|
2020-12-24 23:28:30 -05:00
|
|
|
/// The size in bytes of the ping requests.
|
2020-12-24 23:19:05 -05:00
|
|
|
--pingTimeout: u64 = 2048
|
|
|
|
}
|
|
|
|
|
|
|
|
gflags::define! {
|
2020-12-24 23:28:30 -05:00
|
|
|
/// The size in bytes of the ping requests.
|
2020-12-24 23:19:05 -05:00
|
|
|
--maxHops: u8 = 50
|
2020-12-24 15:48:50 -05:00
|
|
|
}
|
|
|
|
|
2021-01-05 20:58:11 -05:00
|
|
|
fn resolve_host_address(host: &str) -> String {
|
|
|
|
format!("{}", util::resolve_hosts(&vec![host]).unwrap().first().unwrap().unwrap())
|
|
|
|
}
|
|
|
|
|
2020-12-24 15:48:50 -05:00
|
|
|
pub fn start_echo_loop(
|
|
|
|
domain_name: &str,
|
|
|
|
stop_signal: Arc<RwLock<bool>>,
|
2020-12-24 23:19:05 -05:00
|
|
|
ping_latency_guage: IntGaugeVec,
|
|
|
|
ping_counter: CounterVec,
|
2020-12-24 15:48:50 -05:00
|
|
|
) {
|
2021-01-05 20:58:11 -05:00
|
|
|
let resolved = resolve_host_address(domain_name);
|
2021-01-05 20:33:11 -05:00
|
|
|
info!("Attempting to ping domain {} at address: {}", domain_name, resolved);
|
|
|
|
let mut sender = Ekko::with_target(&resolved).unwrap();
|
2020-12-24 15:48:50 -05:00
|
|
|
loop {
|
|
|
|
{
|
|
|
|
// Limit the scope of this lock
|
|
|
|
if *stop_signal.read().unwrap() {
|
|
|
|
info!("Stopping ping thread for {}", domain_name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-01-05 20:33:11 -05:00
|
|
|
match sender
|
|
|
|
.send_with_timeout(MAXHOPS.flag, Some(Duration::from_millis(PINGTIMEOUT.flag))) {
|
|
|
|
Ok(r) => match r {
|
|
|
|
EkkoResponse::DestinationResponse(r) => {
|
2021-01-05 21:56:51 -05:00
|
|
|
let elapsed = r.elapsed.as_millis();
|
2021-01-05 20:33:11 -05:00
|
|
|
info!(
|
|
|
|
"ICMP: Reply from {}: time={}ms",
|
|
|
|
r.address.unwrap(),
|
2021-01-05 21:56:51 -05:00
|
|
|
elapsed,
|
2021-01-05 20:33:11 -05:00
|
|
|
);
|
|
|
|
ping_counter
|
2021-01-05 21:05:35 -05:00
|
|
|
.with(&prometheus::labels! {"result" => "ok", "domain" => domain_name})
|
2021-01-05 20:33:11 -05:00
|
|
|
.inc();
|
2021-01-05 21:56:51 -05:00
|
|
|
if elapsed != 0 {
|
|
|
|
ping_latency_guage
|
|
|
|
.with(&prometheus::labels! {"domain" => domain_name})
|
|
|
|
.set(r.elapsed.as_millis() as i64);
|
|
|
|
}
|
2021-01-05 20:33:11 -05:00
|
|
|
}
|
|
|
|
EkkoResponse::UnreachableResponse((_, ref _code)) => {
|
|
|
|
// If we got unreachable we need to set up a new sender.
|
|
|
|
error!("{:?}", r);
|
|
|
|
info!("Restarting our sender");
|
|
|
|
ping_counter
|
2021-01-05 21:05:35 -05:00
|
|
|
.with(&prometheus::labels! {"result" => "unreachable", "domain" => domain_name})
|
2021-01-05 20:33:11 -05:00
|
|
|
.inc();
|
2021-01-05 20:58:11 -05:00
|
|
|
let resolved = resolve_host_address(domain_name);
|
2021-01-05 20:33:11 -05:00
|
|
|
let mut new_sender = Ekko::with_target(&resolved).unwrap();
|
|
|
|
std::mem::swap(&mut sender, &mut new_sender);
|
|
|
|
|
|
|
|
}
|
|
|
|
EkkoResponse::ExceededResponse(_) => {
|
|
|
|
ping_counter
|
2021-01-05 21:05:35 -05:00
|
|
|
.with(&prometheus::labels! {"result" => "timeout", "domain" => domain_name})
|
2021-01-05 20:33:11 -05:00
|
|
|
.inc();
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
ping_counter
|
2021-01-05 21:05:35 -05:00
|
|
|
.with(&prometheus::labels! {"result" => "err", "domain" => domain_name})
|
2021-01-05 20:33:11 -05:00
|
|
|
.inc();
|
|
|
|
error!("{:?}", r);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(e) => {
|
|
|
|
ping_counter
|
2021-01-05 21:05:35 -05:00
|
|
|
.with(&prometheus::labels! {"result" => "err", "domain" => domain_name})
|
2021-01-05 20:33:11 -05:00
|
|
|
.inc();
|
2021-01-05 20:37:44 -05:00
|
|
|
error!("Ping send to domain: {} address: {} failed: {:?}, Trying again later", domain_name, &resolved, e);
|
2021-01-05 20:33:11 -05:00
|
|
|
}
|
|
|
|
};
|
2020-12-24 23:19:05 -05:00
|
|
|
std::thread::sleep(Duration::from_secs(3));
|
2020-12-24 15:48:50 -05:00
|
|
|
}
|
|
|
|
}
|