github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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 for { 78 msg, err := srv.Recv() 79 if err == io.EOF { 80 return nil 81 } 82 if err != nil { 83 return err 84 } 85 86 payload := &cb.Payload{} 87 err = proto.Unmarshal(msg.Payload, payload) 88 if payload.Header == nil /* || payload.Header.ChannelHeader == nil */ { 89 logger.Debugf("Received malformed message, dropping connection") 90 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 91 } 92 93 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 94 if err != nil { 95 logger.Debugf("Received malformed message (bad channel header), dropping connection") 96 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 97 } 98 99 if chdr.Type == int32(cb.HeaderType_CONFIG_UPDATE) { 100 logger.Debugf("Preprocessing CONFIG_UPDATE") 101 msg, err = bh.sm.Process(msg) 102 if err != nil { 103 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 104 } 105 106 err = proto.Unmarshal(msg.Payload, payload) 107 if payload.Header == nil { 108 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing") 109 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 110 } 111 112 chdr, err = utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 113 if err != nil { 114 logger.Debugf("Generated bad transaction after CONFIG_UPDATE processing (bad channel header)") 115 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 116 } 117 118 if chdr.ChannelId == "" { 119 logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing") 120 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR}) 121 } 122 } 123 124 support, ok := bh.sm.GetChain(chdr.ChannelId) 125 if !ok { 126 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_NOT_FOUND}) 127 } 128 129 if logger.IsEnabledFor(logging.DEBUG) { 130 logger.Debugf("Broadcast is filtering message for channel %s", chdr.ChannelId) 131 } 132 133 // Normal transaction for existing chain 134 _, filterErr := support.Filters().Apply(msg) 135 136 if filterErr != nil { 137 logger.Debugf("Rejecting broadcast message") 138 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST}) 139 } 140 141 if !support.Enqueue(msg) { 142 logger.Debugf("Consenter instructed us to shut down") 143 return srv.Send(&ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE}) 144 } 145 146 if logger.IsEnabledFor(logging.DEBUG) { 147 logger.Debugf("Broadcast is successfully enqueued message for chain %s", chdr.ChannelId) 148 } 149 150 err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS}) 151 152 if err != nil { 153 return err 154 } 155 } 156 }