github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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 return nil 82 } 83 if err != nil { 84 return err 85 } 86 87 payload := &cb.Payload{} 88 err = proto.Unmarshal(msg.Payload, payload) 89 if err != nil { 90 if logger.IsEnabledFor(logging.WARNING) { 91 logger.Warningf("Received malformed message, dropping connection: %s", err) 92 } 93 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 94 } 95 96 if payload.Header == nil { 97 logger.Warningf("Received malformed message, with missing header, dropping connection") 98 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 99 } 100 101 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 102 if err != nil { 103 if logger.IsEnabledFor(logging.WARNING) { 104 logger.Warningf("Received malformed message (bad channel header), dropping connection: %s", err) 105 } 106 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 107 } 108 109 if chdr.Type == int32(cb.HeaderType_CONFIG_UPDATE) { 110 logger.Debugf("Preprocessing CONFIG_UPDATE") 111 msg, err = bh.sm.Process(msg) 112 if err != nil { 113 if logger.IsEnabledFor(logging.WARNING) { 114 logger.Warningf("Rejecting CONFIG_UPDATE because: %s", err) 115 } 116 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 117 } 118 119 err = proto.Unmarshal(msg.Payload, payload) 120 if err != nil || payload.Header == nil { 121 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing") 122 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 123 } 124 125 chdr, err = utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 126 if err != nil { 127 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (bad channel header): %s", err) 128 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 129 } 130 131 if chdr.ChannelId == "" { 132 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (empty channel ID)") 133 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 134 } 135 } 136 137 support, ok := bh.sm.GetChain(chdr.ChannelId) 138 if !ok { 139 if logger.IsEnabledFor(logging.WARNING) { 140 logger.Warningf("Rejecting broadcast because channel %s was not found", chdr.ChannelId) 141 } 142 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_NOT_FOUND}) 143 } 144 145 if logger.IsEnabledFor(logging.DEBUG) { 146 logger.Debugf("Broadcast is filtering message of type %s for channel %s", cb.HeaderType_name[chdr.Type], chdr.ChannelId) 147 } 148 149 // Normal transaction for existing chain 150 _, filterErr := support.Filters().Apply(msg) 151 152 if filterErr != nil { 153 if logger.IsEnabledFor(logging.WARNING) { 154 logger.Warningf("Rejecting broadcast message because of filter error: %s", filterErr) 155 } 156 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 157 } 158 159 if !support.Enqueue(msg) { 160 logger.Infof("Consenter instructed us to shut down") 161 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE}) 162 } 163 164 if logger.IsEnabledFor(logging.DEBUG) { 165 logger.Debugf("Broadcast has successfully enqueued message of type %d for chain %s", chdr.Type, chdr.ChannelId) 166 } 167 168 err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS}) 169 170 if err != nil { 171 return err 172 } 173 } 174 }