More work on datastore
This commit is contained in:
parent
3a4eb78d2c
commit
0fe0b754a1
8 changed files with 2230 additions and 239 deletions
1973
Cargo.lock
generated
1973
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -10,4 +10,5 @@ echo $EDITION_FEATURES
|
|||
echo ENV SETTINGS:
|
||||
env
|
||||
|
||||
OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo build --release --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl
|
||||
#OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 RUSTFLAGS="-C relocation-model=static -C linker=ld.lld" cargo build --release --features "$EDITION_FEATURES" --target x86_64-unknown-linux-musl
|
||||
OPENSSL_LIB_DIR=/usr/lib OPENSSL_INCLUDE_DIR=/usr/include/openssl OPENSSL_STATIC=1 cargo build --release --features "$EDITION_FEATURES"
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@ super-mario-maker:
|
|||
features:
|
||||
- prudpv1
|
||||
- v3-8-15
|
||||
- datastore
|
||||
settings:
|
||||
AUTH_REPORT_VERSION: "branch:origin/project/wup-ama build:3_8_29_3022_0"
|
||||
RNEX_VIRTUAL_PORT_INSECURE: "1:10"
|
||||
RNEX_VIRTUAL_PORT_SECURE: "1:10"
|
||||
RNEX_DEFAULT_PORT: 6000
|
||||
RNEX_ACCESS_KEY: "9f2b4678"
|
||||
RNEX_ACCESS_KEY: "9f2b4678"
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ anyhow = "1.0.100"
|
|||
ureq = { version = "3.1.4", features = [ "json" ] }
|
||||
serde = { version = "1.0.228", features = [ "derive" ] }
|
||||
serde_json = "1.0.149"
|
||||
sqlx = { version = "0.8.6", optional = true }
|
||||
aws-sdk-s3 = { version = "1.129.0", optional = true }
|
||||
aws-config = { version = "1.8.15", optional = true }
|
||||
base64 = "0.22.1"
|
||||
sha2 = "0.10.9"
|
||||
|
||||
[dev-dependencies]
|
||||
# criterion = "0.7.0"
|
||||
|
|
@ -40,7 +45,7 @@ big_pid = []
|
|||
v3-8-15 = ["rmc_struct_header"]
|
||||
v4-3-11 = ["v3-8-15"]
|
||||
nx = ["big_pid"]
|
||||
|
||||
datastore = ["dep:sqlx", "v3-8-15", "dep:aws-sdk-s3", "dep:aws-config"]
|
||||
|
||||
[[bench]]
|
||||
name = "rmc_serialization"
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
72
rnex-core/src/nex/s3presigner.rs
Normal file
72
rnex-core/src/nex/s3presigner.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use macros::{method_id, rmc_proto, RmcSerialize, rmc_struct};
|
||||
use rnex_core::rmc::response::ErrorCode;
|
||||
use rnex_core::rmc::structures::qbuffer::QBuffer;
|
||||
use rnex_core::rmc::response::ErrorCode;
|
||||
|
||||
use rnex_core::kerberos::KerberosDateTime;
|
||||
use rnex_core::PID;
|
||||
|
|
@ -12,7 +12,7 @@ pub struct PersistenceTarget {
|
|||
pub persistence_slot_id: u16,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
#[derive(RmcSerialize, Clone, Debug)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct Permission {
|
||||
pub permission: u8,
|
||||
|
|
@ -49,7 +49,7 @@ pub struct GetMetaInfo {
|
|||
pub dataid: u64,
|
||||
pub owner: PID,
|
||||
pub size: u32,
|
||||
pub name: &'static str,
|
||||
pub name: String,
|
||||
pub data_type: u16,
|
||||
pub meta_binary: QBuffer,
|
||||
pub permission: Permission,
|
||||
|
|
@ -58,17 +58,101 @@ pub struct GetMetaInfo {
|
|||
pub updated_time: KerberosDateTime,
|
||||
pub period: u16,
|
||||
pub status: u8,
|
||||
pub reffered_count: u32,
|
||||
pub referred_count: u32,
|
||||
pub refer_dat_id: u32,
|
||||
pub flag: u32,
|
||||
pub referred_time: KerberosDateTime,
|
||||
pub expire_time: KerberosDateTime,
|
||||
pub tags: Vec<&'static str>,
|
||||
pub tags: Vec<String>,
|
||||
pub ratings: Vec<RatingInfoWithSlot>,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct RatingInitParam {
|
||||
pub flag: u8,
|
||||
pub internal_flag: u8,
|
||||
pub lock_type: u8,
|
||||
pub intial_valie: i64,
|
||||
pub range_min: i32,
|
||||
pub range_max: i32,
|
||||
pub period_hour: i8,
|
||||
pub period_duration: i16
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct RatingInitParamWithSlot {
|
||||
pub slot: i8,
|
||||
pub param: RatingInitParam,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct PersistenceInitParam {
|
||||
pub persistence_slot_id: u16,
|
||||
pub delete_last_object: bool,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct KeyValue {
|
||||
pub key: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct PreparePostParam {
|
||||
pub size: u32,
|
||||
pub name: String,
|
||||
pub data_type: u16,
|
||||
pub meta_binary: QBuffer,
|
||||
pub permission: Permission,
|
||||
pub del_permission: Permission,
|
||||
pub flag: u32,
|
||||
pub period: u16,
|
||||
pub refer_data_id: u32,
|
||||
pub tags: Vec<String>,
|
||||
pub rating_init_params: Vec<RatingInitParamWithSlot>,
|
||||
pub persistence_init_param: PersistenceInitParam,
|
||||
pub extra_data: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct ReqPostInfo {
|
||||
pub dataid: u64,
|
||||
pub url: String,
|
||||
pub request_headers: Vec<KeyValue>,
|
||||
pub form_fields: Vec<KeyValue>,
|
||||
pub root_ca_cert: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct CompletePostParam {
|
||||
pub dataid: u64,
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
#[derive(RmcSerialize, Clone)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct RateCustomRankingParam {
|
||||
pub dataid: u64,
|
||||
pub appid: u32,
|
||||
pub score: u32,
|
||||
pub period: u16,
|
||||
}
|
||||
|
||||
#[rmc_proto(115)]
|
||||
pub trait DataStore{
|
||||
#[method_id(8)]
|
||||
async fn get_meta(&self, metaparam: GetMetaParam) -> Result<GetMetaInfo, ErrorCode>;
|
||||
#[method_id(24)]
|
||||
async fn prepare_post_object(&self, postparam: PreparePostParam) -> Result<ReqPostInfo, ErrorCode>;
|
||||
#[method_id(26)]
|
||||
async fn complete_post_object(&self, completeparam: CompletePostParam) -> Result<(), ErrorCode>;
|
||||
#[method_id(48)]
|
||||
async fn rate_custom_ranking(&self, rankingparam: Vec<RateCustomRankingParam>) -> Result<(), ErrorCode>;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue