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 }