summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
authorNamilskyy <alive6863@gmail.com>2025-11-29 20:26:35 +0300
committerNamilskyy <alive6863@gmail.com>2025-11-29 20:26:35 +0300
commitd10ac4cc08d679e7971296b79c6eafadcdbc78de (patch)
treed12c170704d0632fcdfde809879ec9c477ad8574 /src/net
parent2536cfdb527cd252ed926e3c05313430858a4ca6 (diff)
Big refactors and additions, implemented http package getter and refactored i2p fn
Diffstat (limited to 'src/net')
-rw-r--r--src/net/http_packages.rs92
-rw-r--r--src/net/i2p_package.rs120
-rw-r--r--src/net/i2p_tools.rs0
-rw-r--r--src/net/mod.rs2
4 files changed, 214 insertions, 0 deletions
diff --git a/src/net/http_packages.rs b/src/net/http_packages.rs
new file mode 100644
index 0000000..1e3c6ad
--- /dev/null
+++ b/src/net/http_packages.rs
@@ -0,0 +1,92 @@
+use reqwest;
+use std::fs::File;
+use std::io::Write;
+use std::path::Path;
+use crate::cfg::config::Config;
+
+pub struct HTTPPackage {
+ config: Config,
+}
+
+impl HTTPPackage {
+ /// Creates a new Downloader object with the given configuration.
+ ///
+ /// # Arguments
+ ///
+ /// * `config` - The full mesk
+ ///
+ /// # Returns
+ ///
+ /// A new Downloader object with the given configuration.
+ pub fn new(config: Config) -> Self {
+ Self { config }
+ }
+
+ /// Parse the mesk configuration file and return the Config object.
+ ///
+ /// This function reads the file at `config_path`, parses it and returns the Config object.
+ ///
+ /// # Arguments
+ ///
+ /// * `config_path` - A string representing the path to the mesk configuration file.
+ ///
+ /// # Returns
+ ///
+ /// A new Config object with the parsed configuration. If there's an error while reading or parsing the file, returns an Err containing a Box<dyn std::error::Error>.
+ pub fn parse_config(config_path: &str) -> Result<Config, Box<dyn std::error::Error>> {
+ let config = Config::parse()?;
+ Ok(config)
+ }
+
+
+ /// Downloads the INDEX.tar.gz file from the configured repository
+ /// and stores it in the configured cache directory.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the request fails, if the response status is not successful, or if there's an issue while reading or writing the file.
+ ///
+ pub async fn fetch_index_http(&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 index_url = if repo_url_str.ends_with(".tar.gz") {
+ repo_url_str.clone()
+ } else {
+ format!("{}/INDEX.tar.gz", repo_url_str.trim_end_matches('/'))
+ };
+
+ let client = reqwest::Client::new();
+
+ let response = client
+ .get(&index_url)
+ .send()
+ .await
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Request failed: {}", e)))?;
+
+ if !response.status().is_success() {
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ format!("HTTP Error: {}", response.status()),
+ ));
+ }
+
+ let index_data = response
+ .bytes()
+ .await
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to read response body: {}", e)))?
+ .to_vec();
+
+ let file_path = Path::new(cache_dir).join("INDEX.tar.gz");
+
+ let mut file = File::create(&file_path)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to create file: {}", e)))?;
+ file.write_all(&index_data)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to write file: {}", e)))?;
+ file.flush()
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to flush file: {}", e)))?;
+
+ Ok(true)
+ }
+}
+
diff --git a/src/net/i2p_package.rs b/src/net/i2p_package.rs
new file mode 100644
index 0000000..2776eea
--- /dev/null
+++ b/src/net/i2p_package.rs
@@ -0,0 +1,120 @@
+
+use crate::cfg::config::Config;
+
+use tokio;
+/*
+use emissary_core::runtime::{
+ AsyncRead,
+ AsyncWrite,
+};
+*/
+
+use std::{fs::File,
+ path::Path,
+ io::Write};
+// use emissary_core::Profile;
+// use emissary_core::i2np::Message;
+use tokio::io::{AsyncReadExt,
+ AsyncWriteExt,
+ BufReader};
+
+use yosemite::SessionOptions;
+use yosemite::{Session, style::Stream};
+use url;
+
+pub struct I2PPackage {
+ config: Config,
+
+}
+
+
+impl I2PPackage {
+ /// Creates a new I2P object with the given configuration.
+ ///
+ /// # Returns
+ ///
+ /// A new I2P object with the given configuration. The session is initially set to None and the connected status is set to false.
+ pub fn new(config: Config) -> Self {
+ I2PPackage{
+
+ config: config,
+ }
+ }
+
+
+ /// Downloads the INDEX.tar.gz file from the configured repository
+ /// and stores it in the configured cache directory.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the request fails, if the response status is not successful, or if there's an issue while reading or writing the file.
+ pub 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 url = url::Url::parse(repo_url_str)
+ .map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidInput, "Invalid repo URL"))?;
+
+ let host = url.host_str()
+ .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::InvalidInput, "No host in URL"))?;
+
+ let request_path = url.path();
+ let request_path = if request_path.ends_with(".tar.gz") {
+ request_path.to_string()
+ } else {
+ format!("{}/INDEX.tar.gz", request_path.trim_end_matches('/'))
+ };
+
+ let sam_host = "127.0.0.1";
+ let sam_port = 7656;
+ let session_options = SessionOptions::default();
+ let mut session = Session::new(session_options).await
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to create SAM session: {}", e)))?;
+
+ let mut stream = session.connect(host).await
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::ConnectionAborted, format!("Failed to connect: {}", e)))?;
+
+ let request = format!(
+ "GET {} HTTP/1.1\r\nHost: {}\r\nConnection: close\r\n\r\n",
+ request_path, host
+ );
+
+
+ stream.write_all(request.as_bytes()).await
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to write request: {}", e)))?;
+
+ let mut reader = BufReader::new(stream);
+ let mut response_buffer = Vec::new();
+ reader.read_to_end(&mut response_buffer).await
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to read response: {}", e)))?;
+
+
+ let headers_end = response_buffer
+ .windows(4)
+ .position(|window| window == b"\r\n\r\n")
+ .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid response: no headers end"))?;
+
+ let headers_str = std::str::from_utf8(&response_buffer[..headers_end])
+ .map_err(|_| std::io::Error::new(std::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(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ format!("HTTP Error: {}", headers_str.lines().next().unwrap_or("Unknown")),
+ ));
+ }
+
+ let body_start = headers_end + 4;
+ let file_path = Path::new(cache_dir).join("INDEX.tar.gz");
+
+
+ let mut file = File::create(&file_path)
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to create file: {}", e)))?;
+ file.write_all(&response_buffer[body_start..])
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to write file: {}", e)))?;
+ file.flush()
+ .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to flush file: {}", e)))?;
+
+ Ok(true)
+ }
+}
diff --git a/src/net/i2p_tools.rs b/src/net/i2p_tools.rs
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/net/i2p_tools.rs
diff --git a/src/net/mod.rs b/src/net/mod.rs
new file mode 100644
index 0000000..54f5e7f
--- /dev/null
+++ b/src/net/mod.rs
@@ -0,0 +1,2 @@
+pub mod i2p_package;
+pub mod http_packages; \ No newline at end of file