github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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 "fmt" 21 22 configvaluesapi "github.com/hyperledger/fabric/common/configvalues" 23 "github.com/hyperledger/fabric/common/policies" 24 "github.com/hyperledger/fabric/orderer/common/filter" 25 "github.com/hyperledger/fabric/orderer/common/sigfilter" 26 ordererledger "github.com/hyperledger/fabric/orderer/ledger" 27 cb "github.com/hyperledger/fabric/protos/common" 28 ab "github.com/hyperledger/fabric/protos/orderer" 29 "github.com/op/go-logging" 30 31 "github.com/golang/protobuf/proto" 32 "github.com/hyperledger/fabric/protos/utils" 33 ) 34 35 var logger = logging.MustGetLogger("orderer/common/deliver") 36 37 // Handler defines an interface which handles Deliver requests 38 type Handler interface { 39 Handle(srv ab.AtomicBroadcast_DeliverServer) error 40 } 41 42 // SupportManager provides a way for the Handler to look up the Support for a chain 43 type SupportManager interface { 44 GetChain(chainID string) (Support, bool) 45 } 46 47 // Support provides the backing resources needed to support deliver on a chain 48 type Support interface { 49 // PolicyManager returns the current policy manager as specified by the chain configuration 50 PolicyManager() policies.Manager 51 52 // Reader returns the chain Reader for the chain 53 Reader() ordererledger.Reader 54 55 // SharedConfig returns the shared config manager for this chain 56 SharedConfig() configvaluesapi.Orderer 57 } 58 59 type deliverServer struct { 60 sm SupportManager 61 } 62 63 // NewHandlerImpl creates an implementation of the Handler interface 64 func NewHandlerImpl(sm SupportManager) Handler { 65 return &deliverServer{ 66 sm: sm, 67 } 68 } 69 70 func (ds *deliverServer) Handle(srv ab.AtomicBroadcast_DeliverServer) error { 71 logger.Debugf("Starting new deliver loop") 72 for { 73 logger.Debugf("Attempting to read seek info message") 74 envelope, err := srv.Recv() 75 if err != nil { 76 logger.Errorf("Error reading from stream: %s", err) 77 return err 78 } 79 payload := &cb.Payload{} 80 if err = proto.Unmarshal(envelope.Payload, payload); err != nil { 81 logger.Errorf("Received an envelope with no payload: %s", err) 82 return err 83 } 84 85 if payload.Header == nil /* || payload.Header.ChannelHeader == nil */ { 86 err := fmt.Errorf("Malformed envelope recieved with bad header") 87 logger.Error(err) 88 return err 89 } 90 91 chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader) 92 if err != nil { 93 logger.Error(err) 94 return err 95 } 96 97 chain, ok := ds.sm.GetChain(chdr.ChannelId) 98 if !ok { 99 return sendStatusReply(srv, cb.Status_NOT_FOUND) 100 } 101 102 sf := sigfilter.New(chain.SharedConfig().EgressPolicyNames, chain.PolicyManager()) 103 result, _ := sf.Apply(envelope) 104 if result != filter.Forward { 105 return sendStatusReply(srv, cb.Status_FORBIDDEN) 106 } 107 108 seekInfo := &ab.SeekInfo{} 109 if err = proto.Unmarshal(payload.Data, seekInfo); err != nil { 110 logger.Errorf("Received a signed deliver request with malformed seekInfo payload: %s", err) 111 return err 112 } 113 114 if logger.IsEnabledFor(logging.DEBUG) { 115 logger.Debugf("Received seekInfo %v for chain %s", seekInfo, chdr.ChannelId) 116 } 117 118 cursor, number := chain.Reader().Iterator(seekInfo.Start) 119 var stopNum uint64 120 switch stop := seekInfo.Stop.Type.(type) { 121 case *ab.SeekPosition_Oldest: 122 stopNum = number 123 case *ab.SeekPosition_Newest: 124 stopNum = chain.Reader().Height() - 1 125 case *ab.SeekPosition_Specified: 126 stopNum = stop.Specified.Number 127 } 128 129 for { 130 if seekInfo.Behavior == ab.SeekInfo_BLOCK_UNTIL_READY { 131 <-cursor.ReadyChan() 132 } else { 133 select { 134 case <-cursor.ReadyChan(): 135 default: 136 return sendStatusReply(srv, cb.Status_NOT_FOUND) 137 } 138 } 139 140 block, status := cursor.Next() 141 if status != cb.Status_SUCCESS { 142 logger.Errorf("Error reading from channel, cause was: %v", status) 143 return sendStatusReply(srv, status) 144 } 145 146 logger.Debugf("Delivering block") 147 if err := sendBlockReply(srv, block); err != nil { 148 return err 149 } 150 151 if stopNum == block.Header.Number { 152 break 153 } 154 } 155 156 if err := sendStatusReply(srv, cb.Status_SUCCESS); err != nil { 157 return err 158 } 159 logger.Debugf("Done delivering, waiting for new SeekInfo") 160 } 161 } 162 163 func sendStatusReply(srv ab.AtomicBroadcast_DeliverServer, status cb.Status) error { 164 return srv.Send(&ab.DeliverResponse{ 165 Type: &ab.DeliverResponse_Status{Status: status}, 166 }) 167 168 } 169 170 func sendBlockReply(srv ab.AtomicBroadcast_DeliverServer, block *cb.Block) error { 171 return srv.Send(&ab.DeliverResponse{ 172 Type: &ab.DeliverResponse_Block{Block: block}, 173 }) 174 }