9944ae18921cfd3991c11231eb4aaa4e23f1505a
5 time
::{self, Duration
},
10 message
::header
::ContentType
, transport
::smtp
::authentication
::Credentials
, Message
,
11 SmtpTransport
, Transport
,
13 use rand
::{rngs
::ThreadRng
, Rng
};
15 use crate::config
::Config
;
19 const FILE_CONF
: &str = "config.ron";
20 const PING_PERIOD
: Duration
= Duration
::from_secs(5); // 5 s.
21 const EMAIL_RESEND_PERIOD
: Duration
= Duration
::from_secs(2 * 60 * 60); // 2 h.
22 const STATE_PRINT_PERIOD
: Duration
= Duration
::from_secs(15 * 60); // 15 min.
23 const SOCKET_TIMEOUT
: Duration
= Duration
::from_secs(7);
25 fn main() -> Result
<()> {
26 println!("Staking Watchdog Watchdog");
28 let config
= Config
::read(FILE_CONF
)?
;
31 "Configuration: {:?}",
33 smtp_password
: "*****".to_string(),
38 let mut time_last_email_send
= time
::Instant
::now() - EMAIL_RESEND_PERIOD
;
39 let mut time_last_state_printed
= time
::Instant
::now() - STATE_PRINT_PERIOD
;
40 let mut error_state
= false;
42 let mut rng
= rand
::thread_rng();
44 let mut number_of_pings
= 0;
45 let mut total_ping_duration
= Duration
::default();
47 let socket
= UdpSocket
::bind("0.0.0.0:0").unwrap();
48 socket
.connect("192.168.2.102:8739").unwrap();
49 socket
.set_nonblocking(false).unwrap();
50 socket
.set_read_timeout(Some(SOCKET_TIMEOUT
)).unwrap();
51 socket
.set_write_timeout(Some(SOCKET_TIMEOUT
)).unwrap();
54 let time_beginning_loop
= time
::Instant
::now();
56 match ping(&socket
, &mut rng
) {
58 total_ping_duration
+= t
;
63 println!("End of erroneous state");
66 if time
::Instant
::now() - time_last_state_printed
>= STATE_PRINT_PERIOD
{
68 "No error detected. Mean of ping time: {} μs",
69 total_ping_duration
.as_micros() / number_of_pings
71 total_ping_duration
= Duration
::default();
73 time_last_state_printed
= time
::Instant
::now();
78 println!("Error: {:?}", error
);
79 if time
::Instant
::now() - time_last_email_send
>= EMAIL_RESEND_PERIOD
{
81 println!("Sending email...");
83 "Watchdog Watchdog: Check alive error",
84 &format!("Error: {}", error
),
85 &config
.smtp_relay_address
,
87 &config
.smtp_password
,
89 Err(email_error
) => println!("Error sending email: {:?}", email_error
),
91 println!("Email successfully sent");
92 time_last_email_send
= time
::Instant
::now();
99 let elapsed
= time
::Instant
::now() - time_beginning_loop
;
101 if elapsed
< PING_PERIOD
{
102 let to_wait
= PING_PERIOD
- elapsed
;
103 thread
::sleep(to_wait
);
110 SocketReceiveError(std
::io
::Error
),
111 SocketSendError(std
::io
::Error
),
112 WrongMessageReceived(String
),
115 impl fmt
::Display
for PingError
{
116 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
118 PingError
::SocketReceiveError(error
) => {
119 write!(f
, "Didn't receive any response from watchdog: {}", error
)
121 PingError
::SocketSendError(error
) => {
122 write!(f
, "Unable to send the message: {}", error
)
124 PingError
::WrongMessageReceived(message
) => {
125 write!(f
, "Watchdog replay with a wrong message: {}", message
)
131 fn ping(socket
: &UdpSocket
, rng
: &mut ThreadRng
) -> std
::result
::Result
<Duration
, PingError
> {
133 let number
: u64 = rng
.gen();
134 let mut buffer
= number
.to_le_bytes();
135 let now
= time
::Instant
::now();
136 match socket
.send(&buffer
) {
139 match socket
.recv(&mut buffer
) {
140 Ok(size_received
) => {
141 if size_received
== 8 {
142 let number_received
= u64::from_le_bytes(buffer
);
143 if number_received
== number
{
144 return Ok(time
::Instant
::now() - now
);
146 return Err(PingError
::WrongMessageReceived(format!(
147 "Message number receceived ({}) is not equal to the one sent ({})",
148 number_received
, number
152 return Err(PingError
::WrongMessageReceived(format!(
153 "Size of packet must be 8, received size: {}",
159 // Test the kind because sometime 'recv' returns
160 // '(Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }'.
161 // Try again in this case.
162 Err(error
) if error
.kind() == std
::io
::ErrorKind
::WouldBlock
=> {
163 println!("WouldBlock error: {}", error
)
165 Err(error
) => return Err(PingError
::SocketReceiveError(error
)),
168 Err(error
) => return Err(PingError
::SocketSendError(error
)),
176 smtp_relay_address
: &str,
180 let email
= Message
::builder()
182 .from("Staking Watchdog Watchdog <redmine@d-lan.net>".parse()?
)
183 .to("Greg Burri <greg.burri@gmail.com>".parse()?
)
185 .header(ContentType
::TEXT_PLAIN
)
186 .body(body
.to_string())?
;
188 let creds
= Credentials
::new(login
.to_string(), pass
.to_string());
190 let mailer
= SmtpTransport
::relay(smtp_relay_address
)?
194 let response
= mailer
.send(&email
)?
;
196 println!("{:?}", response
);