1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//! The RFC 959 Transfer Mode (`MODE`) command
//
// The argument is a single Telnet character code specifying
// the data transfer modes described in the Section on
// Transmission Modes.
//
// The following codes are assigned for transfer modes:
//
// S - Stream
// B - Block
// C - Compressed
//
// The default transfer mode is Stream.
use crate::server::commands::Cmd;
use crate::server::error::FTPError;
use crate::server::reply::{Reply, ReplyCode};
use crate::server::CommandArgs;
use crate::storage;
/// The parameter that can be given to the `MODE` command. The `MODE` command is obsolete, and we
/// only support the `Stream` mode. We still have to support the command itself for compatibility
/// reasons, though.
#[derive(Debug, PartialEq, Clone)]
pub enum ModeParam {
/// Data is sent in a continuous stream of bytes.
Stream,
/// Data is sent as a series of blocks preceded by one or more header bytes.
Block,
/// Some round-about way of sending compressed data.
Compressed,
}
pub struct Mode {
params: ModeParam,
}
impl Mode {
pub fn new(params: ModeParam) -> Self {
Mode { params }
}
}
impl<S, U> Cmd<S, U> for Mode
where
U: Send + Sync + 'static,
S: 'static + storage::StorageBackend<U> + Sync + Send,
S::File: tokio_io::AsyncRead + Send,
S::Metadata: storage::Metadata,
{
fn execute(&self, _args: &CommandArgs<S, U>) -> Result<Reply, FTPError> {
match &self.params {
ModeParam::Stream => Ok(Reply::new(ReplyCode::CommandOkay, "Using Stream transfer mode")),
_ => Ok(Reply::new(
ReplyCode::CommandNotImplementedForParameter,
"Only Stream transfer mode is supported",
)),
}
}
}