1// Gemtide — a Gemini browser
2mod main;
3use net::tls::{Stream, Cert};
4use gemini::{Url, Response, GemErr};
5use crate::tofu::TrustStore;
6
7const MAX_REDIRECTS: u8 = 5;
8
9@export("navigate")
10fn navigate<'cap>(url: &'cap Url, store: &mut TrustStore) -> Result<Page<'cap>, GemErr> !net !io {
11 let mut target = url.clone();
12 for hop in 0..MAX_REDIRECTS {
13 let resp = fetch(&target, store)?;
14 match resp.status {
15 10..=11 => return Ok(Page::Prompt(resp.meta)),
16 20 => return Ok(Page::render(resp.body)),
17 30..=39 => target = target.join(&resp.meta)?,
18 51 => return Ok(Page::lost_astronaut()),
19 _ => return Err(GemErr::Status(resp.status)),
20 }
21 }
22 Err(GemErr::TooManyRedirects)
23}
24
25fn fetch(url: &Url, store: &mut TrustStore) -> Result<Response, GemErr> !net {
26 let mut tls = Stream::connect(url.host(), 1965)?;
27 store.verify(url.host(), tls.peer_cert())?; // TOFU
28 tls.write(format!("{}\r\n", url))?;
29 Response::parse(tls.read_to_end()?)
30}
console — press ▶ Recompile