librespot/core/src/proxytunnel.rs

56 lines
1.8 KiB
Rust
Raw Normal View History

2021-02-10 21:50:08 +00:00
use std::io;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
2021-01-21 20:49:39 +00:00
2021-03-17 20:24:28 +00:00
pub async fn proxy_connect<T: AsyncRead + AsyncWrite + Unpin>(
mut proxy_connection: T,
connect_host: &str,
2021-03-17 20:24:28 +00:00
connect_port: &str,
2021-01-21 20:49:39 +00:00
) -> io::Result<T> {
let mut buffer = Vec::new();
buffer.extend_from_slice(b"CONNECT ");
buffer.extend_from_slice(connect_host.as_bytes());
buffer.push(b':');
2021-03-17 20:24:28 +00:00
buffer.extend_from_slice(connect_port.as_bytes());
buffer.extend_from_slice(b" HTTP/1.1\r\n\r\n");
proxy_connection.write_all(buffer.as_ref()).await?;
2021-01-30 13:03:34 +00:00
buffer.resize(buffer.capacity(), 0);
let mut offset = 0;
loop {
let bytes_read = proxy_connection.read(&mut buffer[offset..]).await?;
2021-01-30 13:03:34 +00:00
if bytes_read == 0 {
return Err(io::Error::new(io::ErrorKind::Other, "Early EOF from proxy"));
}
offset += bytes_read;
2021-01-30 13:03:34 +00:00
let mut headers = [httparse::EMPTY_HEADER; 16];
let mut response = httparse::Response::new(&mut headers);
2021-01-30 13:03:34 +00:00
let status = response
.parse(&buffer[..offset])
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
if status.is_complete() {
return match response.code {
Some(200) => Ok(proxy_connection), // Proxy says all is well
2021-01-30 13:03:34 +00:00
Some(code) => {
let reason = response.reason.unwrap_or("no reason");
let msg = format!("Proxy responded with {code}: {reason}");
2021-01-30 13:03:34 +00:00
Err(io::Error::new(io::ErrorKind::Other, msg))
}
None => Err(io::Error::new(
io::ErrorKind::Other,
"Malformed response from proxy",
)),
};
}
2021-01-30 13:03:34 +00:00
if offset >= buffer.len() {
2021-03-17 20:24:28 +00:00
buffer.resize(buffer.len() + 100, 0);
2021-02-10 21:50:08 +00:00
}
}
}