/ node / router / messages / src / disconnect.rs
disconnect.rs
 1  // Copyright (c) 2025 ADnet Contributors
 2  // This file is part of the AlphaOS library.
 3  
 4  // Licensed under the Apache License, Version 2.0 (the "License");
 5  // you may not use this file except in compliance with the License.
 6  // You may obtain a copy of the License at:
 7  
 8  // http://www.apache.org/licenses/LICENSE-2.0
 9  
10  // Unless required by applicable law or agreed to in writing, software
11  // distributed under the License is distributed on an "AS IS" BASIS,
12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  // See the License for the specific language governing permissions and
14  // limitations under the License.
15  
16  use super::*;
17  
18  use alphavm::prelude::{FromBytes, ToBytes};
19  
20  use std::borrow::Cow;
21  
22  #[derive(Copy, Clone, Debug, PartialEq, Eq)]
23  pub struct Disconnect {
24      pub reason: DisconnectReason,
25  }
26  
27  impl From<DisconnectReason> for Disconnect {
28      fn from(reason: DisconnectReason) -> Self {
29          Self { reason }
30      }
31  }
32  
33  impl MessageTrait for Disconnect {
34      /// Returns the message name.
35      #[inline]
36      fn name(&self) -> Cow<'static, str> {
37          "Disconnect".into()
38      }
39  }
40  
41  impl ToBytes for Disconnect {
42      fn write_le<W: io::Write>(&self, writer: W) -> io::Result<()> {
43          self.reason.write_le(writer)
44      }
45  }
46  
47  impl FromBytes for Disconnect {
48      fn read_le<R: io::Read>(mut reader: R) -> io::Result<Self> {
49          Ok(Disconnect { reason: DisconnectReason::read_le(&mut reader)? })
50      }
51  }
52  
53  #[cfg(test)]
54  mod tests {
55      use crate::{Disconnect, DisconnectReason};
56      use alphavm::{
57          console::prelude::{FromBytes, ToBytes},
58          prelude::{Rng, TestRng},
59      };
60  
61      use bytes::{Buf, BufMut, BytesMut};
62  
63      #[test]
64      fn disconnect_roundtrip() {
65          // TODO switch to an iteration method that doesn't require manually updating this vec if variants are added
66          let all_reasons = [
67              DisconnectReason::ExceededForkRange,
68              DisconnectReason::InvalidChallengeResponse,
69              DisconnectReason::InvalidForkDepth,
70              DisconnectReason::INeedToSyncFirst,
71              DisconnectReason::NoReasonGiven,
72              DisconnectReason::ProtocolViolation,
73              DisconnectReason::OutdatedClientVersion,
74              DisconnectReason::PeerHasDisconnected,
75              DisconnectReason::PeerRefresh,
76              DisconnectReason::ShuttingDown,
77              DisconnectReason::SyncComplete,
78              DisconnectReason::TooManyFailures,
79              DisconnectReason::TooManyPeers,
80              DisconnectReason::YouNeedToSyncFirst,
81              DisconnectReason::YourPortIsClosed(TestRng::default().r#gen()),
82          ];
83  
84          for reason in all_reasons.iter() {
85              let disconnect = Disconnect::from(*reason);
86              let mut buf = BytesMut::default().writer();
87              Disconnect::write_le(&disconnect, &mut buf).unwrap();
88  
89              let disconnect = Disconnect::read_le(buf.into_inner().reader()).unwrap();
90              assert_eq!(reason, &disconnect.reason);
91          }
92      }
93  }