Implement version check & transmit more error info

This commit is contained in:
Alex 2022-02-21 13:45:41 +01:00
parent 5bf3886fa2
commit 96a3cc1e1f
Signed by untrusted user: lx
GPG key ID: 0E496D15096376BE
4 changed files with 33 additions and 6 deletions

View file

@ -206,7 +206,8 @@ impl ClientConn {
<T as Message>::Response, <T as Message>::Response,
>(&resp[1..])?) >(&resp[1..])?)
} else { } 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))
} }
} }
} }

View file

@ -34,8 +34,11 @@ pub enum Error {
#[error(display = "Connection closed")] #[error(display = "Connection closed")]
ConnectionClosed, ConnectionClosed,
#[error(display = "Remote error: {}", _0)] #[error(display = "Version mismatch: {}", _0)]
Remote(String), VersionMismatch(String),
#[error(display = "Remote error {}: {}", _0, _1)]
Remote(u8, String),
} }
impl Error { impl Error {
@ -50,7 +53,8 @@ impl Error {
Self::NoHandler => 20, Self::NoHandler => 20,
Self::ConnectionClosed => 21, Self::ConnectionClosed => 21,
Self::Handshake(_) => 30, Self::Handshake(_) => 30,
Self::Remote(_) => 40, Self::VersionMismatch(_) => 31,
Self::Remote(c, _) => *c,
Self::Message(_) => 99, Self::Message(_) => 99,
} }
} }

View file

@ -1,7 +1,7 @@
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use std::sync::Arc; use std::sync::Arc;
use log::trace; use log::{error, trace};
use futures::{AsyncReadExt, AsyncWriteExt}; use futures::{AsyncReadExt, AsyncWriteExt};
use kuska_handshake::async_std::BoxStreamWrite; use kuska_handshake::async_std::BoxStreamWrite;
@ -12,6 +12,10 @@ use async_trait::async_trait;
use crate::error::*; 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). /// Priority of a request (click to read more about priorities).
/// ///
/// This priority value is used to priorize messages /// This priority value is used to priorize messages
@ -114,6 +118,10 @@ pub(crate) trait SendLoop: Sync {
where where
W: AsyncWriteExt + Unpin + Send + Sync, 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 sending = SendQueue::new();
let mut should_exit = false; let mut should_exit = false;
while !should_exit || !sending.is_empty() { while !should_exit || !sending.is_empty() {
@ -169,6 +177,7 @@ pub(crate) trait SendLoop: Sync {
} }
} }
} }
let _ = write.goodbye().await; let _ = write.goodbye().await;
Ok(()) Ok(())
} }
@ -189,6 +198,17 @@ pub(crate) trait RecvLoop: Sync + 'static {
where where
R: AsyncReadExt + Unpin + Send + Sync, 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(); let mut receiving = HashMap::new();
loop { loop {
trace!("recv_loop: reading packet"); trace!("recv_loop: reading packet");

View file

@ -184,7 +184,9 @@ impl RecvLoop for ServerConn {
resp_bytes resp_bytes
} }
Err(e) => { Err(e) => {
vec![e.code()] let mut resp_bytes = vec![e.code()];
resp_bytes.extend(e.to_string().into_bytes());
resp_bytes
} }
}; };