datastore refactor
Some checks failed
Build and Test / wii-sports-club (push) Failing after 20m22s
Build and Test / puyopuyo (push) Failing after 20m41s
Build and Test / minecraft-wiiu (push) Failing after 20m54s
Build and Test / sonic-transformed (push) Failing after 21m17s
Build and Test / mario-tennis (push) Failing after 21m34s
Build and Test / fast-racing-neo (push) Failing after 21m37s
Build and Test / splatoon-testfire (push) Failing after 22m11s
Build and Test / wii-u-chat (push) Failing after 23m6s
Build and Test / splatoon (push) Failing after 23m23s
Build and Test / friends (push) Failing after 3m51s
Build and Test / super-mario-maker (push) Failing after 3m50s
Some checks failed
Build and Test / wii-sports-club (push) Failing after 20m22s
Build and Test / puyopuyo (push) Failing after 20m41s
Build and Test / minecraft-wiiu (push) Failing after 20m54s
Build and Test / sonic-transformed (push) Failing after 21m17s
Build and Test / mario-tennis (push) Failing after 21m34s
Build and Test / fast-racing-neo (push) Failing after 21m37s
Build and Test / splatoon-testfire (push) Failing after 22m11s
Build and Test / wii-u-chat (push) Failing after 23m6s
Build and Test / splatoon (push) Failing after 23m23s
Build and Test / friends (push) Failing after 3m51s
Build and Test / super-mario-maker (push) Failing after 3m50s
This commit is contained in:
parent
115ebf8a3b
commit
3f07e45f08
11 changed files with 1030 additions and 2105 deletions
1035
Cargo.lock
generated
1035
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,116 +0,0 @@
|
|||
use base64::{engine::general_purpose, Engine as _};
|
||||
use hmac::{Hmac, Mac};
|
||||
use sha2::{Sha256, Digest};
|
||||
use chrono::{Utc, Duration};
|
||||
use serde_json::json;
|
||||
use rnex_core::executables::common::RNEX_DATASTORE_S3_ENDPOINT;
|
||||
|
||||
pub struct S3Presigner {
|
||||
endpoint: String,
|
||||
bucket: String,
|
||||
}
|
||||
|
||||
impl S3Presigner {
|
||||
pub async fn new(endpoint: &str, bucket: String) -> Self {
|
||||
Self {
|
||||
endpoint: endpoint.trim_end_matches('/').to_string(),
|
||||
bucket,
|
||||
}
|
||||
}
|
||||
pub async fn generate_presigned_post(&self, key: &str) -> (String, Vec<(String, String)>) {
|
||||
let access_key = std::env::var("AWS_ACCESS_KEY_ID").expect("Missing Access Key");
|
||||
let secret_key = std::env::var("AWS_SECRET_ACCESS_KEY").expect("Missing Secret Key");
|
||||
let region = "us-east-1"; // hardcoded because its the default region for most s3 clones
|
||||
let date_short = Utc::now().format("%Y%m%d").to_string();
|
||||
let date_full = Utc::now().format("%Y%m%dT%H%M%SZ").to_string();
|
||||
let expiration = (Utc::now() + Duration::minutes(15)).format("%Y-%m-%dT%H:%M:%SZ").to_string();
|
||||
|
||||
let credential = format!("{}/{}/{}/s3/aws4_request", access_key, date_short, region);
|
||||
|
||||
let policy_json = json!({
|
||||
"expiration": expiration,
|
||||
"conditions": [
|
||||
{"bucket": self.bucket},
|
||||
["starts-with", "$key", key],
|
||||
{"x-amz-credential": credential},
|
||||
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
|
||||
{"x-amz-date": date_full}
|
||||
]
|
||||
});
|
||||
|
||||
let policy_base64 = general_purpose::STANDARD.encode(policy_json.to_string());
|
||||
|
||||
let signature = self.calculate_signature(&secret_key, &date_short, region, &policy_base64);
|
||||
|
||||
let fields = vec![
|
||||
("key".to_string(), key.to_string()),
|
||||
("X-Amz-Algorithm".to_string(), "AWS4-HMAC-SHA256".to_string()),
|
||||
("X-Amz-Credential".to_string(), credential),
|
||||
("X-Amz-Date".to_string(), date_full),
|
||||
("Policy".to_string(), policy_base64),
|
||||
("X-Amz-Signature".to_string(), signature),
|
||||
];
|
||||
|
||||
let url = format!("https://{}/{}", *RNEX_DATASTORE_S3_ENDPOINT, self.bucket);
|
||||
(url, fields)
|
||||
}
|
||||
|
||||
pub fn generate_presigned_get(&self, key: &str) -> String {
|
||||
let access_key = std::env::var("AWS_ACCESS_KEY_ID").expect("Missing Access Key");
|
||||
let secret_key = std::env::var("AWS_SECRET_ACCESS_KEY").expect("Missing Secret Key");
|
||||
let region = "us-east-1";
|
||||
let date_short = Utc::now().format("%Y%m%d").to_string();
|
||||
let date_full = Utc::now().format("%Y%m%dT%H%M%SZ").to_string();
|
||||
|
||||
let credential_scope = format!("{}/{}/s3/aws4_request", date_short, region);
|
||||
|
||||
let query_string = format!(
|
||||
"X-Amz-Algorithm=AWS4-HMAC-SHA256&\
|
||||
X-Amz-Credential={}%2F{}&\
|
||||
X-Amz-Date={}&\
|
||||
X-Amz-Expires=900&\
|
||||
X-Amz-SignedHeaders=host",
|
||||
access_key,
|
||||
urlencoding::encode(&credential_scope),
|
||||
date_full
|
||||
);
|
||||
|
||||
let canonical_request = format!(
|
||||
"GET\n/{}/{}\n{}\nhost:{}\n\nhost\nUNSIGNED-PAYLOAD",
|
||||
self.bucket, key, query_string, *RNEX_DATASTORE_S3_ENDPOINT
|
||||
);
|
||||
|
||||
let hashed_request = hex::encode(Sha256::digest(canonical_request.as_bytes()));
|
||||
|
||||
let string_to_sign = format!(
|
||||
"AWS4-HMAC-SHA256\n{}\n{}\n{}",
|
||||
date_full, credential_scope, hashed_request
|
||||
);
|
||||
|
||||
let k_date = self.hmac_sha256(format!("AWS4{}", secret_key).as_bytes(), &date_short);
|
||||
let k_region = self.hmac_sha256(&k_date, region);
|
||||
let k_service = self.hmac_sha256(&k_region, "s3");
|
||||
let k_signing = self.hmac_sha256(&k_service, "aws4_request");
|
||||
let signature = hex::encode(self.hmac_sha256(&k_signing, &string_to_sign));
|
||||
|
||||
format!(
|
||||
"https://{}/{}/{}?{}&X-Amz-Signature={}",
|
||||
*RNEX_DATASTORE_S3_ENDPOINT, self.bucket, key, query_string, signature
|
||||
)
|
||||
}
|
||||
|
||||
fn calculate_signature(&self, secret: &str, date: &str, region: &str, policy: &str) -> String {
|
||||
let k_date = self.hmac_sha256(format!("AWS4{}", secret).as_bytes(), date);
|
||||
let k_region = self.hmac_sha256(&k_date, region);
|
||||
let k_service = self.hmac_sha256(&k_region, "s3");
|
||||
let k_signing = self.hmac_sha256(&k_service, "aws4_request");
|
||||
|
||||
hex::encode(self.hmac_sha256(&k_signing, policy))
|
||||
}
|
||||
|
||||
fn hmac_sha256(&self, key: &[u8], data: &str) -> Vec<u8> {
|
||||
let mut mac = Hmac::<Sha256>::new_from_slice(key).expect("HMAC can take key of any size");
|
||||
mac.update(data.as_bytes());
|
||||
mac.finalize().into_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ impl PRUDPSockAddr {
|
|||
}
|
||||
|
||||
pub fn calculate_connection_signature(&self) -> [u8; 16] {
|
||||
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("?");
|
||||
let mut hmac = Md5Hmac::new_from_slice(&[0; 16]).expect("incorrect slice size");
|
||||
|
||||
let data = match self.regular_socket_addr.ip() {
|
||||
IpAddr::V4(v) => v.octets().to_vec(),
|
||||
|
|
@ -33,7 +33,7 @@ impl PRUDPSockAddr {
|
|||
hmac.update(&data);
|
||||
let result: [u8; 16] = hmac.finalize().into_bytes()[0..16]
|
||||
.try_into()
|
||||
.expect("fuck");
|
||||
.expect("incorrect result size");
|
||||
result
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ impl RmcSerialize for SocketAddrV6 {
|
|||
))
|
||||
}
|
||||
fn serialize_write_size(&self) -> Result<u32> {
|
||||
Ok(6)
|
||||
Ok(26)
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ impl RmcSerialize for u128 {
|
|||
}
|
||||
#[inline(always)]
|
||||
fn serialize_write_size(&self) -> Result<u32> {
|
||||
Ok(8)
|
||||
Ok(16)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -465,6 +465,6 @@ impl From<Error> for ErrorCode {
|
|||
|
||||
impl Into<u32> for ErrorCode {
|
||||
fn into(self) -> u32 {
|
||||
unsafe { transmute(self) }
|
||||
self as u32
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ impl<'a, T: Read + ?Sized> SubRead<'a, T> {
|
|||
impl<T: Read + ?Sized> Read for SubRead<'_, T> {
|
||||
#[inline(always)]
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let max_read = usize::max(self.left_to_read, buf.len());
|
||||
let max_read = usize::min(self.left_to_read, buf.len());
|
||||
let read = self.origin.read(&mut buf[..max_read])?;
|
||||
self.left_to_read -= read;
|
||||
Ok(read)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::fmt::Write;
|
||||
use std::io::{self, Read};
|
||||
use std::str::FromStr;
|
||||
|
||||
use rnex_util::station_url::StationUrl;
|
||||
|
||||
|
|
@ -12,7 +13,7 @@ impl RmcSerialize for StationUrl {
|
|||
fn deserialize(reader: &mut (impl Read + ?Sized)) -> Result<Self> {
|
||||
let str = String::deserialize(reader)?;
|
||||
|
||||
Self::try_from(str.as_str()).map_err(|_| StationUrlInvalid)
|
||||
Self::from_str(str.as_str()).map_err(|_| StationUrlInvalid)
|
||||
}
|
||||
fn serialize(&self, writer: &mut (impl io::Write + ?Sized)) -> Result<()> {
|
||||
let str: String = self.into();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ tracing = "0.1.44"
|
|||
chrono = "0.4.39"
|
||||
bytemuck = { version = "1.25.0", features = ["derive"] }
|
||||
md-5 = "0.11.0"
|
||||
thiserror = "2.0.18"
|
||||
|
||||
[features]
|
||||
nx = []
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use std::{
|
||||
fmt::{Debug, Display, Formatter},
|
||||
net::IpAddr,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use thiserror::Error;
|
||||
use tracing::error;
|
||||
|
||||
use crate::PID;
|
||||
|
|
@ -86,11 +88,15 @@ impl StationUrl {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for StationUrl {
|
||||
type Error = ();
|
||||
// todo: add more specific error messages to parsing
|
||||
#[derive(Error, Debug)]
|
||||
#[error("failed to parse station url")]
|
||||
pub struct StationUrlParseError;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, ()> {
|
||||
let (url_type, options) = value.split_at(value.find(":/").ok_or(())?);
|
||||
impl FromStr for StationUrl {
|
||||
type Err = StationUrlParseError;
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
let (url_type, options) = value.split_at(value.find(":/").ok_or(StationUrlParseError)?);
|
||||
|
||||
let options = &options[2..];
|
||||
|
||||
|
|
@ -100,10 +106,10 @@ impl TryFrom<&str> for StationUrl {
|
|||
"udp" => UDP,
|
||||
"prudp" => PRUDP,
|
||||
"prudps" => PRUDPS,
|
||||
_ => return Err(()),
|
||||
_ => return Err(StationUrlParseError),
|
||||
};
|
||||
|
||||
let options = Self::read_options(options).ok_or(())?;
|
||||
let options = Self::read_options(options).ok_or(StationUrlParseError)?;
|
||||
|
||||
Ok(Self { url_type, options })
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue