Skip to main content

russh_sftp/server/
handler.rs

1use std::{collections::HashMap, future::Future};
2
3use crate::{
4    protocol::{Attrs, Data, FileAttributes, Handle, Name, OpenFlags, Packet, Status, Version},
5    server::StatusReply,
6};
7
8/// Server handler for each client. This is `async_trait`
9#[cfg_attr(feature = "async-trait", async_trait::async_trait)]
10pub trait Handler: Sized {
11    /// The type must have an `Into<StatusReply>`
12    /// implementation because a response must be sent
13    /// to any request, even if completed by error.
14    type Error: Into<StatusReply> + Send;
15
16    /// Called by the handler when the packet is not implemented
17    fn unimplemented(&self) -> Self::Error;
18
19    /// The default is to send an SSH_FXP_VERSION response with
20    /// the protocol version and ignore any extensions.
21    #[allow(unused_variables)]
22    fn init(
23        &mut self,
24        version: u32,
25        extensions: HashMap<String, String>,
26    ) -> impl Future<Output = Result<Version, Self::Error>> + Send {
27        async { Ok(Version::new()) }
28    }
29
30    /// Called on SSH_FXP_OPEN
31    #[allow(unused_variables)]
32    fn open(
33        &mut self,
34        id: u32,
35        filename: String,
36        pflags: OpenFlags,
37        attrs: FileAttributes,
38    ) -> impl Future<Output = Result<Handle, Self::Error>> + Send {
39        let err = self.unimplemented();
40        async { Err(err) }
41    }
42
43    /// Called on SSH_FXP_CLOSE.
44    /// The status can be returned as Ok or as Err
45    #[allow(unused_variables)]
46    fn close(
47        &mut self,
48        id: u32,
49        handle: String,
50    ) -> impl Future<Output = Result<Status, Self::Error>> + Send {
51        let err = self.unimplemented();
52        async { Err(err) }
53    }
54
55    /// Called on SSH_FXP_READ
56    #[allow(unused_variables)]
57    fn read(
58        &mut self,
59        id: u32,
60        handle: String,
61        offset: u64,
62        len: u32,
63    ) -> impl Future<Output = Result<Data, Self::Error>> + Send {
64        let err = self.unimplemented();
65        async { Err(err) }
66    }
67
68    /// Called on SSH_FXP_WRITE
69    #[allow(unused_variables)]
70    fn write(
71        &mut self,
72        id: u32,
73        handle: String,
74        offset: u64,
75        data: Vec<u8>,
76    ) -> impl Future<Output = Result<Status, Self::Error>> + Send {
77        let err = self.unimplemented();
78        async { Err(err) }
79    }
80
81    /// Called on SSH_FXP_LSTAT
82    #[allow(unused_variables)]
83    fn lstat(
84        &mut self,
85        id: u32,
86        path: String,
87    ) -> impl Future<Output = Result<Attrs, Self::Error>> + Send {
88        let err = self.unimplemented();
89        async { Err(err) }
90    }
91
92    /// Called on SSH_FXP_FSTAT
93    #[allow(unused_variables)]
94    fn fstat(
95        &mut self,
96        id: u32,
97        handle: String,
98    ) -> impl Future<Output = Result<Attrs, Self::Error>> + Send {
99        let err = self.unimplemented();
100        async { Err(err) }
101    }
102
103    /// Called on SSH_FXP_SETSTAT
104    #[allow(unused_variables)]
105    fn setstat(
106        &mut self,
107        id: u32,
108        path: String,
109        attrs: FileAttributes,
110    ) -> impl Future<Output = Result<Status, Self::Error>> + Send {
111        let err = self.unimplemented();
112        async { Err(err) }
113    }
114
115    /// Called on SSH_FXP_FSETSTAT
116    #[allow(unused_variables)]
117    fn fsetstat(
118        &mut self,
119        id: u32,
120        handle: String,
121        attrs: FileAttributes,
122    ) -> impl Future<Output = Result<Status, Self::Error>> + Send {
123        let err = self.unimplemented();
124        async { Err(err) }
125    }
126
127    /// Called on SSH_FXP_OPENDIR
128    #[allow(unused_variables)]
129    fn opendir(
130        &mut self,
131        id: u32,
132        path: String,
133    ) -> impl Future<Output = Result<Handle, Self::Error>> + Send {
134        let err = self.unimplemented();
135        async { Err(err) }
136    }
137
138    /// Called on SSH_FXP_READDIR.
139    /// EOF error should be returned at the end of reading the directory
140    #[allow(unused_variables)]
141    fn readdir(
142        &mut self,
143        id: u32,
144        handle: String,
145    ) -> impl Future<Output = Result<Name, Self::Error>> + Send {
146        let err = self.unimplemented();
147        async { Err(err) }
148    }
149
150    /// Called on SSH_FXP_REMOVE.
151    /// The status can be returned as Ok or as Err
152    #[allow(unused_variables)]
153    fn remove(
154        &mut self,
155        id: u32,
156        filename: String,
157    ) -> impl Future<Output = Result<Status, Self::Error>> + Send {
158        let err = self.unimplemented();
159        async { Err(err) }
160    }
161
162    /// Called on SSH_FXP_MKDIR
163    #[allow(unused_variables)]
164    fn mkdir(
165        &mut self,
166        id: u32,
167        path: String,
168        attrs: FileAttributes,
169    ) -> impl Future<Output = Result<Status, Self::Error>> + Send {
170        let err = self.unimplemented();
171        async { Err(err) }
172    }
173
174    /// Called on SSH_FXP_RMDIR.
175    /// The status can be returned as Ok or as Err
176    #[allow(unused_variables)]
177    fn rmdir(
178        &mut self,
179        id: u32,
180        path: String,
181    ) -> impl Future<Output = Result<Status, Self::Error>> + Send {
182        let err = self.unimplemented();
183        async { Err(err) }
184    }
185
186    /// Called on SSH_FXP_REALPATH.
187    /// Must contain only one name and a dummy attributes
188    #[allow(unused_variables)]
189    fn realpath(
190        &mut self,
191        id: u32,
192        path: String,
193    ) -> impl Future<Output = Result<Name, Self::Error>> + Send {
194        let err = self.unimplemented();
195        async { Err(err) }
196    }
197
198    /// Called on SSH_FXP_STAT
199    #[allow(unused_variables)]
200    fn stat(
201        &mut self,
202        id: u32,
203        path: String,
204    ) -> impl Future<Output = Result<Attrs, Self::Error>> + Send {
205        let err = self.unimplemented();
206        async { Err(err) }
207    }
208
209    /// Called on SSH_FXP_RENAME.
210    /// The status can be returned as Ok or as Err
211    #[allow(unused_variables)]
212    fn rename(
213        &mut self,
214        id: u32,
215        oldpath: String,
216        newpath: String,
217    ) -> impl Future<Output = Result<Status, Self::Error>> + Send {
218        let err = self.unimplemented();
219        async { Err(err) }
220    }
221
222    /// Called on SSH_FXP_READLINK
223    #[allow(unused_variables)]
224    fn readlink(
225        &mut self,
226        id: u32,
227        path: String,
228    ) -> impl Future<Output = Result<Name, Self::Error>> + Send {
229        let err = self.unimplemented();
230        async { Err(err) }
231    }
232
233    /// Called on SSH_FXP_SYMLINK.
234    /// The status can be returned as Ok or as Err
235    #[allow(unused_variables)]
236    fn symlink(
237        &mut self,
238        id: u32,
239        linkpath: String,
240        targetpath: String,
241    ) -> impl Future<Output = Result<Status, Self::Error>> + Send {
242        let err = self.unimplemented();
243        async { Err(err) }
244    }
245
246    /// Called on SSH_FXP_EXTENDED.
247    /// The extension can return any packet, so it's not specific.
248    /// If the server does not recognize the `request' name
249    /// the server must respond with an SSH_FX_OP_UNSUPPORTED error
250    #[allow(unused_variables)]
251    fn extended(
252        &mut self,
253        id: u32,
254        request: String,
255        data: Vec<u8>,
256    ) -> impl Future<Output = Result<Packet, Self::Error>> + Send {
257        let err = self.unimplemented();
258        async { Err(err) }
259    }
260}