1use std::sync::atomic::{AtomicU64, Ordering};
2use std::sync::Arc;
3use std::time::Duration;
4
5use dashmap::DashMap;
6use serde::de::DeserializeOwned;
7use serde::Serialize;
8use tokio::io::{AsyncBufRead, AsyncWrite};
9use tokio::sync::{mpsc, oneshot};
10use tracing::{debug, error, warn};
11
12use zerolaunch_plugin_protocol::{codes, JsonRpcError, Message, ProtocolError, Request, Response};
13
14use crate::transport::codec;
15
16#[derive(Debug)]
21pub struct IncomingRequest {
22 pub id: u64,
23 pub method: String,
24 pub params: serde_json::Value,
25}
26
27#[derive(Debug)]
29pub struct JsonRpcClient {
30 next_id: AtomicU64,
31 pending: Arc<DashMap<u64, oneshot::Sender<Result<serde_json::Value, JsonRpcError>>>>,
32 outbound_tx: mpsc::Sender<Message>,
33 _read_handle: tokio::task::JoinHandle<()>,
35 _write_handle: tokio::task::JoinHandle<()>,
37}
38
39impl JsonRpcClient {
40 pub fn new<R, W>(
46 reader: R,
47 writer: W,
48 incoming_request_tx: mpsc::Sender<IncomingRequest>,
49 ) -> Arc<Self>
50 where
51 R: AsyncBufRead + Send + Unpin + 'static,
52 W: AsyncWrite + Send + Unpin + 'static,
53 {
54 let pending: Arc<DashMap<u64, oneshot::Sender<Result<serde_json::Value, JsonRpcError>>>> =
55 Arc::new(DashMap::new());
56
57 let (outbound_tx, outbound_rx) = mpsc::channel::<Message>(256);
59
60 let pending_r = pending.clone();
62 let read_handle = tokio::spawn(async move {
63 let mut reader = reader;
64 loop {
65 let frame = match codec::read_frame(&mut reader).await {
66 Ok(f) => f,
67 Err(ProtocolError::TransportClosed) => {
68 debug!("Transport closed (read loop)");
69 break;
70 }
71 Err(e) => {
72 error!("Frame read error: {}", e);
73 break;
74 }
75 };
76
77 debug!(
78 "收到插件原始帧 ({} bytes): {:?}",
79 frame.len(),
80 String::from_utf8_lossy(&frame)
81 );
82
83 let msg: Message = match serde_json::from_slice(&frame) {
84 Ok(m) => m,
85 Err(e) => {
86 warn!(
87 "Failed to parse JSON-RPC message: {}; raw frame ({} bytes): {:?}",
88 e,
89 frame.len(),
90 String::from_utf8_lossy(&frame)
91 );
92 continue;
93 }
94 };
95 debug!(
96 "收到插件消息 ({} bytes): {:?}",
97 frame.len(),
98 zerolaunch_plugin_protocol::codec::summarize_message(&msg)
99 );
100
101 match msg {
102 Message::Response(resp) => {
103 if let Some((_, tx)) = pending_r.remove(&resp.id) {
104 let result = if let Some(err) = resp.error {
105 Err(err)
106 } else {
107 Ok(resp.result.unwrap_or(serde_json::Value::Null))
108 };
109 let _ = tx.send(result);
110 } else {
111 debug!("Response for unknown id: {}", resp.id);
113 }
114 }
115 Message::Request(req) => {
116 let incoming = IncomingRequest {
117 id: req.id,
118 method: req.method,
119 params: req.params,
120 };
121 if incoming_request_tx.send(incoming).await.is_err() {
122 debug!("Incoming request channel closed");
123 }
124 }
125 Message::Notification(notif) => {
127 debug!("忽略插件通知: {}", notif.method);
128 }
129 }
130 }
131
132 let keys: Vec<u64> = pending_r.iter().map(|e| *e.key()).collect();
134 for key in keys {
135 if let Some((_, tx)) = pending_r.remove(&key) {
136 let _ = tx.send(Err(JsonRpcError::new(
137 codes::PLUGIN_CRASHED,
138 "transport closed",
139 )));
140 }
141 }
142 });
143
144 let write_handle = tokio::spawn(async move {
146 let mut writer = writer;
147 let mut rx = outbound_rx;
148 while let Some(msg) = rx.recv().await {
149 debug!(
150 "发送给插件的消息: {:?}",
151 zerolaunch_plugin_protocol::codec::summarize_message(&msg)
152 );
153 let payload = match serde_json::to_vec(&msg) {
154 Ok(p) => p,
155 Err(e) => {
156 error!("Failed to serialize message: {}", e);
157 continue;
158 }
159 };
160 if let Err(e) = codec::write_frame(&mut writer, &payload).await {
161 error!("Failed to write frame: {}", e);
162 break;
163 }
164 }
165 });
166
167 Arc::new(Self {
168 next_id: AtomicU64::new(1),
169 pending,
170 outbound_tx,
171 _read_handle: read_handle,
172 _write_handle: write_handle,
173 })
174 }
175
176 pub fn close_transport(&self) {
179 self._write_handle.abort();
180 }
181
182 pub async fn call<P: Serialize, R: DeserializeOwned>(
184 &self,
185 method: &str,
186 params: P,
187 timeout: Duration,
188 ) -> Result<R, ProtocolError> {
189 let id = self.next_id.fetch_add(1, Ordering::SeqCst);
190 let params_value = serde_json::to_value(params)?;
191
192 let (tx, rx) = oneshot::channel();
193 self.pending.insert(id, tx);
194
195 let request = Request::new(id, method, params_value);
196 tokio::time::timeout(
199 Duration::from_secs(5),
200 self.outbound_tx.send(Message::Request(request)),
201 )
202 .await
203 .map_err(|_| ProtocolError::TransportClosed)?
204 .map_err(|_| ProtocolError::TransportClosed)?;
205
206 match tokio::time::timeout(timeout, rx).await {
207 Ok(Ok(Ok(value))) => {
208 let result: R = serde_json::from_value(value)?;
209 Ok(result)
210 }
211 Ok(Ok(Err(err))) => Err(ProtocolError::Rpc {
212 code: err.code,
213 message: err.message,
214 }),
215 Ok(Err(_)) => {
216 self.pending.remove(&id);
217 Err(ProtocolError::TransportClosed)
218 }
219 Err(_) => {
220 self.pending.remove(&id);
221 Err(ProtocolError::Timeout)
222 }
223 }
224 }
225
226 pub async fn notify<P: Serialize>(&self, method: &str, params: P) -> Result<(), ProtocolError> {
228 let params_value = serde_json::to_value(params)?;
229 let notif = zerolaunch_plugin_protocol::Notification::new(method, params_value);
230 tokio::time::timeout(
231 Duration::from_secs(5),
232 self.outbound_tx.send(Message::Notification(notif)),
233 )
234 .await
235 .map_err(|_| ProtocolError::TransportClosed)?
236 .map_err(|_| ProtocolError::TransportClosed)?;
237 Ok(())
238 }
239
240 pub async fn respond_ok(
242 &self,
243 id: u64,
244 result: serde_json::Value,
245 ) -> Result<(), ProtocolError> {
246 let response = Response::ok(id, result);
247 tokio::time::timeout(
248 Duration::from_secs(5),
249 self.outbound_tx.send(Message::Response(response)),
250 )
251 .await
252 .map_err(|_| ProtocolError::TransportClosed)?
253 .map_err(|_| ProtocolError::TransportClosed)?;
254 Ok(())
255 }
256
257 pub async fn respond_err(&self, id: u64, error: JsonRpcError) -> Result<(), ProtocolError> {
259 let response = Response::err(id, error);
260 tokio::time::timeout(
261 Duration::from_secs(5),
262 self.outbound_tx.send(Message::Response(response)),
263 )
264 .await
265 .map_err(|_| ProtocolError::TransportClosed)?
266 .map_err(|_| ProtocolError::TransportClosed)?;
267 Ok(())
268 }
269}