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 }