diff --git a/Dockerfile b/Dockerfile index a9286b5..709c159 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,14 +15,14 @@ COPY --from=planner /app/recipe.json recipe.json ARG EDITION ARG DATABASE_URL -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/app/target \ +RUN --mount=type=cache,id=${EDITION}-registry,target=/usr/local/cargo/registry \ + --mount=type=cache,id=${EDITION}-target,target=/app/target \ cargo chef cook --release --recipe-path recipe.json --target x86_64-unknown-linux-musl && \ cargo chef cook --tests --target x86_64-unknown-linux-musl --recipe-path recipe.json COPY . . -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/app/target \ +RUN --mount=type=cache,id=${EDITION}-registry,target=/usr/local/cargo/registry \ + --mount=type=cache,id=${EDITION}-target,target=/app/target \ RNEX_STATIC=1 ./test-edition.sh && RNEX_STATIC=1 ./build-edition.sh && \ mkdir -p /app/dist && \ cp /app/target/x86_64-unknown-linux-musl/release/edge_node_holder_server /app/dist/ && \ diff --git a/proxy-common/src/lib.rs b/proxy-common/src/lib.rs index 20f90c1..d696c72 100644 --- a/proxy-common/src/lib.rs +++ b/proxy-common/src/lib.rs @@ -16,7 +16,6 @@ use rnex_core::{ }; use std::{ env::{self, VarError}, - error, net::{AddrParseError, Ipv4Addr, SocketAddr, SocketAddrV4}, ops::Deref, panic, diff --git a/prudpv0/src/crypto/friends_insecure.rs b/prudpv0/src/crypto/friends_insecure.rs index ead738a..e914836 100644 --- a/prudpv0/src/crypto/friends_insecure.rs +++ b/prudpv0/src/crypto/friends_insecure.rs @@ -3,9 +3,12 @@ use std::io::Write; use hmac::Mac; use md5::{Digest, Md5}; use rc4::{KeyInit, Rc4, StreamCipher}; -use rnex_core::prudp::{ - encryption::{DEFAULT_KEY, EncryptionPair}, - types_flags::{TypesFlags, types::DATA}, +use rnex_core::{ + PID, + prudp::{ + encryption::{DEFAULT_KEY, EncryptionPair}, + types_flags::{TypesFlags, types::DATA}, + }, }; use typenum::U5; @@ -29,7 +32,7 @@ impl CryptoInstance for InsecureInstance { fn encrypt_outgoing(&mut self, data: &mut [u8]) { self.pair.send.apply_keystream(data); } - fn get_user_id(&self) -> u32 { + fn get_user_id(&self) -> PID { 0 } fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4] { diff --git a/prudpv0/src/crypto/friends_secure.rs b/prudpv0/src/crypto/friends_secure.rs index 14bdf7c..ca63ccf 100644 --- a/prudpv0/src/crypto/friends_secure.rs +++ b/prudpv0/src/crypto/friends_secure.rs @@ -2,6 +2,7 @@ use hmac::Mac; use md5::{Digest, Md5}; use rc4::{KeyInit, Rc4, StreamCipher}; use rnex_core::{ + PID, executables::common::SECURE_SERVER_ACCOUNT, nex::account::Account, prudp::{ @@ -22,7 +23,7 @@ use crate::crypto::{ pub struct SecureInstance { pair: EncryptionPair>, - uid: u32, + uid: PID, self_signat: [u8; 4], #[allow(dead_code)] remote_signat: [u8; 4], @@ -35,7 +36,7 @@ impl CryptoInstance for SecureInstance { fn encrypt_outgoing(&mut self, data: &mut [u8]) { self.pair.send.apply_keystream(data); } - fn get_user_id(&self) -> u32 { + fn get_user_id(&self) -> PID { self.uid } fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4] { diff --git a/prudpv0/src/crypto/mod.rs b/prudpv0/src/crypto/mod.rs index f4806f6..829f7c5 100644 --- a/prudpv0/src/crypto/mod.rs +++ b/prudpv0/src/crypto/mod.rs @@ -1,5 +1,5 @@ use cfg_if::cfg_if; -use rnex_core::prudp::types_flags::TypesFlags; +use rnex_core::{PID, prudp::types_flags::TypesFlags}; mod common_crypto; @@ -7,7 +7,7 @@ pub trait CryptoInstance: Send + 'static { fn decrypt_incoming(&mut self, data: &mut [u8]); fn encrypt_outgoing(&mut self, data: &mut [u8]); fn generate_signature(&self, types_flags: TypesFlags, data: &[u8]) -> [u8; 4]; - fn get_user_id(&self) -> u32; + fn get_user_id(&self) -> PID; } pub trait Crypto: Send + Sync + 'static { diff --git a/prudpv1/src/prudp/secure.rs b/prudpv1/src/prudp/secure.rs index c7d312f..2618b74 100644 --- a/prudpv1/src/prudp/secure.rs +++ b/prudpv1/src/prudp/secure.rs @@ -3,6 +3,7 @@ use crate::prudp::socket::{CryptoHandler, CryptoHandlerConnectionInstance}; use hmac::digest::consts::U32; use rc4::cipher::StreamCipherCoreWrapper; use rc4::{KeyInit, Rc4, Rc4Core, StreamCipher}; +use rnex_core::PID; use rnex_core::nex::account::Account; use rnex_core::prudp::encryption::EncryptionPair; use rnex_core::prudp::ticket::read_secure_connection_data; @@ -49,7 +50,7 @@ pub struct SecureInstance { self_signature: [u8; 16], #[allow(dead_code)] remote_signature: [u8; 16], - pid: u32, + pid: PID, } impl CryptoHandler for Secure { @@ -108,7 +109,7 @@ impl CryptoHandlerConnectionInstance for SecureInstance { } } - fn get_user_id(&self) -> u32 { + fn get_user_id(&self) -> i32 { self.pid } diff --git a/prudpv1/src/prudp/socket.rs b/prudpv1/src/prudp/socket.rs index c6f5faa..19bf24d 100644 --- a/prudpv1/src/prudp/socket.rs +++ b/prudpv1/src/prudp/socket.rs @@ -6,6 +6,7 @@ use async_trait::async_trait; use log::error; use log::{info, warn}; use rc4::StreamCipher; +use rnex_core::PID; use rnex_core::prudp::socket_addr::PRUDPSockAddr; use rnex_core::prudp::types_flags::TypesFlags; use rnex_core::prudp::types_flags::flags::{ACK, HAS_SIZE, MULTI_ACK, NEED_ACK, RELIABLE}; @@ -31,7 +32,7 @@ use tokio::time::{Instant, sleep}; /// PRUDP Socket for accepting connections to then send and recieve data from those clients pub struct CommonConnection { - pub user_id: u32, + pub user_id: PID, pub socket_addr: PRUDPSockAddr, pub server_port: VirtualPort, session_id: u8, @@ -851,7 +852,7 @@ pub trait CryptoHandlerConnectionInstance: Send + Sync + 'static { fn decrypt_incoming(&mut self, substream: u8, data: &mut [u8]); fn encrypt_outgoing(&mut self, substream: u8, data: &mut [u8]); - fn get_user_id(&self) -> u32; + fn get_user_id(&self) -> i32; fn sign_connect(&self, packet: &mut PRUDPV1Packet); fn sign_packet(&self, packet: &mut PRUDPV1Packet); fn verify_packet(&self, packet: &PRUDPV1Packet) -> bool; diff --git a/prudpv1/src/prudp/unsecure.rs b/prudpv1/src/prudp/unsecure.rs index 79cc908..f9a566a 100644 --- a/prudpv1/src/prudp/unsecure.rs +++ b/prudpv1/src/prudp/unsecure.rs @@ -62,7 +62,7 @@ impl CryptoHandlerConnectionInstance for UnsecureInstance { } } - fn get_user_id(&self) -> u32 { + fn get_user_id(&self) -> i32 { 0 } diff --git a/rnex-core/build.rs b/rnex-core/build.rs new file mode 100644 index 0000000..2af0e5f --- /dev/null +++ b/rnex-core/build.rs @@ -0,0 +1,13 @@ +use std::{env, process::Command}; +fn main() { + let output = Command::new("git") + .args(&["rev-parse", "HEAD"]) + .output() + .unwrap(); + let git_hash = String::from_utf8(output.stdout).unwrap(); + println!("cargo:rustc-env=GIT_HASH={}", git_hash); + println!( + "cargo:rustc-env=FEATURESET={}", + env::var("CARGO_CFG_FEATURE").unwrap() + ); +} diff --git a/rnex-core/src/executables/backend_server_secure.rs b/rnex-core/src/executables/backend_server_secure.rs index 88f2508..aa889ca 100644 --- a/rnex-core/src/executables/backend_server_secure.rs +++ b/rnex-core/src/executables/backend_server_secure.rs @@ -5,23 +5,24 @@ use rnex_core::common::setup; async fn main() { setup(); + #[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 if #[cfg(feature = "datastore")] { - 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"); - use rnex_core::executables::regular_backend; - regular_backend::start_regular_backend().await } else { use rnex_core::executables::regular_backend; regular_backend::start_regular_backend().await diff --git a/rnex-core/src/executables/common.rs b/rnex-core/src/executables/common.rs index ccc5d41..5115531 100644 --- a/rnex-core/src/executables/common.rs +++ b/rnex-core/src/executables/common.rs @@ -1,23 +1,18 @@ +use crate::reggie::UnitPacketRead; +use cfg_if::cfg_if; +use log::error; use once_cell::sync::Lazy; 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; -cfg_if! { - if #[cfg(feature = "datastore")] { - use sqlx::postgres::PgPool; - } -} -use crate::reggie::UnitPacketRead; -use cfg_if::cfg_if; -use log::error; -use std::error::Error; const IP_REQ_SERVICE_URLS: &[(&str, &str, &str)] = &[ ("ipinfo.io:80", "ipinfo.io", "/ip"), @@ -30,11 +25,12 @@ const IP_REQ_SERVICE_URLS: &[(&str, &str, &str)] = &[ ]; cfg_if! { - if #[cfg(feature = "datastore")] { + if #[cfg(feature = "database-support")] { use std::sync::{LazyLock, OnceLock}; - pub static RNEX_DATASTORE_DATABASE_URL: LazyLock = LazyLock::new(|| { - std::env::var("RNEX_DATASTORE_DATABASE_URL") - .expect("RNEX_DATASTORE_DATABASE_URL must be set") + use sqlx::postgres::PgPool; + pub static RNEX_DATABASE_URL: LazyLock = LazyLock::new(|| { + std::env::var("RNEX_DATABASE_URL") + .expect("RNEX_DATABASE_URL must be set") }); pub static DB_POOL: OnceLock = OnceLock::new(); @@ -42,6 +38,10 @@ cfg_if! { 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 = LazyLock::new(|| { std::env::var("RNEX_DATASTORE_S3_ENDPOINT") .expect("RNEX_DATASTORE_S3_ENDPOINT must be set") diff --git a/rnex-core/src/grpc/account.rs b/rnex-core/src/grpc/account.rs index 9d2d4e8..70aca04 100644 --- a/rnex-core/src/grpc/account.rs +++ b/rnex-core/src/grpc/account.rs @@ -166,7 +166,7 @@ impl Client { .find(|v| v.0 == "pid") .ok_or(SomethingHappened)? .1 - .as_u32() + .as_i32() else { return Err(SomethingHappened); }; diff --git a/rnex-core/src/lib.rs b/rnex-core/src/lib.rs index 28bdd48..81e254c 100644 --- a/rnex-core/src/lib.rs +++ b/rnex-core/src/lib.rs @@ -5,9 +5,9 @@ //#![warn(missing_docs)] #[cfg(feature = "big_pid")] -pub type PID = u64; +pub type PID = i64; #[cfg(not(feature = "big_pid"))] -pub type PID = u32; +pub type PID = i32; extern crate self as rnex_core; diff --git a/rnex-core/src/nex/friends_handler.rs b/rnex-core/src/nex/friends_handler.rs index 3af6ff6..71963e3 100644 --- a/rnex-core/src/nex/friends_handler.rs +++ b/rnex-core/src/nex/friends_handler.rs @@ -10,7 +10,9 @@ use macros::rmc_struct; use rnex_core::rmc::protocols::account_management::{ AccountManagement, RawAccountManagement, RawAccountManagementInfo, RemoteAccountManagement, }; -use rnex_core::rmc::protocols::friends::{Friends, RawFriends, RawFriendsInfo, RemoteFriends}; +use rnex_core::rmc::protocols::friends_wiiu::{ + FriendsWiiU, RawFriendsWiiU, RawFriendsWiiUInfo, RemoteFriendsWiiU, +}; use rnex_core::rmc::protocols::nintendo_notification::{ NintendoNotification, RawNintendoNotification, RawNintendoNotificationInfo, RemoteNintendoNotification, @@ -22,19 +24,20 @@ use rnex_core::{ nex::common::get_station_urls, prudp::{socket_addr::PRUDPSockAddr, station_url::StationUrl}, rmc::{ - protocols::friends::{ + protocols::friends_wiiu::{ BlacklistedPrincipal, Comment, FriendInfo, FriendRequest, NNAInfo, NintendoPresenceV2, - PersistentNotification, PrincipalPreference, + PersistentNotification, PrincipalPreference, PrincipalRequestBlockSetting, }, response::ErrorCode, structures::{any::Any, qresult::QResult}, }, }; +use sqlx::query; use std::sync::atomic::Ordering::Relaxed; use tokio::spawn; use tokio::sync::RwLock; -use rnex_core::rmc::protocols::friends::{GameKey, MiiV2, PrincipalBasicInfo}; +use rnex_core::rmc::protocols::friends_wiiu::{GameKey, MiiV2, PrincipalBasicInfo}; use rnex_core::PID; @@ -44,10 +47,12 @@ use rnex_core::rmc::structures::RmcSerialize; use rnex_core::rmc::structures::data::Data; +use crate::executables::common::get_db; + define_rmc_proto!( proto FriendsUser{ Secure, - Friends + FriendsWiiU } ); define_rmc_proto!( @@ -95,29 +100,12 @@ impl FriendsManager { } } -pub fn friend_info_from_user(data: &UserData) -> FriendInfo { - FriendInfo { - data: Data {}, - nna_info: data.info.clone(), - presence: data.presence.clone(), - comment: Comment { - data: Data {}, - unk: 0, - message: "haii =w=".to_string(), - last_changed: KerberosDateTime::now(), - }, - became_friends: KerberosDateTime::now(), - last_online: KerberosDateTime::now(), - unk: 0, - } -} - -impl Friends for FriendsUser { +impl FriendsWiiU for FriendsUser { async fn update_and_get_all_information( &self, info: NNAInfo, presence: NintendoPresenceV2, - _date_time: KerberosDateTime, + date_time: KerberosDateTime, ) -> Result< ( PrincipalPreference, @@ -132,213 +120,105 @@ impl Friends for FriendsUser { ), ErrorCode, > { - println!("updating own data"); - let mut data = self.data.write().await; - *data = Some(UserData { info, presence }); - let self_fr_info = friend_info_from_user(data.as_ref().unwrap()); - let Ok(any_self_fr_info) = Any::new(&self_fr_info) else { - return Err(ErrorCode::RendezVous_ControlScriptFailure); - }; - let Ok(any_self_presence) = Any::new(&self_fr_info.presence) else { - return Err(ErrorCode::RendezVous_ControlScriptFailure); - }; - drop(data); + // let query = query!("select ", self.pid).fetch_all(get_db()).await; + Err(ErrorCode::Core_NotImplemented) + } - let mut fr_list = vec![FriendInfo { - data: Data{}, - became_friends: KerberosDateTime::now(), - comment: Comment { - data: Data{}, - last_changed: KerberosDateTime::now(), - message: "I'm just a dummy account :3".to_string(), - unk: 0, - }, - last_online: KerberosDateTime::now(), - nna_info: NNAInfo { - data: Data{}, - principal_basic_info: PrincipalBasicInfo { - data: Data{}, - pid: 101, - nnid: "dummy:3".to_string(), - mii: MiiV2{ - data: Data{}, - date_time: KerberosDateTime::now(), - name: "TheDummy".to_string(), - mii_data: hex::decode("030000402bd7c32986a771f2dc6b35e31da15e37ff7c0000391e6f006f006d0069000000000000000000000000004040001065033568641e2013661a611821640f0000290052485000000000000000000000000000000000000000000000e838").unwrap(), - unk: 0, - unk2: 0, - }, - unk: 0 - }, - unk: 0, - unk2: 0 - }, - presence: NintendoPresenceV2{ - data: Data{}, - changed_flags: 0, - message: "".to_string(), - app_data: vec![], - game_key: GameKey{ - data: Data{}, - tid: 0x00050002101ce400, - version: 0x0 - }, - game_server_id: 0, - is_online: true, - gid: 0, - pid: 101, - unk: 0, - unk2: 0, - unk3: 0, - unk4: 0, - unk5: 0, - unk6: 0, - unk7: 0 - }, - unk: 0 - }]; + async fn add_friend(&self, friend: PID) -> Result<(FriendRequest, FriendInfo), ErrorCode> { + todo!() + } - println!("acquiring user and current friends locks"); - let users = self.fm.users.read().await; - if users.iter().filter(|u| u.upgrade().is_some()).count() >= 100 { - return Err(ErrorCode::RendezVous_ConnectionFailure); - } - println!("started summing users"); - for u in users.deref().iter().filter_map(|u| u.upgrade()) { - let data = u.data.read().await; - let Some(inner_data) = data.as_ref() else { - continue; - }; - fr_list.push(friend_info_from_user(&inner_data)); - drop(data); + async fn add_friend_by_name( + &self, + name: String, + ) -> Result<(FriendRequest, FriendInfo), ErrorCode> { + todo!() + } - let mut curr_friends = self.current_friends.write().await; - curr_friends.push(u.pid); - drop(curr_friends); + async fn remove_friend(&self, friend: PID) -> Result<(), ErrorCode> { + todo!() + } - let mut fr = u.current_friends.write().await; - if !fr.contains(&self.pid) { - fr.push(self.pid); - drop(fr); - let data = any_self_fr_info.clone(); - let u = u.clone(); - let sender = self.pid; - spawn(async move { - u.remote - .process_nintendo_notification_event_1(NintendoNotificationEvent { - event_type: 30, - sender, - data, - }) - .await; - }); - } else { - let data = any_self_presence.clone(); - let u = u.clone(); - let sender = self.pid; - spawn(async move { - u.remote - .process_nintendo_notification_event_2(NintendoNotificationEvent { - event_type: 24, - sender, - data, - }) - .await; - }); - drop(fr); - } - } - println!("finished summing users"); - drop(users); + async fn add_friend_request( + &self, + friend: PID, + unk1: u8, + message: String, + unk2: u8, + unk3: String, + game_key: GameKey, + unk4: KerberosDateTime, + ) -> Result<(FriendRequest, FriendInfo), ErrorCode> { + todo!() + } - println!("adding self to users"); - let mut users = self.fm.users.write().await; - users.push(self.this.clone()); - drop(users); + async fn cancel_friend_request(&self, id: u64) -> Result<(), ErrorCode> { + todo!() + } - println!("done..."); - Ok(( - PrincipalPreference { - data: Data {}, - block_friend_request: false, - show_online: false, - show_playing_title: false, - }, - Comment { - data: Data {}, - last_changed: KerberosDateTime::now(), - message: "".to_string(), - unk: 0, - }, - fr_list, - vec![], - vec![], - vec![], - false, - vec![], - false, - )) + async fn accept_friend_request(&self, id: u64) -> Result { + todo!() + } + + async fn delete_friend_request(&self, id: u64) -> Result<(), ErrorCode> { + todo!() + } + + async fn deny_friend_request(&self, id: u64) -> Result { + todo!() + } + + async fn mark_friend_requests_as_received(&self, ids: Vec) -> Result<(), ErrorCode> { + todo!() + } + + async fn add_blacklist( + &self, + principal: BlacklistedPrincipal, + ) -> Result { + todo!() + } + + async fn remove_blacklist(&self, id: PID) -> Result<(), ErrorCode> { + todo!() } async fn update_presence(&self, presence: NintendoPresenceV2) -> Result<(), ErrorCode> { - info!("user updated presence: {:?}", presence); - let mut data = self.data.write().await; - let Some(inner_data) = data.as_mut() else { - log::error!("unable to get presence data"); - return Err(ErrorCode::RendezVous_PermissionDenied); - }; - inner_data.presence = presence; - let Ok(any_self_fr_info) = Any::new(&inner_data.presence) else { - log::error!("unable to create presence any data holder"); - return Err(ErrorCode::RendezVous_ControlScriptFailure); - }; - drop(data); + todo!() + } - let users = self.fm.users.read().await; - for u in users.deref().iter().filter_map(|u| u.upgrade()) { - info!("sending presence update"); - u.remote - .process_nintendo_notification_event_2(NintendoNotificationEvent { - event_type: 24, - sender: self.pid, - data: any_self_fr_info.clone(), - }) - .await; - } - drop(users); + async fn update_mii(&self, presence: MiiV2) -> Result { + todo!() + } - Ok(()) + async fn update_comment(&self, presence: Comment) -> Result { + todo!() + } + + async fn update_preference(&self, preference: PrincipalPreference) -> Result<(), ErrorCode> { + todo!() + } + + async fn get_basic_info(&self, pids: Vec) -> Result, ErrorCode> { + todo!() } async fn delete_persistent_notification( &self, - _notifs: Vec, + notifs: Vec, ) -> Result<(), ErrorCode> { - Ok(()) + todo!() } async fn check_setting_status(&self) -> Result { - Ok(0xFF) + todo!() } - - async fn update_preference(&self, preference: PrincipalPreference) -> Result<(),ErrorCode> { - info!("user updated preference: {:?}", preference); - let any_presence: Any = Any::new(&preference).expect("out of memory"); - let users = self.fm.users.read().await; - for u in users.deref().iter().filter_map(|u| u.upgrade()) { - info!("sending preference update"); - u.remote - .process_nintendo_notification_event_2(NintendoNotificationEvent { - event_type: 23, - sender: self.pid, - data: any_presence.clone(), - }) - .await; - } - drop(users); - - Ok(()) + async fn get_request_block_settings( + &self, + unk: Vec, + ) -> Result, ErrorCode> { + todo!() } } diff --git a/rnex-core/src/nex/matchmake.rs b/rnex-core/src/nex/matchmake.rs index 5fc31d8..1b12f04 100644 --- a/rnex-core/src/nex/matchmake.rs +++ b/rnex-core/src/nex/matchmake.rs @@ -1,7 +1,6 @@ use log::info; use rand::random; use rnex_core::PID; -use rnex_core::kerberos::KerberosDateTime; use rnex_core::nex::user::User; use rnex_core::rmc::protocols::notifications::notification_types::{ HOST_CHANGED, OWNERSHIP_CHANGED, @@ -11,9 +10,8 @@ use rnex_core::rmc::response::ErrorCode; use rnex_core::rmc::response::ErrorCode::{Core_InvalidArgument, RendezVous_SessionVoid}; use rnex_core::rmc::structures::matchmake::gathering_flags::PERSISTENT_GATHERING; use rnex_core::rmc::structures::matchmake::{ - Gathering, MatchmakeParam, MatchmakeSession, MatchmakeSessionSearchCriteria, + Gathering, MatchmakeSession, MatchmakeSessionSearchCriteria, }; -use rnex_core::rmc::structures::variant::Variant; use std::collections::HashMap; use std::str::FromStr; use std::sync::atomic::AtomicU32; @@ -28,7 +26,7 @@ pub struct MatchmakeManager { pub sessions: RwLock>>>, pub rv_cid_counter: AtomicU32, pub users: RwLock>>, - pub users_by_pid: RwLock>>, + pub users_by_pid: RwLock>>, } impl MatchmakeManager { @@ -162,6 +160,13 @@ impl ExtendedMatchmakeSession { cfg_if::cfg_if! { if #[cfg(feature = "v3-5-0")]{ + use rnex_core::{ + rmc::structures::{ + variant::Variant, + matchmake::MatchmakeParam + }, + kerberos::KerberosDateTime + }; let mm_session = MatchmakeSession { gathering: Gathering { self_gid: gid, diff --git a/rnex-core/src/nex/user.rs b/rnex-core/src/nex/user.rs index f27ca09..f955fca 100644 --- a/rnex-core/src/nex/user.rs +++ b/rnex-core/src/nex/user.rs @@ -37,7 +37,7 @@ use std::env; use std::str::FromStr; use cfg_if::cfg_if; -use log::{error, info, warn}; +use log::{error, info}; use macros::rmc_struct; use rnex_core::prudp::socket_addr::PRUDPSockAddr; use rnex_core::rmc::protocols::notifications::{NotificationEvent, RemoteNotification}; @@ -456,7 +456,7 @@ impl MatchmakeExtension for User { .users_by_pid .read() .await - .get(&recpipent) + .get(&bytemuck::cast(recpipent)) .and_then(|v| v.upgrade()) else { return Err(ErrorCode::Core_InvalidArgument); @@ -468,8 +468,8 @@ impl MatchmakeExtension for User { .process_notification_event(NotificationEvent { pid_source: self.pid, notif_type: REQUEST_JOIN_GATHERING * 1000, - param_1, - param_2, + param_1: bytemuck::cast(param_1), + param_2: bytemuck::cast(param_2), #[cfg(feature = "third-notif-param")] param_3: 0, str_param, @@ -481,8 +481,8 @@ impl MatchmakeExtension for User { .process_notification_event(NotificationEvent { pid_source: self.pid, notif_type: END_GATHERING * 1000, - param_1, - param_2, + param_1: bytemuck::cast(param_1), + param_2: bytemuck::cast(param_2), #[cfg(feature = "third-notif-param")] param_3: 0, str_param, diff --git a/rnex-core/src/rmc/protocols/account_management.rs b/rnex-core/src/rmc/protocols/account_management.rs index 8ef2d9e..a245fe7 100644 --- a/rnex-core/src/rmc/protocols/account_management.rs +++ b/rnex-core/src/rmc/protocols/account_management.rs @@ -5,7 +5,7 @@ use rnex_core::{ rmc::{response::ErrorCode, structures::any::Any}, }; -use crate::{kerberos::KerberosDateTime, rmc::protocols::friends::NNAInfo}; +use crate::{kerberos::KerberosDateTime, rmc::protocols::friends_wiiu::NNAInfo}; #[derive(RmcSerialize, Debug, Clone)] #[rmc_struct(0)] diff --git a/rnex-core/src/rmc/protocols/friends_3ds.rs b/rnex-core/src/rmc/protocols/friends_3ds.rs new file mode 100644 index 0000000..aaa7af0 --- /dev/null +++ b/rnex-core/src/rmc/protocols/friends_3ds.rs @@ -0,0 +1,250 @@ +use macros::{RmcSerialize, method_id, rmc_proto}; + +use rnex_core::rmc::{response::ErrorCode, structures::data::Data}; + +use crate::{PID, kerberos::KerberosDateTime}; + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct MyProfile { + #[extends] + pub data: Data, + pub region: u8, + pub country: u8, + pub area: u8, + pub language: u8, + pub platform: u8, + pub local_friend_code_seed: u64, + pub mac_address: String, + pub serial_number: String, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct Mii { + #[extends] + pub data: Data, + pub unk1: String, + pub unk2: bool, + pub unk3: u8, + pub mii_data: Vec, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct MiiList { + #[extends] + pub data: Data, + pub unk1: String, + pub unk2: bool, + pub unk3: u8, + pub mii_data: Vec>, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct GameKey { + #[extends] + pub data: Data, + pub title_id: u64, + pub version: u16, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct PlayedGame { + #[extends] + pub data: Data, + pub game_key: GameKey, + pub date_time: KerberosDateTime, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct FriendInfo { + pub unk1: u32, + pub unk2: KerberosDateTime, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct FriendMii { + #[extends] + pub data: Data, + pub pid: PID, + pub mii: Mii, + pub modified_at: KerberosDateTime, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct FriendMiiList { + #[extends] + pub data: Data, + pub unk1: u32, + pub mii_list: MiiList, + pub unk2: KerberosDateTime, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct FriendRelationship { + #[extends] + pub data: Data, + pub unk1: u32, + pub unk2: u64, + pub unk3: u8, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct NintendoPresence { + #[extends] + pub data: Data, + pub changed_bit_flag: u32, + pub game_key: GameKey, + pub game_mode_desctiption: String, + pub join_availibility_flag: u32, + pub mm_system_type: u8, + pub join_game_id: u32, + pub join_game_mode: u32, + pub owner_pid: PID, + pub join_group_id: u32, + pub application_arg: Vec, +} +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct FriendPresence { + #[extends] + pub data: Data, + pub unk: u32, + pub presence: NintendoPresence, +} +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct FriendComment { + #[extends] + pub data: Data, + pub pid: PID, + pub comment: String, + pub modified_at: KerberosDateTime, +} +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct FriendPicture { + #[extends] + pub data: Data, + pub unk1: u32, + pub pic_data: Vec, + pub date_time: KerberosDateTime, +} + +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct FriendPersistentInfo { + #[extends] + pub data: Data, + pub pid: PID, + pub region: u8, + pub country: u8, + pub area: u8, + pub language: u8, + pub platform: u8, + pub game_key: GameKey, + pub message: String, + pub msg_updated_at: KerberosDateTime, + pub friended_at: KerberosDateTime, + pub last_online: KerberosDateTime, +} + +#[rmc_proto(101)] +pub trait Friends3DS { + #[method_id(1)] + async fn update_profile(&self, profile: MyProfile) -> Result<(), ErrorCode>; + #[method_id(2)] + async fn update_mii(&self, profile: Mii) -> Result<(), ErrorCode>; + #[method_id(3)] + async fn update_mii_list(&self, profile: MiiList) -> Result<(), ErrorCode>; + #[method_id(4)] + async fn update_played_games(&self, profile: Vec) -> Result<(), ErrorCode>; + #[method_id(5)] + async fn update_preference( + &self, + show_online_status: bool, + show_current_title: bool, + block_friend_requests: bool, + ) -> Result<(), ErrorCode>; + + #[method_id(6)] + async fn get_friend_mii(&self, friends: Vec) -> Result, ErrorCode>; + #[method_id(7)] + async fn get_friend_mii_list( + &self, + friends: Vec, + ) -> Result, ErrorCode>; + #[method_id(8)] + async fn is_active_game(&self, unk: Vec, game_key: GameKey) + -> Result, ErrorCode>; + #[method_id(9)] + async fn get_principal_id_by_local_friend_code( + &self, + unk1: u64, + unk2: Vec, + ) -> Result, ErrorCode>; + #[method_id(10)] + async fn get_friend_relationships( + &self, + unk2: Vec, + ) -> Result, ErrorCode>; + #[method_id(11)] + async fn add_friend_by_pid(&self, unk: u64, pid: PID) -> Result; + #[method_id(12)] + async fn add_friend_by_lst_pid( + &self, + unk: u64, + pid: Vec, + ) -> Result, ErrorCode>; + #[method_id(13)] + async fn remove_friend_by_local_code(&self, local_code: u64) -> Result<(), ErrorCode>; + #[method_id(14)] + async fn remove_friend_by_pid(&self, pid: PID) -> Result<(), ErrorCode>; + #[method_id(15)] + async fn get_all_friends(&self) -> Result, ErrorCode>; + #[method_id(16)] + async fn update_blacklist(&self) -> Result<(), ErrorCode>; + #[method_id(17)] + async fn sync_friend( + &self, + unk1: u64, + unk2: Vec, + unk3: Vec, + ) -> Result, ErrorCode>; + #[method_id(18)] + async fn update_presence( + &self, + nintendo_presence: NintendoPresence, + unk: bool, + ) -> Result<(), ErrorCode>; + #[method_id(19)] + async fn update_favorite_game_key(&self, game_key: GameKey) -> Result<(), ErrorCode>; + #[method_id(20)] + async fn update_comment(&self, comment: String) -> Result<(), ErrorCode>; + #[method_id(21)] + async fn update_picture(&self, unk: u32, picture: Vec) -> Result<(), ErrorCode>; + #[method_id(22)] + async fn get_friend_presence(&self, unk: Vec) -> Result, ErrorCode>; + #[method_id(23)] + async fn get_friend_comment( + &self, + unk: Vec, + ) -> Result, ErrorCode>; + #[method_id(24)] + async fn get_friend_picture(&self, unk: Vec) -> Result, ErrorCode>; + #[method_id(25)] + async fn get_friend_persistent_info( + &self, + unk: Vec, + ) -> Result, ErrorCode>; + #[method_id(26)] + async fn send_invitation(&self, unk: Vec) -> Result<(), ErrorCode>; +} diff --git a/rnex-core/src/rmc/protocols/friends.rs b/rnex-core/src/rmc/protocols/friends_wiiu.rs similarity index 65% rename from rnex-core/src/rmc/protocols/friends.rs rename to rnex-core/src/rmc/protocols/friends_wiiu.rs index d25ea9e..1764c93 100644 --- a/rnex-core/src/rmc/protocols/friends.rs +++ b/rnex-core/src/rmc/protocols/friends_wiiu.rs @@ -4,6 +4,8 @@ use rnex_core::{kerberos::KerberosDateTime, rmc::response::ErrorCode}; use rnex_core::rmc::structures::data::Data; +use rnex_core::PID; + #[derive(RmcSerialize, Debug, Clone)] #[rmc_struct(0)] pub struct MiiV2 { @@ -21,7 +23,7 @@ pub struct MiiV2 { pub struct PrincipalBasicInfo { #[extends] pub data: Data, - pub pid: u32, + pub pid: PID, pub nnid: String, pub mii: MiiV2, pub unk: u8, @@ -147,8 +149,17 @@ pub struct PersistentNotification { pub unk5: String, } +#[derive(RmcSerialize)] +#[rmc_struct(0)] +pub struct PrincipalRequestBlockSetting { + #[extends] + pub data: Data, + pub pid: PID, + pub blocked: bool, +} + #[rmc_proto(102)] -pub trait Friends { +pub trait FriendsWiiU { #[method_id(1)] async fn update_and_get_all_information( &self, @@ -169,10 +180,53 @@ pub trait Friends { ), ErrorCode, >; + #[method_id(2)] + async fn add_friend(&self, friend: PID) -> Result<(FriendRequest, FriendInfo), ErrorCode>; + #[method_id(3)] + async fn add_friend_by_name( + &self, + name: String, + ) -> Result<(FriendRequest, FriendInfo), ErrorCode>; + #[method_id(4)] + async fn remove_friend(&self, friend: PID) -> Result<(), ErrorCode>; + #[method_id(5)] + async fn add_friend_request( + &self, + friend: PID, + unk1: u8, + message: String, + unk2: u8, + unk3: String, + game_key: GameKey, + unk4: KerberosDateTime, + ) -> Result<(FriendRequest, FriendInfo), ErrorCode>; + #[method_id(6)] + async fn cancel_friend_request(&self, id: u64) -> Result<(), ErrorCode>; + #[method_id(7)] + async fn accept_friend_request(&self, id: u64) -> Result; + #[method_id(8)] + async fn delete_friend_request(&self, id: u64) -> Result<(), ErrorCode>; + #[method_id(9)] + async fn deny_friend_request(&self, id: u64) -> Result; + #[method_id(10)] + async fn mark_friend_requests_as_received(&self, ids: Vec) -> Result<(), ErrorCode>; + #[method_id(11)] + async fn add_blacklist( + &self, + principal: BlacklistedPrincipal, + ) -> Result; + #[method_id(12)] + async fn remove_blacklist(&self, id: PID) -> Result<(), ErrorCode>; #[method_id(13)] async fn update_presence(&self, presence: NintendoPresenceV2) -> Result<(), ErrorCode>; + #[method_id(14)] + async fn update_mii(&self, presence: MiiV2) -> Result; + #[method_id(15)] + async fn update_comment(&self, presence: Comment) -> Result; #[method_id(16)] async fn update_preference(&self, preference: PrincipalPreference) -> Result<(), ErrorCode>; + #[method_id(17)] + async fn get_basic_info(&self, pids: Vec) -> Result, ErrorCode>; #[method_id(18)] async fn delete_persistent_notification( &self, @@ -180,4 +234,9 @@ pub trait Friends { ) -> Result<(), ErrorCode>; #[method_id(19)] async fn check_setting_status(&self) -> Result; + #[method_id(20)] + async fn get_request_block_settings( + &self, + unk: Vec, + ) -> Result, ErrorCode>; } diff --git a/rnex-core/src/rmc/protocols/mod.rs b/rnex-core/src/rmc/protocols/mod.rs index 411ae28..6f14323 100644 --- a/rnex-core/src/rmc/protocols/mod.rs +++ b/rnex-core/src/rmc/protocols/mod.rs @@ -3,7 +3,8 @@ pub mod account_management; pub mod auth; pub mod datastore; -pub mod friends; +pub mod friends_3ds; +pub mod friends_wiiu; pub mod matchmake; pub mod matchmake_ext; pub mod matchmake_extension; diff --git a/rnex-core/src/rmc/protocols/ranking.rs b/rnex-core/src/rmc/protocols/ranking.rs index 68be98f..9a9ca09 100644 --- a/rnex-core/src/rmc/protocols/ranking.rs +++ b/rnex-core/src/rmc/protocols/ranking.rs @@ -1,10 +1,12 @@ use macros::{RmcSerialize, method_id, rmc_proto}; use rnex_core::kerberos::KerberosDateTime; -use rnex_core::rmc::structures::qbuffer::QBuffer; -use rnex_core::rmc::structures::resultsrange::ResultsRange; use rnex_core::rmc::response::ErrorCode; +use rnex_core::rmc::structures::qbuffer::QBuffer; use rnex_core::rmc::structures::ranking::UploadCompetitionData; +use rnex_core::rmc::structures::resultsrange::ResultsRange; + +use crate::PID; #[derive(RmcSerialize, Debug, Default, Clone)] #[rmc_struct(1)] @@ -28,7 +30,7 @@ pub struct CompetitionRankingScoreInfo { #[rmc_struct(0)] pub struct CompetitionRankingScoreData { pub unk: u32, - pub pid: u32, + pub pid: PID, pub score: u32, pub modified: KerberosDateTime, pub unk2: u8, diff --git a/rnex-core/src/rmc/structures/matchmake.rs b/rnex-core/src/rmc/structures/matchmake.rs index 88deea0..0890365 100644 --- a/rnex-core/src/rmc/structures/matchmake.rs +++ b/rnex-core/src/rmc/structures/matchmake.rs @@ -1,6 +1,5 @@ use cfg_if::cfg_if; use macros::RmcSerialize; -use rnex_core::kerberos::KerberosDateTime; use rnex_core::rmc::structures::variant::Variant; use rnex_core::PID; @@ -32,6 +31,7 @@ pub struct MatchmakeParam { cfg_if! { if #[cfg(feature = "v3-5-0")]{ + use rnex_core::kerberos::KerberosDateTime; #[derive(RmcSerialize, Debug, Clone, Default, PartialEq)] #[rmc_struct(3)] pub struct MatchmakeSession { diff --git a/rnex-core/src/server_api/gatherings.rs b/rnex-core/src/server_api/gatherings.rs new file mode 100644 index 0000000..735b34f --- /dev/null +++ b/rnex-core/src/server_api/gatherings.rs @@ -0,0 +1,88 @@ +use std::{ + hash::{DefaultHasher, Hash, Hasher}, + sync::Arc, +}; + +use rnex_server_api::gatherings::{ + Gatherings, gathering_info_service_server::GatheringInfoService, +}; +use tonic::{Request, Response, Status, async_trait}; + +use crate::{ + nex::matchmake::{ExtendedMatchmakeSession, MatchmakeManager}, + rmc::structures::matchmake::{self, MatchmakeSession}, + server_api, +}; + +impl Into for &ExtendedMatchmakeSession { + fn into(self) -> rnex_server_api::gatherings::Gathering { + let players = self.get_active_players().map(|p| *p.pid as u64).collect(); + let ExtendedMatchmakeSession { + session: + MatchmakeSession { + gathering: + matchmake::Gathering { + state, + flags, + host_pid, + description, + maximum_participants, + minimum_participants, + owner_pid, + participant_policy, + policy_argument, + self_gid, + }, + application_buffer, + attributes, + gamemode, + matchmake_system_type, + open_participation, + participation_count, + session_key, + }, + connected_players, + } = self; + rnex_server_api::gatherings::Gathering { + players, + description: description.clone(), + flags: *flags, + host_pid: *host_pid as _, + maximum_participants: *maximum_participants as _, + minimum_participants: *minimum_participants as _, + owner_pid: *owner_pid as _, + participant_policy: *participant_policy, + policy_argument: *policy_argument, + self_gid: *self_gid, + state: *state, + application_buffer: application_buffer.clone(), + attributes: attributes.clone(), + ..Default::default() + } + } +} + +struct GatheringsApi(Arc); + +#[async_trait] +impl GatheringInfoService for GatheringsApi { + async fn get_gatherings( + &self, + request: Request<()>, + ) -> std::result::Result, Status> { + Ok(Response::new(Gatherings { + gatherings: self + .0 + .sessions + .read() + .await + .keys() + .map(|gid| { + let mut hasher = DefaultHasher::new(); + gid.hash(&mut hasher); + hasher.finish() + }) + .collect(), + })) + } +} diff --git a/rnex-core/src/server_api/meta.rs b/rnex-core/src/server_api/meta.rs new file mode 100644 index 0000000..fb5b5ef --- /dev/null +++ b/rnex-core/src/server_api/meta.rs @@ -0,0 +1,36 @@ +use rnex_server_api::meta::{ + ApiFeature, ApiFeatures, BuildInfo, server_meta_service_server::ServerMetaService, +}; +use tonic::{Request, Response, Status, async_trait, transport::Server}; + +pub struct ServerMeta; + +#[async_trait] +impl ServerMetaService for ServerMeta { + async fn get_build_info(&self, request: Request<()>) -> Result, Status> { + Ok(Response::new(BuildInfo { + version: env!("CARGO_PKG_VERSION").to_owned(), + edition: env!("EDITION").to_owned(), + build_hash: env!("GIT_HASH").to_owned(), + feature_set: env!("FEATURESET").to_owned(), + })) + } + async fn get_api_features( + &self, + request: Request<()>, + ) -> Result, Status> { + let mut api_features = vec![ApiFeature { + name: "meta".to_owned(), + needs_admin: false, + version: 0, + }]; + + #[cfg(not(feature = "friends"))] + api_features.push(ApiFeature { + name: "gatherings".to_owned(), + version: 0, + needs_admin: true, + }); + Ok(Response::new(ApiFeatures { api_features })) + } +} diff --git a/rnex-core/src/server_api/mod.rs b/rnex-core/src/server_api/mod.rs new file mode 100644 index 0000000..b1389c8 --- /dev/null +++ b/rnex-core/src/server_api/mod.rs @@ -0,0 +1,22 @@ +use std::{net::SocketAddr, str::FromStr}; + +use rnex_server_api::meta::server_meta_service_server::ServerMetaServiceServer; +use tonic::transport::Server; + +#[cfg(not(feature = "friends"))] +use crate::nex::matchmake::MatchmakeManager; +use crate::server_api::meta::ServerMeta; +#[cfg(not(feature = "friends"))] +use std::sync::Arc; +#[cfg(not(feature = "friends"))] +mod gatherings; + +mod meta; + +pub async fn launch_server_api(#[cfg(not(feature = "friends"))] mmm: Arc) { + let mut server = Server::builder().add_service(ServerMetaServiceServer::new(ServerMeta)); + + server + .serve(SocketAddr::from_str("0.0.0.0:80").expect("unable to make sockaddr from ip")) + .await; +} diff --git a/rnex-server-api-grpc/gatherings.proto b/rnex-server-api-grpc/gatherings.proto new file mode 100644 index 0000000..cef3a90 --- /dev/null +++ b/rnex-server-api-grpc/gatherings.proto @@ -0,0 +1,54 @@ +syntax = "proto3"; +// NOTE: NEVER give out gids to the general public, people can and will be +// able to join random mkatches which they arent supposed to join via them +// +// As an alternative use a unique hash of the Gid + +import "google/protobuf/empty.proto"; + +package gatherings; + +message MatchmakeParam{ + +} + +message KerberosDateTime{ + uint32 raw = 1; +} + +message Gathering{ + repeated uint64 players = 1; + uint32 self_gid = 2; + uint64 owner_pid = 3; + uint64 host_pid = 4; + uint32 minimum_participants = 5; + uint32 maximum_participants = 6; + uint32 participant_policy = 7; + uint32 policy_argument = 8; + uint32 flags = 9; + uint32 state = 10; + string description = 11; + uint32 gamemode = 12; + repeated uint32 attributes = 13; + bool open_participation = 14; + uint32 matchmake_system_type = 15; + bytes application_buffer = 16; + uint32 participation_count = 17; + bytes session_key = 18; + optional uint32 progress_score = 19; + optional uint32 option0 = 20; + optional MatchmakeParam matchmake_param = 21; + optional KerberosDateTime datetime = 22; + optional string user_password = 23; + optional uint32 refer_gid = 24; + optional bool user_password_enabled = 25; + optional bool system_password_enabled = 26; +} + +message Gatherings{ + repeated Gathering gatherings = 1; +} + +service GatheringInfoService{ + rpc GetGatherings(google.protobuf.Empty) returns (Gatherings); +} diff --git a/rnex-server-api-grpc/meta.proto b/rnex-server-api-grpc/meta.proto new file mode 100644 index 0000000..e256e62 --- /dev/null +++ b/rnex-server-api-grpc/meta.proto @@ -0,0 +1,27 @@ +syntax = "proto3"; + +package meta; + +import "google/protobuf/empty.proto"; + +message BuildInfo { + string version = 1; + string edition = 2; + string feature_set = 3; + string build_hash = 4; +} + +message ApiFeature { + string name = 1; + int32 version = 2; + bool needs_admin = 3; +} + +message ApiFeatures { + repeated ApiFeature api_features = 1; +} + +service ServerMetaService { + rpc GetBuildInfo(google.protobuf.Empty) returns (BuildInfo); + rpc GetApiFeatures(google.protobuf.Empty) returns (ApiFeatures); +} diff --git a/rnex-server-api/Cargo.toml b/rnex-server-api/Cargo.toml new file mode 100644 index 0000000..c10be01 --- /dev/null +++ b/rnex-server-api/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "rnex-server-api" +version = "0.1.0" +edition = "2024" + +[dependencies] +prost = "0.14.3" +tonic-prost = "*" +tonic = "0.14.6" + +[build-dependencies] +tonic-prost-build = "0.14.6" diff --git a/rnex-server-api/build.rs b/rnex-server-api/build.rs new file mode 100644 index 0000000..4c9a954 --- /dev/null +++ b/rnex-server-api/build.rs @@ -0,0 +1,24 @@ +use std::{env, fs}; + +fn main() -> Result<(), Box> { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=../rnex-server-api-grpc/"); + + let protos: Vec = fs::read_dir("../rnex-server-api-grpc/")? + .filter(|e| { + e.as_ref().is_ok_and(|e| { + e.file_name() + .to_str() + .is_some_and(|n| n.ends_with(".proto")) + }) + }) + .filter_map(|e| { + e.ok() + .map(|v| v.path().to_str().map(|v| v.to_owned())) + .flatten() + }) + .collect(); + tonic_prost_build::configure() + .compile_protos(&protos[..], &["../rnex-server-api-grpc/".to_owned()])?; + Ok(()) +} diff --git a/rnex-server-api/src/lib.rs b/rnex-server-api/src/lib.rs new file mode 100644 index 0000000..c1a3fed --- /dev/null +++ b/rnex-server-api/src/lib.rs @@ -0,0 +1,6 @@ +pub mod meta { + tonic::include_proto!("meta"); +} +pub mod gatherings { + tonic::include_proto!("gatherings"); +}