merge in latest refactor changes
This commit is contained in:
parent
7af0f0f99f
commit
c2f45557da
49 changed files with 163 additions and 1960 deletions
|
|
@ -3,10 +3,10 @@
|
||||||
This repo contains the code for all game servers using RNEX.
|
This repo contains the code for all game servers using RNEX.
|
||||||
|
|
||||||
## Credits:
|
## Credits:
|
||||||
- Pretendo team for their reverse engineering efforts
|
|
||||||
- Kinnay for his huge work on reversing nex servers and documentation(https://github.com/Kinnay/NintendoClients/)
|
- Kinnay for his huge work on reversing nex servers and documentation(https://github.com/Kinnay/NintendoClients/)
|
||||||
- Splatfestival testing team for helping us test our messes of code
|
- Splatfestival testing team for helping us test our messes of code
|
||||||
- The SPFN team(RusticMaple, BloxerHD, Ceantix, RedBinder0526)
|
- The SPFN team(redbinder0526, bloxerhd, kittentm, et al.)
|
||||||
|
- Pretendo team for their reverse engineering efforts
|
||||||
|
|
||||||
This NEX implementation was not created to rival Pretendo, we don't want any bad blood between anyone.
|
This NEX implementation was not created to rival Pretendo, we don't want any bad blood between anyone.
|
||||||
This project would never have been possible without their reverse engineering efforts.
|
This project would never have been possible without their reverse engineering efforts.
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ async fn main() {
|
||||||
let param = ProxyStartupParam::new(proxy_common::ProxyType::Insecure)
|
let param = ProxyStartupParam::new(proxy_common::ProxyType::Insecure)
|
||||||
.expect("unable to get startup parameters");
|
.expect("unable to get startup parameters");
|
||||||
|
|
||||||
setup_edge_node_connection(¶m, edge_node_dc_callback).await;
|
// setup_edge_node_connection(¶m, edge_node_dc_callback).await;
|
||||||
|
|
||||||
proxy::start_insecure(param).await;
|
proxy::start_insecure(param).await;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -37,27 +37,7 @@ pub async fn start(param: ProxyStartupParam) {
|
||||||
};
|
};
|
||||||
|
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
// todo: add support for checking this to nex-account
|
let stream = match TcpStream::connect(param.forward_destination).await {
|
||||||
/*
|
|
||||||
let Ok(mut c) = rnex_core::grpc::account::Client::new().await else {
|
|
||||||
error!("failed to initialize gql client");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let v = match c.get_user_level(conn.user_id).await {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
error!("failed to get user level: {}", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if v < 0 {
|
|
||||||
warn!("person with too low account level joined");
|
|
||||||
return;
|
|
||||||
} */
|
|
||||||
|
|
||||||
let mut stream = match TcpStream::connect(param.forward_destination).await {
|
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("unable to connect: {}", e);
|
error!("unable to connect: {}", e);
|
||||||
|
|
@ -65,7 +45,9 @@ pub async fn start(param: ProxyStartupParam) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = stream
|
let (mut read_half, mut write_half) = stream.into_split();
|
||||||
|
|
||||||
|
if let Err(e) = write_half
|
||||||
.send_buffer(
|
.send_buffer(
|
||||||
&ConnectionInitData {
|
&ConnectionInitData {
|
||||||
addr: conn.socket_addr.regular_socket_addr,
|
addr: conn.socket_addr.regular_socket_addr,
|
||||||
|
|
@ -80,6 +62,28 @@ pub async fn start(param: ProxyStartupParam) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (tx, mut rx) = tokio::sync::mpsc::channel::<Vec<u8>>(100);
|
||||||
|
|
||||||
|
let reader_handle = task::spawn(async move {
|
||||||
|
loop {
|
||||||
|
match read_half.read_buffer().await {
|
||||||
|
Ok(data) => {
|
||||||
|
if data == [0, 0, 0, 0, 0] {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if tx.send(data).await.is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("error receiving data from backend: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let keepalive_data = vec![0u8; 5];
|
||||||
'a: loop {
|
'a: loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
data = conn.recv() => {
|
data = conn.recv() => {
|
||||||
|
|
@ -87,34 +91,31 @@ pub async fn start(param: ProxyStartupParam) {
|
||||||
break 'a;
|
break 'a;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = stream.send_buffer(&data[..]).await{
|
if let Err(e) = write_half.send_buffer(&data[..]).await {
|
||||||
error!("error sending data to backend: {}", e);
|
error!("error sending data to backend: {}", e);
|
||||||
break 'a;
|
break 'a;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data = stream.read_buffer() => {
|
data = rx.recv() => {
|
||||||
let data = match data{
|
let Some(data) = data else {
|
||||||
Ok(d) => d,
|
break 'a;
|
||||||
Err(e) => {
|
|
||||||
error!("error reveiving data from backend: {}", e);
|
|
||||||
break 'a;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if data == [0,0,0,0,0] {
|
if conn.send(data).await.is_none() {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if conn.send(data).await == None{
|
|
||||||
break 'a;
|
break 'a;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ = sleep(Duration::from_secs(10)) => {
|
_ = sleep(Duration::from_secs(10)) => {
|
||||||
stream.send_buffer(&[0,0,0,0,0].to_vec()).await.ok();
|
if let Err(e) = write_half.send_buffer(&keepalive_data).await {
|
||||||
|
error!("failed to send keepalive: {}", e);
|
||||||
|
break 'a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader_handle.abort();
|
||||||
conn.deref().close_connection().await;
|
conn.deref().close_connection().await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n UPDATE datastore.object_ratings\n SET total_value=total_value+$1, count=count+1\n WHERE data_id=$2 AND slot=$3\n RETURNING total_value, count, initial_value\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "total_value",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "count",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "initial_value",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Int8",
|
|
||||||
"Int2"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "15b108cbdaaf3ebb99254330fdcf31c7038239be4c9e88e76653d36482f74379"
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT owner, under_review FROM datastore.objects WHERE data_id = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "owner",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "under_review",
|
|
||||||
"type_info": "Bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "164708b549c483a041d2e54065ed3ffbd9f8d5304f6aa6d785dbddbb1626c0e9"
|
|
||||||
}
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date\n FROM datastore.objects WHERE data_id = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "owner",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "size",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "data_type",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "meta_binary",
|
|
||||||
"type_info": "Bytea"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "permission",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "permission_recipients",
|
|
||||||
"type_info": "Int4Array"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 8,
|
|
||||||
"name": "delete_permission",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 9,
|
|
||||||
"name": "delete_permission_recipients",
|
|
||||||
"type_info": "Int4Array"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 10,
|
|
||||||
"name": "period",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 11,
|
|
||||||
"name": "refer_data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 12,
|
|
||||||
"name": "flag",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 13,
|
|
||||||
"name": "tags",
|
|
||||||
"type_info": "TextArray"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 14,
|
|
||||||
"name": "creation_date",
|
|
||||||
"type_info": "Timestamp"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 15,
|
|
||||||
"name": "update_date",
|
|
||||||
"type_info": "Timestamp"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "1c2be699b4bfc7e5e6d3a74d7badf67d1812b99e1ec952a044fc03e1a5c63703"
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n INSERT INTO datastore.objects (\n owner, size, name, data_type, meta_binary,\n permission, permission_recipients,\n delete_permission, delete_permission_recipients,\n flag, period, refer_data_id, tags,\n persistence_slot_id, extra_data, creation_date, update_date\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17\n ) RETURNING data_id\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int4",
|
|
||||||
"Int4",
|
|
||||||
"Text",
|
|
||||||
"Int4",
|
|
||||||
"Bytea",
|
|
||||||
"Int4",
|
|
||||||
"Int4Array",
|
|
||||||
"Int4",
|
|
||||||
"Int4Array",
|
|
||||||
"Int4",
|
|
||||||
"Int4",
|
|
||||||
"Int8",
|
|
||||||
"TextArray",
|
|
||||||
"Int4",
|
|
||||||
"TextArray",
|
|
||||||
"Timestamp",
|
|
||||||
"Timestamp"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "219fec3fc852f36de99e5f00ca7a1675439bb44c91158f8b8a696e326c45447c"
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n INSERT INTO datastore.object_custom_rankings (data_id, application_id, value)\n VALUES ($1, $2, $3)\n ON CONFLICT (data_id, application_id)\n DO UPDATE SET value = datastore.object_custom_rankings.value + EXCLUDED.value\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Int8",
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "29d4f5c07b36c3d3b6b54a86a1757f27247530878b7f82feeb65802d995a38c4"
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n INSERT INTO datastore.course_records (\n data_id,\n slot,\n first_pid,\n best_pid,\n best_score,\n creation_date,\n update_date\n ) VALUES (\n $1,\n $2,\n $3,\n $4,\n $5,\n $6,\n $7\n ) ON CONFLICT (data_id, slot) DO UPDATE\n SET best_score = CASE WHEN datastore.course_records.best_score > $5 THEN $5 ELSE datastore.course_records.best_score END,\n best_pid = CASE WHEN datastore.course_records.best_score > $5 THEN $4 ELSE datastore.course_records.best_pid END,\n update_date = CASE WHEN datastore.course_records.best_score > $5 THEN $7 ELSE datastore.course_records.update_date END\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Int4",
|
|
||||||
"Int4",
|
|
||||||
"Int4",
|
|
||||||
"Int4",
|
|
||||||
"Timestamp",
|
|
||||||
"Timestamp"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "2c8f6740e719d786ed05d2d9cdb29a786ff7b34579938258b73504f7971b3849"
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n INSERT INTO datastore.objects (\n owner, size, name, data_type, meta_binary,\n permission, permission_recipients,\n delete_permission, delete_permission_recipients,\n flag, period, refer_data_id, tags,\n persistence_slot_id, extra_data, creation_date, update_date\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17\n ) RETURNING data_id\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int4",
|
|
||||||
"Int4",
|
|
||||||
"Text",
|
|
||||||
"Int4",
|
|
||||||
"Bytea",
|
|
||||||
"Int4",
|
|
||||||
"Int4Array",
|
|
||||||
"Int4",
|
|
||||||
"Int4Array",
|
|
||||||
"Int4",
|
|
||||||
"Int4",
|
|
||||||
"Int8",
|
|
||||||
"TextArray",
|
|
||||||
"Int4",
|
|
||||||
"TextArray",
|
|
||||||
"Timestamp",
|
|
||||||
"Timestamp"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "2d025ae36b11518c43a0531c58f58e6c97c3f4726bae21e0cfaa8cc0ff218692"
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT EXISTS(SELECT 1 FROM datastore.objects WHERE data_id = $1)",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "exists",
|
|
||||||
"type_info": "Bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
null
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "2ff34379bbc32276c3b78ef1283b8158ea907d36588e1e59f6cbe752d89361bb"
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE datastore.objects SET data_type=$1 WHERE data_id=$2",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int4",
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "31e36bb378bcf8e665391d9cd2c5282fea9540a0673456d58f8142cafc330240"
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT data_id\n FROM datastore.objects\n WHERE owner = $1 AND data_type > 2 AND data_type < 50\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int4"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "37d449b81e2aa3abdbdaf38587ae1a6a6c5c38acb06d91c5b0924c3f0a5d2e92"
|
|
||||||
}
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT buffer\n FROM datastore.buffer_queues\n WHERE data_id = $1 AND slot = $2\n ORDER BY creation_date ASC\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "buffer",
|
|
||||||
"type_info": "Bytea"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Int4"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "3d06238fddc72d1ba452602e1a8002e9186ce1dfc6c68b52d9d2a8a38f5c3a1f"
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT update_password, under_review FROM datastore.objects WHERE data_id=$1 AND upload_completed=TRUE AND deleted=FALSE\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "update_password",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "under_review",
|
|
||||||
"type_info": "Bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "433b8cbd7320b5463391b08545c09b11255b363112c3379319b9e69ed003f2eb"
|
|
||||||
}
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT\n object.data_id,\n object.owner,\n object.size,\n object.name,\n object.data_type,\n object.meta_binary,\n object.permission,\n object.permission_recipients,\n object.delete_permission,\n object.delete_permission_recipients,\n object.period,\n object.refer_data_id,\n object.flag,\n object.tags,\n object.creation_date,\n object.update_date,\n ranking.value\n FROM (\n SELECT * FROM datastore.objects object\n WHERE\n object.upload_completed = TRUE AND\n object.deleted = FALSE AND\n object.under_review = FALSE\n ) object\n JOIN (\n SELECT data_id, value\n FROM datastore.object_custom_rankings ranking\n WHERE ranking.application_id = 0\n ) ranking\n ON\n object.data_id = ranking.data_id\n ORDER BY RANDOM()\n LIMIT 100\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "owner",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "size",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "data_type",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "meta_binary",
|
|
||||||
"type_info": "Bytea"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "permission",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "permission_recipients",
|
|
||||||
"type_info": "Int4Array"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 8,
|
|
||||||
"name": "delete_permission",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 9,
|
|
||||||
"name": "delete_permission_recipients",
|
|
||||||
"type_info": "Int4Array"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 10,
|
|
||||||
"name": "period",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 11,
|
|
||||||
"name": "refer_data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 12,
|
|
||||||
"name": "flag",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 13,
|
|
||||||
"name": "tags",
|
|
||||||
"type_info": "TextArray"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 14,
|
|
||||||
"name": "creation_date",
|
|
||||||
"type_info": "Timestamp"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 15,
|
|
||||||
"name": "update_date",
|
|
||||||
"type_info": "Timestamp"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 16,
|
|
||||||
"name": "value",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": []
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "502f3f0fbb3739ddcffa2938680b2399e0b204b25631e14cac0d61fcff8e29c3"
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT\n data_id,\n value\n FROM datastore.object_custom_rankings\n WHERE application_id = $1\n AND value >= $2\n AND value <= $3\n ORDER BY value DESC\n LIMIT $4 OFFSET $5\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "value",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Int8",
|
|
||||||
"Int8",
|
|
||||||
"Int8",
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "555c438210f49e3a8fd279bf3d493cfdef21c64fd31d1b2bd7a7605f97d550ee"
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n INSERT INTO datastore.reports (\n data_id,\n reporter_pid,\n category,\n reason\n ) VALUES (\n $1, $2, $3, $4\n )\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Int4",
|
|
||||||
"Int2",
|
|
||||||
"Varchar"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "5cea63e5c1d279af23ef56d7ba02f49ac8c4cb5668559a92daebea815a2d64ec"
|
|
||||||
}
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT\n first_pid,\n best_pid,\n best_score,\n creation_date,\n update_date\n FROM datastore.course_records WHERE data_id=$1 AND slot=$2\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "first_pid",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "best_pid",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "best_score",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "creation_date",
|
|
||||||
"type_info": "Timestamp"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "update_date",
|
|
||||||
"type_info": "Timestamp"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Int4"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "720b2a71163a0d3907e847d874cf230267f8241bcc261ca968d143d4ab6b5ab8"
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n INSERT INTO datastore.object_ratings (\n data_id,\n slot,\n flag,\n internal_flag,\n lock_type,\n initial_value,\n range_min,\n range_max,\n period_hour,\n period_duration,\n total_value\n ) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11\n )\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Int2",
|
|
||||||
"Int2",
|
|
||||||
"Int2",
|
|
||||||
"Int2",
|
|
||||||
"Int8",
|
|
||||||
"Int4",
|
|
||||||
"Int4",
|
|
||||||
"Int2",
|
|
||||||
"Int4",
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "744047264f63b5eac396d8c0606824f43eb87c2739404d423b2d94bb727ed1c9"
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE datastore.objects SET deleted=true WHERE data_id=$1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "75f4e823a82add9c1608a43a0dff6633db4cd635037622fd61d7a3a6a872db2e"
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT\n rankings.data_id,\n rankings.value\n FROM datastore.object_custom_rankings rankings\n JOIN UNNEST($1::bigint[]) WITH ORDINALITY AS rows(data_id, ord)\n ON rankings.data_id = rows.data_id\n AND rankings.application_id = $2\n ORDER BY rows.ord\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "value",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8Array",
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "8605011b998a4608c739bf5ab388a7a9bf551126712c1d1089a4263453090e79"
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT slot, total_value, count, initial_value\n FROM datastore.object_ratings\n WHERE data_id = $1\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "slot",
|
|
||||||
"type_info": "Int2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "total_value",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "count",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "initial_value",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "8706ac06d78ffaa2a45418be7ae71340561031d8e5c91f46c041f83e54c31a7d"
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT slot, total_value, count, initial_value FROM datastore.object_ratings WHERE data_id=$1\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "slot",
|
|
||||||
"type_info": "Int2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "total_value",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "count",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "initial_value",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "8df96ce41787673f9fd03aadf142f3a77f61ff0d3fbe54cf34e967fbb852cbb8"
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT under_review, access_password\n FROM datastore.objects\n WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "under_review",
|
|
||||||
"type_info": "Bool"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "access_password",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "93be6b6b0ac5d85881e6e223a7d48f5eb4a3761dd71129ba6939cdd0d62569fb"
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE datastore.objects SET meta_binary=$1 WHERE data_id=$2",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Bytea",
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "c27439038dc25c17738b4a9cc37f94f83f23239a0c37c7adbccaef571e0128da"
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE datastore.objects SET period=$1 WHERE data_id=$2",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int4",
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "daac203a168b0aab9550176524d0741da291e8861fd7c6ac4838d7fe20a871f8"
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "UPDATE datastore.objects SET upload_completed = true WHERE data_id = $1",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "e28d8776cc49b55fe76cf33ac12fe18e500d243f1b55fd18e7d96d281605bcf9"
|
|
||||||
}
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "SELECT data_id, owner, size, name, data_type, meta_binary,\n permission, permission_recipients, delete_permission, delete_permission_recipients,\n period, refer_data_id, flag, tags, creation_date, update_date,\n access_password, under_review\n FROM datastore.objects\n WHERE owner = $1 AND persistence_slot_id = $2\n AND upload_completed = TRUE AND deleted = FALSE",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 1,
|
|
||||||
"name": "owner",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 2,
|
|
||||||
"name": "size",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 3,
|
|
||||||
"name": "name",
|
|
||||||
"type_info": "Text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 4,
|
|
||||||
"name": "data_type",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 5,
|
|
||||||
"name": "meta_binary",
|
|
||||||
"type_info": "Bytea"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 6,
|
|
||||||
"name": "permission",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 7,
|
|
||||||
"name": "permission_recipients",
|
|
||||||
"type_info": "Int4Array"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 8,
|
|
||||||
"name": "delete_permission",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 9,
|
|
||||||
"name": "delete_permission_recipients",
|
|
||||||
"type_info": "Int4Array"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 10,
|
|
||||||
"name": "period",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 11,
|
|
||||||
"name": "refer_data_id",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 12,
|
|
||||||
"name": "flag",
|
|
||||||
"type_info": "Int4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 13,
|
|
||||||
"name": "tags",
|
|
||||||
"type_info": "TextArray"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 14,
|
|
||||||
"name": "creation_date",
|
|
||||||
"type_info": "Timestamp"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 15,
|
|
||||||
"name": "update_date",
|
|
||||||
"type_info": "Timestamp"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 16,
|
|
||||||
"name": "access_password",
|
|
||||||
"type_info": "Int8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ordinal": 17,
|
|
||||||
"name": "under_review",
|
|
||||||
"type_info": "Bool"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int4",
|
|
||||||
"Int4"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "efe4bf3602782a0d521274956e0fcecccf8f0f8dd20d890a76acf85265b2192c"
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n INSERT INTO datastore.buffer_queues (\n data_id,\n slot,\n creation_date,\n buffer\n ) VALUES (\n $1,\n $2,\n $3,\n $4\n ) ON CONFLICT (data_id, slot, buffer) DO UPDATE SET creation_date=$3\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8",
|
|
||||||
"Int4",
|
|
||||||
"Timestamp",
|
|
||||||
"Bytea"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "f66ad3f63457ee6b256d909dbbe9269ec6b63387a44b9beaa0da2e11c73d2680"
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "PostgreSQL",
|
|
||||||
"query": "\n SELECT update_password\n FROM datastore.objects\n WHERE data_id = $1 AND upload_completed = TRUE AND deleted = FALSE\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [
|
|
||||||
{
|
|
||||||
"ordinal": 0,
|
|
||||||
"name": "update_password",
|
|
||||||
"type_info": "Int8"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"parameters": {
|
|
||||||
"Left": [
|
|
||||||
"Int8"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"nullable": [
|
|
||||||
false
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"hash": "f7c6fdbd098c8c6f3e5520794c115a39af3e23d1acd523118088cf6f1b9dab92"
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "rnex-core"
|
|
||||||
version = "0.1.1"
|
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
[lints]
|
|
||||||
workspace = true
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
bytemuck = { version = "1.21.0", features = ["derive"] }
|
|
||||||
dotenv = "0.15.0"
|
|
||||||
rc4 = "0.1.0"
|
|
||||||
thiserror = "2.0.11"
|
|
||||||
v-byte-helpers = { git = "https://github.com/RusticMaple/VByteMacros", version = "0.1.1" }
|
|
||||||
chrono = "0.4.39"
|
|
||||||
rand = "0.10.0"
|
|
||||||
cfg-if = "1.0.4"
|
|
||||||
hmac = "0.12.1"
|
|
||||||
md-5 = "^0.10.6"
|
|
||||||
tokio = { version = "1.43.0", features = ["full"] }
|
|
||||||
hex = "0.4.3"
|
|
||||||
|
|
||||||
rnex-rmc = { path = "../rnex-rmc" }
|
|
||||||
paste = "1.0.15"
|
|
||||||
typenum = "1.18.0"
|
|
||||||
json = "0.12.4"
|
|
||||||
anyhow = "1.0.100"
|
|
||||||
ureq = { version = "3.3.0", features = [ "json" ] }
|
|
||||||
serde = { version = "1.0.228", features = [ "derive" ] }
|
|
||||||
serde_json = "1.0.149"
|
|
||||||
sqlx = { version = "0.9.0", optional = true, features = ["postgres", "runtime-tokio", "chrono"] }
|
|
||||||
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"
|
|
||||||
urlencoding = "2.1.3"
|
|
||||||
futures = "0.3.32"
|
|
||||||
async-trait = "0.1.89"
|
|
||||||
ctor = "1.0.7"
|
|
||||||
nex-account = { version = "0.2.1", registry = "spbr" }
|
|
||||||
tonic = "0.14.6"
|
|
||||||
tracing = { version = "0.1.44" }
|
|
||||||
tracing-subscriber = "0.3.23"
|
|
||||||
sentry-tracing = "0.48.4"
|
|
||||||
sentry = { version = "0.48.4", features = ["tracing"] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
# criterion = "0.7.0"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
rmc_struct_header = []
|
|
||||||
guest_login = []
|
|
||||||
friends = ["guest_login", "database-support"]
|
|
||||||
big_pid = []
|
|
||||||
third-notif-param = []
|
|
||||||
v3-3-2 = []
|
|
||||||
v3-4-0 = ["v3-3-2", "third-notif-param", "rmc_struct_header"]
|
|
||||||
v3-5-0 = ["v3-4-0"]
|
|
||||||
v3-8-15 = ["v3-5-0"]
|
|
||||||
v3-10-22 = ["v3-8-15"]
|
|
||||||
v4-3-11 = ["v3-8-15"]
|
|
||||||
nx = ["big_pid"]
|
|
||||||
splatoon = ["v3-5-0"]
|
|
||||||
datastore = ["database-support", "v3-8-15", "dep:aws-sdk-s3", "dep:aws-config"]
|
|
||||||
database-support = ["dep:sqlx"]
|
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "rmc_serialization"
|
|
||||||
harness = false
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "backend_server_insecure"
|
|
||||||
path = "src/executables/backend_server_insecure.rs"
|
|
||||||
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "backend_server_secure"
|
|
||||||
path = "src/executables/backend_server_secure.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "edge_node_holder_server"
|
|
||||||
path = "src/executables/edge_node_holder_server.rs"
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
use std::hint::black_box;
|
|
||||||
use std::io::Cursor;
|
|
||||||
use std::ops::Deref;
|
|
||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use rnex_core::kerberos::KerberosDateTime;
|
|
||||||
use rnex_core::rmc::structures::matchmake::{AutoMatchmakeParam, Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria};
|
|
||||||
use rnex_core::rmc::structures::RmcSerialize;
|
|
||||||
use rnex_core::rmc::structures::variant::Variant;
|
|
||||||
|
|
||||||
static DUMMY: Lazy<AutoMatchmakeParam> = Lazy::new(|| AutoMatchmakeParam{
|
|
||||||
additional_participants: vec![1,2,3,4],
|
|
||||||
auto_matchmake_option: 10,
|
|
||||||
gid_for_participation_check: 9,
|
|
||||||
join_message: "hi".to_string(),
|
|
||||||
participation_count: 32,
|
|
||||||
target_gids: vec![45,2,51,1,1,1,1],
|
|
||||||
search_criteria: vec![MatchmakeSessionSearchCriteria{
|
|
||||||
attribs: vec!["hi".to_string(), "ig".to_string(), "gotta put data here".to_string()],
|
|
||||||
exclude_locked: true,
|
|
||||||
exclude_non_host_pid: false,
|
|
||||||
exclude_system_password_set: true,
|
|
||||||
exclude_user_password_set: false,
|
|
||||||
game_mode: "some gamemode".to_string(),
|
|
||||||
matchmake_param: MatchmakeParam{
|
|
||||||
params: vec![
|
|
||||||
("SR".to_string(), Variant::Bool(true)),
|
|
||||||
("SR2".to_string(), Variant::Double(1.0)),
|
|
||||||
("SR3".to_string(), Variant::SInt64(42)),
|
|
||||||
("SR4".to_string(), Variant::String("test".to_string()))
|
|
||||||
]
|
|
||||||
},
|
|
||||||
matchmake_system_type: "some type".to_string(),
|
|
||||||
maximum_participants: "???".to_string(),
|
|
||||||
minimum_participants: "-99".to_string(),
|
|
||||||
refer_gid: 123,
|
|
||||||
selection_method: 9999999,
|
|
||||||
vacant_only: true,
|
|
||||||
vacant_participants: 1000
|
|
||||||
}],
|
|
||||||
matchmake_session: MatchmakeSession{
|
|
||||||
refer_gid: 10,
|
|
||||||
matchmake_system_type: 139,
|
|
||||||
matchmake_param: MatchmakeParam{
|
|
||||||
params: vec![
|
|
||||||
("QSR".to_string(), Variant::Bool(false)),
|
|
||||||
("SRQ2".to_string(), Variant::Double(1.1)),
|
|
||||||
("SQR3".to_string(), Variant::SInt64(422)),
|
|
||||||
("SDR4".to_string(), Variant::String("tetst".to_string()))
|
|
||||||
]
|
|
||||||
},
|
|
||||||
participation_count: 99,
|
|
||||||
application_buffer: vec![1,2,3,4,5,6,7,8,9],
|
|
||||||
attributes: vec![10,20,99,100000],
|
|
||||||
datetime: KerberosDateTime::now(),
|
|
||||||
gamemode: 111,
|
|
||||||
open_participation: false,
|
|
||||||
option0: 100,
|
|
||||||
progress_score: 1,
|
|
||||||
system_password_enabled: false,
|
|
||||||
user_password: "aaa".to_string(),
|
|
||||||
session_key: vec![91,123,5,2,1,2,4,124,4],
|
|
||||||
user_password_enabled: false,
|
|
||||||
gathering: Gathering{
|
|
||||||
minimum_participants: 1,
|
|
||||||
maximum_participants: 12,
|
|
||||||
description: "aaargh".to_string(),
|
|
||||||
flags: 100,
|
|
||||||
host_pid: 999999919,
|
|
||||||
owner_pid: 138830,
|
|
||||||
participant_policy: 1,
|
|
||||||
policy_argument: 99837,
|
|
||||||
self_gid: 129,
|
|
||||||
state: 1389488
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
static DUMMY_SER: Lazy<Vec<u8>> = Lazy::new(|| serialize_to_vec(DUMMY.deref()));
|
|
||||||
|
|
||||||
fn serialize_to_vec(r: &impl RmcSerialize) -> Vec<u8>{
|
|
||||||
let mut vec = r.to_data();
|
|
||||||
|
|
||||||
vec.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_struct<T: RmcSerialize>(r: &[u8]) -> T{
|
|
||||||
T::deserialize(&mut Cursor::new(r)).unwrap()
|
|
||||||
}
|
|
||||||
fn matchmake_with_param(c: &mut Criterion) {
|
|
||||||
let raw = DUMMY.deref();
|
|
||||||
let ser = DUMMY_SER.deref().as_slice();
|
|
||||||
c.bench_function("mmparam: ser", |b| b.iter(move || serialize_to_vec(black_box(raw))));
|
|
||||||
c.bench_function("mmparam: de", |b| b.iter(move || read_struct::<AutoMatchmakeParam>(black_box(ser))));
|
|
||||||
}
|
|
||||||
|
|
||||||
criterion_group!(benches, matchmake_with_param);
|
|
||||||
criterion_main!(benches);
|
|
||||||
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use rnex_core::common::with_setup;
|
|
||||||
use rnex_core::executables::common::{SECURE_SERVER_ACCOUNT, new_simple_backend};
|
|
||||||
use rnex_core::nex::auth_handler::AuthHandler;
|
|
||||||
use rnex_core::reggie::EdgeNodeHolderConnectOption::DontRegister;
|
|
||||||
use rnex_core::reggie::RemoteEdgeNodeHolder;
|
|
||||||
use rnex_core::rmc::protocols::{OnlyRemote, new_rmc_gateway_connection};
|
|
||||||
use rnex_core::rmc::structures::RmcSerialize;
|
|
||||||
use rnex_core::util::SplittableBufferConnection;
|
|
||||||
use std::env;
|
|
||||||
use std::net::SocketAddrV4;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::net::TcpStream;
|
|
||||||
|
|
||||||
pub static FORWARD_EDGE_NODE_HOLDER: Lazy<SocketAddrV4> = Lazy::new(|| {
|
|
||||||
env::var("FORWARD_EDGE_NODE_HOLDER")
|
|
||||||
.ok()
|
|
||||||
.and_then(|s| Some(s.parse().unwrap()))
|
|
||||||
.expect("FORWARD_EDGE_NODE_HOLDER not set")
|
|
||||||
});
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
with_setup(async || {
|
|
||||||
let conn = TcpStream::connect(&*FORWARD_EDGE_NODE_HOLDER)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let conn: SplittableBufferConnection = conn.into();
|
|
||||||
|
|
||||||
conn.send(DontRegister.to_data().unwrap()).await;
|
|
||||||
|
|
||||||
let conn = new_rmc_gateway_connection(conn, |r| {
|
|
||||||
Arc::new(OnlyRemote::<RemoteEdgeNodeHolder>::new(r))
|
|
||||||
});
|
|
||||||
|
|
||||||
new_simple_backend(move |_, _| {
|
|
||||||
let controller = conn.clone();
|
|
||||||
Arc::new(AuthHandler {
|
|
||||||
destination_server_acct: &SECURE_SERVER_ACCOUNT,
|
|
||||||
build_name: env!("AUTH_REPORT_VERSION"),
|
|
||||||
control_server: controller,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
use cfg_if::cfg_if;
|
|
||||||
use rnex_core::common::with_setup;
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
with_setup(async || {
|
|
||||||
#[cfg(feature = "database-support")]
|
|
||||||
{
|
|
||||||
use rnex_core::executables::common::DB_POOL;
|
|
||||||
use sqlx::PgPool;
|
|
||||||
let database_url = std::env::var("RNEX_DATASTORE_DATABASE_URL")
|
|
||||||
.expect("RNEX_DATASTORE_DATABASE_URL must be set");
|
|
||||||
|
|
||||||
let pool = PgPool::connect(&database_url)
|
|
||||||
.await
|
|
||||||
.expect("Failed to create pool");
|
|
||||||
|
|
||||||
DB_POOL.set(pool).expect("failed to set global DB_POOL");
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(feature = "friends")]{
|
|
||||||
use rnex_core::executables::friends_backend::start_friends_backend;
|
|
||||||
start_friends_backend().await;
|
|
||||||
} else {
|
|
||||||
use rnex_core::executables::regular_backend;
|
|
||||||
regular_backend::start_regular_backend().await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
@ -1,171 +0,0 @@
|
||||||
use crate::reggie::UnitPacketRead;
|
|
||||||
use cfg_if::cfg_if;
|
|
||||||
use rnex_core::nex::account::Account;
|
|
||||||
use rnex_core::rmc::protocols::{RmcCallable, RmcConnection, new_rmc_gateway_connection};
|
|
||||||
use rnex_core::rmc::structures::RmcSerialize;
|
|
||||||
use rnex_core::rnex_proxy_common::ConnectionInitData;
|
|
||||||
use std::env;
|
|
||||||
use std::error::Error;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::io::{Cursor, Read, Write};
|
|
||||||
use std::net::{Ipv4Addr, SocketAddrV4, TcpStream};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::net::TcpListener;
|
|
||||||
use tracing::error;
|
|
||||||
|
|
||||||
const IP_REQ_SERVICE_URLS: &[(&str, &str, &str)] = &[
|
|
||||||
("ipinfo.io:80", "ipinfo.io", "/ip"),
|
|
||||||
("api.ipify.org:80", "api.ipify.org", "/"),
|
|
||||||
// preresolved
|
|
||||||
("34.117.59.81:80", "ipinfo.io", "/ip"),
|
|
||||||
("104.26.13.205:80", "api.ipify.org", "/"),
|
|
||||||
("172.67.74.152:80", "api.ipify.org", "/"),
|
|
||||||
("104.26.12.205:80", "api.ipify.org", "/"),
|
|
||||||
];
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(feature = "database-support")] {
|
|
||||||
use std::sync::{LazyLock, OnceLock};
|
|
||||||
use sqlx::postgres::PgPool;
|
|
||||||
pub static RNEX_DATABASE_URL: LazyLock<String> = LazyLock::new(|| {
|
|
||||||
std::env::var("RNEX_DATABASE_URL")
|
|
||||||
.expect("RNEX_DATABASE_URL must be set")
|
|
||||||
});
|
|
||||||
|
|
||||||
pub static DB_POOL: OnceLock<PgPool> = OnceLock::new();
|
|
||||||
|
|
||||||
pub fn get_db() -> &'static PgPool {
|
|
||||||
DB_POOL.get().expect("db_pool not initialized")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(feature = "datastore")]{
|
|
||||||
pub static RNEX_DATASTORE_S3_ENDPOINT: LazyLock<String> = LazyLock::new(|| {
|
|
||||||
std::env::var("RNEX_DATASTORE_S3_ENDPOINT")
|
|
||||||
.expect("RNEX_DATASTORE_S3_ENDPOINT must be set")
|
|
||||||
});
|
|
||||||
pub static RNEX_DATASTORE_S3_BUCKET: LazyLock<String> = LazyLock::new(|| {
|
|
||||||
std::env::var("RNEX_DATASTORE_S3_BUCKET")
|
|
||||||
.expect("RNEX_DATASTORE_S3_BUCKET must be set")
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_to_log<R, E: Display>(fun: impl FnOnce() -> Result<R, E>) -> Option<R> {
|
|
||||||
match fun() {
|
|
||||||
Ok(v) => Some(v),
|
|
||||||
Err(e) => {
|
|
||||||
println!("{}", e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_get_ip() -> Option<Ipv4Addr> {
|
|
||||||
for url in IP_REQ_SERVICE_URLS {
|
|
||||||
println!("trying to get ip via: {:?}", url);
|
|
||||||
if let Some(v) = try_to_log::<_, Box<dyn Error>>(|| {
|
|
||||||
let mut stream = TcpStream::connect(url.0)?;
|
|
||||||
stream.write_all(
|
|
||||||
format!(
|
|
||||||
"GET {} HTTP/1.0
|
|
||||||
Host: {}
|
|
||||||
User-Agent: RNEX
|
|
||||||
Accept: */*
|
|
||||||
|
|
||||||
",
|
|
||||||
url.2, url.1
|
|
||||||
)
|
|
||||||
.as_str()
|
|
||||||
.as_bytes(),
|
|
||||||
)?;
|
|
||||||
let mut data = vec![];
|
|
||||||
stream.read_to_end(&mut data)?;
|
|
||||||
let string = String::from_utf8(data)?;
|
|
||||||
let (_, ip) = string
|
|
||||||
.split_once("\r\n\r\n")
|
|
||||||
.ok_or("unable to get ip from response")?;
|
|
||||||
Ok(ip.parse()?)
|
|
||||||
}) {
|
|
||||||
return Some(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub static OWN_IP_PRIVATE: LazyLock<Ipv4Addr> = LazyLock::new(|| {
|
|
||||||
env::var("SERVER_IP")
|
|
||||||
.ok()
|
|
||||||
.map(|s| s.parse().expect("invalid ip address"))
|
|
||||||
.unwrap_or(Ipv4Addr::UNSPECIFIED)
|
|
||||||
});
|
|
||||||
|
|
||||||
pub static OWN_IP_PUBLIC: LazyLock<Ipv4Addr> = LazyLock::new(|| {
|
|
||||||
env::var("SERVER_IP_PUBLIC")
|
|
||||||
.ok()
|
|
||||||
.map(|s| s.parse().expect("invalid ip address"))
|
|
||||||
.unwrap_or_else(|| try_get_ip().unwrap())
|
|
||||||
});
|
|
||||||
|
|
||||||
pub static SERVER_PORT: LazyLock<u16> = LazyLock::new(|| {
|
|
||||||
env::var("SERVER_PORT")
|
|
||||||
.ok()
|
|
||||||
.and_then(|s| s.parse().ok())
|
|
||||||
.unwrap_or(10000)
|
|
||||||
});
|
|
||||||
|
|
||||||
pub static KERBEROS_SERVER_PASSWORD: LazyLock<String> = LazyLock::new(|| {
|
|
||||||
env::var("AUTH_SERVER_PASSWORD")
|
|
||||||
.ok()
|
|
||||||
.unwrap_or("password".to_owned())
|
|
||||||
});
|
|
||||||
|
|
||||||
pub static AUTH_SERVER_ACCOUNT: LazyLock<Account> =
|
|
||||||
LazyLock::new(|| Account::new(1, "Quazal Authentication", &KERBEROS_SERVER_PASSWORD));
|
|
||||||
pub static SECURE_SERVER_ACCOUNT: LazyLock<Account> =
|
|
||||||
LazyLock::new(|| Account::new(2, "Quazal Rendez-Vous", &KERBEROS_SERVER_PASSWORD));
|
|
||||||
|
|
||||||
pub async fn new_simple_backend<T: RmcCallable + Sync + Send + 'static, F>(mut creation_function: F)
|
|
||||||
where
|
|
||||||
F: FnMut(ConnectionInitData, RmcConnection) -> Arc<T>,
|
|
||||||
{
|
|
||||||
let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
while let Ok((mut stream, _addr)) = listen.accept().await {
|
|
||||||
let buffer = match stream.read_buffer().await {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
error!(
|
|
||||||
"an error ocurred whilst reading connection data buffer: {:?}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let user_connection_data = ConnectionInitData::deserialize(&mut Cursor::new(buffer));
|
|
||||||
|
|
||||||
let user_connection_data = match user_connection_data {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
error!("an error ocurred whilst reading connection data: {:?}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let fun_ref = &mut creation_function;
|
|
||||||
new_rmc_gateway_connection(stream.into(), move |r| fun_ref(user_connection_data, r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
|
|
||||||
use crate::executables::common::try_get_ip;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn get_ip() {
|
|
||||||
println!("{}", try_get_ip().unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
use macros::rmc_struct;
|
|
||||||
use rnex_core::common::with_setup;
|
|
||||||
use rnex_core::executables::common::{OWN_IP_PRIVATE, SERVER_PORT};
|
|
||||||
use rnex_core::reggie::{EdgeNodeHolderConnectOption, EdgeNodeManagement, LocalEdgeNodeHolder};
|
|
||||||
use rnex_core::rmc::protocols::new_rmc_gateway_connection;
|
|
||||||
use rnex_core::rmc::response::ErrorCode;
|
|
||||||
use rnex_core::rmc::structures::RmcSerialize;
|
|
||||||
use rnex_core::util::SplittableBufferConnection;
|
|
||||||
use std::io::Cursor;
|
|
||||||
use std::net::SocketAddrV4;
|
|
||||||
use std::sync::{Arc, Weak};
|
|
||||||
use tokio::net::TcpListener;
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
#[rmc_struct(EdgeNodeHolder)]
|
|
||||||
struct EdgeNode {
|
|
||||||
data_holder: Arc<DataHolder>,
|
|
||||||
address: SocketAddrV4,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EdgeNodeManagement for EdgeNode {
|
|
||||||
async fn get_url(&self, seed: u64) -> Result<SocketAddrV4, ErrorCode> {
|
|
||||||
self.data_holder.get_url(seed).await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rmc_struct(EdgeNodeHolder)]
|
|
||||||
#[derive(Default)]
|
|
||||||
struct DataHolder {
|
|
||||||
edge_nodes: RwLock<Vec<Weak<EdgeNode>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EdgeNodeManagement for DataHolder {
|
|
||||||
async fn get_url(&self, seed: u64) -> Result<SocketAddrV4, ErrorCode> {
|
|
||||||
let nodes = self.edge_nodes.read().await;
|
|
||||||
|
|
||||||
let nodes: Vec<_> = nodes.iter().filter_map(|n| n.upgrade()).collect();
|
|
||||||
|
|
||||||
// avoid a devide by zero
|
|
||||||
if nodes.len() == 0 {
|
|
||||||
return Err(ErrorCode::Core_InvalidIndex);
|
|
||||||
};
|
|
||||||
|
|
||||||
let node = &nodes[seed as usize % nodes.len()];
|
|
||||||
|
|
||||||
Ok(node.address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() {
|
|
||||||
with_setup(async || {
|
|
||||||
log::error!("test");
|
|
||||||
let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let holder: Arc<DataHolder> = Default::default();
|
|
||||||
|
|
||||||
while let Ok((stream, _addr)) = listen.accept().await {
|
|
||||||
let mut conn: SplittableBufferConnection = stream.into();
|
|
||||||
|
|
||||||
let Some(data) = conn.recv().await else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let Ok(data) = EdgeNodeHolderConnectOption::deserialize(&mut Cursor::new(data)) else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
|
|
||||||
let holder = holder.clone();
|
|
||||||
|
|
||||||
match data {
|
|
||||||
EdgeNodeHolderConnectOption::DontRegister => {
|
|
||||||
new_rmc_gateway_connection(conn, |_| holder);
|
|
||||||
}
|
|
||||||
EdgeNodeHolderConnectOption::Register(address) => {
|
|
||||||
let edge_node = EdgeNode {
|
|
||||||
address,
|
|
||||||
data_holder: holder.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let node = new_rmc_gateway_connection(conn, move |_| Arc::new(edge_node));
|
|
||||||
|
|
||||||
let mut nodes = holder.edge_nodes.write().await;
|
|
||||||
nodes.push(Arc::downgrade(&node));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
use std::{
|
|
||||||
io::Cursor,
|
|
||||||
net::SocketAddrV4,
|
|
||||||
sync::{Arc, atomic::AtomicU32},
|
|
||||||
};
|
|
||||||
|
|
||||||
use tokio::net::TcpListener;
|
|
||||||
use tracing::error;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
executables::common::{OWN_IP_PRIVATE, SERVER_PORT},
|
|
||||||
nex::friends_handler::{FriendsGuest, FriendsManager, FriendsUser, RemoteFriendRemote},
|
|
||||||
reggie::UnitPacketRead,
|
|
||||||
rmc::{
|
|
||||||
protocols::{RmcPureRemoteObject, new_rmc_gateway_connection},
|
|
||||||
structures::RmcSerialize,
|
|
||||||
},
|
|
||||||
rnex_proxy_common::ConnectionInitData,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub async fn start_friends_backend() {
|
|
||||||
let fm = Arc::new(FriendsManager {
|
|
||||||
cid_counter: AtomicU32::new(1),
|
|
||||||
users: Default::default(),
|
|
||||||
});
|
|
||||||
let listen = TcpListener::bind(SocketAddrV4::new(*OWN_IP_PRIVATE, *SERVER_PORT))
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
while let Ok((mut stream, _addr)) = listen.accept().await {
|
|
||||||
let buffer = match stream.read_buffer().await {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
error!(
|
|
||||||
"an error ocurred whilst reading connection data buffer: {:?}",
|
|
||||||
e
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let user_connection_data = ConnectionInitData::deserialize(&mut Cursor::new(buffer));
|
|
||||||
|
|
||||||
let c = match user_connection_data {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
error!("an error ocurred whilst reading connection data: {:?}", e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let fm = fm.clone();
|
|
||||||
if c.pid != 100 {
|
|
||||||
new_rmc_gateway_connection(stream.into(), move |r| {
|
|
||||||
Arc::new_cyclic(move |this| FriendsUser {
|
|
||||||
fm,
|
|
||||||
addr: c.prudpsock_addr,
|
|
||||||
pid: c.pid,
|
|
||||||
this: this.clone(),
|
|
||||||
remote: RemoteFriendRemote::new(r),
|
|
||||||
friend_pids: Default::default(),
|
|
||||||
maybe_remote_friend: Default::default(),
|
|
||||||
presence: Default::default(),
|
|
||||||
})
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
new_rmc_gateway_connection(stream.into(), move |_| {
|
|
||||||
Arc::new_cyclic(move |_| FriendsGuest {
|
|
||||||
fm,
|
|
||||||
addr: c.prudpsock_addr,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
use cfg_if::cfg_if;
|
|
||||||
|
|
||||||
pub mod common;
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(feature = "friends")]{
|
|
||||||
pub mod friends_backend;
|
|
||||||
} else {
|
|
||||||
pub mod regular_backend;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
use std::sync::{Arc, atomic::AtomicU32};
|
|
||||||
|
|
||||||
use tokio::sync::{Mutex, mpsc::channel};
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
executables::common::new_simple_backend,
|
|
||||||
nex::{
|
|
||||||
matchmake::MatchmakeManager,
|
|
||||||
remote_console::RemoteConsole,
|
|
||||||
user::{ConnectionTicket, User},
|
|
||||||
},
|
|
||||||
rmc::protocols::RmcPureRemoteObject,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub async fn start_regular_backend() {
|
|
||||||
let mmm = Arc::new(MatchmakeManager {
|
|
||||||
//gid_counter: AtomicU32::new(1),
|
|
||||||
sessions: Default::default(),
|
|
||||||
users: Default::default(),
|
|
||||||
users_by_pid: Default::default(),
|
|
||||||
rv_cid_counter: AtomicU32::new(1),
|
|
||||||
});
|
|
||||||
|
|
||||||
let weak_mmm = Arc::downgrade(&mmm);
|
|
||||||
|
|
||||||
MatchmakeManager::initialize_garbage_collect_thread(weak_mmm).await;
|
|
||||||
|
|
||||||
new_simple_backend(move |c, r| {
|
|
||||||
let mmm = mmm.clone();
|
|
||||||
Arc::new_cyclic(move |this| {
|
|
||||||
let (join_tickets_stage1_sender, join_tickets_stage1_recv) =
|
|
||||||
channel::<ConnectionTicket>(100);
|
|
||||||
let join_tickets_stage1_recv = Mutex::new(join_tickets_stage1_recv);
|
|
||||||
|
|
||||||
let (join_tickets_stage2_sender, join_tickets_stage2_recv) =
|
|
||||||
channel::<ConnectionTicket>(100);
|
|
||||||
let join_tickets_stage2_recv = Mutex::new(join_tickets_stage2_recv);
|
|
||||||
let cid = mmm.next_cid();
|
|
||||||
|
|
||||||
User {
|
|
||||||
cid,
|
|
||||||
this: this.clone(),
|
|
||||||
ip: c.prudpsock_addr,
|
|
||||||
pid: c.pid,
|
|
||||||
remote: RemoteConsole::new(r),
|
|
||||||
matchmake_manager: mmm,
|
|
||||||
station_url: Default::default(),
|
|
||||||
join_tickets_stage1_recv,
|
|
||||||
join_tickets_stage1_sender,
|
|
||||||
join_tickets_stage2_recv,
|
|
||||||
join_tickets_stage2_sender,
|
|
||||||
self_join_ticket_requesters: Default::default(),
|
|
||||||
remote_join_ticket_requesters: Default::default(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#![allow(dead_code)]
|
|
||||||
// rnex makes extensive use of async functions in public traits
|
|
||||||
// this is however fine because these traits should never(and i mean NEVER) be used dynamically
|
|
||||||
#![allow(async_fn_in_trait)]
|
|
||||||
//#![warn(missing_docs)]
|
|
||||||
|
|
||||||
pub use ctor::ctor;
|
|
||||||
|
|
||||||
pub mod prudp;
|
|
||||||
pub mod rmc;
|
|
||||||
//mod protocols;
|
|
||||||
|
|
||||||
pub mod common;
|
|
||||||
pub mod executables;
|
|
||||||
pub mod grpc;
|
|
||||||
pub mod kerberos;
|
|
||||||
pub mod nex;
|
|
||||||
pub mod reggie;
|
|
||||||
pub mod rnex_proxy_common;
|
|
||||||
pub mod util;
|
|
||||||
pub mod versions;
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
use rnex_core::prudp::station_url::StationUrl;
|
|
||||||
use rnex_core::prudp::station_url::UrlOptions::{
|
|
||||||
Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID,
|
|
||||||
};
|
|
||||||
use rnex_core::prudp::station_url::nat_types::PUBLIC;
|
|
||||||
use rnex_core::rmc::response::ErrorCode::Core_Exception;
|
|
||||||
|
|
||||||
use rnex_core::prudp::socket_addr::PRUDPSockAddr;
|
|
||||||
use rnex_core::rmc::response::ErrorCode;
|
|
||||||
|
|
||||||
use rnex_core::PID;
|
|
||||||
|
|
||||||
use crate::prudp::station_url::UrlOptions::ConnectionID;
|
|
||||||
|
|
||||||
pub async fn get_station_urls(
|
|
||||||
station_urls: &[StationUrl],
|
|
||||||
addr: PRUDPSockAddr,
|
|
||||||
pid: PID,
|
|
||||||
cid: u32,
|
|
||||||
) -> Result<Vec<StationUrl>, ErrorCode> {
|
|
||||||
let mut public_station: Option<StationUrl> = None;
|
|
||||||
let mut private_station: Option<StationUrl> = None;
|
|
||||||
|
|
||||||
for station in station_urls {
|
|
||||||
let is_public = station.options.iter().any(|v| {
|
|
||||||
if let NatType(v) = v
|
|
||||||
&& *v & PUBLIC != 0
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
});
|
|
||||||
|
|
||||||
let Some(nat_filtering) = station.options.iter().find_map(|v| match v {
|
|
||||||
NatFiltering(v) => Some(v),
|
|
||||||
_ => None,
|
|
||||||
}) else {
|
|
||||||
return Err(Core_Exception);
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(nat_mapping) = station.options.iter().find_map(|v| match v {
|
|
||||||
NatMapping(v) => Some(v),
|
|
||||||
_ => None,
|
|
||||||
}) else {
|
|
||||||
return Err(Core_Exception);
|
|
||||||
};
|
|
||||||
|
|
||||||
if !is_public || (*nat_filtering == 0 && *nat_mapping == 0) {
|
|
||||||
private_station = Some(station.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_public {
|
|
||||||
public_station = Some(station.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(mut private_station) = private_station else {
|
|
||||||
return Err(Core_Exception);
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut public_station = if let Some(public_station) = public_station {
|
|
||||||
public_station
|
|
||||||
} else {
|
|
||||||
let mut public_station = private_station.clone();
|
|
||||||
|
|
||||||
public_station.options.retain(|v| {
|
|
||||||
!matches!(
|
|
||||||
v,
|
|
||||||
Address(_) | Port(_) | NatFiltering(_) | NatMapping(_) | NatType(_)
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
public_station
|
|
||||||
.options
|
|
||||||
.push(Address(addr.regular_socket_addr.ip()));
|
|
||||||
public_station
|
|
||||||
.options
|
|
||||||
.push(Port(addr.regular_socket_addr.port()));
|
|
||||||
public_station.options.push(NatFiltering(0));
|
|
||||||
public_station.options.push(NatMapping(0));
|
|
||||||
public_station.options.push(NatType(3));
|
|
||||||
|
|
||||||
public_station
|
|
||||||
};
|
|
||||||
|
|
||||||
let both = [&mut public_station, &mut private_station];
|
|
||||||
|
|
||||||
for station in both {
|
|
||||||
station
|
|
||||||
.options
|
|
||||||
.retain(|v| !matches!(v, PrincipalID(_) | RVConnectionID(_)));
|
|
||||||
|
|
||||||
station.options.push(PrincipalID(pid));
|
|
||||||
station.options.push(RVConnectionID(cid));
|
|
||||||
station.options.push(ConnectionID(cid));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(vec![public_station])
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
#[cfg(feature = "database-support")]
|
|
||||||
fn test() {}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
use cfg_if::cfg_if;
|
|
||||||
|
|
||||||
pub mod account;
|
|
||||||
pub mod auth_handler;
|
|
||||||
pub mod common;
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(feature = "friends")]{
|
|
||||||
pub mod friends_handler;
|
|
||||||
} else {
|
|
||||||
pub mod matchmake;
|
|
||||||
pub mod remote_console;
|
|
||||||
pub mod user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg_if! {
|
|
||||||
if #[cfg(feature = "datastore")] {
|
|
||||||
pub mod s3presigner;
|
|
||||||
pub mod datastore;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
use crate::define_rmc_proto;
|
|
||||||
use crate::rmc::protocols::message_delivery::{
|
|
||||||
MessageDeliveryNoResponse, RawMessageDeliveryNoResponse, RawMessageDeliveryNoResponseInfo,
|
|
||||||
RemoteMessageDeliveryNoResponse,
|
|
||||||
};
|
|
||||||
use crate::rmc::protocols::nat_traversal::{
|
|
||||||
NatTraversalConsole, RawNatTraversalConsole, RawNatTraversalConsoleInfo,
|
|
||||||
RemoteNatTraversalConsole,
|
|
||||||
};
|
|
||||||
use crate::rmc::protocols::notifications::{
|
|
||||||
Notification, RawNotification, RawNotificationInfo, RemoteNotification,
|
|
||||||
};
|
|
||||||
|
|
||||||
define_rmc_proto!(
|
|
||||||
proto Console{
|
|
||||||
Notification,
|
|
||||||
NatTraversalConsole,
|
|
||||||
MessageDeliveryNoResponse
|
|
||||||
}
|
|
||||||
);
|
|
||||||
/*
|
|
||||||
#[rmc_struct(Console)]
|
|
||||||
pub struct TestRemoteConsole{
|
|
||||||
pub remote: RemoteUserProtocol,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Notification for TestRemoteConsole{
|
|
||||||
async fn process_notification_event(&self, event: NotificationEvent) {
|
|
||||||
println!("NOTIF RECIEVED: {:?}", event);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
use rnex_rmc::{
|
use rnex_rmc::{
|
||||||
RmcSerialize, any::Any, data::Data, method_id, qresult::QResult, response::ErrorCode,
|
RmcSerialize, any::Any, data::Data, method_id, qbuffer::QBuffer, qresult::QResult, response::ErrorCode, rmc_proto, util::station_url::StationUrl
|
||||||
rmc_proto, util::station_url::StationUrl,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(RmcSerialize)]
|
#[derive(RmcSerialize)]
|
||||||
|
|
@ -35,4 +34,6 @@ pub trait Secure {
|
||||||
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
) -> Result<(QResult, u32, StationUrl), ErrorCode>;
|
||||||
#[method_id(7)]
|
#[method_id(7)]
|
||||||
async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode>;
|
async fn replace_url(&self, target: StationUrl, dest: StationUrl) -> Result<(), ErrorCode>;
|
||||||
|
#[method_id(8)]
|
||||||
|
async fn send_report(&self, id: u32, data: QBuffer) -> Result<(), ErrorCode>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use rnex_base_protos::{LocalBaseProtocol, secure::Secure, util::Utility};
|
use rnex_base_protos::{LocalBaseProtocol, secure::Secure, util::Utility};
|
||||||
use rnex_rmc::{any::Any, qresult::QResult, response::ErrorCode, rmc_struct};
|
use rnex_rmc::{any::Any, qbuffer::QBuffer, qresult::QResult, response::ErrorCode, rmc_struct};
|
||||||
use rnex_util::{
|
use rnex_util::{
|
||||||
PID,
|
PID,
|
||||||
station_url::{StationUrl, UrlOptions, nat_types::PUBLIC},
|
station_url::{StationUrl, UrlOptions, nat_types::PUBLIC},
|
||||||
|
|
@ -176,6 +176,10 @@ impl Secure for BaseUser {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn send_report(&self,id: u32,data: QBuffer) -> Result<(),ErrorCode> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Utility for BaseUser {
|
impl Utility for BaseUser {
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ macro_rules! launch_rnex_module_server {
|
||||||
{
|
{
|
||||||
$init_ty:ty;
|
$init_ty:ty;
|
||||||
$(
|
$(
|
||||||
$(#[$($tt:tt)*])*
|
$(#[$meta:meta])*
|
||||||
$module_type:ty
|
$module_type:ty
|
||||||
),* $(,)?} => {{
|
),* $(,)?} => {{
|
||||||
use $crate::tracing::Instrument;
|
use $crate::tracing::Instrument;
|
||||||
|
|
@ -165,22 +165,22 @@ macro_rules! launch_rnex_module_server {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct MultiEndpoint {
|
struct MultiEndpoint {
|
||||||
$(
|
$(
|
||||||
$(#[$($tt)*])*
|
$(#[$meta])*
|
||||||
[<user_ $module_type>]: $crate::PassthroughInitModule<
|
[<user_ $module_type>]: $crate::PassthroughInitModule<
|
||||||
<<$module_type as $crate::RnexModule>::Manager as $crate::RnexManager>::User,
|
<<$module_type as $crate::RnexModule>::Manager as $crate::RnexManager>::User,
|
||||||
>
|
>,
|
||||||
),*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$crate::paste::paste!{
|
$crate::paste::paste!{
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct MultiManager {
|
struct MultiManager {
|
||||||
$(
|
$(
|
||||||
$(#[$($tt)*])*
|
$(#[$meta])*
|
||||||
[<manager_ $module_type>]: $crate::PassthroughInitModule<
|
[<manager_ $module_type>]: $crate::PassthroughInitModule<
|
||||||
<$module_type as $crate::RnexModule>::Manager,
|
<$module_type as $crate::RnexModule>::Manager,
|
||||||
>
|
>,
|
||||||
),*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl $crate::rmc::RmcCallable for MultiEndpoint {
|
impl $crate::rmc::RmcCallable for MultiEndpoint {
|
||||||
|
|
@ -191,13 +191,13 @@ macro_rules! launch_rnex_module_server {
|
||||||
method_id: u32,
|
method_id: u32,
|
||||||
call_id: u32,
|
call_id: u32,
|
||||||
rest: &[u8],
|
rest: &[u8],
|
||||||
) -> bool{
|
) -> bool {
|
||||||
$(
|
$(
|
||||||
$(#[$($tt)*])*
|
$(#[$meta])*
|
||||||
$crate::paste::paste!{
|
$crate::paste::paste!{
|
||||||
if self. [<user_ $module_type>]
|
if self.[<user_ $module_type>]
|
||||||
.rmc_call(responder, protocol_id, method_id, call_id, rest)
|
.rmc_call(responder, protocol_id, method_id, call_id, rest)
|
||||||
.await{
|
.await {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -210,22 +210,22 @@ macro_rules! launch_rnex_module_server {
|
||||||
let mut holder = $crate::ModuleHolder::default();
|
let mut holder = $crate::ModuleHolder::default();
|
||||||
|
|
||||||
$(
|
$(
|
||||||
$(#[$($tt)*])*
|
$(#[$meta])*
|
||||||
$crate::tracing::info!(
|
$crate::tracing::info!(
|
||||||
module_manager = ::std::any::type_name::<<$module_type as $crate::RnexModule>::Manager>(),
|
module_manager = ::std::any::type_name::<<$module_type as $crate::RnexModule>::Manager>(),
|
||||||
"creating module slot"
|
"creating module slot"
|
||||||
);
|
);
|
||||||
$(#[$($tt)*])*
|
$(#[$meta])*
|
||||||
holder.create_empty_module_slot::<<$module_type as $crate::RnexModule>::Manager>();
|
holder.create_empty_module_slot::<<$module_type as $crate::RnexModule>::Manager>();
|
||||||
)*
|
)*
|
||||||
|
|
||||||
$(
|
$(
|
||||||
$(#[$($tt)*])*
|
$(#[$meta])*
|
||||||
$crate::tracing::info!(
|
$crate::tracing::info!(
|
||||||
module_manager = ::std::any::type_name::<<$module_type as $crate::RnexModule>::Manager>(),
|
module_manager = ::std::any::type_name::<<$module_type as $crate::RnexModule>::Manager>(),
|
||||||
"initializing and filling module slot"
|
"initializing and filling module slot"
|
||||||
);
|
);
|
||||||
$(#[$($tt)*])*
|
$(#[$meta])*
|
||||||
let $crate::paste::paste!{[<manager_ $module_type>]} = holder
|
let $crate::paste::paste!{[<manager_ $module_type>]} = holder
|
||||||
.init_slot::<<$module_type as $crate::RnexModule>::Manager>(
|
.init_slot::<<$module_type as $crate::RnexModule>::Manager>(
|
||||||
<$module_type as $crate::RnexModule>::create_manager(&holder).await?,
|
<$module_type as $crate::RnexModule>::create_manager(&holder).await?,
|
||||||
|
|
@ -233,8 +233,8 @@ macro_rules! launch_rnex_module_server {
|
||||||
.expect("initialized manager twice");
|
.expect("initialized manager twice");
|
||||||
)*
|
)*
|
||||||
$crate::paste::paste!{
|
$crate::paste::paste!{
|
||||||
Ok::<_, $crate::anyhow::Error>(MultiManager{
|
Ok::<_, $crate::anyhow::Error>(MultiManager {
|
||||||
$( $(#[$($tt)*])* [<manager_ $module_type>] ),*
|
$( $(#[$meta])* [<manager_ $module_type>] ),*
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -247,7 +247,7 @@ macro_rules! launch_rnex_module_server {
|
||||||
while let Ok((mut stream, _addr)) = socket.accept().await {
|
while let Ok((mut stream, _addr)) = socket.accept().await {
|
||||||
$crate::tracing::info!("new incoming connection");
|
$crate::tracing::info!("new incoming connection");
|
||||||
async {
|
async {
|
||||||
let Some(conn_data) = async {
|
let Some(conn_data) = async {
|
||||||
let buffer = match stream.read_buffer().await {
|
let buffer = match stream.read_buffer().await {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -274,39 +274,51 @@ macro_rules! launch_rnex_module_server {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
$crate::rmc::new_rmc_gateway_connection(stream.into(),
|
$crate::rmc::new_rmc_gateway_connection(stream.into(),
|
||||||
async |r| {
|
async |r| {
|
||||||
$crate::tracing::info!("creating module holder for module users");
|
$crate::tracing::info!("creating module holder for module users");
|
||||||
let mut holder = $crate::ModuleHolder::default();
|
let mut holder = $crate::ModuleHolder::default();
|
||||||
|
|
||||||
$(
|
$(
|
||||||
$(#[$($tt)*])*
|
$(#[$meta])*
|
||||||
$crate::tracing::info!(
|
$crate::tracing::info!(
|
||||||
module_manager = ::std::any::type_name::<<<$module_type as $crate::RnexModule>::Manager as $crate::RnexManager>::User>(),
|
module_manager = ::std::any::type_name::<<<$module_type as $crate::RnexModule>::Manager as $crate::RnexManager>::User>(),
|
||||||
"creating user module slot"
|
"creating user module slot"
|
||||||
);
|
);
|
||||||
$(#[$($tt)*])*
|
$(#[$meta])*
|
||||||
holder.create_empty_module_slot::<<<$module_type as $crate::RnexModule>::Manager as $crate::RnexManager>::User>();
|
holder.create_empty_module_slot::<<<$module_type as $crate::RnexModule>::Manager as $crate::RnexManager>::User>();
|
||||||
)*
|
)*
|
||||||
$(
|
|
||||||
$(#[$($tt)*])*
|
|
||||||
$crate::tracing::info!(
|
|
||||||
module_manager = ::std::any::type_name::<<<$module_type as $crate::RnexModule>::Manager as $crate::RnexManager>::User>(),
|
|
||||||
"initializing and filling user module slot if specified as present"
|
|
||||||
);
|
|
||||||
$crate::paste::paste!{
|
|
||||||
$(#[$($tt)*])*
|
|
||||||
let [<user_ $module_type>] = holder.init_slot($crate::RnexManager::init_new_user(managers.[<manager_ $module_type>].clone(), &holder, &r, &conn_data, $crate::PassthroughInitModule::downgrade(&holder.get_ref_init_pt().expect("module slot should be initialized by now"))).await).expect("double init or uninit slot");
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
$crate::paste::paste!{
|
|
||||||
::std::sync::Arc::new(MultiEndpoint{
|
|
||||||
|
|
||||||
$( $(#[$($tt)*])* [<user_ $module_type>] ),*
|
$(
|
||||||
})
|
$(#[$meta])*
|
||||||
}
|
$crate::tracing::info!(
|
||||||
}
|
module_manager = ::std::any::type_name::<<<$module_type as $crate::RnexModule>::Manager as $crate::RnexManager>::User>(),
|
||||||
).instrument($crate::tracing::info_span!("initializing user"))
|
"initializing and filling user module slot if specified as present"
|
||||||
|
);
|
||||||
|
$crate::paste::paste!{
|
||||||
|
$(#[$meta])*
|
||||||
|
let [<user_ $module_type>] = holder.init_slot(
|
||||||
|
$crate::RnexManager::init_new_user(
|
||||||
|
managers.[<manager_ $module_type>].clone(),
|
||||||
|
&holder,
|
||||||
|
&r,
|
||||||
|
&conn_data,
|
||||||
|
$crate::PassthroughInitModule::downgrade(&holder.get_ref_init_pt().expect("module slot should be initialized by now"))
|
||||||
|
).await
|
||||||
|
).expect("double init or uninit slot");
|
||||||
|
|
||||||
|
$(#[$meta])*
|
||||||
|
<<$module_type as $crate::RnexModule>::Manager as $crate::RnexManager>::post_init([<user_ $module_type>].as_ref()).await;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
$crate::paste::paste!{
|
||||||
|
::std::sync::Arc::new(MultiEndpoint {
|
||||||
|
$( $(#[$meta])* [<user_ $module_type>] ),*
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).instrument($crate::tracing::info_span!("initializing user"))
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
.instrument($crate::tracing::info_span!("handeling new incoming connection"))
|
.instrument($crate::tracing::info_span!("handeling new incoming connection"))
|
||||||
|
|
@ -502,4 +514,4 @@ mod test {
|
||||||
man.create_empty_module_slot::<i32>();
|
man.create_empty_module_slot::<i32>();
|
||||||
man.get_ref::<i32>();
|
man.get_ref::<i32>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,8 +9,8 @@ use std::ops::Deref;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use tokio::io::{self, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
use tokio::io::{self, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||||
|
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||||
use tokio::sync::Notify;
|
use tokio::sync::Notify;
|
||||||
use tokio::sync::mpsc::{Receiver, Sender, channel};
|
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
|
|
||||||
|
|
@ -19,36 +19,44 @@ pub type PID = i64;
|
||||||
#[cfg(not(feature = "nx"))]
|
#[cfg(not(feature = "nx"))]
|
||||||
pub type PID = i32;
|
pub type PID = i32;
|
||||||
|
|
||||||
|
pub const MAX_PACKET_SIZE: usize = 128 * 1024 * 1024;
|
||||||
|
|
||||||
pub trait UnitPacketRead: AsyncRead + Unpin {
|
pub trait UnitPacketRead: AsyncRead + Unpin {
|
||||||
async fn read_buffer(&mut self) -> Result<Vec<u8>, io::Error> {
|
async fn read_buffer(&mut self) -> Result<Vec<u8>, io::Error> {
|
||||||
let mut len_raw: [u8; _] = [0; size_of::<usize>()];
|
let mut len_raw = [0u8; 8];
|
||||||
|
|
||||||
self.read_exact(&mut len_raw).await?;
|
self.read_exact(&mut len_raw).await?;
|
||||||
|
|
||||||
let len = usize::from_le_bytes(len_raw);
|
let len = u64::from_le_bytes(len_raw) as usize;
|
||||||
|
|
||||||
let mut vec = vec![0u8; len as _];
|
if len > MAX_PACKET_SIZE {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
format!("packet size {len} bytes exceeds maximum allowed limit of {MAX_PACKET_SIZE} bytes"),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut vec = vec![0u8; len];
|
||||||
self.read_exact(&mut vec).await?;
|
self.read_exact(&mut vec).await?;
|
||||||
|
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsyncRead + Unpin> UnitPacketRead for T {}
|
impl<T: AsyncRead + Unpin + ?Sized> UnitPacketRead for T {}
|
||||||
|
|
||||||
pub trait UnitPacketWrite: AsyncWrite + Unpin {
|
pub trait UnitPacketWrite: AsyncWrite + Unpin {
|
||||||
async fn send_buffer(&mut self, data: &[u8]) -> Result<(), io::Error> {
|
async fn send_buffer(&mut self, data: &[u8]) -> Result<(), io::Error> {
|
||||||
let len_data = data.len().to_le_bytes();
|
let len_data = (data.len() as u64).to_le_bytes();
|
||||||
self.write_all(&len_data[..]).await?;
|
self.write_all(&len_data[..]).await?;
|
||||||
self.write_all(data).await?;
|
self.write_all(data).await?;
|
||||||
|
|
||||||
self.flush().await?;
|
self.flush().await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AsyncWrite + Unpin> UnitPacketWrite for T {}
|
impl<T: AsyncWrite + Unpin + ?Sized> UnitPacketWrite for T {}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SendingBufferConnection(Sender<Vec<u8>>, Arc<Notify>);
|
pub struct SendingBufferConnection(Sender<Vec<u8>>, Arc<Notify>);
|
||||||
|
|
@ -77,18 +85,40 @@ impl<T: Send + Unpin + AsyncWrite + AsyncRead + 'static> From<T> for SplittableB
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SplittableBufferConnection {
|
impl SplittableBufferConnection {
|
||||||
fn new<T: Send + Unpin + AsyncWrite + AsyncRead + 'static>(stream: T) -> Self {
|
fn new<T>(stream: T) -> Self
|
||||||
|
where
|
||||||
|
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
||||||
|
{
|
||||||
let (outside_send, inside_recv) = channel::<Vec<u8>>(10);
|
let (outside_send, inside_recv) = channel::<Vec<u8>>(10);
|
||||||
let (inside_send, outside_recv) = channel::<Vec<u8>>(10);
|
let (inside_send, outside_recv) = channel::<Vec<u8>>(10);
|
||||||
|
|
||||||
let notify = Arc::new(Notify::new());
|
let notify = Arc::new(Notify::new());
|
||||||
|
let (mut reader, mut writer) = io::split(stream);
|
||||||
|
|
||||||
|
{
|
||||||
|
task::spawn(async move {
|
||||||
|
loop {
|
||||||
|
match reader.read_buffer().await {
|
||||||
|
Ok(data) => {
|
||||||
|
if inside_send.send(data).await.is_err() {
|
||||||
|
// reciever dropped
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("error receiving data from backend: {e}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let notify = notify.clone();
|
let notify = notify.clone();
|
||||||
|
|
||||||
task::spawn(async move {
|
task::spawn(async move {
|
||||||
let sender = inside_send;
|
|
||||||
let mut recver = inside_recv;
|
let mut recver = inside_recv;
|
||||||
let mut stream = stream;
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
|
@ -97,33 +127,19 @@ impl SplittableBufferConnection {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = stream.send_buffer(&data[..]).await{
|
if let Err(e) = writer.send_buffer(&data[..]).await {
|
||||||
error!("error sending data to backend: {e}");
|
error!("error sending data to backend: {e}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data = stream.read_buffer() => {
|
|
||||||
let data = match data{
|
|
||||||
Ok(d) => d,
|
|
||||||
Err(e) => {
|
|
||||||
error!("error reveiving data from backend: {e}");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = sender.send(data).await{
|
|
||||||
error!("a send error occurred {e}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
() = notify.notified() => {
|
() = notify.notified() => {
|
||||||
info!("shutting down connection");
|
info!("shutting down writer task");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Err(e) = stream.shutdown().await {
|
if let Err(e) = writer.shutdown().await {
|
||||||
error!("failed to shut down stream: {e}");
|
error!("failed to shut down stream writer: {e}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -179,4 +195,4 @@ impl<T> WeakVec<T> {
|
||||||
pub fn iter(&self) -> impl Iterator<Item = Arc<T>> {
|
pub fn iter(&self) -> impl Iterator<Item = Arc<T>> {
|
||||||
self.0.iter().filter_map(Weak::upgrade)
|
self.0.iter().filter_map(Weak::upgrade)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +96,10 @@ pub struct StationUrlParseError;
|
||||||
impl FromStr for StationUrl {
|
impl FromStr for StationUrl {
|
||||||
type Err = StationUrlParseError;
|
type Err = StationUrlParseError;
|
||||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||||
|
if value.len() >= 1024 {
|
||||||
|
return Err(StationUrlParseError);
|
||||||
|
}
|
||||||
|
|
||||||
let (url_type, options) = value.split_at(value.find(":/").ok_or(StationUrlParseError)?);
|
let (url_type, options) = value.split_at(value.find(":/").ok_or(StationUrlParseError)?);
|
||||||
|
|
||||||
let options = &options[2..];
|
let options = &options[2..];
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue