1use tokio::io::{AsyncReadExt, AsyncWriteExt};
11use tokio::sync::mpsc;
12use tracing::Instrument as _;
13
14use crate::core::types::MsgId;
15use crate::io::reactor::ConnRole;
16use crate::msg::{Msg, MsgParseResult, MsgType};
17use crate::net::conn::Conn;
18use crate::net::dispatcher::OutboundEnvelope;
19use crate::net::server::OutboundRequest;
20use crate::net::NetError;
21use crate::proto::dnode::{dmsg_write, DmsgType, DnodeParser, ParseStep};
22
23fn is_data_plane_ty(ty: DmsgType) -> bool {
28 matches!(
29 ty,
30 DmsgType::Req | DmsgType::ReqForward | DmsgType::Res | DmsgType::Unknown
31 )
32}
33
34pub struct DnodeServerConn {
36 conn: Conn,
37 requests: mpsc::Receiver<OutboundRequest>,
38 pending: std::collections::VecDeque<(
39 MsgId,
40 tracing::Span,
41 Option<u32>,
42 mpsc::Sender<OutboundEnvelope>,
43 )>,
44}
45
46impl DnodeServerConn {
47 #[must_use]
63 pub fn new(conn: Conn, requests: mpsc::Receiver<OutboundRequest>) -> Self {
64 debug_assert!(matches!(conn.role(), ConnRole::DnodePeerServer));
65 Self {
66 conn,
67 requests,
68 pending: std::collections::VecDeque::new(),
69 }
70 }
71
72 pub async fn run(mut self) -> Result<(), NetError> {
77 let mut requests = std::mem::replace(&mut self.requests, {
78 let (_tx, rx) = mpsc::channel::<OutboundRequest>(1);
79 rx
80 });
81 self.run_with(&mut requests).await
82 }
83
84 pub async fn run_with(
91 &mut self,
92 requests: &mut mpsc::Receiver<OutboundRequest>,
93 ) -> Result<(), NetError> {
94 let mut read_buf = vec![0u8; 4096];
95 let mut accumulated = Vec::<u8>::new();
96 let mut parser = DnodeParser::new();
97
98 loop {
99 if self.conn.is_eof() && self.pending.is_empty() {
100 self.conn.set_done();
101 return Ok(());
102 }
103
104 tokio::select! {
105 req = requests.recv() => {
106 let Some(req) = req else { continue; };
107 let send_span = tracing::info_span!(
108 parent: &req.span,
109 "peer.send",
110 req_id = req.req_id,
111 bytes = req.bytes.len(),
112 );
113 let req_span = req.span.clone();
114 let req_bytes = req.bytes;
115 let req_id = req.req_id;
116 let req_ty = req.ty;
117 let mut header_buf = self.conn.mbuf_pool().get();
118 dmsg_write(
119 &mut header_buf,
120 req_id,
121 if matches!(req_ty, DmsgType::Unknown) { DmsgType::Req } else { req_ty },
122 0,
123 true,
124 None,
125 u32::try_from(req_bytes.len()).unwrap_or(u32::MAX),
126 )?;
127 let header_len = header_buf.readable().len();
128 let transport = self.conn.transport_mut().ok_or(NetError::Closed)?;
129 let write_res = async {
130 transport.write_all(header_buf.readable()).await?;
131 transport.write_all(&req_bytes).await?;
132 Ok::<(), std::io::Error>(())
133 }
134 .instrument(send_span)
135 .await;
136 write_res?;
137 self.conn.record_send(header_len + req_bytes.len());
138 if is_data_plane_ty(req_ty) {
139 self.pending.push_back((
147 req_id,
148 req_span,
149 req.target_peer_idx,
150 req.responder,
151 ));
152 } else {
153 drop(req.responder);
158 }
159 }
160 read_res = async {
161 if let Some(t) = self.conn.transport_mut() {
162 t.read(&mut read_buf).await
163 } else {
164 Ok(0)
165 }
166 } => {
167 let n = read_res?;
168 if n == 0 {
169 self.conn.set_eof();
170 continue;
171 }
172 self.conn.record_recv(n);
173 accumulated.extend_from_slice(&read_buf[..n]);
174 self.drive_response(&mut accumulated, &mut parser).await?;
175 }
176 }
177 }
178 }
179
180 async fn drive_response(
181 &mut self,
182 accumulated: &mut Vec<u8>,
183 parser: &mut DnodeParser,
184 ) -> Result<(), NetError> {
185 loop {
186 if accumulated.is_empty() {
187 return Ok(());
188 }
189 let step = parser.step(accumulated.as_slice());
190 match step {
191 ParseStep::NeedMore { .. } => return Ok(()),
192 ParseStep::Error { consumed } => {
193 return Err(NetError::Dnode(format!(
194 "dnode peer-server parse error after {consumed} bytes"
195 )));
196 }
197 ParseStep::HeaderDone { consumed } => {
198 let dmsg = parser.take_dmsg();
199 let plen = dmsg.plen as usize;
200 let total = consumed + plen;
201 if accumulated.len() < total {
202 parser.reset();
203 return Ok(());
204 }
205 let payload = accumulated[consumed..total].to_vec();
206 accumulated.drain(0..total);
207 parser.reset();
208
209 let (req_id, req_span, source_peer_idx, reply_to) =
215 match self.pending.pop_front() {
216 Some(entry) => (entry.0, entry.1, entry.2, Some(entry.3)),
217 None => (dmsg.id, tracing::Span::current(), None, None),
218 };
219 let parse_span = tracing::info_span!(
220 parent: &req_span,
221 "peer.parse",
222 req_id,
223 bytes = plen,
224 );
225 let env = parse_span.in_scope(|| {
226 let mut rsp = Msg::new(req_id, MsgType::Unknown, false);
227 let pool = self.conn.mbuf_pool().clone();
228 let mut buf = pool.get();
229 buf.recv(&payload);
230 rsp.mbufs_mut().push_back(buf);
231 rsp.recompute_mlen();
232 rsp.set_dmsg(dmsg);
233 rsp.set_parse_result(MsgParseResult::Ok);
236 OutboundEnvelope {
237 req_id,
238 rsp,
239 span: req_span,
240 source_peer_idx,
241 }
242 });
243 if let Some(sender) = reply_to.as_ref() {
244 let _ = sender.send(env).await;
245 }
246 }
247 }
248 }
249 }
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255 use crate::io::reactor::TcpTransport;
256 use tokio::net::{TcpListener, TcpStream};
257
258 #[tokio::test]
259 async fn build_and_drop() {
260 let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
261 let addr = listener.local_addr().unwrap();
262 let _accept = tokio::spawn(async move {
263 let (s, _) = listener.accept().await.unwrap();
264 drop(s);
265 });
266 let s = TcpStream::connect(addr).await.unwrap();
267 let conn = Conn::new(
268 Box::new(TcpTransport::new(s, ConnRole::DnodePeerServer)),
269 ConnRole::DnodePeerServer,
270 );
271 let (_tx, rx) = mpsc::channel(1);
272 let _server = DnodeServerConn::new(conn, rx);
273 }
274
275 #[tokio::test]
282 async fn concurrent_requests_route_replies_to_their_own_responders() {
283 use crate::proto::dnode::{dmsg_write, DmsgType, DnodeParser, ParseStep};
284 let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
285 let addr = listener.local_addr().unwrap();
286
287 let peer = tokio::spawn(async move {
291 use tokio::io::{AsyncReadExt, AsyncWriteExt};
292 let (mut s, _) = listener.accept().await.unwrap();
293 let mut acc = Vec::new();
294 let mut parser = DnodeParser::new();
295 let mut ids = Vec::new();
296 let mut buf = [0u8; 4096];
297 while ids.len() < 2 {
298 let n = s.read(&mut buf).await.unwrap();
299 if n == 0 {
300 break;
301 }
302 acc.extend_from_slice(&buf[..n]);
303 while let ParseStep::HeaderDone { consumed } = parser.step(&acc) {
304 let dmsg = parser.take_dmsg();
305 let total = consumed + dmsg.plen as usize;
306 if acc.len() < total {
307 parser.reset();
308 break;
309 }
310 ids.push(dmsg.id);
311 acc.drain(0..total);
312 parser.reset();
313 }
314 }
315 let pool = crate::io::mbuf::MbufPool::default();
317 for (i, id) in ids.iter().enumerate() {
318 let payload: &[u8] = if i == 0 { b"+A\r\n" } else { b"+B\r\n" };
319 let mut hb = pool.get();
320 let plen = u32::try_from(payload.len()).unwrap_or(0);
321 dmsg_write(&mut hb, *id, DmsgType::Res, 0, false, None, plen).unwrap();
322 s.write_all(hb.readable()).await.unwrap();
323 s.write_all(payload).await.unwrap();
324 }
325 s.flush().await.unwrap();
326 tokio::time::sleep(std::time::Duration::from_millis(200)).await;
328 });
329
330 let stream = TcpStream::connect(addr).await.unwrap();
331 let conn = Conn::new(
332 Box::new(TcpTransport::new(stream, ConnRole::DnodePeerServer)),
333 ConnRole::DnodePeerServer,
334 );
335 let (req_tx, req_rx) = mpsc::channel::<OutboundRequest>(4);
336 let (resp_a_tx, mut resp_a_rx) = mpsc::channel::<OutboundEnvelope>(1);
337 let (resp_b_tx, mut resp_b_rx) = mpsc::channel::<OutboundEnvelope>(1);
338 req_tx
341 .send(OutboundRequest {
342 bytes: b"*1\r\n$4\r\nPING\r\n".to_vec(),
343 req_id: 1,
344 responder: resp_a_tx,
345 span: tracing::Span::current(),
346 ty: DmsgType::Req,
347 target_peer_idx: None,
348 })
349 .await
350 .unwrap();
351 req_tx
352 .send(OutboundRequest {
353 bytes: b"*1\r\n$4\r\nPING\r\n".to_vec(),
354 req_id: 2,
355 responder: resp_b_tx,
356 span: tracing::Span::current(),
357 ty: DmsgType::Req,
358 target_peer_idx: None,
359 })
360 .await
361 .unwrap();
362 drop(req_tx);
363
364 let server = DnodeServerConn::new(conn, req_rx);
365 let driver = tokio::spawn(async move {
366 let _ = tokio::time::timeout(std::time::Duration::from_secs(3), server.run()).await;
367 });
368
369 let a = tokio::time::timeout(std::time::Duration::from_secs(2), resp_a_rx.recv())
370 .await
371 .expect("responder A timed out")
372 .expect("responder A closed");
373 let b = tokio::time::timeout(std::time::Duration::from_secs(2), resp_b_rx.recv())
374 .await
375 .expect("responder B timed out")
376 .expect("responder B closed");
377 assert_eq!(a.req_id, 1, "responder A got the wrong request's reply");
379 assert_eq!(b.req_id, 2, "responder B got the wrong request's reply");
380 peer.abort();
381 driver.abort();
382 }
383}