github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/orderer/common/broadcast/broadcast.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 broadcast
    18  
    19  import (
    20  	"github.com/hyperledger/fabric/orderer/common/filter"
    21  	cb "github.com/hyperledger/fabric/protos/common"
    22  	ab "github.com/hyperledger/fabric/protos/orderer"
    23  	"github.com/op/go-logging"
    24  
    25  	"io"
    26  
    27  	"github.com/golang/protobuf/proto"
    28  	"github.com/hyperledger/fabric/protos/utils"
    29  )
    30  
    31  var logger = logging.MustGetLogger("orderer/common/broadcast")
    32  
    33  // ConfigUpdateProcessor is used to transform CONFIG_UPDATE transactions which are used to generate other envelope
    34  // message types with preprocessing by the orderer
    35  type ConfigUpdateProcessor interface {
    36  	// Process takes in an envelope of type CONFIG_UPDATE and proceses it
    37  	// to transform it either into another envelope type
    38  	Process(envConfigUpdate *cb.Envelope) (*cb.Envelope, error)
    39  }
    40  
    41  // Handler defines an interface which handles broadcasts
    42  type Handler interface {
    43  	// Handle starts a service thread for a given gRPC connection and services the broadcast connection
    44  	Handle(srv ab.AtomicBroadcast_BroadcastServer) error
    45  }
    46  
    47  // SupportManager provides a way for the Handler to look up the Support for a chain
    48  type SupportManager interface {
    49  	ConfigUpdateProcessor
    50  
    51  	// GetChain gets the chain support for a given ChannelId
    52  	GetChain(chainID string) (Support, bool)
    53  }
    54  
    55  // Support provides the backing resources needed to support broadcast on a chain
    56  type Support interface {
    57  	// Enqueue accepts a message and returns true on acceptance, or false on shutdown
    58  	Enqueue(env *cb.Envelope) bool
    59  
    60  	// Filters returns the set of broadcast filters for this chain
    61  	Filters() *filter.RuleSet
    62  }
    63  
    64  type handlerImpl struct {
    65  	sm SupportManager
    66  }
    67  
    68  // NewHandlerImpl constructs a new implementation of the Handler interface
    69  func NewHandlerImpl(sm SupportManager) Handler {
    70  	return &handlerImpl{
    71  		sm: sm,
    72  	}
    73  }
    74  
    75  // Handle starts a service thread for a given gRPC connection and services the broadcast connection
    76  func (bh *handlerImpl) Handle(srv ab.AtomicBroadcast_BroadcastServer) error {
    77  	logger.Debugf("Starting new broadcast loop")
    78  	for {
    79  		msg, err := srv.Recv()
    80  		if err == io.EOF {
    81  			return nil
    82  		}
    83  		if err != nil {
    84  			return err
    85  		}
    86  
    87  		payload := &cb.Payload{}
    88  		err = proto.Unmarshal(msg.Payload, payload)
    89  		if err != nil {
    90  			if logger.IsEnabledFor(logging.WARNING) {
    91  				logger.Warningf("Received malformed message, dropping connection: %s", err)
    92  			}
    93  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
    94  		}
    95  
    96  		if payload.Header == nil {
    97  			logger.Warningf("Received malformed message, with missing header, dropping connection")
    98  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
    99  		}
   100  
   101  		chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   102  		if err != nil {
   103  			if logger.IsEnabledFor(logging.WARNING) {
   104  				logger.Warningf("Received malformed message (bad channel header), dropping connection: %s", err)
   105  			}
   106  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
   107  		}
   108  
   109  		if chdr.Type == int32(cb.HeaderType_CONFIG_UPDATE) {
   110  			logger.Debugf("Preprocessing CONFIG_UPDATE")
   111  			msg, err = bh.sm.Process(msg)
   112  			if err != nil {
   113  				if logger.IsEnabledFor(logging.WARNING) {
   114  					logger.Warningf("Rejecting CONFIG_UPDATE because: %s", err)
   115  				}
   116  				return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
   117  			}
   118  
   119  			err = proto.Unmarshal(msg.Payload, payload)
   120  			if err != nil || payload.Header == nil {
   121  				logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing")
   122  				return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR})
   123  			}
   124  
   125  			chdr, err = utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   126  			if err != nil {
   127  				logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (bad channel header): %s", err)
   128  				return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR})
   129  			}
   130  
   131  			if chdr.ChannelId == "" {
   132  				logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (empty channel ID)")
   133  				return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR})
   134  			}
   135  		}
   136  
   137  		support, ok := bh.sm.GetChain(chdr.ChannelId)
   138  		if !ok {
   139  			if logger.IsEnabledFor(logging.WARNING) {
   140  				logger.Warningf("Rejecting broadcast because channel %s was not found", chdr.ChannelId)
   141  			}
   142  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_NOT_FOUND})
   143  		}
   144  
   145  		if logger.IsEnabledFor(logging.DEBUG) {
   146  			logger.Debugf("Broadcast is filtering message of type %s for channel %s", cb.HeaderType_name[chdr.Type], chdr.ChannelId)
   147  		}
   148  
   149  		// Normal transaction for existing chain
   150  		_, filterErr := support.Filters().Apply(msg)
   151  
   152  		if filterErr != nil {
   153  			if logger.IsEnabledFor(logging.WARNING) {
   154  				logger.Warningf("Rejecting broadcast message because of filter error: %s", filterErr)
   155  			}
   156  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
   157  		}
   158  
   159  		if !support.Enqueue(msg) {
   160  			logger.Infof("Consenter instructed us to shut down")
   161  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE})
   162  		}
   163  
   164  		if logger.IsEnabledFor(logging.DEBUG) {
   165  			logger.Debugf("Broadcast has successfully enqueued message of type %d for chain %s", chdr.Type, chdr.ChannelId)
   166  		}
   167  
   168  		err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS})
   169  
   170  		if err != nil {
   171  			return err
   172  		}
   173  	}
   174  }