feat: refactor prudp code and start working on refactoring rmc
This commit is contained in:
parent
7d24a71f09
commit
3ea7c7e671
37 changed files with 2029 additions and 456 deletions
26
src/nex-implementation/auth/method_login.rs
Normal file
26
src/nex-implementation/auth/method_login.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use log::error;
|
||||
use tokio::sync::Mutex;
|
||||
use crate::protocols::auth::AuthProtocolConfig;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
pub async fn login(rmcmessage: &RMCMessage, _name: &str) -> RMCResponseResult{
|
||||
|
||||
|
||||
rmcmessage.error_result_with_code(ErrorCode::Core_NotImplemented)
|
||||
}
|
||||
|
||||
pub async fn login_raw_params(rmcmessage: &RMCMessage, _: &Arc<SocketData>, _: &Arc<Mutex<ConnectionData>>, _data: AuthProtocolConfig) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(str) = String::deserialize(&mut reader) else {
|
||||
error!("error reading packet");
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
|
||||
login(rmcmessage, &str).await
|
||||
}
|
||||
81
src/nex-implementation/auth/method_login_ex.rs
Normal file
81
src/nex-implementation/auth/method_login_ex.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use std::io::{Cursor, Write};
|
||||
use std::sync::Arc;
|
||||
use bytemuck::bytes_of;
|
||||
use log::{error};
|
||||
use tokio::sync::Mutex;
|
||||
use crate::grpc::account;
|
||||
use crate::kerberos::KerberosDateTime;
|
||||
use crate::protocols::auth::AuthProtocolConfig;
|
||||
use crate::protocols::auth::ticket_generation::generate_ticket;
|
||||
use crate::rmc;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::{RmcSerialize};
|
||||
use crate::rmc::structures::any::Any;
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
|
||||
pub async fn login_ex(rmcmessage: &RMCMessage, proto_data: AuthProtocolConfig, pid: u32) -> RMCResponseResult{
|
||||
// todo: figure out how the AuthenticationInfo struct works, parse it and validate login info
|
||||
|
||||
let Ok(mut client) = account::Client::new().await else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
let Ok(passwd) = client.get_nex_password(pid).await else{
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
let source_login_data = (pid, passwd);
|
||||
let destination_login_data = proto_data.secure_server_account.get_login_data();
|
||||
|
||||
let ticket = generate_ticket(source_login_data, destination_login_data);
|
||||
|
||||
let result = QResult::success(ErrorCode::Core_Unknown);
|
||||
|
||||
let connection_data = rmc::structures::connection_data::ConnectionData{
|
||||
station_url: proto_data.station_url,
|
||||
special_station_url: "",
|
||||
date_time: KerberosDateTime::now(),
|
||||
special_protocols: Vec::new()
|
||||
};
|
||||
|
||||
let mut response: Vec<u8> = Vec::new();
|
||||
|
||||
result.serialize(&mut response).expect("failed serializing result");
|
||||
response.write_all(bytes_of(&source_login_data.0)).expect("failed writing pid");
|
||||
ticket.serialize(&mut response).expect("failed serializing ticket");
|
||||
connection_data.serialize(&mut response).expect("failed writing connection data");
|
||||
proto_data.build_name.serialize(&mut response).expect("failed writing build name");
|
||||
|
||||
return rmcmessage.success_with_data(response);
|
||||
}
|
||||
|
||||
pub async fn login_ex_raw_params(rmcmessage: &RMCMessage, _: &Arc<SocketData>, _: &Arc<Mutex<ConnectionData>>, data: AuthProtocolConfig) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(str) = String::deserialize(&mut reader) else {
|
||||
error!("error reading packet");
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
let Ok(any) = Any::deserialize(&mut reader) else {
|
||||
error!("error reading packet");
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
match any.name.as_ref(){
|
||||
"AuthenticationInfo" => {
|
||||
|
||||
}
|
||||
v => {
|
||||
error!("error reading packet: invalid structure type: {}", v);
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
}
|
||||
}
|
||||
|
||||
let Ok(pid) = str.parse() else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
login_ex(rmcmessage, data, pid).await
|
||||
}
|
||||
51
src/nex-implementation/auth/method_request_ticket.rs
Normal file
51
src/nex-implementation/auth/method_request_ticket.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::protocols::auth::{AuthProtocolConfig, get_login_data_by_pid};
|
||||
use crate::protocols::auth::ticket_generation::generate_ticket;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::response::ErrorCode::Core_Unknown;
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
pub async fn request_ticket(rmcmessage: &RMCMessage, data: AuthProtocolConfig, source_pid: u32, destination_pid: u32) -> RMCResponseResult{
|
||||
let Some(source_login_data) = get_login_data_by_pid(source_pid).await else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
let desgination_login_data = if destination_pid == data.secure_server_account.pid{
|
||||
data.secure_server_account.get_login_data()
|
||||
} else {
|
||||
let Some(login) = get_login_data_by_pid(destination_pid).await else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_Exception);
|
||||
};
|
||||
login
|
||||
};
|
||||
|
||||
let result = QResult::success(Core_Unknown);
|
||||
|
||||
let ticket = generate_ticket(source_login_data, desgination_login_data);
|
||||
|
||||
let mut response: Vec<u8> = Vec::new();
|
||||
|
||||
result.serialize(&mut response).expect("failed serializing result");
|
||||
ticket.serialize(&mut response).expect("failed serializing ticket");
|
||||
|
||||
rmcmessage.success_with_data(response)
|
||||
}
|
||||
|
||||
pub async fn request_ticket_raw_params(rmcmessage: &RMCMessage, _: &Arc<SocketData>, _: &Arc<Mutex<ConnectionData>>, data: AuthProtocolConfig) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(source_pid) = reader.read_struct(IS_BIG_ENDIAN) else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
let Ok(destination_pid) = reader.read_struct(IS_BIG_ENDIAN) else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
request_ticket(rmcmessage, data, source_pid, destination_pid).await
|
||||
}
|
||||
38
src/nex-implementation/auth/mod.rs
Normal file
38
src/nex-implementation/auth/mod.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
mod method_login_ex;
|
||||
mod method_login;
|
||||
mod ticket_generation;
|
||||
mod method_request_ticket;
|
||||
|
||||
use crate::define_protocol;
|
||||
use crate::grpc::account;
|
||||
use crate::nex::account::Account;
|
||||
use crate::protocols::auth::method_login::login_raw_params;
|
||||
use crate::protocols::auth::method_login_ex::login_ex_raw_params;
|
||||
use crate::protocols::auth::method_request_ticket::request_ticket_raw_params;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct AuthProtocolConfig {
|
||||
pub secure_server_account: &'static Account,
|
||||
pub build_name: &'static str,
|
||||
pub station_url: &'static str
|
||||
}
|
||||
|
||||
define_protocol!{
|
||||
10(proto_data: AuthProtocolConfig) => {
|
||||
0x01 => login_raw_params,
|
||||
0x02 => login_ex_raw_params,
|
||||
0x03 => request_ticket_raw_params
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_login_data_by_pid(pid: u32) -> Option<(u32, [u8; 16])> {
|
||||
let Ok(mut client) = account::Client::new().await else {
|
||||
return None
|
||||
};
|
||||
|
||||
let Ok(passwd) = client.get_nex_password(pid).await else{
|
||||
return None
|
||||
};
|
||||
|
||||
Some((pid, passwd))
|
||||
}
|
||||
19
src/nex-implementation/auth/ticket_generation.rs
Normal file
19
src/nex-implementation/auth/ticket_generation.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use crate::kerberos;
|
||||
use crate::kerberos::{derive_key, Ticket};
|
||||
|
||||
|
||||
pub fn generate_ticket(source_act_login_data: (u32, [u8;16]), dest_act_login_data: (u32, [u8;16])) -> Box<[u8]>{
|
||||
let source_key = derive_key(source_act_login_data.0, source_act_login_data.1);
|
||||
let dest_key = derive_key(dest_act_login_data.0, dest_act_login_data.1);
|
||||
|
||||
let internal_data = kerberos::TicketInternalData::new(source_act_login_data.0);
|
||||
|
||||
let encrypted_inner = internal_data.encrypt(dest_key);
|
||||
let encrypted_session_ticket = Ticket{
|
||||
pid: dest_act_login_data.0,
|
||||
session_key: internal_data.session_key,
|
||||
}.encrypt(source_key, &encrypted_inner);
|
||||
|
||||
|
||||
encrypted_session_ticket
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use crate::protocols::matchmake_common::MatchmakeData;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
pub async fn unregister_gathering(rmcmessage: &RMCMessage, gid: u32, data: Arc<RwLock<MatchmakeData>>) -> RMCResponseResult{
|
||||
let mut rd = data.write().await;
|
||||
|
||||
rd.matchmake_sessions.remove(&gid);
|
||||
|
||||
let result = QResult::success(ErrorCode::Core_Unknown);
|
||||
|
||||
let mut response = Vec::new();
|
||||
|
||||
result.serialize(&mut response).expect("aaa");
|
||||
|
||||
rmcmessage.success_with_data(response)
|
||||
}
|
||||
|
||||
pub async fn unregister_gathering_raw_params(rmcmessage: &RMCMessage, _: &Arc<SocketData>, _: &Arc<Mutex<ConnectionData>>, data: Arc<RwLock<MatchmakeData>>) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(gid) = u32::deserialize(&mut reader) else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
unregister_gathering(rmcmessage, gid, data).await
|
||||
}
|
||||
13
src/nex-implementation/matchmake/mod.rs
Normal file
13
src/nex-implementation/matchmake/mod.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
mod method_unregister_gathering;
|
||||
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
use crate::define_protocol;
|
||||
use crate::protocols::matchmake::method_unregister_gathering::unregister_gathering_raw_params;
|
||||
use crate::protocols::matchmake_common::MatchmakeData;
|
||||
|
||||
define_protocol!{
|
||||
21(matchmake_data: Arc<RwLock<MatchmakeData>>) => {
|
||||
2 => unregister_gathering_raw_params
|
||||
}
|
||||
}
|
||||
136
src/nex-implementation/matchmake_common/mod.rs
Normal file
136
src/nex-implementation/matchmake_common/mod.rs
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
use std::collections::{BTreeMap};
|
||||
use std::sync::Arc;
|
||||
use log::error;
|
||||
use rand::random;
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use crate::kerberos::KerberosDateTime;
|
||||
use crate::protocols::notification::Notification;
|
||||
use crate::rmc::structures::matchmake::{Gathering, MatchmakeParam, MatchmakeSession};
|
||||
use crate::rmc::structures::variant::Variant;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ExtendedMatchmakeSession{
|
||||
pub session: MatchmakeSession,
|
||||
pub connected_players: Vec<Arc<Mutex<ConnectionData>>>,
|
||||
}
|
||||
|
||||
pub struct MatchmakeData{
|
||||
pub(crate) matchmake_sessions: BTreeMap<u32, Arc<Mutex<ExtendedMatchmakeSession>>>
|
||||
}
|
||||
|
||||
impl ExtendedMatchmakeSession{
|
||||
pub async fn from_matchmake_session(session: MatchmakeSession, host: &Mutex<ConnectionData>) -> Self{
|
||||
let host = host.lock().await;
|
||||
|
||||
let ConnectionData{
|
||||
active_connection_data,
|
||||
..
|
||||
} = &*host;
|
||||
|
||||
let Some(active_connection_data) = active_connection_data else{
|
||||
return Default::default();
|
||||
};
|
||||
|
||||
let ActiveConnectionData{
|
||||
active_secure_connection_data,
|
||||
..
|
||||
} = active_connection_data;
|
||||
|
||||
let Some(active_secure_connection_data) = active_secure_connection_data else{
|
||||
return Default::default();
|
||||
};
|
||||
|
||||
|
||||
let mm_session = MatchmakeSession{
|
||||
gathering: Gathering{
|
||||
self_gid: 1,
|
||||
owner_pid: active_secure_connection_data.pid,
|
||||
host_pid: active_secure_connection_data.pid,
|
||||
..session.gathering.clone()
|
||||
},
|
||||
datetime: KerberosDateTime::now(),
|
||||
session_key: (0..32).map(|_| random()).collect(),
|
||||
matchmake_param: MatchmakeParam{
|
||||
params: vec![
|
||||
("@SR".to_owned(), Variant::Bool(true)),
|
||||
("@GIR".to_owned(), Variant::SInt64(3))
|
||||
]
|
||||
},
|
||||
system_password_enabled: false,
|
||||
..session
|
||||
};
|
||||
|
||||
Self{
|
||||
session: mm_session,
|
||||
connected_players: Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn add_player(&mut self, socket: &SocketData, conn: Arc<Mutex<ConnectionData>>, join_msg: String) {
|
||||
let locked = conn.lock().await;
|
||||
|
||||
let Some(joining_pid) = locked.active_connection_data.as_ref()
|
||||
.map(|c|
|
||||
c.active_secure_connection_data.as_ref()
|
||||
.map(|c| c.pid)
|
||||
).flatten() else {
|
||||
error!("tried to add player without secure connection");
|
||||
return
|
||||
};
|
||||
|
||||
drop(locked);
|
||||
|
||||
self.connected_players.push(conn);
|
||||
self.session.participation_count = self.connected_players.len() as u32;
|
||||
|
||||
|
||||
for other_connection in &self.connected_players{
|
||||
let mut conn = other_connection.lock().await;
|
||||
|
||||
|
||||
let Some(other_pid) = conn.active_connection_data.as_ref()
|
||||
.map(|c|
|
||||
c.active_secure_connection_data.as_ref()
|
||||
.map(|c| c.pid
|
||||
)
|
||||
).flatten() else {
|
||||
error!("tried to send connection notification to player secure connection");
|
||||
return
|
||||
};
|
||||
|
||||
/*if other_pid == self.session.gathering.owner_pid &&
|
||||
joining_pid == self.session.gathering.owner_pid{
|
||||
continue;
|
||||
}*/
|
||||
|
||||
conn.send_notification(socket, Notification{
|
||||
pid_source: joining_pid,
|
||||
notif_type: 3001,
|
||||
param_1: self.session.gathering.self_gid,
|
||||
param_2: other_pid,
|
||||
str_param: join_msg.clone(),
|
||||
param_3: self.session.participation_count
|
||||
}).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
pub async fn add_matchmake_session(mm_data: Arc<RwLock<MatchmakeData>>,session: ExtendedMatchmakeSession) -> Arc<Mutex<ExtendedMatchmakeSession>> {
|
||||
let gid = session.session.gathering.self_gid;
|
||||
|
||||
let mut mm_data = mm_data.write().await;
|
||||
|
||||
let session = Arc::new(Mutex::new(session));
|
||||
|
||||
mm_data.matchmake_sessions.insert(gid, session.clone());
|
||||
|
||||
session
|
||||
}
|
||||
|
||||
impl MatchmakeData {
|
||||
|
||||
|
||||
|
||||
pub async fn try_find_session_with_criteria(&self, ) -> Option<Arc<Mutex<ExtendedMatchmakeSession>>>{
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use chrono::SecondsFormat::Millis;
|
||||
use log::info;
|
||||
use rand::random;
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use tokio::time::sleep;
|
||||
use crate::protocols::matchmake_common::{ExtendedMatchmakeSession, MatchmakeData};
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::matchmake::{AutoMatchmakeParam, MatchmakeSession};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
|
||||
|
||||
pub async fn auto_matchmake_with_param_postpone(
|
||||
rmcmessage: &RMCMessage,
|
||||
conn: &Arc<Mutex<ConnectionData>>,
|
||||
socket: &Arc<SocketData>,
|
||||
mm_data: Arc<RwLock<MatchmakeData>>,
|
||||
auto_matchmake_param: AutoMatchmakeParam
|
||||
) -> RMCResponseResult{
|
||||
//println!("auto_matchmake_with_param_postpone: {:?}", auto_matchmake_param);
|
||||
let locked_conn = conn.lock().await;
|
||||
let Some(secure_conn) =
|
||||
locked_conn.active_connection_data.as_ref().map(|a| a.active_secure_connection_data.as_ref()).flatten() else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_Exception);
|
||||
};
|
||||
|
||||
let pid = secure_conn.pid;
|
||||
|
||||
drop(locked_conn);
|
||||
|
||||
let mm_data_read = mm_data.read().await;
|
||||
//todo: there is a bit of a race condition here, i dont have any idea on how to fix it though...
|
||||
let session = if let Some(session) = mm_data_read.try_find_session_with_criteria().await{
|
||||
session
|
||||
} else {
|
||||
// drop it first so that we dont cause a deadlock, also drop it right here so we dont hold
|
||||
// up anything else unnescesarily
|
||||
drop(mm_data_read);
|
||||
|
||||
let session =
|
||||
ExtendedMatchmakeSession::from_matchmake_session(auto_matchmake_param.matchmake_session, &conn).await;
|
||||
|
||||
let gid = session.session.gathering.self_gid;
|
||||
|
||||
let mut mm_data = mm_data.write().await;
|
||||
|
||||
let session = Arc::new(Mutex::new(session));
|
||||
|
||||
mm_data.matchmake_sessions.insert(gid, session.clone());
|
||||
|
||||
session
|
||||
};
|
||||
|
||||
let mut locked_session = session.lock().await;
|
||||
|
||||
//todo: refactor so that this works
|
||||
{
|
||||
let session = session.clone();
|
||||
let socket = socket.clone();
|
||||
let connection = conn.clone();
|
||||
let join_msg = auto_matchmake_param.join_message.clone();
|
||||
tokio::spawn(async move{
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
println!("adding player");
|
||||
let mut session = session.lock().await;
|
||||
session.add_player(&socket, connection, join_msg).await;
|
||||
});
|
||||
}
|
||||
|
||||
info!("new session: {:?}", locked_session);
|
||||
|
||||
let mut response = Vec::new();
|
||||
|
||||
locked_session.session.serialize(&mut response).expect("unable to serialize matchmake session");
|
||||
|
||||
rmcmessage.success_with_data(response)
|
||||
}
|
||||
|
||||
pub async fn auto_matchmake_with_param_postpone_raw_params(
|
||||
rmcmessage: &RMCMessage,
|
||||
socket: &Arc<SocketData>,
|
||||
connection_data: &Arc<Mutex<ConnectionData>>,
|
||||
data: Arc<RwLock<MatchmakeData>>
|
||||
) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(matchmake_param) = AutoMatchmakeParam::deserialize(&mut reader) else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
|
||||
|
||||
auto_matchmake_with_param_postpone(rmcmessage, connection_data, socket, data, matchmake_param).await
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use log::info;
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use tokio::time::sleep;
|
||||
use crate::protocols::matchmake_common::{add_matchmake_session, ExtendedMatchmakeSession, MatchmakeData};
|
||||
use crate::protocols::matchmake_extension::method_auto_matchmake_with_param_postpone::auto_matchmake_with_param_postpone;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::matchmake::{AutoMatchmakeParam, CreateMatchmakeSessionParam};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
pub async fn create_matchmake_session_with_param(
|
||||
rmcmessage: &RMCMessage,
|
||||
conn: &Arc<Mutex<ConnectionData>>,
|
||||
socket: &Arc<SocketData>,
|
||||
mm_data: Arc<RwLock<MatchmakeData>>,
|
||||
create_matchmake_session: CreateMatchmakeSessionParam
|
||||
) -> RMCResponseResult {
|
||||
|
||||
let mut session =
|
||||
ExtendedMatchmakeSession::from_matchmake_session(create_matchmake_session.matchmake_session, &conn).await;
|
||||
|
||||
session.session.participation_count = create_matchmake_session.participation_count as u32;
|
||||
|
||||
let session = add_matchmake_session(mm_data, session).await;
|
||||
|
||||
let mut session = session.lock().await;
|
||||
|
||||
session.add_player(&socket, conn.clone(), create_matchmake_session.join_message).await;
|
||||
|
||||
|
||||
|
||||
let mut response = Vec::new();
|
||||
|
||||
|
||||
session.session.serialize(&mut response).expect("unable to serialize session");
|
||||
|
||||
println!("{}", hex::encode(&response));
|
||||
|
||||
|
||||
|
||||
rmcmessage.success_with_data(response)
|
||||
}
|
||||
|
||||
pub async fn create_matchmake_session_with_param_raw_params(
|
||||
rmcmessage: &RMCMessage,
|
||||
socket: &Arc<SocketData>,
|
||||
connection_data: &Arc<Mutex<ConnectionData>>,
|
||||
data: Arc<RwLock<MatchmakeData>>
|
||||
) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(matchmake_param) = CreateMatchmakeSessionParam::deserialize(&mut reader) else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
create_matchmake_session_with_param(rmcmessage, connection_data, socket, data, matchmake_param).await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test{
|
||||
use std::io::Cursor;
|
||||
use crate::prudp::packet::PRUDPPacket;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::structures::matchmake::MatchmakeSession;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
#[test]
|
||||
fn test(){
|
||||
let data = hex::decode("ead001030000a1af12001800050002010000000000000000000000000000000000").unwrap();
|
||||
|
||||
let packet = PRUDPPacket::new(&mut Cursor::new(data)).unwrap();
|
||||
|
||||
println!("{:?}", packet);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2(){
|
||||
let data = hex::decode("250000008e0100000001000000001700000051b39957b90b00000100000051b3995701000001000000").unwrap();
|
||||
|
||||
let msg = RMCMessage::new(&mut Cursor::new(data)).unwrap();
|
||||
|
||||
println!("{:?}", msg)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use log::info;
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use crate::protocols::matchmake_common::MatchmakeData;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
type PIDList = Vec<u32>;
|
||||
|
||||
async fn get_playing_session(rmcmessage: &RMCMessage, _data: Arc<RwLock<MatchmakeData>>) -> RMCResponseResult {
|
||||
//todo: propperly implement this
|
||||
|
||||
let cheeseburger = PIDList::new();
|
||||
|
||||
let mut vec = Vec::new();
|
||||
|
||||
cheeseburger.serialize(&mut vec).expect("somehow unable to write cheeseburger");
|
||||
|
||||
rmcmessage.success_with_data(vec)
|
||||
}
|
||||
|
||||
pub async fn get_playing_session_raw_params(rmcmessage: &RMCMessage, _: &Arc<SocketData>, _: &Arc<Mutex<ConnectionData>>, data: Arc<RwLock<MatchmakeData>>) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(list) = PIDList::deserialize(&mut reader) else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::FPD_FriendNotExists);
|
||||
};
|
||||
|
||||
info!("get_playing_session got called with {:?}", list);
|
||||
|
||||
get_playing_session(rmcmessage, data).await
|
||||
}
|
||||
19
src/nex-implementation/matchmake_extension/mod.rs
Normal file
19
src/nex-implementation/matchmake_extension/mod.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
mod method_get_playing_session;
|
||||
mod method_auto_matchmake_with_param_postpone;
|
||||
mod method_create_matchmake_session_with_param;
|
||||
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::{RwLock};
|
||||
use crate::define_protocol;
|
||||
use crate::protocols::matchmake_common::MatchmakeData;
|
||||
use method_get_playing_session::get_playing_session_raw_params;
|
||||
use method_auto_matchmake_with_param_postpone::auto_matchmake_with_param_postpone_raw_params;
|
||||
use crate::protocols::matchmake_extension::method_create_matchmake_session_with_param::create_matchmake_session_with_param_raw_params;
|
||||
|
||||
define_protocol!{
|
||||
109(matchmake_data: Arc<RwLock<MatchmakeData>>) => {
|
||||
16 => get_playing_session_raw_params,
|
||||
38 => create_matchmake_session_with_param_raw_params,
|
||||
40 => auto_matchmake_with_param_postpone_raw_params
|
||||
}
|
||||
}
|
||||
118
src/nex-implementation/mod.rs
Normal file
118
src/nex-implementation/mod.rs
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
use std::env;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use log::warn;
|
||||
use once_cell::sync::Lazy;
|
||||
use tokio::sync::Mutex;
|
||||
use crate::grpc;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponse};
|
||||
|
||||
|
||||
pub mod auth;
|
||||
pub mod server;
|
||||
pub mod secure;
|
||||
pub mod matchmake_extension;
|
||||
pub mod matchmake_common;
|
||||
pub mod matchmake;
|
||||
pub mod notification;
|
||||
pub mod nat_traversal;
|
||||
|
||||
static IS_MAINTENANCE: Lazy<bool> = Lazy::new(|| {
|
||||
env::var("IS_MAINTENANCE")
|
||||
.ok()
|
||||
.map(|v| v.parse().expect("IS_MAINTENANCE should be a boolean value"))
|
||||
.unwrap_or(false)
|
||||
});
|
||||
static BYPASS_LEVEL: Lazy<i32> = Lazy::new(|| {
|
||||
env::var("MAINTENANCE_BYPASS_MINIMUM_ACCESS_LEVEL")
|
||||
.ok()
|
||||
.map(|v| v.parse().expect("IS_MAINTENANCE should be a boolean value"))
|
||||
.unwrap_or(3)
|
||||
});
|
||||
|
||||
|
||||
pub fn block_if_maintenance<'a>(rmcmessage: &'a RMCMessage, _: &'a Arc<SocketData> , conn: &'a Arc<Mutex<ConnectionData>>) -> Pin<Box<(dyn Future<Output=Option<RMCResponse>> + Send + 'a)>> {
|
||||
Box::pin(async move {
|
||||
let conn = conn.lock().await;
|
||||
|
||||
if let Some(active_conn) = conn.active_connection_data.as_ref() {
|
||||
if let Some(secure_conn) = active_conn.active_secure_connection_data.as_ref() {
|
||||
if let Ok(mut client) = grpc::account::Client::new().await {
|
||||
if let Ok(client_data) = client.get_user_data(secure_conn.pid).await{
|
||||
if client_data.access_level >= *BYPASS_LEVEL{
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
warn!("login attempted whilest servers are in maintenance");
|
||||
|
||||
if *IS_MAINTENANCE {
|
||||
Some(RMCResponse {
|
||||
protocol_id: rmcmessage.protocol_id as u8,
|
||||
response_result: rmcmessage.error_result_with_code(ErrorCode::RendezVous_GameServerMaintenance),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! define_protocol {
|
||||
($id:literal ($($varname:ident : $ty:ty),*) => {$($func_id:literal => $func:path),*} ) => {
|
||||
#[allow(unused_parens)]
|
||||
async fn protocol (rmcmessage: &crate::RMCMessage, socket: &::std::sync::Arc<crate::prudp::socket::SocketData>, connection: &::std::sync::Arc<::tokio::sync::Mutex<crate::protocols::ConnectionData>>, $($varname : $ty),*) -> Option<crate::rmc::response::RMCResponse>{
|
||||
if rmcmessage.protocol_id != $id{
|
||||
return None;
|
||||
}
|
||||
|
||||
let self_data: ( $( $ty ),* ) = ($( $varname ),*);
|
||||
|
||||
let response_result = match rmcmessage.method_id{
|
||||
$(
|
||||
$func_id => $func ( rmcmessage, socket, connection, self_data).await,
|
||||
)*
|
||||
_ => {
|
||||
log::error!("invalid method id sent to protocol {}: {:?}", $id, rmcmessage.method_id);
|
||||
return Some(
|
||||
crate::rmc::response::RMCResponse{
|
||||
protocol_id: $id,
|
||||
response_result: rmcmessage.error_result_with_code(crate::rmc::response::ErrorCode::Core_NotImplemented)
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Some(crate::rmc::response::RMCResponse{
|
||||
protocol_id: $id,
|
||||
response_result
|
||||
})
|
||||
}
|
||||
#[allow(unused_parens)]
|
||||
pub fn bound_protocol($($varname : $ty,)*) -> Box<dyn for<'message_lifetime> Fn(&'message_lifetime crate::RMCMessage, &'message_lifetime ::std::sync::Arc<crate::prudp::socket::SocketData>, &'message_lifetime ::std::sync::Arc<::tokio::sync::Mutex<crate::protocols::ConnectionData>>)
|
||||
-> ::std::pin::Pin<Box<dyn ::std::future::Future<Output = Option<crate::rmc::response::RMCResponse>> + Send + 'message_lifetime>> + Send + Sync>{
|
||||
Box::new(
|
||||
move |v, s, cd| {
|
||||
Box::pin({
|
||||
$(
|
||||
let $varname = $varname.clone();
|
||||
)*
|
||||
|
||||
async move {
|
||||
$(
|
||||
let $varname = $varname.clone();
|
||||
)*
|
||||
protocol(v, s, cd, $($varname,)*).await
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tokio::sync::{Mutex, RwLock};
|
||||
use tokio::time::sleep;
|
||||
use crate::protocols::matchmake_common::MatchmakeData;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::matchmake::CreateMatchmakeSessionParam;
|
||||
|
||||
pub async fn report_nat_properties(
|
||||
rmcmessage: &RMCMessage,
|
||||
socket: &Arc<SocketData>,
|
||||
connection_data: &Arc<Mutex<ConnectionData>>,
|
||||
) -> RMCResponseResult{
|
||||
sleep(Duration::from_millis(50)).await;
|
||||
rmcmessage.success_with_data(Vec::new())
|
||||
}
|
||||
|
||||
pub async fn report_nat_properties_raw_params(
|
||||
rmcmessage: &RMCMessage,
|
||||
socket: &Arc<SocketData>,
|
||||
connection_data: &Arc<Mutex<ConnectionData>>,
|
||||
_: ()
|
||||
) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
report_nat_properties(rmcmessage, socket, connection_data).await
|
||||
}
|
||||
10
src/nex-implementation/nat_traversal/mod.rs
Normal file
10
src/nex-implementation/nat_traversal/mod.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
mod method_report_nat_properties;
|
||||
|
||||
use crate::define_protocol;
|
||||
use crate::protocols::nat_traversal::method_report_nat_properties::report_nat_properties_raw_params;
|
||||
|
||||
define_protocol!{
|
||||
3() => {
|
||||
5 => report_nat_properties_raw_params
|
||||
}
|
||||
}
|
||||
159
src/nex-implementation/notification/mod.rs
Normal file
159
src/nex-implementation/notification/mod.rs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
use macros::RmcSerialize;
|
||||
use rand::random;
|
||||
use crate::prudp::packet::{PRUDPHeader, PRUDPPacket, PacketOption, TypesFlags};
|
||||
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
|
||||
use crate::prudp::packet::types::DATA;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, RmcSerialize)]
|
||||
#[rmc_struct(0)]
|
||||
pub struct Notification{
|
||||
pub pid_source: u32,
|
||||
pub notif_type: u32,
|
||||
pub param_1: u32,
|
||||
pub param_2: u32,
|
||||
pub str_param: String,
|
||||
pub param_3: u32,
|
||||
}
|
||||
|
||||
|
||||
impl ConnectionData{
|
||||
pub async fn send_notification(&mut self, socket: &SocketData, notif: Notification){
|
||||
println!("sending notification");
|
||||
|
||||
let mut data = Vec::new();
|
||||
|
||||
notif.serialize(&mut data).expect("unable to write");
|
||||
|
||||
let message = RMCMessage{
|
||||
protocol_id: 14,
|
||||
method_id: 1,
|
||||
call_id: 1,
|
||||
rest_of_data: data
|
||||
};
|
||||
|
||||
println!("notif: {}", hex::encode(message.to_data()));
|
||||
|
||||
|
||||
let mut prudp_packet = PRUDPPacket{
|
||||
header: PRUDPHeader{
|
||||
types_and_flags: TypesFlags::default().types(DATA).flags(NEED_ACK | RELIABLE),
|
||||
source_port: socket.get_virual_port(),
|
||||
destination_port: self.sock_addr.virtual_port,
|
||||
..Default::default()
|
||||
},
|
||||
options: vec![
|
||||
PacketOption::FragmentId(0),
|
||||
],
|
||||
payload: message.to_data(),
|
||||
packet_signature: [0;16]
|
||||
};
|
||||
|
||||
self.finish_and_send_packet_to(socket, prudp_packet).await;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test{
|
||||
use std::io::Cursor;
|
||||
use rand::random;
|
||||
use crate::protocols::notification::Notification;
|
||||
use crate::prudp::packet::{PRUDPHeader, PRUDPPacket, PacketOption, TypesFlags};
|
||||
use crate::prudp::packet::flags::{NEED_ACK, RELIABLE};
|
||||
use crate::prudp::packet::types::DATA;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
#[test]
|
||||
fn test(){
|
||||
let data = hex::decode("ead001032900a1af62000000000000000000000000000000000000000000020100250000000e57238a6601000000001700000051b39957b90b00003661636851b3995701000001000000").unwrap();
|
||||
|
||||
|
||||
let packet = PRUDPPacket::new(&mut Cursor::new(data)).expect("invalid packet");
|
||||
|
||||
println!("{:?}", packet);
|
||||
|
||||
let rmc = RMCMessage::new(&mut Cursor::new(packet.payload)).expect("invalid rmc message");
|
||||
|
||||
println!("{:?}", rmc);
|
||||
|
||||
let notif = Notification::deserialize(&mut Cursor::new(rmc.rest_of_data)).expect("invalid notification");
|
||||
|
||||
println!("{:?}", notif);
|
||||
}
|
||||
#[test]
|
||||
fn test2(){
|
||||
|
||||
let data = hex::decode("250000000e57b6801001000000001700000051b39957b90b0000248a5a9851b3995701000001000000").unwrap();
|
||||
//let packet = PRUDPPacket::new(&mut Cursor::new(data)).expect("invalid packet");
|
||||
|
||||
//println!("{:?}", packet);
|
||||
|
||||
let rmc = RMCMessage::new(&mut Cursor::new(data)).expect("invalid rmc message");
|
||||
|
||||
println!("{:?}", rmc);
|
||||
|
||||
let notif = Notification::deserialize(&mut Cursor::new(rmc.rest_of_data)).expect("invalid notification");
|
||||
|
||||
println!("{:?}", notif);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rmc_serialization(){
|
||||
let notif = Notification{
|
||||
pid_source: random(),
|
||||
notif_type: random(),
|
||||
param_1: random(),
|
||||
param_2: random(),
|
||||
str_param: "".to_string(),
|
||||
param_3: random(),
|
||||
};
|
||||
|
||||
let mut notif_data = Vec::new();
|
||||
|
||||
notif.serialize(&mut notif_data).unwrap();
|
||||
|
||||
let message = RMCMessage{
|
||||
protocol_id: 14,
|
||||
method_id: 1,
|
||||
call_id: random(),
|
||||
rest_of_data: notif_data
|
||||
};
|
||||
|
||||
let mut prudp_packet = PRUDPPacket{
|
||||
header: PRUDPHeader{
|
||||
..Default::default()
|
||||
},
|
||||
options: vec![
|
||||
PacketOption::FragmentId(0),
|
||||
],
|
||||
payload: message.to_data(),
|
||||
packet_signature: [0;16]
|
||||
};
|
||||
|
||||
prudp_packet.set_sizes();
|
||||
|
||||
|
||||
|
||||
let mut packet_data: Vec<u8> = Vec::new();
|
||||
|
||||
prudp_packet.write_to(&mut packet_data).expect("what");
|
||||
|
||||
let packet_deserialized = PRUDPPacket::new(&mut Cursor::new(packet_data)).unwrap();
|
||||
|
||||
assert_eq!(prudp_packet, packet_deserialized);
|
||||
|
||||
let message_deserialized = RMCMessage::new(&mut Cursor::new(packet_deserialized.payload)).unwrap();
|
||||
|
||||
assert_eq!(message, message_deserialized);
|
||||
|
||||
let notification_deserialized = Notification::deserialize(&mut Cursor::new(message_deserialized.rest_of_data)).unwrap();
|
||||
|
||||
assert_eq!(notification_deserialized, notif);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
63
src/nex-implementation/secure/method_register.rs
Normal file
63
src/nex-implementation/secure/method_register.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use std::io::{Cursor, Write};
|
||||
use std::sync::Arc;
|
||||
use bytemuck::bytes_of;
|
||||
use tokio::sync::Mutex;
|
||||
use crate::prudp::station_url::{nat_types, StationUrl};
|
||||
use crate::prudp::station_url::Type::PRUDPS;
|
||||
use crate::prudp::station_url::UrlOptions::{Address, NatFiltering, NatMapping, NatType, Port, PrincipalID, RVConnectionID};
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{ErrorCode, RMCResponseResult};
|
||||
use crate::rmc::structures::qresult::QResult;
|
||||
use crate::rmc::structures::RmcSerialize;
|
||||
|
||||
type StringList = Vec<String>;
|
||||
|
||||
pub async fn register(rmcmessage: &RMCMessage, _station_urls: Vec<StationUrl>, conn_data: &Arc<Mutex<ConnectionData>>) -> RMCResponseResult{
|
||||
let locked = conn_data.lock().await;
|
||||
let Some(active_connection_data) = locked.active_connection_data.as_ref() else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::RendezVous_NotAuthenticated)
|
||||
};
|
||||
|
||||
let Some(active_secure_connection_data) = active_connection_data.active_secure_connection_data.as_ref() else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::RendezVous_NotAuthenticated)
|
||||
};
|
||||
|
||||
let public_station = StationUrl{
|
||||
url_type: PRUDPS,
|
||||
options: vec![
|
||||
RVConnectionID(active_connection_data.connection_id),
|
||||
Address(*locked.sock_addr.regular_socket_addr.ip()),
|
||||
Port(locked.sock_addr.regular_socket_addr.port()),
|
||||
NatFiltering(0),
|
||||
NatMapping(0),
|
||||
NatType(nat_types::BEHIND_NAT),
|
||||
PrincipalID(active_secure_connection_data.pid),
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
|
||||
let result = QResult::success(ErrorCode::Core_Unknown);
|
||||
|
||||
let mut response = Vec::new();
|
||||
|
||||
result.serialize(&mut response).expect("unable to serialize result");
|
||||
response.write_all(bytes_of(&active_connection_data.connection_id)).expect("unable to serialize connection id");
|
||||
public_station.to_string().serialize(&mut response).expect("unable to serialize station id");
|
||||
|
||||
rmcmessage.success_with_data(response)
|
||||
}
|
||||
|
||||
pub async fn register_raw_params(rmcmessage: &RMCMessage, _: &Arc<SocketData>, conn_data: &Arc<Mutex<ConnectionData>>, _: ()) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(station_urls) = StringList::deserialize(&mut reader) else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
let Ok(station_urls): Result<Vec<StationUrl>, _> = station_urls.iter().map(|c| StationUrl::try_from((&c) as &str)).collect() else {
|
||||
return rmcmessage.error_result_with_code(ErrorCode::Core_InvalidArgument);
|
||||
};
|
||||
|
||||
register(rmcmessage, station_urls, conn_data).await
|
||||
}
|
||||
35
src/nex-implementation/secure/method_send_report.rs
Normal file
35
src/nex-implementation/secure/method_send_report.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
use log::error;
|
||||
use tokio::sync::Mutex;
|
||||
use crate::endianness::{IS_BIG_ENDIAN, ReadExtensions};
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{RMCResponseResult};
|
||||
use crate::rmc::response::ErrorCode::Core_InvalidArgument;
|
||||
use crate::rmc::structures::{qbuffer, RmcSerialize};
|
||||
use crate::rmc::structures::qbuffer::QBuffer;
|
||||
|
||||
pub async fn send_report(rmcmessage: &RMCMessage, report_id: u32, data: Vec<u8>) -> RMCResponseResult{
|
||||
let result = tokio::fs::write(format!("./reports/{}", report_id), data).await;
|
||||
|
||||
match result{
|
||||
Ok(_) => {},
|
||||
Err(e) => error!("{}", e)
|
||||
}
|
||||
|
||||
rmcmessage.success_with_data(Vec::new())
|
||||
}
|
||||
|
||||
pub async fn send_report_raw_params(rmcmessage: &RMCMessage, _: &Arc<SocketData>, _conn_data: &Arc<Mutex<ConnectionData>>, _: ()) -> RMCResponseResult{
|
||||
let mut reader = Cursor::new(&rmcmessage.rest_of_data);
|
||||
|
||||
let Ok(error_id) = reader.read_struct(IS_BIG_ENDIAN) else {
|
||||
return rmcmessage.error_result_with_code(Core_InvalidArgument);
|
||||
};
|
||||
|
||||
let Ok(QBuffer(data)) = QBuffer::deserialize(&mut reader) else {
|
||||
return rmcmessage.error_result_with_code(Core_InvalidArgument);
|
||||
};
|
||||
|
||||
send_report(rmcmessage, error_id, data).await
|
||||
}
|
||||
13
src/nex-implementation/secure/mod.rs
Normal file
13
src/nex-implementation/secure/mod.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
mod method_register;
|
||||
mod method_send_report;
|
||||
|
||||
use crate::define_protocol;
|
||||
use crate::protocols::secure::method_register::register_raw_params;
|
||||
use crate::protocols::secure::method_send_report::send_report_raw_params;
|
||||
|
||||
define_protocol!{
|
||||
11() => {
|
||||
0x01 => register_raw_params,
|
||||
0x08 => send_report_raw_params
|
||||
}
|
||||
}
|
||||
61
src/nex-implementation/server.rs
Normal file
61
src/nex-implementation/server.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
use std::future::Future;
|
||||
use std::io::Cursor;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use log::error;
|
||||
use tokio::sync::Mutex;
|
||||
use crate::prudp::packet::PRUDPPacket;
|
||||
use crate::rmc::message::RMCMessage;
|
||||
use crate::rmc::response::{RMCResponse, RMCResponseResult, send_response};
|
||||
use crate::rmc::response::ErrorCode::Core_NotImplemented;
|
||||
use crate::web::DirectionalData::Incoming;
|
||||
use crate::web::WEB_DATA;
|
||||
|
||||
type ContainedProtocolList = Box<[Box<dyn for<'a> Fn(&'a RMCMessage, &'a Arc<SocketData>, &'a Arc<Mutex<ConnectionData>>) -> Pin<Box<dyn Future<Output = Option<RMCResponse>> + Send + 'a>> + Send + Sync>]>;
|
||||
|
||||
pub struct RMCProtocolServer(ContainedProtocolList);
|
||||
|
||||
impl RMCProtocolServer{
|
||||
pub fn new(protocols: ContainedProtocolList) -> Arc<Self>{
|
||||
Arc::new(Self(protocols))
|
||||
}
|
||||
|
||||
pub async fn process_message(&self, packet: PRUDPPacket, socket: Arc<SocketData>, connection: Arc<Mutex<ConnectionData>>){
|
||||
let locked = connection.lock().await;
|
||||
let addr = locked.sock_addr.regular_socket_addr;
|
||||
drop(locked);
|
||||
let mut web = WEB_DATA.lock().await;
|
||||
web.data.push((addr, Incoming(hex::encode(&packet.payload))));
|
||||
drop(web);
|
||||
|
||||
let Ok(rmc) = RMCMessage::new(&mut Cursor::new(&packet.payload)) else {
|
||||
error!("error reading rmc message");
|
||||
return;
|
||||
};
|
||||
|
||||
println!("got rmc message {},{}", rmc.protocol_id, rmc.method_id);
|
||||
|
||||
for proto in &self.0 {
|
||||
if let Some(response) = proto(&rmc, &socket, &connection).await {
|
||||
if matches!(response.response_result, RMCResponseResult::Error {..}){
|
||||
error!("an rmc error occurred")
|
||||
}
|
||||
let mut locked = connection.lock().await;
|
||||
send_response(&packet, &socket, &mut locked, response).await;
|
||||
drop(locked);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error!("tried to send message to unimplemented protocol {} with method id {}", rmc.protocol_id, rmc.method_id);
|
||||
let mut locked = connection.lock().await;
|
||||
send_response(&packet, &socket, &mut locked, RMCResponse{
|
||||
protocol_id: rmc.protocol_id as u8,
|
||||
response_result: RMCResponseResult::Error {
|
||||
call_id: rmc.call_id,
|
||||
error_code: Core_NotImplemented
|
||||
}
|
||||
}).await;
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue