Created
December 23, 2015 06:48
-
-
Save supr/a5b63f592575d52941f5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::env; | |
use std::process; | |
use std::str; | |
use std::io::{Error, Read}; | |
extern crate hyper; | |
use hyper::client::Client; | |
use hyper::header::UserAgent; | |
use hyper::method::Method; | |
extern crate getopts; | |
use getopts::Options; | |
#[macro_use] | |
extern crate log; | |
extern crate env_logger; | |
extern crate xml; | |
use xml::attribute::OwnedAttribute; | |
use xml::reader::{EventReader, XmlEvent}; | |
type IoError = std::io::Error; | |
type HyperError = hyper::error::Error; | |
type ParseError = xml::reader::Error; | |
const SPEEDTEST_CONFIG:&'static str = "https://www.speedtest.net/speedtest-config.php"; | |
struct Config { | |
client: Vec<OwnedAttribute>, | |
times: Vec<OwnedAttribute>, | |
download: Vec<OwnedAttribute>, | |
upload: Vec<OwnedAttribute> | |
} | |
#[derive(Debug)] | |
enum SpeedtestError { | |
Http(HyperError), | |
Xml(ParseError), | |
} | |
impl From<ParseError> for SpeedtestError { | |
fn from(err: ParseError) -> SpeedtestError { | |
SpeedtestError::Xml(err) | |
} | |
} | |
impl From<HyperError> for SpeedtestError { | |
fn from(err: HyperError) -> SpeedtestError { | |
SpeedtestError::Http(err) | |
} | |
} | |
fn print_usage(program: &str, opts: Options) { | |
let brief = format!("Usage: {} [options]", program); | |
println!("{}", opts.usage(&brief)); | |
} | |
fn find_xml_key<'r>(parser: &mut EventReader<&'r [u8]>, key: &str) -> Result<XmlEvent::StartElement, SpeedtestError> { | |
loop { | |
let evnt = parser.next(); | |
match evnt { | |
Ok(XmlEvent::StartElement { ref name, .. }) if name.local_name == key => { | |
return Ok(evnt.unwrap()); | |
}, | |
Ok(XmlEvent::StartDocument { .. }) | Ok(XmlEvent::StartElement { .. }) | Ok(XmlEvent::EndElement { .. }) | Ok(XmlEvent::EndDocument) | Ok(XmlEvent::ProcessingInstruction { ..}) | Ok(XmlEvent::CData(_)) | Ok(XmlEvent::Comment(_)) | Ok(XmlEvent::Characters(_)) | Ok(XmlEvent::Whitespace(_)) => { | |
continue; | |
}, | |
Err(e) => { | |
return Err(SpeedtestError::from(e)); | |
} | |
} | |
} | |
} | |
fn find_xml_key_attrs<'r>(mut parser: EventReader<&'r [u8]>, key: &str) -> Result<Vec<OwnedAttribute>, SpeedtestError> { | |
match find_xml_key(&mut parser, key) { | |
Ok(XmlEvent::StartElement { name, attributes, .. }) => { return Ok(attributes); }, | |
Err(e) => { return Err(e); } | |
} | |
} | |
fn get_config() -> Result<Config, SpeedtestError> { | |
//Gather config data from speedtest | |
let resp = try!(Client::new().request(Method::Get, SPEEDTEST_CONFIG).header(UserAgent("Mozilla/5.0".to_owned())).send()); | |
info!("code={}; headers={};", resp.status, resp.headers); | |
let mut body = String::new(); | |
resp.read_to_string(&mut body); | |
Ok(Config { | |
client: try!(find_xml_key_attrs(EventReader::from_str(&*body), "client")), | |
times: try!(find_xml_key_attrs(EventReader::from_str(&*body), "times")), | |
download: try!(find_xml_key_attrs(EventReader::from_str(&*body), "download")), | |
upload: try!(find_xml_key_attrs(EventReader::from_str(&*body), "download")) | |
}) | |
} | |
fn main() { | |
env_logger::init().unwrap(); | |
let args: Vec<String> = env::args().collect(); | |
let program = args[0].clone(); | |
let mut opts = Options::new(); | |
opts.optflag("h", "help", "Print this help"); | |
opts.optflag("l", "list", "Display a list of speedtest.net servers sorted by distance"); | |
opts.optopt("s", "server", "Specify a server ID to test against", "SERVER"); | |
opts.optopt("t", "timeout", "HTTP timeout in seconds. Default 10", "TIMEOUT"); | |
let matches = match opts.parse(&args[1..]) { | |
Ok(m) => m, | |
Err(e) => { error!("{}", e.to_string()); process::exit(1); } | |
}; | |
if matches.opt_present("h") { | |
print_usage(&program, opts); | |
process::exit(0); | |
} | |
let timeout: u16 = matches.opt_str("t").unwrap_or("10".to_string()).parse::<u16>().unwrap_or(10u16); | |
let server_id: u16 = matches.opt_str("s").unwrap_or("0".to_string()).parse::<u16>().unwrap_or(0u16); | |
info!("Timeout is {}", timeout); | |
info!("Server ID is {}", server_id); | |
get_config(); | |
} |
Author
supr
commented
Dec 23, 2015
- Causes compiler to crash
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment