github.com/braveheart12/just@v0.8.7/network/hostnetwork/transport_consensus.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 hostnetwork
    19  
    20  import (
    21  	"context"
    22  
    23  	"github.com/insolar/insolar/configuration"
    24  	"github.com/insolar/insolar/consensus"
    25  	"github.com/insolar/insolar/consensus/packets"
    26  	"github.com/insolar/insolar/core"
    27  	"github.com/insolar/insolar/log"
    28  	"github.com/insolar/insolar/network"
    29  	"github.com/insolar/insolar/network/sequence"
    30  	"github.com/insolar/insolar/network/transport"
    31  	"github.com/insolar/insolar/network/transport/host"
    32  	"github.com/insolar/insolar/network/transport/packet"
    33  	"github.com/insolar/insolar/network/transport/relay"
    34  	"github.com/pkg/errors"
    35  	"go.opencensus.io/stats"
    36  	"go.opencensus.io/tag"
    37  )
    38  
    39  type transportConsensus struct {
    40  	transportBase
    41  	resolver network.RoutingTable
    42  	handlers map[packets.PacketType]network.ConsensusPacketHandler
    43  }
    44  
    45  func (tc *transportConsensus) Start(ctx context.Context) error {
    46  	tc.transportBase.Start(ctx)
    47  	return nil
    48  }
    49  
    50  func (tc *transportConsensus) Stop(ctx context.Context) error {
    51  	tc.transportBase.Stop()
    52  	return nil
    53  }
    54  
    55  // RegisterPacketHandler register a handler function to process incoming requests of a specific type.
    56  func (tc *transportConsensus) RegisterPacketHandler(t packets.PacketType, handler network.ConsensusPacketHandler) {
    57  	_, exists := tc.handlers[t]
    58  	if exists {
    59  		log.Warnf("Multiple handlers for packet type %s are not supported! New handler will replace the old one!", t)
    60  	}
    61  	tc.handlers[t] = handler
    62  }
    63  
    64  func (tc *transportConsensus) SignAndSendPacket(packet packets.ConsensusPacket,
    65  	receiver core.RecordRef, service core.CryptographyService) error {
    66  
    67  	receiverHost, err := tc.resolver.ResolveConsensusRef(receiver)
    68  	if err != nil {
    69  		return errors.Wrapf(err, "Failed to resolve %s request to node %s", packet.GetType(), receiver.String())
    70  	}
    71  	log.Debugf("Send %s request to host %s", packet.GetType(), receiverHost)
    72  	packet.SetRouting(tc.origin.ShortID, receiverHost.ShortID)
    73  	err = packet.Sign(service)
    74  	if err != nil {
    75  		return errors.Wrapf(err, "Failed to sign %s request to node %s", packet.GetType(), receiver.String())
    76  	}
    77  	ctx := context.Background()
    78  	p := tc.buildPacket(packet, receiverHost)
    79  	err = tc.transport.SendPacket(ctx, p)
    80  	if err == nil {
    81  		statsErr := stats.RecordWithTags(ctx, []tag.Mutator{
    82  			tag.Upsert(consensus.TagPhase, packet.GetType().String()),
    83  		}, consensus.PacketsSent.M(1))
    84  		if statsErr != nil {
    85  			log.Warn(" [ transportConsensus ] Failed to record sent packets metric: " + statsErr.Error())
    86  		}
    87  	}
    88  	return err
    89  }
    90  
    91  func (tc *transportConsensus) buildPacket(p packets.ConsensusPacket, receiver *host.Host) *packet.Packet {
    92  	return packet.NewBuilder(tc.origin).Receiver(receiver).Request(p).Build()
    93  }
    94  
    95  func (tc *transportConsensus) processMessage(msg *packet.Packet) {
    96  	p, ok := msg.Data.(packets.ConsensusPacket)
    97  	if !ok {
    98  		log.Error("Error processing incoming message: failed to convert to ConsensusPacket")
    99  		return
   100  	}
   101  	log.Debugf("Got %s request from host, shortID: %d", p.GetType(), p.GetOrigin())
   102  	if p.GetTarget() != tc.origin.ShortID {
   103  		log.Errorf("Error processing incoming message: target ID %d differs from origin %d", p.GetTarget(), tc.origin.ShortID)
   104  		return
   105  	}
   106  	if p.GetOrigin() == tc.origin.ShortID {
   107  		log.Errorf("Error processing incoming message: sender ID %d equals to origin %d", p.GetTarget(), tc.origin.ShortID)
   108  		return
   109  	}
   110  	sender, err := tc.resolver.ResolveConsensus(p.GetOrigin())
   111  	// TODO: NETD18-79
   112  	// special case for Phase1 because we can get a valid packet from a node we don't know yet (first consensus case)
   113  	if err != nil && p.GetType() != packets.Phase1 {
   114  		log.Errorf("Error processing incoming message: failed to resolve ShortID (%d) -> NodeID", p.GetOrigin())
   115  		return
   116  	}
   117  	if sender == nil {
   118  		sender = &host.Host{}
   119  	}
   120  	handler, exist := tc.handlers[p.GetType()]
   121  	if !exist {
   122  		log.Errorf("No handler set for packet type %s from node %d, %s", p.GetType(), sender.ShortID, sender.NodeID)
   123  		return
   124  	}
   125  	handler(p, sender.NodeID)
   126  }
   127  
   128  func NewConsensusNetwork(address, nodeID string, shortID core.ShortNodeID,
   129  	resolver network.RoutingTable) (network.ConsensusNetwork, error) {
   130  
   131  	conf := configuration.Transport{}
   132  	conf.Address = address
   133  	conf.Protocol = "PURE_UDP"
   134  	conf.BehindNAT = false
   135  
   136  	tp, err := transport.NewTransport(conf, relay.NewProxy())
   137  	if err != nil {
   138  		return nil, errors.Wrap(err, "error creating transport")
   139  	}
   140  	origin, err := getOrigin(tp, nodeID)
   141  	if err != nil {
   142  		go tp.Stop()
   143  		<-tp.Stopped()
   144  		tp.Close()
   145  		return nil, errors.Wrap(err, "error getting origin")
   146  	}
   147  	origin.ShortID = shortID
   148  	result := &transportConsensus{handlers: make(map[packets.PacketType]network.ConsensusPacketHandler)}
   149  
   150  	result.transport = tp
   151  	result.sequenceGenerator = sequence.NewGeneratorImpl()
   152  	result.resolver = resolver
   153  	result.origin = origin
   154  	result.messageProcessor = result.processMessage
   155  	return result, nil
   156  }