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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright 2015 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which
// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be
// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use super::{Prefix, Xorable};
use id::PublicId;
use std::fmt::{self, Binary, Debug, Display, Formatter};

/// An entity that can act as a source or destination of a message.
///
/// `Client` and `ManagedNode` are single-node authorities (i.e. no verification of messages from
/// additional sources needed); other authorities require agreement by a quorum of some set.
/// `NodeManager`, `ClientManager` and `NaeManager` use _group_ verification of messages: they
/// require quorum agreement from the group of nodes closest to the source, while `Section` and
/// `PrefixSection` use _section_ verification: the set from which a quorum is required is all
/// members of the section (`Section`) or of all sections matching the prefix (`PrefixSection`).
#[derive(Serialize, Deserialize, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)]
pub enum Authority<N: Xorable + Clone + Copy + Binary + Default> {
    /// Manager of a Client.  XorName is the hash of the Client's `client_key`.
    ClientManager(N),
    /// Manager of a network-addressable element, i.e. the group matching this name.
    /// `XorName` is the name of the element in question.
    NaeManager(N),
    /// Manager of a ManagedNode.  XorName is that of the ManagedNode.
    NodeManager(N),
    /// A set of nodes with names sharing a common prefix.
    Section(N),
    /// A set of nodes with names sharing a common prefix - may span multiple `Section`s present in
    /// the routing table or only a part of a `Section`
    PrefixSection(Prefix<N>),
    /// A non-client node (i.e. a vault) which is managed by NodeManagers.  XorName is provided
    /// by the network relocation process immediately after bootstrapping.
    ManagedNode(N),
    /// A Client.
    Client {
        /// The Public ID of the client.
        client_id: PublicId,
        /// The name of the single ManagedNode which the Client connects to and proxies all messages
        /// through.
        proxy_node_name: N,
    },
}

impl<N: Xorable + Clone + Copy + Binary + Default> Authority<N> {
    /// Returns `true` if the authority consists of multiple nodes, otherwise `false`.
    pub fn is_multiple(&self) -> bool {
        match *self {
            Authority::Section(_) |
            Authority::PrefixSection(_) |
            Authority::ClientManager(_) |
            Authority::NaeManager(_) |
            Authority::NodeManager(_) => true,
            Authority::ManagedNode(_) |
            Authority::Client { .. } => false,
        }
    }

    /// Returns `true` if the authority is a single node, and `false` otherwise.
    pub fn is_single(&self) -> bool {
        match *self {
            Authority::ClientManager(_) |
            Authority::NaeManager(_) |
            Authority::Section(_) |
            Authority::PrefixSection(_) |
            Authority::NodeManager(_) => false,
            Authority::ManagedNode(_) |
            Authority::Client { .. } => true,
        }
    }

    /// Returns `true` if a client, `false` if a node or section.
    pub fn is_client(&self) -> bool {
        if let Authority::Client { .. } = *self {
            true
        } else {
            false
        }
    }

    /// Returns the name of authority.
    pub fn name(&self) -> N {
        match *self {
            Authority::ClientManager(ref name) |
            Authority::NaeManager(ref name) |
            Authority::NodeManager(ref name) |
            Authority::Section(ref name) |
            Authority::ManagedNode(ref name) => *name,
            Authority::PrefixSection(ref prefix) => prefix.lower_bound(),
            Authority::Client { ref proxy_node_name, .. } => *proxy_node_name,
        }
    }
}

impl<N: Xorable + Clone + Copy + Binary + Default + Display> Debug for Authority<N> {
    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
        match *self {
            Authority::ClientManager(ref name) => {
                write!(formatter, "ClientManager(name: {})", name)
            }
            Authority::NaeManager(ref name) => write!(formatter, "NaeManager(name: {})", name),
            Authority::NodeManager(ref name) => write!(formatter, "NodeManager(name: {})", name),
            Authority::Section(ref name) => write!(formatter, "Section(name: {})", name),
            Authority::PrefixSection(ref prefix) => {
                write!(formatter, "PrefixSection(prefix: {:?})", prefix)
            }
            Authority::ManagedNode(ref name) => write!(formatter, "ManagedNode(name: {})", name),
            Authority::Client {
                ref proxy_node_name,
                ref client_id,
            } => {
                write!(
                    formatter,
                    "Client {{ client_name: {}, proxy_node_name: {} }}",
                    client_id.name(),
                    proxy_node_name
                )
            }
        }
    }
}