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