2025-02-19 23:30:15 +01:00
|
|
|
use macros::method_id;
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
use std::ops::Add;
|
|
|
|
|
use std::sync::{Arc, Condvar};
|
|
|
|
|
use std::time::Duration;
|
2025-02-18 22:55:33 +01:00
|
|
|
use async_trait::async_trait;
|
2025-02-19 23:30:15 +01:00
|
|
|
use chrono::TimeDelta;
|
|
|
|
|
use macros::{rmc_proto, rmc_struct};
|
|
|
|
|
use paste::paste;
|
|
|
|
|
use tokio::sync::{Mutex, Notify};
|
|
|
|
|
use tokio::time::{sleep_until, Instant};
|
|
|
|
|
use crate::prudp::socket::{ExternalConnection, SendingConnection};
|
2025-02-18 22:55:33 +01:00
|
|
|
use crate::rmc::structures::connection_data::ConnectionData;
|
|
|
|
|
|
2025-02-19 23:30:15 +01:00
|
|
|
struct RmcConnection(SendingConnection, RmcResponseReceiver);
|
|
|
|
|
|
|
|
|
|
struct RmcResponseReceiver(Notify, Mutex<HashMap<(u16, u32), Vec<u8>>>);
|
|
|
|
|
|
|
|
|
|
impl RmcResponseReceiver{
|
|
|
|
|
// returns none if timed out
|
|
|
|
|
pub async fn get_response_data(&self, proto: u16, method: u32) -> Option<Vec<u8>>{
|
|
|
|
|
let mut end_wait_time = Instant::now();
|
|
|
|
|
end_wait_time += Duration::from_secs(5);
|
|
|
|
|
|
|
|
|
|
let sleep_fut = sleep_until(end_wait_time);
|
|
|
|
|
tokio::pin!(sleep_fut);
|
|
|
|
|
|
|
|
|
|
loop {
|
|
|
|
|
let mut locked = self.1.lock().await;
|
|
|
|
|
|
|
|
|
|
if let Some(v) = locked.remove(&(proto, method)){
|
|
|
|
|
return Some(v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let notif_fut = self.0.notified();
|
|
|
|
|
|
|
|
|
|
drop(locked);
|
|
|
|
|
|
|
|
|
|
tokio::select! {
|
|
|
|
|
_ = &mut sleep_fut => {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
_ = notif_fut => {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-18 22:55:33 +01:00
|
|
|
pub trait RmcCallable{
|
2025-02-19 23:30:15 +01:00
|
|
|
async fn rmc_call(&self, protocol_id: u16, method_id: u32, rest: Vec<u8>);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
macro_rules! define_rmc_proto {
|
|
|
|
|
(proto $name:ident{
|
|
|
|
|
$($protocol:path),*
|
|
|
|
|
}) => {
|
|
|
|
|
paste!{
|
|
|
|
|
trait [<Local $name>]: std::any::Any $( + [<Raw $protocol>])* {
|
|
|
|
|
async fn rmc_call(&self, protocol_id: u16, method_id: u32, rest: Vec<u8>){
|
|
|
|
|
match protocol_id{
|
|
|
|
|
$(
|
|
|
|
|
[<Raw $protocol Info>]::PROTOCOL_ID => <Self as [<Raw $protocol>]>::rmc_call_proto(self, method_id, rest).await,
|
|
|
|
|
)*
|
|
|
|
|
v => log::error!("invalid protocol called on rmc object {}", v)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trait RawNotif{
|
|
|
|
|
async fn rmc_call_proto(&self, method_id: u32, rest: Vec<u8>){
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct RawNotifInfo;
|
|
|
|
|
impl RawNotifInfo{
|
|
|
|
|
const PROTOCOL_ID: u16 = 10;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[rmc_proto(1)]
|
|
|
|
|
pub trait Another{
|
|
|
|
|
#[method_id(1)]
|
|
|
|
|
async fn test();
|
2025-02-18 22:55:33 +01:00
|
|
|
}
|
|
|
|
|
|
2025-02-19 23:30:15 +01:00
|
|
|
define_rmc_proto!{
|
|
|
|
|
proto TestProto{
|
|
|
|
|
Notif,
|
|
|
|
|
Another
|
2025-02-18 22:55:33 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-19 23:30:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
#[rmc_struct(TestProto)]
|
|
|
|
|
struct TestProtoImplementor{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl RawNotif for TestProtoImplementor{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|