pub struct FtpReceiver { /* private fields */ }
Expand description
“Passive” side of FTP protocol, which mean that receiver expects some data from remote server. As soon as it receives enough data it can “advance” to transmitter state, i.e. fill buffer with commands to be further sent to the remote server.
Implementations§
Source§impl FtpReceiver
impl FtpReceiver
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
examples/ftp-get.rs (line 66)
35fn main() {
36 let url = env::args().nth(1).unwrap();
37 println!("url: {}", url);
38 let ftp_url = Url::parse(&url).unwrap();
39 assert!(ftp_url.scheme() == "ftp");
40
41 let mut username = ftp_url.username();
42 if username == "" { username = "anonymous" };
43
44 let password = match ftp_url.password() {
45 Some(value) => value,
46 None => "unspecified",
47 };
48
49 assert!(ftp_url.path() != "");
50
51 let host = ftp_url.host().unwrap();
52 let port:u16 = ftp_url.port().or(Some(21)).unwrap();
53 let filename = ftp_url.path_segments().unwrap().last().unwrap();
54 let remote_path = ftp_url.path_segments().unwrap()
55 .take_while(|part| part.to_string() != filename.to_string())
56 .fold(String::new(), |mut acc, part| { acc.push_str("/"); acc.push_str(part); acc } );
57
58 println!("start dowloading {} at {}...", filename, remote_path);
59
60 let mut tx_buff:[u8; 1024] = [0; 1024];
61 let mut tx_count = 0;
62 let mut rx_buff:[u8; 1024] = [0; 1024];
63
64 let host_port = format!("{}:{}", host, port);
65 let mut stream = TcpStream::connect(host_port.as_str()).unwrap();
66 let mut ftp_receiver = FtpReceiver::new();
67
68 let mut transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
69 println!("connected to {}:{}", host, port);
70
71 ftp_receiver = transmitter.send_login(&mut tx_buff, &mut tx_count, username);
72 let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
73 println!("login sent...");
74
75 transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
76 println!("expecting password...");
77
78 ftp_receiver = transmitter.send_password(&mut tx_buff, &mut tx_count, password);
79 let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
80 println!("password sent...");
81
82 transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
83 println!("logged in...");
84
85 ftp_receiver = transmitter.send_system_req(&mut tx_buff, &mut tx_count);
86 let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
87 transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
88 {
89 let (system, subtype) = transmitter.get_system().clone();
90 println!("remote system {} / {}", system, subtype);
91 }
92
93 ftp_receiver = transmitter.send_cwd_req(&mut tx_buff, &mut tx_count, &remote_path);
94 let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
95 transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
96 println!("cwd to {}", remote_path);
97
98 ftp_receiver = transmitter.send_pwd_req(&mut tx_buff, &mut tx_count);
99 let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
100 transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
101 println!("changed remote directory is {}", transmitter.get_wd());
102
103 ftp_receiver = transmitter.send_type_req(&mut tx_buff, &mut tx_count, DataMode::Binary);
104 let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
105 transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
106 println!("switched to binary mode");
107
108 let mut data_stream = {
109 ftp_receiver = transmitter.send_pasv_req(&mut tx_buff, &mut tx_count);
110 let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
111 transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
112 let (addr, port) = transmitter.take_endpoint().clone();
113 println!("confirmed passive connection on {}:{}", addr, port);
114 TcpStream::connect((addr, port)).unwrap()
115 };
116 println!("passive connection opened");
117
118 ftp_receiver = transmitter.send_get_req(&mut tx_buff, &mut tx_count, ftp_url.path());
119
120 let _ = stream.write_all(&tx_buff[0 .. tx_count]).unwrap();
121 transmitter = get_reply(&mut stream, &mut rx_buff, ftp_receiver);
122 println!("starting downloading file {}", filename);
123
124 let mut local_file = File::create(filename).unwrap();
125 let mut eof = false;
126 let mut data_in = [0; 40960];
127 while !eof {
128 let count = data_stream.read(&mut data_in).unwrap();
129 // println!("got {} bytes", count);
130 eof = count == 0;
131 if !eof { let _ = local_file.write(&data_in[0 .. count]).unwrap(); };
132 }
133 local_file.flush().unwrap();
134 println!("");
135
136 println!("got file {}", filename);
137 let _ = get_reply(&mut stream, &mut rx_buff, transmitter.to_receiver());
138 println!("Success ... ");
139
140}
Sourcepub fn try_advance(self, buffer: &[u8]) -> Result<FtpTransmitter, Self>
pub fn try_advance(self, buffer: &[u8]) -> Result<FtpTransmitter, Self>
Try to consume Receiver
by parsing buffer and advance into Transmitter
.
In the case of an error, it returns unmodified Receiver
as the error. The
actually happened error can be obtained via take_error
.
In case of success it remembers the last successful state, probably switches
it and returns Transmitter
object.
Examples found in repository?
examples/ftp-get.rs (line 21)
13fn get_reply(stream:&mut TcpStream, rx_buff: &mut [u8], receiver: FtpReceiver) -> FtpTransmitter {
14 let mut opt_transmitter = None;
15 let mut opt_receiver = Some(receiver);
16 let mut total_size = 0;
17 while opt_receiver.is_some() {
18 let sz = stream.read(rx_buff).unwrap();
19 total_size = total_size + sz;
20 let ftp_receiver = opt_receiver.take().unwrap();
21 match ftp_receiver.try_advance(&rx_buff[0 .. total_size]) {
22 Ok(transmitter) => { opt_transmitter = Some(transmitter) }
23 Err(mut receiver) => {
24 match receiver.take_error() {
25 Some(FtpError::NotEnoughData) => { opt_receiver = Some(receiver) }
26 Some(e) => { panic!(format!("Got unexpected error {}", e )) }
27 _ => {panic!("no advance nor error?")}
28 };
29 }
30 }
31 }
32 opt_transmitter.unwrap()
33}
Sourcepub fn take_error(&mut self) -> Option<FtpError>
pub fn take_error(&mut self) -> Option<FtpError>
Returns tha last occurred error, and internally
sets up None
.
Examples found in repository?
examples/ftp-get.rs (line 24)
13fn get_reply(stream:&mut TcpStream, rx_buff: &mut [u8], receiver: FtpReceiver) -> FtpTransmitter {
14 let mut opt_transmitter = None;
15 let mut opt_receiver = Some(receiver);
16 let mut total_size = 0;
17 while opt_receiver.is_some() {
18 let sz = stream.read(rx_buff).unwrap();
19 total_size = total_size + sz;
20 let ftp_receiver = opt_receiver.take().unwrap();
21 match ftp_receiver.try_advance(&rx_buff[0 .. total_size]) {
22 Ok(transmitter) => { opt_transmitter = Some(transmitter) }
23 Err(mut receiver) => {
24 match receiver.take_error() {
25 Some(FtpError::NotEnoughData) => { opt_receiver = Some(receiver) }
26 Some(e) => { panic!(format!("Got unexpected error {}", e )) }
27 _ => {panic!("no advance nor error?")}
28 };
29 }
30 }
31 }
32 opt_transmitter.unwrap()
33}
Sourcepub fn to_transmitter(self) -> FtpTransmitter
pub fn to_transmitter(self) -> FtpTransmitter
Sometimes you need to manually advance to Transmitter
e.g. in case of Authorization Error, you can re-send
other credentials.
Auto Trait Implementations§
impl Freeze for FtpReceiver
impl RefUnwindSafe for FtpReceiver
impl !Send for FtpReceiver
impl !Sync for FtpReceiver
impl Unpin for FtpReceiver
impl UnwindSafe for FtpReceiver
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more