github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/orderer/common/broadcast/broadcast.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package broadcast 18 19 import ( 20 "github.com/hyperledger/fabric/orderer/common/filter" 21 cb "github.com/hyperledger/fabric/protos/common" 22 ab "github.com/hyperledger/fabric/protos/orderer" 23 "github.com/op/go-logging" 24 25 "io" 26 27 "github.com/golang/protobuf/proto" 28 "github.com/hyperledger/fabric/protos/utils" 29 ) 30 31 var logger = logging.MustGetLogger("orderer/common/broadcast") 32 33 // ConfigUpdateProcessor is used to transform CONFIG_UPDATE transactions which are used to generate other envelope 34 // message types with preprocessing by the orderer 35 type ConfigUpdateProcessor interface { 36 // Process takes in an envelope of type CONFIG_UPDATE and proceses it 37 // to transform it either into another envelope type 38 Process(envConfigUpdate *cb.Envelope) (*cb.Envelope, error) 39 } 40 41 // Handler defines an interface which handles broadcasts 42 type Handler interface { 43 // Handle starts a service thread for a given gRPC connection and services the broadcast connection 44 Handle(srv ab.AtomicBroadcast_BroadcastServer) error 45 } 46 47 // SupportManager provides a way for the Handler to look up the Support for a chain 48 type SupportManager interface { 49 ConfigUpdateProcessor 50 51 // GetChain gets the chain support for a given ChannelId 52 GetChain(chainID string) (Support, bool) 53 } 54 55 // Support provides the backing resources needed to support broadcast on a chain 56 type Support interface { 57 // Enqueue accepts a message and returns true on acceptance, or false on shutdown 58 Enqueue(env *cb.Envelope) bool 59 60 // Filters returns the set of broadcast filters for this chain 61 Filters() *filter.RuleSet 62 } 63 64 type handlerImpl struct { 65 sm SupportManager 66 } 67 68 // NewHandlerImpl constructs a new implementation of the Handler interface 69 func NewHandlerImpl(sm SupportManager) Handler { 70 return &handlerImpl{ 71 sm: sm, 72 } 73 } 74 75 // Handle starts a service thread for a given gRPC connection and services the broadcast connection 76 func (bh *handlerImpl) Handle(srv ab.AtomicBroadcast_BroadcastServer) error { 77 logger.Debugf("Starting new broadcast loop") 78 for { 79 msg, err := srv.Recv() 80 if err == io.EOF { 81 logger.Debugf("Received EOF, hangup") 82 return nil 83 } 84 if err != nil { 85 logger.Warningf("Error reading from stream: %s", err) 86 return err 87 } 88 89 payload, err := utils.UnmarshalPayload(msg.Payload) 90 if err != nil { 91 logger.Warningf("Received malformed message, dropping connection: %s", err) 92 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 93 } 94 95 if payload.Header == nil { 96 logger.Warningf("Received malformed message, with missing header, dropping connection") 97 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 98 } 99 100 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 101 if err != nil { 102 logger.Warningf("Received malformed message (bad channel header), dropping connection: %s", err) 103 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 104 } 105 106 if chdr.Type == int32(cb.HeaderType_CONFIG_UPDATE) { 107 logger.Debugf("Preprocessing CONFIG_UPDATE") 108 msg, err = bh.sm.Process(msg) 109 if err != nil { 110 logger.Warningf("Rejecting CONFIG_UPDATE because: %s", err) 111 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 112 } 113 114 err = proto.Unmarshal(msg.Payload, payload) 115 if err != nil || payload.Header == nil { 116 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing") 117 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 118 } 119 120 chdr, err = utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 121 if err != nil { 122 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (bad channel header): %s", err) 123 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 124 } 125 126 if chdr.ChannelId == "" { 127 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (empty channel ID)") 128 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 129 } 130 } 131 132 support, ok := bh.sm.GetChain(chdr.ChannelId) 133 if !ok { 134 logger.Warningf("Rejecting broadcast because channel %s was not found", chdr.ChannelId) 135 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_NOT_FOUND}) 136 } 137 138 logger.Debugf("[channel: %s] Broadcast is filtering message of type %s", chdr.ChannelId, cb.HeaderType_name[chdr.Type]) 139 140 // Normal transaction for existing chain 141 _, filterErr := support.Filters().Apply(msg) 142 143 if filterErr != nil { 144 logger.Warningf("[channel: %s] Rejecting broadcast message because of filter error: %s", chdr.ChannelId, filterErr) 145 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 146 } 147 148 if !support.Enqueue(msg) { 149 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE}) 150 } 151 152 if logger.IsEnabledFor(logging.DEBUG) { 153 logger.Debugf("[channel: %s] Broadcast has successfully enqueued message of type %s", chdr.ChannelId, cb.HeaderType_name[chdr.Type]) 154 } 155 156 err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS}) 157 if err != nil { 158 logger.Warningf("[channel: %s] Error sending to stream: %s", chdr.ChannelId, err) 159 return err 160 } 161 } 162 }