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  }