aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2022-02-21 13:45:41 +0100
committerAlex Auvolat <alex@adnab.me>2022-02-21 13:45:41 +0100
commit96a3cc1e1f5c0c4e73ad1036a7e0add19d9a197e (patch)
tree3903e11ac310ec441db2360b6951b35c63617974
parent5bf3886fa28812d7009fb3bb481f0d3ce3004e18 (diff)
downloadnetapp-96a3cc1e1f5c0c4e73ad1036a7e0add19d9a197e.tar.gz
netapp-96a3cc1e1f5c0c4e73ad1036a7e0add19d9a197e.zip
Implement version check & transmit more error info
-rw-r--r--src/client.rs3
-rw-r--r--src/error.rs10
-rw-r--r--src/proto.rs22
-rw-r--r--src/server.rs4
4 files changed, 33 insertions, 6 deletions
diff --git a/src/client.rs b/src/client.rs
index 62f876b..e84c85e 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -206,7 +206,8 @@ impl ClientConn {
<T as Message>::Response,
>(&resp[1..])?)
} else {
- Err(Error::Remote(format!("Remote error code {}", code)))
+ let msg = String::from_utf8(resp[1..].to_vec()).unwrap_or_default();
+ Err(Error::Remote(code, msg))
}
}
}
diff --git a/src/error.rs b/src/error.rs
index 0ed30a5..99acdd1 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -34,8 +34,11 @@ pub enum Error {
#[error(display = "Connection closed")]
ConnectionClosed,
- #[error(display = "Remote error: {}", _0)]
- Remote(String),
+ #[error(display = "Version mismatch: {}", _0)]
+ VersionMismatch(String),
+
+ #[error(display = "Remote error {}: {}", _0, _1)]
+ Remote(u8, String),
}
impl Error {
@@ -50,7 +53,8 @@ impl Error {
Self::NoHandler => 20,
Self::ConnectionClosed => 21,
Self::Handshake(_) => 30,
- Self::Remote(_) => 40,
+ Self::VersionMismatch(_) => 31,
+ Self::Remote(c, _) => *c,
Self::Message(_) => 99,
}
}
diff --git a/src/proto.rs b/src/proto.rs
index 2db3f83..146211b 100644
--- a/src/proto.rs
+++ b/src/proto.rs
@@ -1,7 +1,7 @@
use std::collections::{HashMap, VecDeque};
use std::sync::Arc;
-use log::trace;
+use log::{error, trace};
use futures::{AsyncReadExt, AsyncWriteExt};
use kuska_handshake::async_std::BoxStreamWrite;
@@ -12,6 +12,10 @@ use async_trait::async_trait;
use crate::error::*;
+/// Tag which is exchanged between client and server upon connection establishment
+/// to check that they are running compatible versions of Netapp
+pub const VERSION_TAG: [u8; 8] = [b'n', b'e', b't', b'a', b'p', b'p', 0x00, 0x04];
+
/// Priority of a request (click to read more about priorities).
///
/// This priority value is used to priorize messages
@@ -114,6 +118,10 @@ pub(crate) trait SendLoop: Sync {
where
W: AsyncWriteExt + Unpin + Send + Sync,
{
+ // Before anything, send version tag, which is checked in recv_loop
+ write.write_all(&VERSION_TAG[..]).await?;
+ write.flush().await?;
+
let mut sending = SendQueue::new();
let mut should_exit = false;
while !should_exit || !sending.is_empty() {
@@ -169,6 +177,7 @@ pub(crate) trait SendLoop: Sync {
}
}
}
+
let _ = write.goodbye().await;
Ok(())
}
@@ -189,6 +198,17 @@ pub(crate) trait RecvLoop: Sync + 'static {
where
R: AsyncReadExt + Unpin + Send + Sync,
{
+ let mut their_version_tag = [0u8; 8];
+ read.read_exact(&mut their_version_tag[..]).await?;
+ if their_version_tag != VERSION_TAG {
+ let msg = format!(
+ "Different netapp versions: {:?} (theirs) vs. {:?} (ours)",
+ their_version_tag, VERSION_TAG
+ );
+ error!("{}", msg);
+ return Err(Error::VersionMismatch(msg));
+ }
+
let mut receiving = HashMap::new();
loop {
trace!("recv_loop: reading packet");
diff --git a/src/server.rs b/src/server.rs
index eb70057..31f6ad6 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -184,7 +184,9 @@ impl RecvLoop for ServerConn {
resp_bytes
}
Err(e) => {
- vec![e.code()]
+ let mut resp_bytes = vec![e.code()];
+ resp_bytes.extend(e.to_string().into_bytes());
+ resp_bytes
}
};