Check the alive UDP socket
authorGreg Burri <greg.burri@gmail.com>
Mon, 2 Oct 2023 21:21:09 +0000 (23:21 +0200)
committerGreg Burri <greg.burri@gmail.com>
Mon, 2 Oct 2023 21:21:09 +0000 (23:21 +0200)
and send an email if there is an error.

src/main.rs

index 84dd95c..49668d0 100644 (file)
@@ -3,6 +3,8 @@
  */
 
 use std::{
+    net::UdpSocket,
+    sync::{Arc, Mutex},
     thread,
     time::{self, Duration},
 };
@@ -17,11 +19,11 @@ use serde::Deserialize;
 use crate::config::Config;
 
 mod config;
-// mod error;
 
 const FILE_CONF: &str = "config.ron";
 const CHECK_PERIOD: Duration = Duration::from_secs(10); // 10 s.
-const EMAIL_RESEND_PERIOD: Duration = Duration::from_secs(6 * 60 * 60); // 6 h.
+const PING_TIMEOUT: Duration = Duration::from_secs(10); // 10 s.
+const EMAIL_RESEND_PERIOD: Duration = Duration::from_secs(2 * 60 * 60); // 2 h.
 const STATE_PRINT_PERIOD: Duration = Duration::from_secs(15 * 60); // 15 min.
 const BASE_URI: &str = "http://localhost:5052/eth/v1/";
 
@@ -38,6 +40,8 @@ fn main() -> Result<()> {
         }
     );
 
+    let check_alive_error_mutex = start_check_alive_thread();
+
     let mut time_last_email_send = time::Instant::now() - EMAIL_RESEND_PERIOD;
     let mut time_last_state_printed = time::Instant::now() - STATE_PRINT_PERIOD;
     let mut error_state = false;
@@ -45,7 +49,10 @@ fn main() -> Result<()> {
     loop {
         let time_beginning_loop = time::Instant::now();
 
-        if let Err(error) = check_validators(&config.pub_keys) {
+        if let Err(error) = check_validators(&config.pub_keys)
+            .as_ref()
+            .and(check_alive_error_mutex.lock().unwrap().as_ref())
+        {
             error_state = true;
             println!("Error: {:?}", error);
             if time::Instant::now() - time_last_email_send >= EMAIL_RESEND_PERIOD {
@@ -95,6 +102,7 @@ enum CheckError {
     ReqwestError(reqwest::Error),
     ValidatorError { pub_key: String, message: String },
     ValidatorStatusError { pub_key: String, message: String },
+    CheckAlive,
 }
 
 impl From<reqwest::Error> for CheckError {
@@ -207,3 +215,36 @@ fn send_email(title: &str, body: &str, login: &str, pass: &str) -> Result<()> {
 
     Ok(())
 }
+
+fn start_check_alive_thread() -> Arc<Mutex<std::result::Result<(), CheckError>>> {
+    let check_alive_error_mutex: Arc<Mutex<std::result::Result<(), CheckError>>> =
+        Arc::new(Mutex::new(Ok(())));
+    let check_alive_error_mutex_copy = check_alive_error_mutex.clone();
+
+    let _thread_check_alive_handle = thread::spawn(move || {
+        let socket = UdpSocket::bind("0.0.0.0:8739").unwrap();
+        socket.set_read_timeout(Some(PING_TIMEOUT)).unwrap();
+
+        let mut buffer = [0u8; 8];
+
+        loop {
+            match socket.recv_from(&mut buffer) {
+                Ok((size, src)) => {
+                    let mut check_alive_error = check_alive_error_mutex.lock().unwrap();
+                    if size == 8 {
+                        *check_alive_error = Ok(());
+                        socket.send_to(&buffer, &src).unwrap();
+                    } else {
+                        *check_alive_error = Err(CheckError::CheckAlive);
+                    }
+                }
+                Err(_error) => {
+                    let mut check_alive_error = check_alive_error_mutex.lock().unwrap();
+                    *check_alive_error = Err(CheckError::CheckAlive);
+                }
+            }
+        }
+    });
+
+    check_alive_error_mutex_copy
+}