github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/cluster/service.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package cluster
     8  
     9  import (
    10  	"context"
    11  	"io"
    12  	"time"
    13  
    14  	"github.com/hyperledger/fabric-protos-go/orderer"
    15  	"github.com/hyperledger/fabric/common/flogging"
    16  	"github.com/hyperledger/fabric/common/util"
    17  	"github.com/hyperledger/fabric/internal/pkg/comm"
    18  	"go.uber.org/zap"
    19  	"google.golang.org/grpc"
    20  )
    21  
    22  //go:generate mockery -dir . -name Dispatcher -case underscore -output ./mocks/
    23  
    24  // Dispatcher dispatches requests
    25  type Dispatcher interface {
    26  	DispatchSubmit(ctx context.Context, request *orderer.SubmitRequest) error
    27  	DispatchConsensus(ctx context.Context, request *orderer.ConsensusRequest) error
    28  }
    29  
    30  //go:generate mockery -dir . -name StepStream -case underscore -output ./mocks/
    31  
    32  // StepStream defines the gRPC stream for sending
    33  // transactions, and receiving corresponding responses
    34  type StepStream interface {
    35  	Send(response *orderer.StepResponse) error
    36  	Recv() (*orderer.StepRequest, error)
    37  	grpc.ServerStream
    38  }
    39  
    40  // Service defines the raft Service
    41  type Service struct {
    42  	StreamCountReporter              *StreamCountReporter
    43  	Dispatcher                       Dispatcher
    44  	Logger                           *flogging.FabricLogger
    45  	StepLogger                       *flogging.FabricLogger
    46  	MinimumExpirationWarningInterval time.Duration
    47  	CertExpWarningThreshold          time.Duration
    48  }
    49  
    50  // Step passes an implementation-specific message to another cluster member.
    51  func (s *Service) Step(stream orderer.Cluster_StepServer) error {
    52  	s.StreamCountReporter.Increment()
    53  	defer s.StreamCountReporter.Decrement()
    54  
    55  	addr := util.ExtractRemoteAddress(stream.Context())
    56  	commonName := commonNameFromContext(stream.Context())
    57  	exp := s.initializeExpirationCheck(stream, addr, commonName)
    58  	s.Logger.Debugf("Connection from %s(%s)", commonName, addr)
    59  	defer s.Logger.Debugf("Closing connection from %s(%s)", commonName, addr)
    60  	for {
    61  		err := s.handleMessage(stream, addr, exp)
    62  		if err == io.EOF {
    63  			s.Logger.Debugf("%s(%s) disconnected", commonName, addr)
    64  			return nil
    65  		}
    66  		if err != nil {
    67  			return err
    68  		}
    69  		// Else, no error occurred, so we continue to the next iteration
    70  	}
    71  }
    72  
    73  func (s *Service) handleMessage(stream StepStream, addr string, exp *certificateExpirationCheck) error {
    74  	request, err := stream.Recv()
    75  	if err == io.EOF {
    76  		return err
    77  	}
    78  	if err != nil {
    79  		s.Logger.Warningf("Stream read from %s failed: %v", addr, err)
    80  		return err
    81  	}
    82  
    83  	exp.checkExpiration(time.Now(), extractChannel(request))
    84  
    85  	if s.StepLogger.IsEnabledFor(zap.DebugLevel) {
    86  		nodeName := commonNameFromContext(stream.Context())
    87  		s.StepLogger.Debugf("Received message from %s(%s): %v", nodeName, addr, requestAsString(request))
    88  	}
    89  
    90  	if submitReq := request.GetSubmitRequest(); submitReq != nil {
    91  		nodeName := commonNameFromContext(stream.Context())
    92  		s.Logger.Debugf("Received message from %s(%s): %v", nodeName, addr, requestAsString(request))
    93  		return s.handleSubmit(submitReq, stream, addr)
    94  	}
    95  
    96  	// Else, it's a consensus message.
    97  	return s.Dispatcher.DispatchConsensus(stream.Context(), request.GetConsensusRequest())
    98  }
    99  
   100  func (s *Service) handleSubmit(request *orderer.SubmitRequest, stream StepStream, addr string) error {
   101  	err := s.Dispatcher.DispatchSubmit(stream.Context(), request)
   102  	if err != nil {
   103  		s.Logger.Warningf("Handling of Submit() from %s failed: %v", addr, err)
   104  		return err
   105  	}
   106  	return err
   107  }
   108  
   109  func (s *Service) initializeExpirationCheck(stream orderer.Cluster_StepServer, endpoint, nodeName string) *certificateExpirationCheck {
   110  	return &certificateExpirationCheck{
   111  		minimumExpirationWarningInterval: s.MinimumExpirationWarningInterval,
   112  		expirationWarningThreshold:       s.CertExpWarningThreshold,
   113  		expiresAt:                        expiresAt(stream),
   114  		endpoint:                         endpoint,
   115  		nodeName:                         nodeName,
   116  		alert: func(template string, args ...interface{}) {
   117  			s.Logger.Warningf(template, args...)
   118  		},
   119  	}
   120  }
   121  
   122  func expiresAt(stream orderer.Cluster_StepServer) time.Time {
   123  	cert := comm.ExtractCertificateFromContext(stream.Context())
   124  	if cert == nil {
   125  		return time.Time{}
   126  	}
   127  	return cert.NotAfter
   128  }
   129  
   130  func extractChannel(msg *orderer.StepRequest) string {
   131  	if consReq := msg.GetConsensusRequest(); consReq != nil {
   132  		return consReq.Channel
   133  	}
   134  
   135  	if submitReq := msg.GetSubmitRequest(); submitReq != nil {
   136  		return submitReq.Channel
   137  	}
   138  
   139  	return ""
   140  }