2
0
mirror of https://github.com/xvxx/phetch synced 2024-11-05 00:00:58 +00:00

enable try tls mode

This commit is contained in:
dvkt 2020-01-06 00:26:05 -08:00
parent 612bbffa28
commit 7148ddd999
3 changed files with 36 additions and 26 deletions

View File

@ -41,15 +41,15 @@ pub const TCP_TIMEOUT_IN_SECS: u64 = 8;
pub const TCP_TIMEOUT_DURATION: Duration = Duration::from_secs(TCP_TIMEOUT_IN_SECS);
/// Fetches a gopher URL and returns a raw Gopher response.
pub fn fetch_url(url: &str) -> Result<String> {
pub fn fetch_url(url: &str, try_tls: bool) -> Result<String> {
let (_, host, port, sel) = parse_url(url);
fetch(host, port, sel)
fetch(host, port, sel, try_tls)
}
/// Fetches a gopher URL by its component parts and returns a raw
/// Gopher response.
pub fn fetch(host: &str, port: &str, selector: &str) -> Result<String> {
let mut stream = request(host, port, selector)?;
pub fn fetch(host: &str, port: &str, selector: &str, try_tls: bool) -> Result<String> {
let mut stream = request(host, port, selector, try_tls)?;
let mut body = String::new();
stream.read_to_string(&mut body)?;
Ok(body)
@ -57,7 +57,7 @@ pub fn fetch(host: &str, port: &str, selector: &str) -> Result<String> {
/// Downloads a binary to disk. Allows canceling with Ctrl-c.
/// Returns the path it was saved to and the size in bytes.
pub fn download_url(url: &str) -> Result<(String, usize)> {
pub fn download_url(url: &str, try_tls: bool) -> Result<(String, usize)> {
let (_, host, port, sel) = parse_url(url);
let filename = sel
.split_terminator('/')
@ -69,7 +69,7 @@ pub fn download_url(url: &str) -> Result<(String, usize)> {
let stdin = termion::async_stdin();
let mut keys = stdin.keys();
let mut stream = request(host, port, sel)?;
let mut stream = request(host, port, sel, try_tls)?;
let mut file = std::fs::OpenOptions::new()
.write(true)
.create(true)
@ -95,21 +95,23 @@ pub fn download_url(url: &str) -> Result<(String, usize)> {
/// Make a Gopher request and return a TcpStream ready to be read()'d.
/// Will attempt a TLS connection first, then retry a regular
/// connection if it fails.
pub fn request(host: &str, port: &str, selector: &str) -> Result<Stream> {
pub fn request(host: &str, port: &str, selector: &str, try_tls: bool) -> Result<Stream> {
let selector = selector.replace('?', "\t"); // search queries
let sock = format!("{}:{}", host, port)
.to_socket_addrs()
.and_then(|mut socks| socks.next().ok_or_else(|| error!("Can't create socket")))?;
// attempt tls connection
if let Ok(connector) = TlsConnector::new() {
let stream = TcpStream::connect_timeout(&sock, TCP_TIMEOUT_DURATION)?;
stream.set_read_timeout(Some(TCP_TIMEOUT_DURATION))?;
if let Ok(mut stream) = connector.connect(host, stream) {
stream.write(format!("{}\r\n", selector).as_ref())?;
return Ok(Stream {
io: Box::new(stream),
});
if try_tls {
if let Ok(connector) = TlsConnector::new() {
let stream = TcpStream::connect_timeout(&sock, TCP_TIMEOUT_DURATION)?;
stream.set_read_timeout(Some(TCP_TIMEOUT_DURATION))?;
if let Ok(mut stream) = connector.connect(host, stream) {
stream.write(format!("{}\r\n", selector).as_ref())?;
return Ok(Stream {
io: Box::new(stream),
});
}
}
}

View File

@ -8,6 +8,7 @@ fn main() {
fn run() -> i32 {
let args: Vec<String> = std::env::args().collect();
let mut url = "gopher://phetch/1/home";
let mut praw = false;
let mut tls = false;
let mut iter = args.iter();
while let Some(arg) = iter.next() {
@ -22,9 +23,7 @@ fn run() -> i32 {
}
"-r" | "--raw" | "-raw" => {
if args.len() > 2 {
let url = args.get(2).unwrap();
print_raw(url);
return 0;
praw = true;
} else {
eprintln!("--raw needs gopher-url");
return 1;
@ -44,7 +43,12 @@ fn run() -> i32 {
}
}
let mut ui = UI::new();
if praw {
print_raw(url, tls);
return 0;
}
let mut ui = UI::new(tls);
if let Err(e) = ui.open(url, url).and_then(|_| ui.run()) {
eprintln!("{}", e);
return 1;
@ -71,8 +75,8 @@ Once you've launched phetch, use `ctrl-h` to view the on-line help."
);
}
fn print_raw(url: &str) {
match gopher::fetch_url(url) {
fn print_raw(url: &str, try_tls: bool) {
match gopher::fetch_url(url, try_tls) {
Ok(response) => println!("{}", response),
Err(e) => {
eprintln!("{}", e);

View File

@ -40,11 +40,12 @@ pub struct UI {
running: bool, // main ui loop running?
pub size: (usize, usize), // cols, rows
status: String, // status message, if any
tls: bool, // tls mode?
out: RefCell<AlternateScreen<RawTerminal<io::Stdout>>>,
}
impl UI {
pub fn new() -> UI {
pub fn new(tls: bool) -> UI {
UI {
views: vec![],
focused: 0,
@ -52,6 +53,7 @@ impl UI {
running: true,
size: (0, 0),
status: String::new(),
tls,
out: RefCell::new(AlternateScreen::from(stdout().into_raw_mode().unwrap())),
}
}
@ -141,8 +143,9 @@ impl UI {
fn download(&mut self, url: &str) -> Result<()> {
let url = url.to_string();
let tls = self.tls;
self.spinner(&format!("Downloading {}", url), move || {
gopher::download_url(&url)
gopher::download_url(&url, tls)
})
.and_then(|res| res)
.and_then(|(path, bytes)| {
@ -166,11 +169,12 @@ impl UI {
thread::spawn(move || history::save(&hname, &hurl));
// request thread
let thread_url = url.to_string();
let try_tls = self.tls;
// don't spin on first ever request
let res = if self.views.is_empty() {
gopher::fetch_url(&thread_url)?
gopher::fetch_url(&thread_url, try_tls)?
} else {
self.spinner("", move || gopher::fetch_url(&thread_url))??
self.spinner("", move || gopher::fetch_url(&thread_url, try_tls))??
};
let (typ, _, _, _) = gopher::parse_url(&url);
match typ {
@ -501,7 +505,7 @@ impl UI {
impl Default for UI {
fn default() -> Self {
UI::new()
UI::new(false)
}
}