russh_sftp/server/
handler.rs

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