diff options
Diffstat (limited to '')
| -rw-r--r-- | src/version.rs | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/src/version.rs b/src/version.rs index c1dcee5..adc2a8d 100644 --- a/src/version.rs +++ b/src/version.rs | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | //! accepted until the server has answered it. | 5 | //! accepted until the server has answered it. |
| 6 | 6 | ||
| 7 | use std::env; | 7 | use std::env; |
| 8 | use std::time::{SystemTime, UNIX_EPOCH}; | ||
| 8 | 9 | ||
| 9 | /// Version this build reports. The client and the server share it. | 10 | /// Version this build reports. The client and the server share it. |
| 10 | pub const VERSION: &str = env!("CARGO_PKG_VERSION"); | 11 | pub const VERSION: &str = env!("CARGO_PKG_VERSION"); |
| @@ -73,9 +74,9 @@ pub fn is_newer(latest: &str, current: &str) -> bool { | |||
| 73 | } | 74 | } |
| 74 | } | 75 | } |
| 75 | 76 | ||
| 76 | /// The server line that accepts a handshake. | 77 | /// The server line that accepts a handshake. `time` is Unix milliseconds. |
| 77 | pub fn hello_line(version: &str, latest: &str, url: &str) -> String { | 78 | pub fn hello_line(version: &str, latest: &str, url: &str, time: u64) -> String { |
| 78 | format!("HELLO {version} latest={latest} url={url}") | 79 | format!("HELLO {version} latest={latest} url={url} time={time}") |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | #[derive(Debug, Clone, PartialEq, Eq)] | 82 | #[derive(Debug, Clone, PartialEq, Eq)] |
| @@ -83,9 +84,11 @@ pub struct HelloReply { | |||
| 83 | pub version: String, | 84 | pub version: String, |
| 84 | pub latest: String, | 85 | pub latest: String, |
| 85 | pub url: String, | 86 | pub url: String, |
| 87 | /// Server clock at the moment the reply was built, Unix milliseconds. | ||
| 88 | pub time: u64, | ||
| 86 | } | 89 | } |
| 87 | 90 | ||
| 88 | /// Parse `HELLO <version> latest=<version> url=<url>`. | 91 | /// Parse `HELLO <version> latest=<version> url=<url> time=<unix_ms>`. |
| 89 | pub fn parse_hello(line: &str) -> Option<HelloReply> { | 92 | pub fn parse_hello(line: &str) -> Option<HelloReply> { |
| 90 | let rest = line.trim().strip_prefix("HELLO ")?; | 93 | let rest = line.trim().strip_prefix("HELLO ")?; |
| 91 | let mut tokens = rest.split_whitespace(); | 94 | let mut tokens = rest.split_whitespace(); |
| @@ -93,11 +96,14 @@ pub fn parse_hello(line: &str) -> Option<HelloReply> { | |||
| 93 | 96 | ||
| 94 | let mut latest = None; | 97 | let mut latest = None; |
| 95 | let mut url = None; | 98 | let mut url = None; |
| 99 | let mut time = None; | ||
| 96 | for token in tokens { | 100 | for token in tokens { |
| 97 | if let Some(value) = token.strip_prefix("latest=") { | 101 | if let Some(value) = token.strip_prefix("latest=") { |
| 98 | latest = Some(value.to_string()); | 102 | latest = Some(value.to_string()); |
| 99 | } else if let Some(value) = token.strip_prefix("url=") { | 103 | } else if let Some(value) = token.strip_prefix("url=") { |
| 100 | url = Some(value.to_string()); | 104 | url = Some(value.to_string()); |
| 105 | } else if let Some(value) = token.strip_prefix("time=") { | ||
| 106 | time = value.parse().ok(); | ||
| 101 | } | 107 | } |
| 102 | } | 108 | } |
| 103 | 109 | ||
| @@ -105,9 +111,29 @@ pub fn parse_hello(line: &str) -> Option<HelloReply> { | |||
| 105 | version, | 111 | version, |
| 106 | latest: latest?, | 112 | latest: latest?, |
| 107 | url: url?, | 113 | url: url?, |
| 114 | time: time?, | ||
| 108 | }) | 115 | }) |
| 109 | } | 116 | } |
| 110 | 117 | ||
| 118 | /// The reply to `PING`: `PONG <unix_ms>`. | ||
| 119 | pub fn pong_line(time: u64) -> String { | ||
| 120 | format!("PONG {time}") | ||
| 121 | } | ||
| 122 | |||
| 123 | /// Parse a `PONG` reply's server time. | ||
| 124 | pub fn parse_pong(line: &str) -> Option<u64> { | ||
| 125 | line.trim().strip_prefix("PONG ")?.trim().parse().ok() | ||
| 126 | } | ||
| 127 | |||
| 128 | /// Current Unix time in milliseconds. Used for handshake timestamps and crash | ||
| 129 | /// anchors; a system clock before the epoch reads as zero. | ||
| 130 | pub fn unix_time_ms() -> u64 { | ||
| 131 | SystemTime::now() | ||
| 132 | .duration_since(UNIX_EPOCH) | ||
| 133 | .map(|duration| duration.as_millis().min(u128::from(u64::MAX)) as u64) | ||
| 134 | .unwrap_or(0) | ||
| 135 | } | ||
| 136 | |||
| 111 | /// Download page advertised by the server. `DOWNLOAD_URL` wins when set. | 137 | /// Download page advertised by the server. `DOWNLOAD_URL` wins when set. |
| 112 | pub fn download_url() -> String { | 138 | pub fn download_url() -> String { |
| 113 | env::var("DOWNLOAD_URL") | 139 | env::var("DOWNLOAD_URL") |
