1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
crate::ix!();

pub trait MaybeDiscourageAndDisconnect {
    fn maybe_discourage_and_disconnect(self: Arc<Self>, 
        pnode: Amo<Box<dyn NodeInterface>>,
        peer:  &mut Peer) -> bool;
}
    
impl MaybeDiscourageAndDisconnect for PeerManager {

    /**
      | Maybe disconnect a peer and discourage
      | future connections from its address.
      | 
      | -----------
      | @param[in] pnode
      | 
      | The node to check.
      | ----------
      | @param[in] peer
      | 
      | The peer object to check.
      | 
      | -----------
      | @return
      | 
      | True if the peer was marked for disconnection
      | in this function
      |
      */
    fn maybe_discourage_and_disconnect(self: Arc<Self>, 
        pnode: Amo<Box<dyn NodeInterface>>,
        peer:  &mut Peer) -> bool {

        {
            let mut guard = peer.misbehavior.lock();

            // There's nothing to do if the
            // m_should_discourage flag isn't set
            if !guard.should_discourage {
                return false;
            }

            guard.should_discourage = false;
        }

        if pnode.get().has_permission(NetPermissionFlags::NoBan) {
            // We never disconnect or discourage
            // peers for bad behavior if they have
            // NetPermissionFlags::NoBan
            // permission
            log_printf!(
                "Warning: not punishing noban peer %d!\n",
                peer.id
            );

            return false;
        }

        if pnode.get().is_manual_conn() {

            // We never disconnect or discourage
            // manual peers for bad behavior
            log_printf!(
                "Warning: not punishing manually connected peer %d!\n",
                peer.id
            );

            return false;
        }

        if pnode.get().addr().is_local() {

            // We disconnect local peers for bad
            // behavior but don't discourage
            // (since that would discourage all
            // peers on the same local address)
            log_print!(
                LogFlags::NET,
                "Warning: disconnecting but not discouraging %s peer %d!\n",
                match pnode.inbound_onion {
                    true   => "inbound onion",
                    false  => "local"
                },
                peer.id
            );

            pnode.get().mark_for_disconnect();

            return true;
        }

        // Normal case: Disconnect the peer and
        // discourage all nodes sharing the
        // address
        log_print!(
            LogFlags::NET,
            "Disconnecting and discouraging peer %d!\n",
            peer.id
        );

        if self.banman.is_some() {
            self.banman.get_mut().discourage(&pnode.get().service().base);
        }

        let node = pnode.get();

        let netaddr = &node.service().base;

        self.connman.get_mut()
            .disconnect_node_with_netaddr(netaddr);

        true
    }
}