github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/server/server.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package server
     8  
     9  import (
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"runtime/debug"
    14  	"time"
    15  
    16  	"github.com/golang/protobuf/proto"
    17  	cb "github.com/hyperledger/fabric-protos-go/common"
    18  	ab "github.com/hyperledger/fabric-protos-go/orderer"
    19  	"github.com/hyperledger/fabric/common/deliver"
    20  	"github.com/hyperledger/fabric/common/metrics"
    21  	"github.com/hyperledger/fabric/common/policies"
    22  	"github.com/hyperledger/fabric/orderer/common/broadcast"
    23  	localconfig "github.com/hyperledger/fabric/orderer/common/localconfig"
    24  	"github.com/hyperledger/fabric/orderer/common/msgprocessor"
    25  	"github.com/hyperledger/fabric/orderer/common/multichannel"
    26  	"github.com/hyperledger/fabric/protoutil"
    27  	"github.com/pkg/errors"
    28  )
    29  
    30  type broadcastSupport struct {
    31  	*multichannel.Registrar
    32  }
    33  
    34  func (bs broadcastSupport) BroadcastChannelSupport(msg *cb.Envelope) (*cb.ChannelHeader, bool, broadcast.ChannelSupport, error) {
    35  	return bs.Registrar.BroadcastChannelSupport(msg)
    36  }
    37  
    38  type deliverSupport struct {
    39  	*multichannel.Registrar
    40  }
    41  
    42  func (ds deliverSupport) GetChain(chainID string) deliver.Chain {
    43  	chain := ds.Registrar.GetChain(chainID)
    44  	if chain == nil {
    45  		return nil
    46  	}
    47  	return chain
    48  }
    49  
    50  type server struct {
    51  	bh    *broadcast.Handler
    52  	dh    *deliver.Handler
    53  	debug *localconfig.Debug
    54  	*multichannel.Registrar
    55  }
    56  
    57  type responseSender struct {
    58  	ab.AtomicBroadcast_DeliverServer
    59  }
    60  
    61  func (rs *responseSender) SendStatusResponse(status cb.Status) error {
    62  	reply := &ab.DeliverResponse{
    63  		Type: &ab.DeliverResponse_Status{Status: status},
    64  	}
    65  	return rs.Send(reply)
    66  }
    67  
    68  // SendBlockResponse sends block data and ignores pvtDataMap.
    69  func (rs *responseSender) SendBlockResponse(
    70  	block *cb.Block,
    71  	channelID string,
    72  	chain deliver.Chain,
    73  	signedData *protoutil.SignedData,
    74  ) error {
    75  	response := &ab.DeliverResponse{
    76  		Type: &ab.DeliverResponse_Block{Block: block},
    77  	}
    78  	return rs.Send(response)
    79  }
    80  
    81  func (rs *responseSender) DataType() string {
    82  	return "block"
    83  }
    84  
    85  // NewServer creates an ab.AtomicBroadcastServer based on the broadcast target and ledger Reader
    86  func NewServer(
    87  	r *multichannel.Registrar,
    88  	metricsProvider metrics.Provider,
    89  	debug *localconfig.Debug,
    90  	timeWindow time.Duration,
    91  	mutualTLS bool,
    92  	expirationCheckDisabled bool,
    93  ) ab.AtomicBroadcastServer {
    94  	s := &server{
    95  		dh: deliver.NewHandler(deliverSupport{Registrar: r}, timeWindow, mutualTLS, deliver.NewMetrics(metricsProvider), expirationCheckDisabled),
    96  		bh: &broadcast.Handler{
    97  			SupportRegistrar: broadcastSupport{Registrar: r},
    98  			Metrics:          broadcast.NewMetrics(metricsProvider),
    99  		},
   100  		debug:     debug,
   101  		Registrar: r,
   102  	}
   103  	return s
   104  }
   105  
   106  type msgTracer struct {
   107  	function string
   108  	debug    *localconfig.Debug
   109  }
   110  
   111  func (mt *msgTracer) trace(traceDir string, msg *cb.Envelope, err error) {
   112  	if err != nil {
   113  		return
   114  	}
   115  
   116  	now := time.Now().UnixNano()
   117  	path := fmt.Sprintf("%s%c%d_%p.%s", traceDir, os.PathSeparator, now, msg, mt.function)
   118  	logger.Debugf("Writing %s request trace to %s", mt.function, path)
   119  	go func() {
   120  		pb, err := proto.Marshal(msg)
   121  		if err != nil {
   122  			logger.Debugf("Error marshaling trace msg for %s: %s", path, err)
   123  			return
   124  		}
   125  		err = ioutil.WriteFile(path, pb, 0660)
   126  		if err != nil {
   127  			logger.Debugf("Error writing trace msg for %s: %s", path, err)
   128  		}
   129  	}()
   130  }
   131  
   132  type broadcastMsgTracer struct {
   133  	ab.AtomicBroadcast_BroadcastServer
   134  	msgTracer
   135  }
   136  
   137  func (bmt *broadcastMsgTracer) Recv() (*cb.Envelope, error) {
   138  	msg, err := bmt.AtomicBroadcast_BroadcastServer.Recv()
   139  	if traceDir := bmt.debug.BroadcastTraceDir; traceDir != "" {
   140  		bmt.trace(bmt.debug.BroadcastTraceDir, msg, err)
   141  	}
   142  	return msg, err
   143  }
   144  
   145  type deliverMsgTracer struct {
   146  	deliver.Receiver
   147  	msgTracer
   148  }
   149  
   150  func (dmt *deliverMsgTracer) Recv() (*cb.Envelope, error) {
   151  	msg, err := dmt.Receiver.Recv()
   152  	if traceDir := dmt.debug.DeliverTraceDir; traceDir != "" {
   153  		dmt.trace(traceDir, msg, err)
   154  	}
   155  	return msg, err
   156  }
   157  
   158  // Broadcast receives a stream of messages from a client for ordering
   159  func (s *server) Broadcast(srv ab.AtomicBroadcast_BroadcastServer) error {
   160  	logger.Debugf("Starting new Broadcast handler")
   161  	defer func() {
   162  		if r := recover(); r != nil {
   163  			logger.Criticalf("Broadcast client triggered panic: %s\n%s", r, debug.Stack())
   164  		}
   165  		logger.Debugf("Closing Broadcast stream")
   166  	}()
   167  	return s.bh.Handle(&broadcastMsgTracer{
   168  		AtomicBroadcast_BroadcastServer: srv,
   169  		msgTracer: msgTracer{
   170  			debug:    s.debug,
   171  			function: "Broadcast",
   172  		},
   173  	})
   174  }
   175  
   176  // Deliver sends a stream of blocks to a client after ordering
   177  func (s *server) Deliver(srv ab.AtomicBroadcast_DeliverServer) error {
   178  	logger.Debugf("Starting new Deliver handler")
   179  	defer func() {
   180  		if r := recover(); r != nil {
   181  			logger.Criticalf("Deliver client triggered panic: %s\n%s", r, debug.Stack())
   182  		}
   183  		logger.Debugf("Closing Deliver stream")
   184  	}()
   185  
   186  	policyChecker := func(env *cb.Envelope, channelID string) error {
   187  		chain := s.GetChain(channelID)
   188  		if chain == nil {
   189  			return errors.Errorf("channel %s not found", channelID)
   190  		}
   191  		// In maintenance mode, we typically require the signature of /Channel/Orderer/Readers.
   192  		// This will block Deliver requests from peers (which normally satisfy /Channel/Readers).
   193  		sf := msgprocessor.NewSigFilter(policies.ChannelReaders, policies.ChannelOrdererReaders, chain)
   194  		return sf.Apply(env)
   195  	}
   196  	deliverServer := &deliver.Server{
   197  		PolicyChecker: deliver.PolicyCheckerFunc(policyChecker),
   198  		Receiver: &deliverMsgTracer{
   199  			Receiver: srv,
   200  			msgTracer: msgTracer{
   201  				debug:    s.debug,
   202  				function: "Deliver",
   203  			},
   204  		},
   205  		ResponseSender: &responseSender{
   206  			AtomicBroadcast_DeliverServer: srv,
   207  		},
   208  	}
   209  	return s.dh.Handle(srv.Context(), deliverServer)
   210  }