Remove two useless comments.
[stakingWatchdogWatchdog.git] / src / main.rs
index 967eb5b..9944ae1 100644 (file)
@@ -1,4 +1,5 @@
 use std::{
+    fmt,
     net::UdpSocket,
     thread,
     time::{self, Duration},
@@ -19,6 +20,7 @@ const FILE_CONF: &str = "config.ron";
 const PING_PERIOD: Duration = Duration::from_secs(5); // 5 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 SOCKET_TIMEOUT: Duration = Duration::from_secs(7);
 
 fn main() -> Result<()> {
     println!("Staking Watchdog Watchdog");
@@ -44,12 +46,9 @@ fn main() -> Result<()> {
 
     let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
     socket.connect("192.168.2.102:8739").unwrap();
-    socket
-        .set_read_timeout(Some(Duration::from_secs(5)))
-        .unwrap();
-    socket
-        .set_write_timeout(Some(Duration::from_secs(5)))
-        .unwrap();
+    socket.set_nonblocking(false).unwrap();
+    socket.set_read_timeout(Some(SOCKET_TIMEOUT)).unwrap();
+    socket.set_write_timeout(Some(SOCKET_TIMEOUT)).unwrap();
 
     loop {
         let time_beginning_loop = time::Instant::now();
@@ -81,8 +80,9 @@ fn main() -> Result<()> {
                     // Send e-mail.
                     println!("Sending email...");
                     match send_email(
-                        "Watchdog ERROR",
-                        &format!("Error: {:?}", error),
+                        "Watchdog Watchdog: Check alive error",
+                        &format!("Error: {}", error),
+                        &config.smtp_relay_address,
                         &config.smtp_login,
                         &config.smtp_password,
                     ) {
@@ -107,48 +107,79 @@ fn main() -> Result<()> {
 
 #[derive(Debug)]
 enum PingError {
-    SocketError(std::io::Error),
+    SocketReceiveError(std::io::Error),
+    SocketSendError(std::io::Error),
     WrongMessageReceived(String),
 }
 
+impl fmt::Display for PingError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            PingError::SocketReceiveError(error) => {
+                write!(f, "Didn't receive any response from watchdog: {}", error)
+            }
+            PingError::SocketSendError(error) => {
+                write!(f, "Unable to send the message: {}", error)
+            }
+            PingError::WrongMessageReceived(message) => {
+                write!(f, "Watchdog replay with a wrong message: {}", message)
+            }
+        }
+    }
+}
+
 fn ping(socket: &UdpSocket, rng: &mut ThreadRng) -> std::result::Result<Duration, PingError> {
-    let number: u64 = rng.gen();
-    let mut buffer = number.to_le_bytes();
-
-    let now = time::Instant::now();
-    match socket.send(&buffer) {
-        Ok(_size_sent) => {
-            buffer.fill(0);
-            match socket.recv(&mut buffer) {
-                Ok(size_received) => {
-                    if size_received == 8 {
-                        let number_received = u64::from_le_bytes(buffer);
-                        if number_received != number {
+    loop {
+        let number: u64 = rng.gen();
+        let mut buffer = number.to_le_bytes();
+        let now = time::Instant::now();
+        match socket.send(&buffer) {
+            Ok(_size_sent) => {
+                buffer.fill(0);
+                match socket.recv(&mut buffer) {
+                    Ok(size_received) => {
+                        if size_received == 8 {
+                            let number_received = u64::from_le_bytes(buffer);
+                            if number_received == number {
+                                return Ok(time::Instant::now() - now);
+                            } else {
+                                return Err(PingError::WrongMessageReceived(format!(
+                                    "Message number receceived ({}) is not equal to the one sent ({})",
+                                    number_received, number
+                                )));
+                            }
+                        } else {
                             return Err(PingError::WrongMessageReceived(format!(
-                                "Message number receceived ({}) is not equal to the one sent ({})",
-                                number_received, number
+                                "Size of packet must be 8, received size: {}",
+                                size_received
                             )));
                         }
-                    } else {
-                        return Err(PingError::WrongMessageReceived(format!(
-                            "Size of packet must be 8, received size: {}",
-                            size_received
-                        )));
                     }
+                    // FIXME.
+                    // Test the kind because sometime 'recv' returns
+                    // '(Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }'.
+                    // Try again in this case.
+                    Err(error) if error.kind() == std::io::ErrorKind::WouldBlock => {
+                        println!("WouldBlock error: {}", error)
+                    }
+                    Err(error) => return Err(PingError::SocketReceiveError(error)),
                 }
-                Err(error) => return Err(PingError::SocketError(error)),
             }
+            Err(error) => return Err(PingError::SocketSendError(error)),
         }
-        Err(error) => return Err(PingError::SocketError(error)),
     }
-
-    Ok(time::Instant::now() - now)
 }
 
-fn send_email(title: &str, body: &str, login: &str, pass: &str) -> Result<()> {
+fn send_email(
+    title: &str,
+    body: &str,
+    smtp_relay_address: &str,
+    login: &str,
+    pass: &str,
+) -> Result<()> {
     let email = Message::builder()
         .message_id(None)
-        .from("Staking Watchdog <redmine@d-lan.net>".parse()?)
+        .from("Staking Watchdog Watchdog <redmine@d-lan.net>".parse()?)
         .to("Greg Burri <greg.burri@gmail.com>".parse()?)
         .subject(title)
         .header(ContentType::TEXT_PLAIN)
@@ -156,12 +187,10 @@ fn send_email(title: &str, body: &str, login: &str, pass: &str) -> Result<()> {
 
     let creds = Credentials::new(login.to_string(), pass.to_string());
 
-    // Open a remote connection to gmail
-    let mailer = SmtpTransport::relay("mail.gandi.net")?
+    let mailer = SmtpTransport::relay(smtp_relay_address)?
         .credentials(creds)
         .build();
 
-    // Send the email
     let response = mailer.send(&email)?;
 
     println!("{:?}", response);