Created
August 16, 2021 09:04
-
-
Save sajattack/801c32e3e9e61c12c28858133e21fb8b to your computer and use it in GitHub Desktop.
psp-tls-downloader
This file contains 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
#![no_std] | |
#![no_main] | |
extern crate alloc; | |
use psp::sys; | |
use drogue_tls::blocking::*; | |
use drogue_network::addr::HostSocketAddr; | |
use drogue_network::dns::Dns; | |
use drogue_network::dns::AddrType; | |
use rand_chacha::ChaCha20Rng; | |
use rand_chacha::rand_core::SeedableRng; | |
psp::module!("tls-weather", 1, 1); | |
mod net; | |
#[no_mangle] | |
fn psp_main() { | |
psp::enable_home_button(); | |
unsafe { | |
load_modules(); | |
init(); | |
psp::sys::sceNetApctlConnect(1); | |
loop { | |
let mut state: psp::sys::ApctlState = core::mem::zeroed(); | |
psp::sys::sceNetApctlGetState(&mut state); | |
if let psp::sys::ApctlState::GotIp = state { | |
break; | |
} | |
psp::sys::sceKernelDelayThread(50_000); | |
} | |
} | |
download_url("https://paulsajna.com/resume.pdf", "ms0:/PSP/GAME/tls-downloader/resume.pdf"); | |
} | |
fn download_url(url: &str, filename: &str) { | |
let (_protocol, rest) = url.split_once("://").unwrap(); | |
let (hostname, path) = rest.split_once("/").unwrap(); | |
let socket = net::Socket::open().expect("failed to open socket"); | |
let dns_resolver = net::DnsResolver::new(); | |
let addr = dns_resolver.gethostbyname(hostname, AddrType::IPv4).expect("dns failed"); | |
socket.connect(HostSocketAddr::new(addr, 443)).unwrap(); | |
let mut seed: u64 = 0; | |
unsafe { | |
sys::sceRtcGetCurrentTick(&mut seed as *mut u64); | |
} | |
let rng = ChaCha20Rng::seed_from_u64(seed); | |
let mut record_buffer = [0u8; 32768]; | |
let tls_context = TlsContext::new(rng, &mut record_buffer).with_server_name(hostname); | |
let mut tls: TlsConnection<ChaCha20Rng, net::Socket, Aes128GcmSha256> = | |
TlsConnection::new(tls_context, socket); | |
tls.open().expect("error establishing TLS connection"); | |
let get_req = alloc::format!("GET /{} HTTP/1.1\r\nHost: {}\r\nUser-Agent: A fucking PSP!\r\n\r\n", path, hostname); | |
tls.write(get_req.as_bytes()).expect("error writing data"); | |
let mut rx_buf = [0u8; 16384]; | |
let sz_read = tls.read(&mut rx_buf).expect("error reading header"); | |
// this code is brittle af | |
let packet1 = unsafe { alloc::string::String::from_utf8_unchecked(rx_buf.to_vec()) }; | |
let header_end = packet1.find("\r\n\r\n").unwrap()+4; | |
let temp = packet1.split_once("Content-Length: ").unwrap(); | |
let content_length_str = temp.1.split_once("\r\n").unwrap().0; | |
let content_length = content_length_str.parse::<usize>().expect("parse content_length error"); | |
psp::dprintln!("file size: {}", content_length); | |
let file_cstr = alloc::string::String::from(filename) + "\0"; | |
let fd = unsafe { sys::sceIoOpen(file_cstr.as_bytes().as_ptr(), sys::IoOpenFlags::CREAT | sys::IoOpenFlags::RD_WR, 0o777) }; | |
unsafe { sys::sceIoWrite(fd, rx_buf[header_end..sz_read].as_ptr() as *const _, sz_read-header_end) }; | |
let mut size_read = sz_read-header_end; | |
psp::dprintln!("read {}/{} bytes", size_read, content_length); | |
while size_read < content_length - rx_buf.len() { | |
let sz = tls.read(&mut rx_buf).expect("error reading data"); | |
unsafe { | |
sys::sceIoWrite(fd, rx_buf.as_ptr() as *const _, sz); | |
} | |
size_read += sz; | |
psp::dprintln!("read {}/{} bytes", size_read, content_length); | |
} | |
let rem = content_length - size_read; | |
let sz = tls.read(&mut rx_buf).expect("error reading remainder"); | |
unsafe { | |
sys::sceIoWrite(fd, rx_buf.as_ptr() as *const _, rem); | |
} | |
size_read += sz; | |
psp::dprintln!("read {}/{} bytes", size_read, content_length); | |
unsafe { sys::sceIoClose(fd) }; | |
} | |
unsafe fn load_modules() { | |
psp::sys::sceUtilityLoadNetModule(psp::sys::NetModule::NetCommon); | |
psp::sys::sceUtilityLoadNetModule(psp::sys::NetModule::NetInet); | |
} | |
unsafe fn init() { | |
psp::sys::sceNetInit(0x20000, 0x20, 0x1000, 0x20, 0x1000); | |
psp::sys::sceNetInetInit(); | |
psp::sys::sceNetResolverInit(); | |
psp::sys::sceNetApctlInit(0x1600, 42); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment