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
// 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, version 1.0.  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.

#[cfg(not(feature = "use-mock-crust"))]
use crust::PeerId;

#[cfg(feature = "use-mock-crust")]
use mock_crust::crust::PeerId;

use core::GROUP_SIZE;
use kademlia_routing_table::Destination;
use sodiumoxide::crypto::{hash, sign};
use std::fmt::{self, Debug, Formatter};
use xor_name::XorName;

/// An entity that can act as a source or destination of a message.
///
/// An `Authority` can be an individual `Client` or `ManagedNode`, or a group of nodes, like a
/// `NodeManager`, `ClientManager` or `NaeManager`.
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Eq, Ord, Clone, Hash)]
pub enum Authority {
    /// Manager of a Client.  XorName is the hash of the Client's `client_key`.
    ClientManager(XorName),
    /// Manager of a network-addressable element.  XorName is the name of the element in question.
    NaeManager(XorName),
    /// Manager of a ManagedNode.  XorName is that of the ManagedNode.
    NodeManager(XorName),
    /// 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(XorName),
    /// A Client.
    Client {
        /// The client's public signing key.  The hash of this specifies the location of the Client
        /// in the network address space.
        client_key: sign::PublicKey,
        /// The Crust peer ID of the client.
        peer_id: PeerId,
        /// The name of the single ManagedNode which the Client connects to and proxies all messages
        /// through.
        proxy_node_name: XorName,
    },
}

impl Authority {
    /// Returns true if group authority, otherwise false.
    pub fn is_group(&self) -> bool {
        match *self {
            Authority::ClientManager(_) |
            Authority::NaeManager(_) |
            Authority::NodeManager(_) => true,
            Authority::ManagedNode(_) |
            Authority::Client { .. } => false,
        }
    }

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

    /// Returns the `Destination` for the `RoutingTable`.
    pub fn to_destination(&self) -> Destination<XorName> {
        if self.is_group() {
            Destination::Group(*self.name(), GROUP_SIZE)
        } else {
            Destination::Node(*self.name())
        }
    }
}

impl Debug for Authority {
    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::ManagedNode(ref name) => write!(formatter, "ManagedNode(name: {})", name),
            Authority::Client { ref client_key, ref proxy_node_name, ref peer_id } => {
                write!(formatter,
                       "Client {{ client_name: {}, proxy_node_name: {}, peer_id: {:?} }}",
                       XorName(hash::sha256::hash(&client_key[..]).0),
                       proxy_node_name,
                       peer_id)
            }
        }
    }
}