github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/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/sigfilter" 25 "github.com/hyperledger/fabric/orderer/ledger" 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 payload, err := utils.UnmarshalPayload(envelope.Payload) 88 if err != nil { 89 logger.Warningf("Received an envelope with no payload: %s", err) 90 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 91 } 92 93 if payload.Header == nil { 94 logger.Warningf("Malformed envelope received with bad header") 95 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 96 } 97 98 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 99 if err != nil { 100 logger.Warningf("Failed to unmarshal channel header: %s", err) 101 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 102 } 103 104 chain, ok := ds.sm.GetChain(chdr.ChannelId) 105 if !ok { 106 // Note, we log this at DEBUG because SDKs will poll waiting for channels to be created 107 // So we would expect our log to be somewhat flooded with these 108 logger.Debugf("Rejecting deliver because channel %s not found", chdr.ChannelId) 109 return sendStatusReply(srv, cb.Status_NOT_FOUND) 110 } 111 112 erroredChan := chain.Errored() 113 select { 114 case <-erroredChan: 115 logger.Warningf("[channel: %s] Rejecting deliver request because of consenter error", chdr.ChannelId) 116 return sendStatusReply(srv, cb.Status_SERVICE_UNAVAILABLE) 117 default: 118 119 } 120 121 lastConfigSequence := chain.Sequence() 122 123 sf := sigfilter.New(policies.ChannelReaders, chain.PolicyManager()) 124 result, _ := sf.Apply(envelope) 125 if result != filter.Forward { 126 logger.Warningf("[channel: %s] Received unauthorized deliver request", chdr.ChannelId) 127 return sendStatusReply(srv, cb.Status_FORBIDDEN) 128 } 129 130 seekInfo := &ab.SeekInfo{} 131 if err = proto.Unmarshal(payload.Data, seekInfo); err != nil { 132 logger.Warningf("[channel: %s] Received a signed deliver request with malformed seekInfo payload: %s", chdr.ChannelId, err) 133 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 134 } 135 136 if seekInfo.Start == nil || seekInfo.Stop == nil { 137 logger.Warningf("[channel: %s] Received seekInfo message with missing start or stop %v, %v", chdr.ChannelId, seekInfo.Start, seekInfo.Stop) 138 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 139 } 140 141 logger.Debugf("[channel: %s] Received seekInfo (%p) %v", chdr.ChannelId, seekInfo, seekInfo) 142 143 cursor, number := chain.Reader().Iterator(seekInfo.Start) 144 var stopNum uint64 145 switch stop := seekInfo.Stop.Type.(type) { 146 case *ab.SeekPosition_Oldest: 147 stopNum = number 148 case *ab.SeekPosition_Newest: 149 stopNum = chain.Reader().Height() - 1 150 case *ab.SeekPosition_Specified: 151 stopNum = stop.Specified.Number 152 if stopNum < number { 153 logger.Warningf("[channel: %s] Received invalid seekInfo message: start number %d greater than stop number %d", chdr.ChannelId, number, stopNum) 154 return sendStatusReply(srv, cb.Status_BAD_REQUEST) 155 } 156 } 157 158 for { 159 if seekInfo.Behavior == ab.SeekInfo_BLOCK_UNTIL_READY { 160 select { 161 case <-erroredChan: 162 logger.Warningf("[channel: %s] Aborting deliver request because of consenter error", chdr.ChannelId) 163 return sendStatusReply(srv, cb.Status_SERVICE_UNAVAILABLE) 164 case <-cursor.ReadyChan(): 165 } 166 } else { 167 select { 168 case <-cursor.ReadyChan(): 169 default: 170 return sendStatusReply(srv, cb.Status_NOT_FOUND) 171 } 172 } 173 174 currentConfigSequence := chain.Sequence() 175 if currentConfigSequence > lastConfigSequence { 176 lastConfigSequence = currentConfigSequence 177 sf := sigfilter.New(policies.ChannelReaders, chain.PolicyManager()) 178 result, _ := sf.Apply(envelope) 179 if result != filter.Forward { 180 logger.Warningf("[channel: %s] Client authorization revoked for deliver request", chdr.ChannelId) 181 return sendStatusReply(srv, cb.Status_FORBIDDEN) 182 } 183 } 184 185 block, status := cursor.Next() 186 if status != cb.Status_SUCCESS { 187 logger.Errorf("[channel: %s] Error reading from channel, cause was: %v", chdr.ChannelId, status) 188 return sendStatusReply(srv, status) 189 } 190 191 logger.Debugf("[channel: %s] Delivering block for (%p)", chdr.ChannelId, seekInfo) 192 193 if err := sendBlockReply(srv, block); err != nil { 194 logger.Warningf("[channel: %s] Error sending to stream: %s", chdr.ChannelId, err) 195 return err 196 } 197 198 if stopNum == block.Header.Number { 199 break 200 } 201 } 202 203 if err := sendStatusReply(srv, cb.Status_SUCCESS); err != nil { 204 logger.Warningf("[channel: %s] Error sending to stream: %s", chdr.ChannelId, err) 205 return err 206 } 207 208 logger.Debugf("[channel: %s] Done delivering for (%p), waiting for new SeekInfo", chdr.ChannelId, seekInfo) 209 } 210 } 211 212 func sendStatusReply(srv ab.AtomicBroadcast_DeliverServer, status cb.Status) error { 213 return srv.Send(&ab.DeliverResponse{ 214 Type: &ab.DeliverResponse_Status{Status: status}, 215 }) 216 217 } 218 219 func sendBlockReply(srv ab.AtomicBroadcast_DeliverServer, block *cb.Block) error { 220 return srv.Send(&ab.DeliverResponse{ 221 Type: &ab.DeliverResponse_Block{Block: block}, 222 }) 223 }