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