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