github.com/braveheart12/just@v0.8.7/network/nodenetwork/node.go (about)

     1  /*
     2   * The Clear BSD License
     3   *
     4   * Copyright (c) 2019 Insolar Technologies
     5   *
     6   * All rights reserved.
     7   *
     8   * Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met:
     9   *
    10   *  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    11   *  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    12   *  Neither the name of Insolar Technologies nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
    13   *
    14   * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    15   *
    16   */
    17  
    18  package nodenetwork
    19  
    20  import (
    21  	"crypto"
    22  	"encoding/gob"
    23  	"fmt"
    24  	"strconv"
    25  	"strings"
    26  	"sync"
    27  	"sync/atomic"
    28  
    29  	"github.com/insolar/insolar/consensus/packets"
    30  	"github.com/insolar/insolar/core"
    31  	"github.com/insolar/insolar/network/utils"
    32  	"github.com/insolar/insolar/platformpolicy"
    33  	"github.com/pkg/errors"
    34  )
    35  
    36  type MutableNode interface {
    37  	core.Node
    38  
    39  	SetShortID(shortID core.ShortNodeID)
    40  	SetState(state core.NodeState)
    41  	ChangeState()
    42  	SetLeavingETA(number core.PulseNumber)
    43  	SetVersion(version string)
    44  }
    45  
    46  type node struct {
    47  	NodeID        core.RecordRef
    48  	NodeShortID   uint32
    49  	NodeRole      core.StaticRole
    50  	NodePublicKey crypto.PublicKey
    51  
    52  	NodePulseNum core.PulseNumber
    53  
    54  	NodeAddress string
    55  	CAddress    string
    56  
    57  	versionMutex sync.RWMutex
    58  	NodeVersion  string
    59  
    60  	leavingMutex   sync.RWMutex
    61  	NodeLeaving    bool
    62  	NodeLeavingETA core.PulseNumber
    63  
    64  	state uint32
    65  }
    66  
    67  func (n *node) SetVersion(version string) {
    68  	n.versionMutex.Lock()
    69  	defer n.versionMutex.Unlock()
    70  
    71  	n.NodeVersion = version
    72  }
    73  
    74  func (n *node) SetState(state core.NodeState) {
    75  	atomic.StoreUint32(&n.state, uint32(state))
    76  }
    77  
    78  func (n *node) GetState() core.NodeState {
    79  	return core.NodeState(atomic.LoadUint32(&n.state))
    80  }
    81  
    82  func (n *node) ChangeState() {
    83  	// we don't expect concurrent changes, so do not CAS
    84  
    85  	currentState := atomic.LoadUint32(&n.state)
    86  	if currentState == uint32(core.NodeReady) {
    87  		return
    88  	}
    89  	atomic.StoreUint32(&n.state, currentState+1)
    90  }
    91  
    92  func newMutableNode(
    93  	id core.RecordRef,
    94  	role core.StaticRole,
    95  	publicKey crypto.PublicKey,
    96  	address, version string) MutableNode {
    97  
    98  	consensusAddress, err := incrementPort(address)
    99  	if err != nil {
   100  		panic(err)
   101  	}
   102  	return &node{
   103  		NodeID:        id,
   104  		NodeShortID:   utils.GenerateUintShortID(id),
   105  		NodeRole:      role,
   106  		NodePublicKey: publicKey,
   107  		NodeAddress:   address,
   108  		CAddress:      consensusAddress,
   109  		NodeVersion:   version,
   110  		state:         uint32(core.NodeReady),
   111  	}
   112  }
   113  
   114  func NewNode(
   115  	id core.RecordRef,
   116  	role core.StaticRole,
   117  	publicKey crypto.PublicKey,
   118  	address, version string) core.Node {
   119  	return newMutableNode(id, role, publicKey, address, version)
   120  }
   121  
   122  func (n *node) ID() core.RecordRef {
   123  	return n.NodeID
   124  }
   125  
   126  func (n *node) ShortID() core.ShortNodeID {
   127  	return core.ShortNodeID(atomic.LoadUint32(&n.NodeShortID))
   128  }
   129  
   130  func (n *node) Role() core.StaticRole {
   131  	return n.NodeRole
   132  }
   133  
   134  func (n *node) PublicKey() crypto.PublicKey {
   135  	return n.NodePublicKey
   136  }
   137  
   138  func (n *node) Address() string {
   139  	return n.NodeAddress
   140  }
   141  
   142  func (n *node) ConsensusAddress() string {
   143  	return n.CAddress
   144  }
   145  
   146  func (n *node) GetGlobuleID() core.GlobuleID {
   147  	return 0
   148  }
   149  
   150  func (n *node) Version() string {
   151  	n.versionMutex.RLock()
   152  	defer n.versionMutex.RUnlock()
   153  
   154  	return n.NodeVersion
   155  }
   156  
   157  func (n *node) IsWorking() bool {
   158  	return atomic.LoadUint32(&n.state) == uint32(core.NodeReady)
   159  }
   160  
   161  func (n *node) SetShortID(id core.ShortNodeID) {
   162  	atomic.StoreUint32(&n.NodeShortID, uint32(id))
   163  }
   164  
   165  func (n *node) Leaving() bool {
   166  	n.leavingMutex.RLock()
   167  	defer n.leavingMutex.RUnlock()
   168  	return n.NodeLeaving
   169  }
   170  func (n *node) LeavingETA() core.PulseNumber {
   171  	n.leavingMutex.RLock()
   172  	defer n.leavingMutex.RUnlock()
   173  	return n.NodeLeavingETA
   174  }
   175  
   176  func (n *node) SetLeavingETA(number core.PulseNumber) {
   177  	n.leavingMutex.Lock()
   178  	defer n.leavingMutex.Unlock()
   179  
   180  	n.NodeLeaving = true
   181  	n.NodeLeavingETA = number
   182  }
   183  
   184  func init() {
   185  	gob.Register(&node{})
   186  }
   187  
   188  func ClaimToNode(version string, claim *packets.NodeJoinClaim) (core.Node, error) {
   189  	keyProc := platformpolicy.NewKeyProcessor()
   190  	key, err := keyProc.ImportPublicKeyBinary(claim.NodePK[:])
   191  	if err != nil {
   192  		return nil, errors.Wrap(err, "[ ClaimToNode ] failed to import a public key")
   193  	}
   194  	node := newMutableNode(
   195  		claim.NodeRef,
   196  		claim.NodeRoleRecID,
   197  		key,
   198  		claim.NodeAddress.Get(),
   199  		version)
   200  	node.SetShortID(claim.ShortNodeID)
   201  	return node, nil
   202  }
   203  
   204  // incrementPort increments port number if it not equals 0
   205  func incrementPort(address string) (string, error) {
   206  	parts := strings.Split(address, ":")
   207  	if len(parts) != 2 {
   208  		return address, errors.New("failed to get port from address")
   209  	}
   210  	port, err := strconv.Atoi(parts[1])
   211  	if err != nil {
   212  		return address, err
   213  	}
   214  
   215  	if port != 0 {
   216  		port++
   217  	}
   218  	return fmt.Sprintf("%s:%d", parts[0], port), nil
   219  }