1use std::collections::HashMap;
37use std::net::SocketAddr;
38use std::sync::atomic::{AtomicU64, Ordering};
39
40use crate::core::types::MsgId;
41use crate::io::mbuf::{MbufPool, MbufQueue};
42use crate::io::reactor::{ConnRole, Transport};
43use crate::msg::{ConsistencyLevel, Msg, MsgQueue};
44
45use super::NetError;
46
47pub const MAX_CONN_QUEUE_SIZE: usize = 20_000;
53
54#[derive(Debug, Default, Clone)]
59pub struct ConnStats {
60 pub recv_bytes: u64,
62 pub send_bytes: u64,
64 pub recv_msgs: u64,
66 pub send_msgs: u64,
68 pub recv_events: u64,
70 pub send_events: u64,
72}
73
74#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
80pub struct ConnHandle(u64);
81
82impl ConnHandle {
83 #[must_use]
103 pub fn raw(self) -> u64 {
104 self.0
105 }
106}
107
108static NEXT_HANDLE: AtomicU64 = AtomicU64::new(1);
109
110fn next_handle() -> ConnHandle {
111 ConnHandle(NEXT_HANDLE.fetch_add(1, Ordering::Relaxed))
112}
113
114#[allow(clippy::struct_excessive_bools)]
116pub struct Conn {
117 handle: ConnHandle,
118 role: ConnRole,
119 transport: Option<Box<dyn Transport>>,
120 peer_addr: Option<SocketAddr>,
121 recv: MbufQueue,
122 send: MbufQueue,
123 imsg_q: MsgQueue,
124 omsg_q: MsgQueue,
125 rmsg: Option<Msg>,
126 smsg: Option<Msg>,
127 stats: ConnStats,
128 eof: bool,
129 done: bool,
130 err: Option<String>,
131 read_consistency: ConsistencyLevel,
132 write_consistency: ConsistencyLevel,
133 same_dc: bool,
134 dyn_mode: bool,
135 dnode_secured: bool,
136 crypto_key_sent: bool,
137 aes_key: Option<[u8; 32]>,
138 outstanding: HashMap<MsgId, MsgId>,
139 pool: MbufPool,
140}
141
142impl std::fmt::Debug for Conn {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 let _ = (
147 &self.transport,
148 &self.read_consistency,
149 &self.write_consistency,
150 &self.same_dc,
151 &self.dyn_mode,
152 &self.dnode_secured,
153 &self.crypto_key_sent,
154 &self.aes_key,
155 &self.outstanding,
156 &self.pool,
157 &self.stats,
158 &self.rmsg,
159 &self.smsg,
160 );
161 f.debug_struct("Conn")
162 .field("handle", &self.handle)
163 .field("role", &self.role)
164 .field("peer_addr", &self.peer_addr)
165 .field("recv_chain", &self.recv.len())
166 .field("send_chain", &self.send.len())
167 .field("imsg_q", &self.imsg_q.len())
168 .field("omsg_q", &self.omsg_q.len())
169 .field("recv_bytes", &self.stats.recv_bytes)
170 .field("send_bytes", &self.stats.send_bytes)
171 .field("eof", &self.eof)
172 .field("done", &self.done)
173 .field("err", &self.err)
174 .field("read_consistency", &self.read_consistency)
175 .field("write_consistency", &self.write_consistency)
176 .field("same_dc", &self.same_dc)
177 .field("dyn_mode", &self.dyn_mode)
178 .field("dnode_secured", &self.dnode_secured)
179 .field("crypto_key_sent", &self.crypto_key_sent)
180 .field("aes_key_set", &self.aes_key.is_some())
181 .field("outstanding", &self.outstanding.len())
182 .finish()
183 }
184}
185
186impl Conn {
187 pub fn new(transport: Box<dyn Transport>, role: ConnRole) -> Self {
207 let peer_addr = transport.peer_addr();
208 Self {
209 handle: next_handle(),
210 role,
211 transport: Some(transport),
212 peer_addr,
213 recv: MbufQueue::new(),
214 send: MbufQueue::new(),
215 imsg_q: MsgQueue::new(),
216 omsg_q: MsgQueue::new(),
217 rmsg: None,
218 smsg: None,
219 stats: ConnStats::default(),
220 eof: false,
221 done: false,
222 err: None,
223 read_consistency: ConsistencyLevel::DcOne,
224 write_consistency: ConsistencyLevel::DcOne,
225 same_dc: true,
226 dyn_mode: matches!(
227 role,
228 ConnRole::DnodePeerProxy | ConnRole::DnodePeerClient | ConnRole::DnodePeerServer
229 ),
230 dnode_secured: false,
231 crypto_key_sent: false,
232 aes_key: None,
233 outstanding: HashMap::new(),
234 pool: MbufPool::default(),
235 }
236 }
237
238 #[must_use]
240 pub fn handle(&self) -> ConnHandle {
241 self.handle
242 }
243
244 #[must_use]
246 pub fn role(&self) -> ConnRole {
247 self.role
248 }
249
250 #[must_use]
252 pub fn peer_addr(&self) -> Option<SocketAddr> {
253 self.peer_addr
254 }
255
256 #[must_use]
258 pub fn stats(&self) -> &ConnStats {
259 &self.stats
260 }
261
262 #[must_use]
264 pub fn recv_chain(&self) -> &MbufQueue {
265 &self.recv
266 }
267
268 pub fn recv_chain_mut(&mut self) -> &mut MbufQueue {
270 &mut self.recv
271 }
272
273 #[must_use]
275 pub fn send_chain(&self) -> &MbufQueue {
276 &self.send
277 }
278
279 pub fn send_chain_mut(&mut self) -> &mut MbufQueue {
281 &mut self.send
282 }
283
284 #[must_use]
286 pub fn imsg_q(&self) -> &MsgQueue {
287 &self.imsg_q
288 }
289
290 pub fn imsg_q_mut(&mut self) -> &mut MsgQueue {
292 &mut self.imsg_q
293 }
294
295 #[must_use]
297 pub fn omsg_q(&self) -> &MsgQueue {
298 &self.omsg_q
299 }
300
301 pub fn omsg_q_mut(&mut self) -> &mut MsgQueue {
303 &mut self.omsg_q
304 }
305
306 #[must_use]
308 pub fn rmsg(&self) -> Option<&Msg> {
309 self.rmsg.as_ref()
310 }
311
312 pub fn rmsg_mut(&mut self) -> Option<&mut Msg> {
314 self.rmsg.as_mut()
315 }
316
317 pub fn take_rmsg(&mut self) -> Option<Msg> {
320 self.rmsg.take()
321 }
322
323 pub fn set_rmsg(&mut self, msg: Option<Msg>) {
325 self.rmsg = msg;
326 }
327
328 #[must_use]
330 pub fn smsg(&self) -> Option<&Msg> {
331 self.smsg.as_ref()
332 }
333
334 pub fn take_smsg(&mut self) -> Option<Msg> {
336 self.smsg.take()
337 }
338
339 pub fn set_smsg(&mut self, msg: Option<Msg>) {
341 self.smsg = msg;
342 }
343
344 #[must_use]
346 pub fn is_eof(&self) -> bool {
347 self.eof
348 }
349
350 pub fn set_eof(&mut self) {
352 self.eof = true;
353 }
354
355 #[must_use]
358 pub fn is_done(&self) -> bool {
359 self.done
360 }
361
362 pub fn set_done(&mut self) {
364 self.done = true;
365 }
366
367 #[must_use]
369 pub fn err(&self) -> Option<&str> {
370 self.err.as_deref()
371 }
372
373 pub fn set_err<S: Into<String>>(&mut self, msg: S) {
375 self.err = Some(msg.into());
376 }
377
378 #[must_use]
381 pub fn read_consistency(&self) -> ConsistencyLevel {
382 self.read_consistency
383 }
384
385 #[must_use]
388 pub fn write_consistency(&self) -> ConsistencyLevel {
389 self.write_consistency
390 }
391
392 pub fn set_read_consistency(&mut self, c: ConsistencyLevel) {
394 self.read_consistency = c;
395 }
396
397 pub fn set_write_consistency(&mut self, c: ConsistencyLevel) {
399 self.write_consistency = c;
400 }
401
402 #[must_use]
404 pub fn same_dc(&self) -> bool {
405 self.same_dc
406 }
407
408 pub fn set_same_dc(&mut self, on: bool) {
411 self.same_dc = on;
412 }
413
414 #[must_use]
417 pub fn dyn_mode(&self) -> bool {
418 self.dyn_mode
419 }
420
421 #[must_use]
424 pub fn dnode_secured(&self) -> bool {
425 self.dnode_secured
426 }
427
428 pub fn set_dnode_secured(&mut self, on: bool) {
430 self.dnode_secured = on;
431 }
432
433 #[must_use]
435 pub fn crypto_key_sent(&self) -> bool {
436 self.crypto_key_sent
437 }
438
439 pub fn set_crypto_key_sent(&mut self, on: bool) {
441 self.crypto_key_sent = on;
442 }
443
444 #[must_use]
447 pub fn aes_key(&self) -> Option<&[u8; 32]> {
448 self.aes_key.as_ref()
449 }
450
451 pub fn set_aes_key(&mut self, key: [u8; 32]) {
453 self.aes_key = Some(key);
454 }
455
456 #[must_use]
458 pub fn outstanding(&self) -> &HashMap<MsgId, MsgId> {
459 &self.outstanding
460 }
461
462 pub fn outstanding_mut(&mut self) -> &mut HashMap<MsgId, MsgId> {
464 &mut self.outstanding
465 }
466
467 #[must_use]
469 pub fn mbuf_pool(&self) -> &MbufPool {
470 &self.pool
471 }
472
473 pub fn set_mbuf_pool(&mut self, pool: MbufPool) {
476 self.pool = pool;
477 }
478
479 pub fn take_transport(&mut self) -> Option<Box<dyn Transport>> {
484 self.transport.take()
485 }
486
487 pub fn set_transport(&mut self, transport: Box<dyn Transport>) {
490 self.peer_addr = transport.peer_addr();
491 self.transport = Some(transport);
492 }
493
494 #[must_use]
496 pub fn has_transport(&self) -> bool {
497 self.transport.is_some()
498 }
499
500 pub fn transport_mut(&mut self) -> Option<&mut Box<dyn Transport>> {
503 self.transport.as_mut()
504 }
505
506 pub fn enqueue_in(&mut self, msg: Msg) -> Result<(), NetError> {
512 if self.imsg_q.len() >= MAX_CONN_QUEUE_SIZE {
513 return Err(NetError::PoolExhausted);
514 }
515 self.imsg_q.push_back(msg);
516 self.stats.recv_msgs += 1;
517 Ok(())
518 }
519
520 pub fn enqueue_out(&mut self, msg: Msg) -> Result<(), NetError> {
526 if self.omsg_q.len() >= MAX_CONN_QUEUE_SIZE {
527 return Err(NetError::PoolExhausted);
528 }
529 self.omsg_q.push_back(msg);
530 self.stats.send_msgs += 1;
531 Ok(())
532 }
533
534 pub fn close(&mut self) {
536 self.transport = None;
537 self.done = true;
538 }
539
540 pub fn run(&mut self) -> Result<(), NetError> {
554 if self.transport.is_none() {
555 return Err(NetError::Closed);
556 }
557 if self.done {
558 return Ok(());
559 }
560 Ok(())
561 }
562
563 pub fn record_recv(&mut self, bytes: usize) {
565 self.stats.recv_bytes += bytes as u64;
566 self.stats.recv_events += 1;
567 }
568
569 pub fn record_send(&mut self, bytes: usize) {
571 self.stats.send_bytes += bytes as u64;
572 self.stats.send_events += 1;
573 }
574}
575
576#[cfg(test)]
577mod tests {
578 use super::*;
579 use crate::io::reactor::TcpTransport;
580 use crate::msg::MsgType;
581 use tokio::net::{TcpListener, TcpStream};
582
583 async fn pair() -> (Conn, Conn) {
584 let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
585 let addr = listener.local_addr().unwrap();
586 let accept = tokio::spawn(async move {
587 let (s, _) = listener.accept().await.unwrap();
588 s
589 });
590 let client = TcpStream::connect(addr).await.unwrap();
591 let server = accept.await.unwrap();
592 let c = Conn::new(
593 Box::new(TcpTransport::new(client, ConnRole::Client)),
594 ConnRole::Client,
595 );
596 let s = Conn::new(
597 Box::new(TcpTransport::new(server, ConnRole::Server)),
598 ConnRole::Server,
599 );
600 (c, s)
601 }
602
603 #[tokio::test]
604 async fn enqueue_in_and_out() {
605 let (mut c, _s) = pair().await;
606 c.enqueue_in(Msg::new(1, MsgType::ReqRedisGet, true))
607 .unwrap();
608 c.enqueue_out(Msg::new(2, MsgType::RspRedisStatus, false))
609 .unwrap();
610 assert_eq!(c.imsg_q().len(), 1);
611 assert_eq!(c.omsg_q().len(), 1);
612 assert_eq!(c.stats().recv_msgs, 1);
613 assert_eq!(c.stats().send_msgs, 1);
614 }
615
616 #[tokio::test]
617 async fn close_drops_transport() {
618 let (mut c, _s) = pair().await;
619 assert!(c.has_transport());
620 c.close();
621 assert!(!c.has_transport());
622 assert!(c.is_done());
623 }
624
625 #[tokio::test]
626 async fn handle_is_unique() {
627 let (a, b) = pair().await;
628 assert_ne!(a.handle(), b.handle());
629 }
630
631 #[tokio::test]
632 async fn role_seed_drives_dyn_mode() {
633 let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
634 let addr = listener.local_addr().unwrap();
635 let _accept = tokio::spawn(async move {
636 let (s, _) = listener.accept().await.unwrap();
637 drop(s);
638 });
639 let s = TcpStream::connect(addr).await.unwrap();
640 let c = Conn::new(
641 Box::new(TcpTransport::new(s, ConnRole::DnodePeerServer)),
642 ConnRole::DnodePeerServer,
643 );
644 assert!(c.dyn_mode());
645 assert!(c.same_dc());
646 }
647}