-
Notifications
You must be signed in to change notification settings - Fork 240
/
Copy pathmulti-dl.rs
88 lines (75 loc) · 2.61 KB
/
multi-dl.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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use std::collections::HashMap;
use std::time::Duration;
use anyhow::Result;
use curl::easy::{Easy2, Handler, WriteError};
use curl::multi::{Easy2Handle, Multi};
const URLS: &[&str] = &[
"https://www.microsoft.com",
"https://www.google.com",
"https://www.amazon.com",
"https://www.apple.com",
];
struct Collector(Vec<u8>);
impl Handler for Collector {
fn write(&mut self, data: &[u8]) -> Result<usize, WriteError> {
self.0.extend_from_slice(data);
Ok(data.len())
}
}
fn download(multi: &mut Multi, token: usize, url: &str) -> Result<Easy2Handle<Collector>> {
let version = curl::Version::get();
let mut request = Easy2::new(Collector(Vec::new()));
request.url(&url)?;
request.useragent(&format!("curl/{}", version.version()))?;
let mut handle = multi.add2(request)?;
handle.set_token(token)?;
Ok(handle)
}
fn main() -> Result<()> {
let mut multi = Multi::new();
let mut handles = URLS
.iter()
.enumerate()
.map(|(token, url)| Ok((token, download(&mut multi, token, url)?)))
.collect::<Result<HashMap<_, _>>>()?;
let mut still_alive = true;
while still_alive {
// We still need to process the last messages when
// `Multi::perform` returns "0".
if multi.perform()? == 0 {
still_alive = false;
}
multi.messages(|message| {
let token = message.token().expect("failed to get the token");
let handle = handles
.get_mut(&token)
.expect("the download value should exist in the HashMap");
match message
.result_for2(&handle)
.expect("token mismatch with the `EasyHandle`")
{
Ok(()) => {
let http_status = handle
.response_code()
.expect("HTTP request finished without status code");
println!(
"R: Transfer succeeded (Status: {}) {} (Download length: {})",
http_status,
URLS[token],
handle.get_ref().0.len()
);
}
Err(error) => {
println!("E: {} - <{}>", error, URLS[token]);
}
}
});
if still_alive {
// The sleeping time could be reduced to allow other processing.
// For instance, a thread could check a condition signalling the
// thread shutdown.
multi.wait(&mut [], Duration::from_secs(60))?;
}
}
Ok(())
}