snarkos_node_router_messages/helpers/
disconnect.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkOS 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
16use snarkvm::prelude::{FromBytes, ToBytes, error};
17
18use std::io;
19
20/// The reason behind the node disconnecting from a peer.
21#[derive(Copy, Clone, Debug, PartialEq, Eq)]
22pub enum DisconnectReason {
23    /// The fork length limit was exceeded.
24    ExceededForkRange,
25    /// The peer's challenge response is invalid.
26    InvalidChallengeResponse,
27    /// The peer's client uses an invalid fork depth.
28    InvalidForkDepth,
29    /// The node is a sync node and the peer is ahead.
30    INeedToSyncFirst,
31    /// No reason given.
32    NoReasonGiven,
33    /// The peer is not following the protocol.
34    ProtocolViolation,
35    /// The peer's client is outdated, judging by its version.
36    OutdatedClientVersion,
37    /// Dropping a dead connection.
38    PeerHasDisconnected,
39    /// Dropping a connection for a periodic refresh.
40    PeerRefresh,
41    /// The node is shutting down.
42    ShuttingDown,
43    /// The sync node has served its purpose.
44    SyncComplete,
45    /// The peer has caused too many failures.
46    TooManyFailures,
47    /// The node has too many connections already.
48    TooManyPeers,
49    /// The peer is a sync node that's behind our node, and it needs to sync itself first.
50    YouNeedToSyncFirst,
51    /// The peer's listening port is closed.
52    YourPortIsClosed(u16),
53}
54
55impl ToBytes for DisconnectReason {
56    fn write_le<W: io::Write>(&self, mut writer: W) -> io::Result<()> {
57        match self {
58            Self::ExceededForkRange => 0u8.write_le(writer),
59            Self::InvalidChallengeResponse => 1u8.write_le(writer),
60            Self::InvalidForkDepth => 2u8.write_le(writer),
61            Self::INeedToSyncFirst => 3u8.write_le(writer),
62            Self::NoReasonGiven => 4u8.write_le(writer),
63            Self::ProtocolViolation => 5u8.write_le(writer),
64            Self::OutdatedClientVersion => 6u8.write_le(writer),
65            Self::PeerHasDisconnected => 7u8.write_le(writer),
66            Self::PeerRefresh => 8u8.write_le(writer),
67            Self::ShuttingDown => 9u8.write_le(writer),
68            Self::SyncComplete => 10u8.write_le(writer),
69            Self::TooManyFailures => 11u8.write_le(writer),
70            Self::TooManyPeers => 12u8.write_le(writer),
71            Self::YouNeedToSyncFirst => 13u8.write_le(writer),
72            Self::YourPortIsClosed(port) => {
73                14u8.write_le(&mut writer)?;
74                port.write_le(writer)
75            }
76        }
77    }
78}
79
80impl FromBytes for DisconnectReason {
81    fn read_le<R: io::Read>(mut reader: R) -> io::Result<Self> {
82        match u8::read_le(&mut reader)? {
83            0 => Ok(Self::ExceededForkRange),
84            1 => Ok(Self::InvalidChallengeResponse),
85            2 => Ok(Self::InvalidForkDepth),
86            3 => Ok(Self::INeedToSyncFirst),
87            4 => Ok(Self::NoReasonGiven),
88            5 => Ok(Self::ProtocolViolation),
89            6 => Ok(Self::OutdatedClientVersion),
90            7 => Ok(Self::PeerHasDisconnected),
91            8 => Ok(Self::PeerRefresh),
92            9 => Ok(Self::ShuttingDown),
93            10 => Ok(Self::SyncComplete),
94            11 => Ok(Self::TooManyFailures),
95            12 => Ok(Self::TooManyPeers),
96            13 => Ok(Self::YouNeedToSyncFirst),
97            14 => {
98                let port = u16::read_le(reader)?;
99                Ok(Self::YourPortIsClosed(port))
100            }
101            _ => Err(error("Invalid disconnect reason")),
102        }
103    }
104}