github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/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  			logger.Debugf("Received EOF, hangup")
    82  			return nil
    83  		}
    84  		if err != nil {
    85  			logger.Warningf("Error reading from stream: %s", err)
    86  			return err
    87  		}
    88  
    89  		payload, err := utils.UnmarshalPayload(msg.Payload)
    90  		if err != nil {
    91  			logger.Warningf("Received malformed message, dropping connection: %s", err)
    92  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
    93  		}
    94  
    95  		if payload.Header == nil {
    96  			logger.Warningf("Received malformed message, with missing header, dropping connection")
    97  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
    98  		}
    99  
   100  		chdr, err := utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   101  		if err != nil {
   102  			logger.Warningf("Received malformed message (bad channel header), dropping connection: %s", err)
   103  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
   104  		}
   105  
   106  		if chdr.Type == int32(cb.HeaderType_CONFIG_UPDATE) {
   107  			logger.Debugf("Preprocessing CONFIG_UPDATE")
   108  			msg, err = bh.sm.Process(msg)
   109  			if err != nil {
   110  				logger.Warningf("Rejecting CONFIG_UPDATE because: %s", err)
   111  				return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
   112  			}
   113  
   114  			err = proto.Unmarshal(msg.Payload, payload)
   115  			if err != nil || payload.Header == nil {
   116  				logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing")
   117  				return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR})
   118  			}
   119  
   120  			chdr, err = utils.UnmarshalChannelHeader(payload.Header.ChannelHeader)
   121  			if err != nil {
   122  				logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (bad channel header): %s", err)
   123  				return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR})
   124  			}
   125  
   126  			if chdr.ChannelId == "" {
   127  				logger.Criticalf("Generated bad transaction after CONFIG_UPDATE processing (empty channel ID)")
   128  				return srv.Send(&ab.BroadcastResponse{Status: cb.Status_INTERNAL_SERVER_ERROR})
   129  			}
   130  		}
   131  
   132  		support, ok := bh.sm.GetChain(chdr.ChannelId)
   133  		if !ok {
   134  			logger.Warningf("Rejecting broadcast because channel %s was not found", chdr.ChannelId)
   135  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_NOT_FOUND})
   136  		}
   137  
   138  		logger.Debugf("[channel: %s] Broadcast is filtering message of type %s", chdr.ChannelId, cb.HeaderType_name[chdr.Type])
   139  
   140  		// Normal transaction for existing chain
   141  		_, filterErr := support.Filters().Apply(msg)
   142  
   143  		if filterErr != nil {
   144  			logger.Warningf("[channel: %s] Rejecting broadcast message because of filter error: %s", chdr.ChannelId, filterErr)
   145  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_BAD_REQUEST})
   146  		}
   147  
   148  		if !support.Enqueue(msg) {
   149  			return srv.Send(&ab.BroadcastResponse{Status: cb.Status_SERVICE_UNAVAILABLE})
   150  		}
   151  
   152  		if logger.IsEnabledFor(logging.DEBUG) {
   153  			logger.Debugf("[channel: %s] Broadcast has successfully enqueued message of type %s", chdr.ChannelId, cb.HeaderType_name[chdr.Type])
   154  		}
   155  
   156  		err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS})
   157  		if err != nil {
   158  			logger.Warningf("[channel: %s] Error sending to stream: %s", chdr.ChannelId, err)
   159  			return err
   160  		}
   161  	}
   162  }