github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/orderer/common/deliver/deliver.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 deliver 18 19 import ( 20 "io" 21 22 "github.com/hyperledger/fabric/common/policies" 23 "github.com/hyperledger/fabric/orderer/common/filter" 24 "github.com/hyperledger/fabric/orderer/common/ledger" 25 "github.com/hyperledger/fabric/orderer/common/sigfilter" 26 cb "github.com/hyperledger/fabric/protos/common" 27 ab "github.com/hyperledger/fabric/protos/orderer" 28 "github.com/op/go-logging" 29 30 "github.com/golang/protobuf/proto" 31 "github.com/hyperledger/fabric/protos/utils" 32 ) 33 34 var logger = logging.MustGetLogger("orderer/common/deliver") 35 36 // Handler defines an interface which handles Deliver requests 37 type Handler interface { 38 Handle(srv ab.AtomicBroadcast_DeliverServer) error 39 } 40 41 // SupportManager provides a way for the Handler to look up the Support for a chain 42 type SupportManager interface { 43 GetChain(chainID string) (Support, bool) 44 } 45 46 // Support provides the backing resources needed to support deliver on a chain 47 type Support interface { 48 // Sequence returns the current config sequence number, can be used to detect config changes 49 Sequence() uint64 50 51 // PolicyManager returns the current policy manager as specified by the chain configuration 52 PolicyManager() policies.Manager 53 54 // Reader returns the chain Reader for the chain 55 Reader() ledger.Reader 56 57 // Errored returns a channel which closes when the backing consenter has errored 58 Errored() <-chan struct{} 59 } 60 61 type deliverServer struct { 62 sm SupportManager 63 } 64 65 // NewHandlerImpl creates an implementation of the Handler interface 66 func NewHandlerImpl(sm SupportManager) Handler { 67 return &deliverServer{ 68 sm: sm, 69 } 70 } 71 72 func (ds *deliverServer) Handle(srv ab.AtomicBroadcast_DeliverServer) error { 73 logger.Debugf("Starting new deliver loop") 74 for { 75 logger.Debugf("Attempting to read seek info message") 76 envelope, err := srv.Recv() 77 if err == io.EOF { 78 logger.Debugf("Received EOF, hangup") 79 return nil 80 } 81 82 if err != nil { 83 logger.Warningf("Error reading from stream: %s", err) 84 return err 85 } 86 87 if err := ds.deliverBlocks(srv, envelope); err != nil { 88 return err 89 } 90 91 logger.Debugf("Waiting for new SeekInfo") 92 } 93 } 94 95 func (ds *deliverServer) deliverBlocks(srv ab.AtomicBroadcast_DeliverServer, envelope *cb.Envelope) error { 96 97 payload, err := utils.UnmarshalPayload(envelope.Payload) 98 if err != nil { 99 logger.Warningf("Received an envelope with no payload: %s", err) 100 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 101 } 102 103 if payload.Header == nil { 104 logger.Warningf("Malformed envelope received with bad header") 105 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 106 } 107 108 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 109 if err != nil { 110 logger.Warningf("Failed to unmarshal channel header: %s", err) 111 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 112 } 113 114 chain, ok := ds.sm.GetChain(chdr.ChannelId) 115 if !ok { 116 // Note, we log this at DEBUG because SDKs will poll waiting for channels to be created 117 // So we would expect our log to be somewhat flooded with these 118 logger.Debugf("Rejecting deliver because channel %s not found", chdr.ChannelId) 119 return sendStatusReply(srv, cb.Status_NOT_FOUND) 120 } 121 122 erroredChan := chain.Errored() 123 select { 124 case <-erroredChan: 125 logger.Warningf("[channel: %s] Rejecting deliver request because of consenter error", chdr.ChannelId) 126 return sendStatusReply(srv, cb.Status_SERVICE_UNAVAILABLE) 127 default: 128 129 } 130 131 lastConfigSequence := chain.Sequence() 132 133 sf := sigfilter.New(policies.ChannelReaders, chain.PolicyManager()) 134 result, _ := sf.Apply(envelope) 135 if result != filter.Forward { 136 logger.Warningf("[channel: %s] Received unauthorized deliver request", chdr.ChannelId) 137 return sendStatusReply(srv, cb.Status_FORBIDDEN) 138 } 139 140 seekInfo := &ab.SeekInfo{} 141 if err = proto.Unmarshal(payload.Data, seekInfo); err != nil { 142 logger.Warningf("[channel: %s] Received a signed deliver request with malformed seekInfo payload: %s", chdr.ChannelId, err) 143 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 144 } 145 146 if seekInfo.Start == nil || seekInfo.Stop == nil { 147 logger.Warningf("[channel: %s] Received seekInfo message with missing start or stop %v, %v", chdr.ChannelId, seekInfo.Start, seekInfo.Stop) 148 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 149 } 150 151 logger.Debugf("[channel: %s] Received seekInfo (%p) %v", chdr.ChannelId, seekInfo, seekInfo) 152 153 cursor, number := chain.Reader().Iterator(seekInfo.Start) 154 defer cursor.Close() 155 var stopNum uint64 156 switch stop := seekInfo.Stop.Type.(type) { 157 case *ab.SeekPosition_Oldest: 158 stopNum = number 159 case *ab.SeekPosition_Newest: 160 stopNum = chain.Reader().Height() - 1 161 case *ab.SeekPosition_Specified: 162 stopNum = stop.Specified.Number 163 if stopNum < number { 164 logger.Warningf("[channel: %s] Received invalid seekInfo message: start number %d greater than stop number %d", chdr.ChannelId, number, stopNum) 165 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 166 } 167 } 168 169 for { 170 if seekInfo.Behavior == ab.SeekInfo_BLOCK_UNTIL_READY { 171 select { 172 case <-erroredChan: 173 logger.Warningf("[channel: %s] Aborting deliver request because of consenter error", chdr.ChannelId) 174 return sendStatusReply(srv, cb.Status_SERVICE_UNAVAILABLE) 175 case <-cursor.ReadyChan(): 176 } 177 } else { 178 select { 179 case <-cursor.ReadyChan(): 180 default: 181 return sendStatusReply(srv, cb.Status_NOT_FOUND) 182 } 183 } 184 185 currentConfigSequence := chain.Sequence() 186 if currentConfigSequence > lastConfigSequence { 187 lastConfigSequence = currentConfigSequence 188 sf := sigfilter.New(policies.ChannelReaders, chain.PolicyManager()) 189 result, _ := sf.Apply(envelope) 190 if result != filter.Forward { 191 logger.Warningf("[channel: %s] Client authorization revoked for deliver request", chdr.ChannelId) 192 return sendStatusReply(srv, cb.Status_FORBIDDEN) 193 } 194 } 195 196 block, status := cursor.Next() 197 if status != cb.Status_SUCCESS { 198 logger.Errorf("[channel: %s] Error reading from channel, cause was: %v", chdr.ChannelId, status) 199 return sendStatusReply(srv, status) 200 } 201 202 logger.Debugf("[channel: %s] Delivering block for (%p)", chdr.ChannelId, seekInfo) 203 204 if err := sendBlockReply(srv, block); err != nil { 205 logger.Warningf("[channel: %s] Error sending to stream: %s", chdr.ChannelId, err) 206 return err 207 } 208 209 if stopNum == block.Header.Number { 210 break 211 } 212 } 213 214 if err := sendStatusReply(srv, cb.Status_SUCCESS); err != nil { 215 logger.Warningf("[channel: %s] Error sending to stream: %s", chdr.ChannelId, err) 216 return err 217 } 218 219 logger.Debugf("[channel: %s] Done delivering for (%p)", chdr.ChannelId, seekInfo) 220 221 return nil 222 223 } 224 225 func sendStatusReply(srv ab.AtomicBroadcast_DeliverServer, status cb.Status) error { 226 return srv.Send(&ab.DeliverResponse{ 227 Type: &ab.DeliverResponse_Status{Status: status}, 228 }) 229 230 } 231 232 func sendBlockReply(srv ab.AtomicBroadcast_DeliverServer, block *cb.Block) error { 233 return srv.Send(&ab.DeliverResponse{ 234 Type: &ab.DeliverResponse_Block{Block: block}, 235 }) 236 }