-
Notifications
You must be signed in to change notification settings - Fork 35
/
quit.rs
51 lines (48 loc) · 1.77 KB
/
quit.rs
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
//! The RFC 959 Logout (`QUIT`) command.
//
// This command terminates a USER and if file transfer is not
// in progress, the server closes the control connection. If
// file transfer is in progress, the connection will remain
// open for result response and the server will then close it.
// If the user-process is transferring files for several USERs
// but does not wish to close and then reopen connections for
// each, then the REIN command should be used instead of QUIT.
//
// An unexpected close on the control connection will cause the
// server to take the effective action of an abort (ABOR) and a
// logout (QUIT).
use crate::{
auth::UserDetail,
server::{
chancomms::ControlChanMsg,
controlchan::{
error::ControlChanError,
handler::{CommandContext, CommandHandler},
Reply, ReplyCode,
},
},
storage::{Metadata, StorageBackend},
};
use async_trait::async_trait;
use tokio::sync::mpsc::Sender;
#[derive(Debug)]
pub struct Quit;
#[async_trait]
impl<Storage, User> CommandHandler<Storage, User> for Quit
where
User: UserDetail + 'static,
Storage: StorageBackend<User> + 'static,
Storage::Metadata: Metadata,
{
#[tracing_attributes::instrument]
async fn handle(&self, args: CommandContext<Storage, User>) -> Result<Reply, ControlChanError> {
let tx: Sender<ControlChanMsg> = args.tx_control_chan.clone();
let logger = args.logger;
// Let the control loop know it can exit.
if let Err(send_res) = tx.send(ControlChanMsg::ExitControlLoop).await {
slog::warn!(logger, "could not send internal message: QUIT. {}", send_res);
}
slog::info!(logger, "QUIT: User logged out");
Ok(Reply::new(ReplyCode::ClosingControlConnection, "Bye!"))
}
}