diff options
| author | Namilskyy <alive6863@gmail.com> | 2025-11-26 22:07:47 +0300 |
|---|---|---|
| committer | Namilskyy <alive6863@gmail.com> | 2025-11-26 22:07:47 +0300 |
| commit | cfb0e5909b379c92411d5373758c7ba9c6b04357 (patch) | |
| tree | 4e1cb3057865cfb9e79e26134d2aa70518f22598 | |
| parent | 691aadb4c28a93be7bfb7d87b245702795cfd4ca (diff) | |
Refactor i2p/fetch() function
| -rw-r--r-- | src/i2impl/mi2p.rs | 76 |
1 files changed, 66 insertions, 10 deletions
diff --git a/src/i2impl/mi2p.rs b/src/i2impl/mi2p.rs index e0bbe3d..6d095f9 100644 --- a/src/i2impl/mi2p.rs +++ b/src/i2impl/mi2p.rs @@ -2,15 +2,18 @@ use crate::cfg::config::Config; use tokio; - use emissary_core::runtime::{ AsyncRead, AsyncWrite, }; -use std::io; -use emissary_core::Profile; -use emissary_core::i2np::Message; -use tokio::io::AsyncWriteExt; + +use std::{io, + fs::File, + path::Path, + io::Write}; +// use emissary_core::Profile; +// use emissary_core::i2np::Message; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; use yosemite::SessionOptions; use yosemite::{Session, style::Stream}; /* @@ -70,25 +73,30 @@ impl<S> I2P<S> { /// /// Returns an error if the repository URL is invalid or if the request fails. /// - async fn fetch(&mut self) -> Result<bool, std::io::Error> { + async fn fetch_index(&mut self) -> Result<bool, std::io::Error> { let repo_url_str = &self.config.repo.repo_url; + let cache_dir = &self.config.paths.cache_dir; let repo_pos = repo_url_str.find("/repo").ok_or_else(|| { io::Error::new(io::ErrorKind::InvalidData, "URL does not contain '/repo'") })?; + // BaseURL let base_url = &repo_url_str[..repo_pos]; + // Url after /repo let path_suffix = &repo_url_str[repo_pos + "/repo".len()..]; + // HTTP path let request_path = format!("/repo{}{}", path_suffix, if path_suffix.ends_with(".tar.gz") { "" } else { "/INDEX.tar.gz" }); - let opts = SessionOptions::default(); + let mut opts = SessionOptions::default(); + // FIXME: Make sure, opts setted to I2P // opts.set_host("127.0.0.1"); - // opts.set_port(7656); + // opts.set_port(7656); let mut session = Session::<Stream>::new(opts).await.map_err(|e| { io::Error::new(io::ErrorKind::Other, format!("Failed to create session: {}", e)) })?; let mut stream = session.connect(base_url).await.map_err(|e| { - io::Error::new(io::ErrorKind::ConnectionReset, format!("Failed to connect: {}", e)) + io::Error::new(io::ErrorKind::ConnectionAborted, format!("Failed to connect: {}", e)) })?; let request = format!("GET {} HTTP/1.1\r\nHost: {}\r\n\r\n", request_path, base_url); @@ -96,6 +104,54 @@ impl<S> I2P<S> { io::Error::new(io::ErrorKind::Other, format!("Failed to write request: {}", e)) })?; + let mut response_buffer = Vec::new(); + let mut chunk = [0u8; 1024]; + + loop { + // FIXME: Check docs and make suro stream allows to AsyncReadExt + let bytes_read = stream.read(&mut chunk).await.map_err(|e| { + io::Error::new(io::ErrorKind::Other, format!("Failed to read response: {}", e)) + })?; + + if bytes_read == 0 { + break; + } + + response_buffer.extend_from_slice(&chunk[..bytes_read]); + + if let Some(headers_end) = Self::find_double_crlf(&response_buffer) { + let body_start = headers_end + 4; + let headers_str = std::str::from_utf8(&response_buffer[..headers_end]) + .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid header encoding"))?; + + if !headers_str.starts_with("HTTP/1.1 200") && !headers_str.starts_with("HTTP/1.0 200") { + return Err(io::Error::new(io::ErrorKind::Other, format!("HTTP Error: {}", headers_str.lines().next().unwrap_or("Unknown")))); + } + + let file_path = Path::new(cache_dir).join("INDEX.tar.gz"); + let mut file = File::create(&file_path)?; + file.write_all(&response_buffer[body_start..])?; + while let Ok(bytes_read) = stream.read(&mut chunk).await { + if bytes_read == 0 { + break; + } + file.write_all(&chunk[..bytes_read])?; + } + + file.flush()?; + break; + } + } + Ok(true) -} + } + + fn find_double_crlf(buf: &[u8]) -> Option<usize> { + for i in 0..buf.len().saturating_sub(3) { + if buf[i] == b'\r' && buf[i+1] == b'\n' && buf[i+2] == b'\r' && buf[i+3] == b'\n' { + return Some(i); + } + } + None + } }
\ No newline at end of file |
