1mod client;
2
3use std::hash::Hash;
4use std::ops::Deref;
5use std::sync::Arc;
6use std::time::Duration;
7use bucky_raw_codec::{RawDecode, RawEncode, RawFixedBytes};
8use callback_result::CallbackWaiter;
9use num::{FromPrimitive, ToPrimitive};
10use sfo_pool::WorkerClassification;
11pub use client::*;
12
13mod classified_client;
14pub use classified_client::*;
15
16use crate::{CmdBody, CmdHandler, CmdTunnelMeta, PeerId, TunnelId};
17use crate::errors::CmdResult;
18
19pub trait CmdSend<M: CmdTunnelMeta>: Send + 'static {
20 fn get_tunnel_meta(&self) -> Option<Arc<M>>;
21 fn get_remote_peer_id(&self) -> PeerId;
22}
23
24pub trait SendGuard<M: CmdTunnelMeta, S: CmdSend<M>>: Send + 'static + Deref<Target = S> {
25}
26
27#[async_trait::async_trait]
28pub trait CmdClient<LEN: RawEncode + for<'a> RawDecode<'a> + Copy + RawFixedBytes + Sync + Send + 'static + FromPrimitive + ToPrimitive,
29 CMD: RawEncode + for<'a> RawDecode<'a> + Copy + RawFixedBytes + Sync + Send + 'static + Eq + Hash,
30 M: CmdTunnelMeta,
31 S: CmdSend<M>,
32 G: SendGuard<M, S>>: Send + Sync + 'static {
33 fn register_cmd_handler(&self, cmd: CMD, handler: impl CmdHandler<LEN, CMD>);
34 async fn send(&self, cmd: CMD, version: u8, body: &[u8]) -> CmdResult<()>;
35 async fn send_with_resp(&self, cmd: CMD, version: u8, body: &[u8], timeout: Duration) -> CmdResult<CmdBody>;
36 async fn send2(&self, cmd: CMD, version: u8, body: &[&[u8]]) -> CmdResult<()>;
37 async fn send2_with_resp(&self, cmd: CMD, version: u8, body: &[&[u8]], timeout: Duration) -> CmdResult<CmdBody>;
38 async fn send_cmd(&self, cmd: CMD, version: u8, body: CmdBody) -> CmdResult<()>;
39 async fn send_cmd_with_resp(&self, cmd: CMD, version: u8, body: CmdBody, timeout: Duration) -> CmdResult<CmdBody>;
40 async fn send_by_specify_tunnel(&self, tunnel_id: TunnelId, cmd: CMD, version: u8, body: &[u8]) -> CmdResult<()>;
41 async fn send_by_specify_tunnel_with_resp(&self, tunnel_id: TunnelId, cmd: CMD, version: u8, body: &[u8], timeout: Duration) -> CmdResult<CmdBody>;
42 async fn send2_by_specify_tunnel(&self, tunnel_id: TunnelId, cmd: CMD, version: u8, body: &[&[u8]]) -> CmdResult<()>;
43 async fn send2_by_specify_tunnel_with_resp(&self, tunnel_id: TunnelId, cmd: CMD, version: u8, body: &[&[u8]], timeout: Duration) -> CmdResult<CmdBody>;
44 async fn send_cmd_by_specify_tunnel(&self, tunnel_id: TunnelId, cmd: CMD, version: u8, body: CmdBody) -> CmdResult<()>;
45 async fn send_cmd_by_specify_tunnel_with_resp(&self, tunnel_id: TunnelId, cmd: CMD, version: u8, body: CmdBody, timeout: Duration) -> CmdResult<CmdBody>;
46 async fn clear_all_tunnel(&self);
47 async fn get_send(&self, tunnel_id: TunnelId) -> CmdResult<G>;
48}
49
50#[async_trait::async_trait]
51pub trait ClassifiedCmdClient<LEN: RawEncode + for<'a> RawDecode<'a> + Copy + RawFixedBytes + Sync + Send + 'static + FromPrimitive + ToPrimitive,
52 CMD: RawEncode + for<'a> RawDecode<'a> + Copy + RawFixedBytes + Sync + Send + 'static + Eq + Hash,
53 C: WorkerClassification,
54 M: CmdTunnelMeta,
55 S: CmdSend<M>,
56 G: SendGuard<M, S>>: CmdClient<LEN, CMD, M, S, G> {
57 async fn send_by_classified_tunnel(&self, classification: C, cmd: CMD, version: u8, body: &[u8]) -> CmdResult<()>;
58 async fn send_by_classified_tunnel_with_resp(&self, classification: C, cmd: CMD, version: u8, body: &[u8], timeout: Duration) -> CmdResult<CmdBody>;
59 async fn send2_by_classified_tunnel(&self, classification: C, cmd: CMD, version: u8, body: &[&[u8]]) -> CmdResult<()>;
60 async fn send2_by_classified_tunnel_with_resp(&self, classification: C, cmd: CMD, version: u8, body: &[&[u8]], timeout: Duration) -> CmdResult<CmdBody>;
61 async fn send_cmd_by_classified_tunnel(&self, classification: C, cmd: CMD, version: u8, body: CmdBody) -> CmdResult<()>;
62 async fn send_cmd_by_classified_tunnel_with_resp(&self, classification: C, cmd: CMD, version: u8, body: CmdBody, timeout: Duration) -> CmdResult<CmdBody>;
63 async fn find_tunnel_id_by_classified(&self, classification: C) -> CmdResult<TunnelId>;
64 async fn get_send_by_classified(&self, classification: C) -> CmdResult<G>;
65}
66
67
68pub(crate) type RespWaiter = CallbackWaiter<u64, CmdBody>;
69pub(crate) type RespWaiterRef = Arc<RespWaiter>;
70
71pub(crate) fn gen_resp_id<CMD: RawEncode + for<'a> RawDecode<'a> + Copy + RawFixedBytes + Sync + Send + 'static>(cmd: CMD, seq: u32) -> u64 {
72 let cmd_buf = cmd.raw_encode_to_buffer().unwrap();
73 let mut id = seq as u64;
74 let cmd = if cmd_buf.len() > 4 {
75 u32::from_be_bytes(cmd_buf[..4].try_into().unwrap())
76 } else {
77 let mut buf = [0u8; 4];
78 buf[..cmd_buf.len()].copy_from_slice(&cmd_buf);
79 u32::from_be_bytes(buf)
80 };
81 id |= (cmd as u64) << 32;
82 id
83}
84
85pub(crate) fn gen_seq() -> u32 {
86 rand::random::<u32>()
87}