More work on datastore

This commit is contained in:
red binder 2026-04-14 09:00:49 +02:00
commit 0fe0b754a1
8 changed files with 2230 additions and 239 deletions

View file

@ -4,23 +4,53 @@ use rnex_core::prudp::socket_addr::PRUDPSockAddr;
use std::sync::{Weak};
use rnex_core::PID;
use rnex_core::nex::remote_console::RemoteConsole;
use rnex_core::nex::s3presigner::S3Presigner;
use rnex_core::rmc::response::ErrorCode;
use rnex_core::rmc::protocols::secure::{Secure, RawSecure, RawSecureInfo, RemoteSecure};
use rnex_core::rmc::protocols::datastore::{GetMetaInfo, GetMetaParam};
use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore};
use rnex_core::rmc::protocols::datastore::{CompletePostParam, GetMetaInfo, GetMetaParam, KeyValue, RateCustomRankingParam};
use rnex_core::rmc::protocols::datastore::{DataStore, RawDataStore, RawDataStoreInfo, RemoteDataStore, PreparePostParam, ReqPostInfo};
use crate::nex::user::User;
impl DataStore for User {
async fn get_meta(&self, metaparam: GetMetaParam) -> Result<GetMetaInfo, ErrorCode> {
// // bogus
// let info: GetMetaInfo = GetMetaInfo {
// dataid: 10,
// owner: 1121,
// size: 1024,
// name: "idk"
// }
println!("dataid: {}", metaparam.dataid);
println!("access password: {}", metaparam.access_password);
// just trying to see what methods it tries to use
Err(ErrorCode::DataStore_NotFound)
}
async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result<ReqPostInfo, ErrorCode> {
let data_id: u64 = 9400001;
let presigner = S3Presigner::new("https://s3.perditum.com", "miku".into()).await;
let key = format!("data/{}.bin", data_id);
let (upload_url, fields) = presigner.generate_presigned_post(&key).await;
let form_fields = fields.into_iter().map(|(k, v)| {
KeyValue { key: k, value: v }
}).collect();
Ok(ReqPostInfo {
dataid: data_id,
url: upload_url,
request_headers: vec![],
form_fields,
root_ca_cert: vec![],
})
}
async fn complete_post_object(&self, completeparam: CompletePostParam) -> Result<(), ErrorCode> {
// whatever
println!("dataid: {}", completeparam.dataid);
println!("succeeded?: {}", completeparam.success);
Ok(())
}
async fn rate_custom_ranking(&self, rankingparam: Vec<RateCustomRankingParam>) -> Result<(), ErrorCode> {
// this returns nothing
Ok(())
}
}

View file

@ -5,4 +5,5 @@ pub mod friends_handler;
pub mod matchmake;
pub mod remote_console;
pub mod user;
pub mod datastore;
pub mod datastore;
pub mod s3presigner;

View file

@ -0,0 +1,72 @@
use aws_sdk_s3::presigning::PresigningConfig;
use base64::{engine::general_purpose, Engine as _};
use hmac::{Hmac, Mac};
use sha2::{Sha256, Digest};
use chrono::{Utc, Duration};
use serde_json::json;
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";
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 mut 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://s3.perditum.com/{}", self.bucket);
(url, fields)
}
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()
}
}