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  }