github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/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 transforms an envelope of type CONFIG_UPDATE to another type 37 Process(envConfigUpdate *cb.Envelope) (*cb.Envelope, error) 38 } 39 40 // Handler defines an interface which handles broadcasts 41 type Handler interface { 42 // Handle starts a service thread for a given gRPC connection and services the broadcast connection 43 Handle(srv ab.AtomicBroadcast_BroadcastServer) error 44 } 45 46 // SupportManager provides a way for the Handler to look up the Support for a chain 47 type SupportManager interface { 48 ConfigUpdateProcessor 49 50 // GetChain gets the chain support for a given ChannelId 51 GetChain(chainID string) (Support, bool) 52 } 53 54 // Support provides the backing resources needed to support broadcast on a chain 55 type Support interface { 56 // Enqueue accepts a message and returns true on acceptance, or false on shutdown 57 Enqueue(env *cb.Envelope) bool 58 59 // Filters returns the set of broadcast filters for this chain 60 Filters() *filter.RuleSet 61 } 62 63 type handlerImpl struct { 64 sm SupportManager 65 } 66 67 // NewHandlerImpl constructs a new implementation of the Handler interface 68 func NewHandlerImpl(sm SupportManager) Handler { 69 return &handlerImpl{ 70 sm: sm, 71 } 72 } 73 74 // Handle starts a service thread for a given gRPC connection and services the broadcast connection 75 func (bh *handlerImpl) Handle(srv ab.AtomicBroadcast_BroadcastServer) error { 76 logger.Debugf("Starting new broadcast loop") 77 for { 78 msg, err := srv.Recv() 79 if err == io.EOF { 80 logger.Debugf("Received EOF, hangup") 81 return nil 82 } 83 if err != nil { 84 logger.Warningf("Error reading from stream: %s", err) 85 return err 86 } 87 88 payload, err := utils.UnmarshalPayload(msg.Payload) 89 if err != nil { 90 logger.Warningf("Received malformed message, dropping connection: %s", err) 91 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 92 } 93 94 if payload.Header == nil { 95 logger.Warningf("Received malformed message, with missing header, dropping connection") 96 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 97 } 98 99 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 100 if err != nil { 101 logger.Warningf("Received malformed message (bad channel header), dropping connection: %s", err) 102 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 103 } 104 105 if chdr.Type == int32(cb.HeaderType_CONFIG_UPDATE) { 106 logger.Debugf("Preprocessing CONFIG_UPDATE") 107 msg, err = bh.sm.Process(msg) 108 if err != nil { 109 logger.Warningf("Rejecting CONFIG_UPDATE because: %s", err) 110 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 111 } 112 113 err = proto.Unmarshal(msg.Payload, payload) 114 if err != nil || payload.Header == nil { 115 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing") 116 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 117 } 118 119 chdr, err = utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 120 if err != nil { 121 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (bad channel header): %s", err) 122 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 123 } 124 125 if chdr.ChannelId == "" { 126 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (empty channel ID)") 127 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 128 } 129 } 130 131 support, ok := bh.sm.GetChain(chdr.ChannelId) 132 if !ok { 133 logger.Warningf("Rejecting broadcast because channel %s was not found", chdr.ChannelId) 134 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_NOT_FOUND}) 135 } 136 137 logger.Debugf("[channel: %s] Broadcast is filtering message of type %s", chdr.ChannelId, cb.HeaderType_name[chdr.Type]) 138 139 // Normal transaction for existing chain 140 _, filterErr := support.Filters().Apply(msg) 141 142 if filterErr != nil { 143 logger.Warningf("[channel: %s] Rejecting broadcast message because of filter error: %s", chdr.ChannelId, filterErr) 144 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 145 } 146 147 if !support.Enqueue(msg) { 148 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE}) 149 } 150 151 if logger.IsEnabledFor(logging.DEBUG) { 152 logger.Debugf("[channel: %s] Broadcast has successfully enqueued message of type %s", chdr.ChannelId, cb.HeaderType_name[chdr.Type]) 153 } 154 155 err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS}) 156 if err != nil { 157 logger.Warningf("[channel: %s] Error sending to stream: %s", chdr.ChannelId, err) 158 return err 159 } 160 } 161 }