flare_core/client/builder/
common.rs1use crate::client::Client;
4use crate::common::config_types::{HeartbeatAppState, HeartbeatConfig, TransportProtocol};
5use crate::common::error::Result;
6use crate::common::protocol::Frame;
7use std::sync::Arc;
8use std::time::Duration;
9use tokio::sync::Mutex;
10
11#[cfg(not(target_arch = "wasm32"))]
12use crate::client::HybridClient;
13
14#[cfg(target_arch = "wasm32")]
15use crate::client::WebSocketClient;
16
17#[derive(Clone)]
19pub struct ClientWrapper {
20 #[cfg(not(target_arch = "wasm32"))]
21 client: Arc<Mutex<HybridClient>>,
22 #[cfg(target_arch = "wasm32")]
23 client: Arc<Mutex<WebSocketClient>>,
24 reconnect_gate: Arc<Mutex<()>>,
25}
26
27impl ClientWrapper {
28 #[cfg(not(target_arch = "wasm32"))]
29 pub fn new(client: HybridClient) -> Self {
30 Self {
31 client: Arc::new(Mutex::new(client)),
32 reconnect_gate: Arc::new(Mutex::new(())),
33 }
34 }
35
36 #[cfg(target_arch = "wasm32")]
37 pub fn new(client: WebSocketClient) -> Self {
38 Self {
39 client: Arc::new(Mutex::new(client)),
40 reconnect_gate: Arc::new(Mutex::new(())),
41 }
42 }
43
44 pub async fn connect(&self) -> Result<()> {
45 let mut client = self.client.lock().await;
46 client.connect().await
47 }
48
49 pub async fn disconnect(&self) -> Result<()> {
50 let mut client = self.client.lock().await;
51 client.disconnect().await
52 }
53
54 pub async fn send_frame_and_wait(&self, frame: &Frame, timeout: Duration) -> Result<Frame> {
55 let mut client = self.client.lock().await;
56 client.send_frame_and_wait(frame, timeout).await
57 }
58
59 pub async fn send_frame(&self, frame: &Frame) -> Result<()> {
60 self.ensure_ready_for_send().await?;
61 let mut client = self.client.lock().await;
62 client.send_frame(frame).await
63 }
64
65 async fn ensure_ready_for_send(&self) -> Result<()> {
66 if self.is_send_ready().await {
67 return Ok(());
68 }
69
70 let _single_flight = self.reconnect_gate.lock().await;
71 if self.is_send_ready().await {
72 return Ok(());
73 }
74
75 {
76 let mut client = self.client.lock().await;
77 if !client.is_connected() {
78 client.connect().await?;
79 }
80 }
81
82 let core = {
83 let client = self.client.lock().await;
84 client.core().clone()
85 };
86 core.wait_for_negotiation(Duration::from_secs(10)).await
87 }
88
89 async fn is_send_ready(&self) -> bool {
90 let client = self.client.lock().await;
91 client.is_connected()
92 && client.core().can_send()
93 && client.core().is_negotiation_completed()
94 }
95
96 pub async fn add_observer(&self, observer: crate::transport::events::ArcObserver) {
97 let mut client = self.client.lock().await;
98 client.add_observer(observer);
99 }
100
101 #[cfg(not(target_arch = "wasm32"))]
102 pub async fn set_event_handler(
103 &self,
104 handler: Option<Arc<dyn crate::client::events::handler::ClientEventHandler>>,
105 ) {
106 let mut client = self.client.lock().await;
107 client.core_mut().set_event_handler(handler);
108 }
109
110 pub async fn is_connected_async(&self) -> bool {
111 let client = self.client.lock().await;
112 client.is_connected()
113 }
114
115 pub async fn connection_id_async(&self) -> Option<String> {
116 let client = self.client.lock().await;
117 client.connection_id()
118 }
119
120 pub fn active_protocol(&self) -> TransportProtocol {
121 #[cfg(not(target_arch = "wasm32"))]
122 {
123 crate::client::runtime::run_client_async(async {
124 let client = self.client.lock().await;
125 client.active_protocol()
126 })
127 }
128 #[cfg(target_arch = "wasm32")]
129 {
130 TransportProtocol::WebSocket
131 }
132 }
133
134 pub async fn with_core<F, R>(&self, f: F) -> R
135 where
136 F: FnOnce(&crate::client::transports::ClientCore) -> R,
137 {
138 let client = self.client.lock().await;
139 f(client.core())
140 }
141
142 pub async fn update_heartbeat_config(&self, config: HeartbeatConfig) {
143 self.with_core(|core| {
144 core.update_heartbeat_config(|current| {
145 *current = config;
146 });
147 })
148 .await;
149 }
150
151 pub async fn set_heartbeat_app_state(&self, state: HeartbeatAppState) {
152 self.with_core(|core| {
153 core.set_heartbeat_app_state(state);
154 })
155 .await;
156 }
157
158 pub async fn set_heartbeat_nat_timeout(&self, timeout: Option<Duration>) {
159 self.with_core(|core| {
160 core.set_heartbeat_nat_timeout(timeout);
161 })
162 .await;
163 }
164
165 pub async fn heartbeat_effective_interval(&self) -> Duration {
166 self.with_core(|core| core.heartbeat_effective_interval())
167 .await
168 }
169
170 pub async fn parser_snapshot(&self) -> crate::common::MessageParser {
172 let client = self.client.lock().await;
173 client.core().parser.lock().await.clone()
174 }
175
176 pub async fn wait_for_negotiation(&self, timeout: Duration) -> Result<()> {
178 let core = {
179 let client = self.client.lock().await;
180 client.core().clone()
181 };
182 core.wait_for_negotiation(timeout).await
183 }
184}