github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/error.go (about) 1 package sync 2 3 import ( 4 "bytes" 5 "errors" 6 7 libp2pcore "github.com/libp2p/go-libp2p-core" 8 "github.com/libp2p/go-libp2p-core/mux" 9 "github.com/libp2p/go-libp2p-core/network" 10 "github.com/prysmaticlabs/prysm/beacon-chain/p2p" 11 "github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder" 12 "github.com/prysmaticlabs/prysm/beacon-chain/p2p/types" 13 "github.com/prysmaticlabs/prysm/shared/params" 14 "github.com/sirupsen/logrus" 15 ) 16 17 var responseCodeSuccess = byte(0x00) 18 var responseCodeInvalidRequest = byte(0x01) 19 var responseCodeServerError = byte(0x02) 20 21 func (s *Service) generateErrorResponse(code byte, reason string) ([]byte, error) { 22 return createErrorResponse(code, reason, s.cfg.P2P) 23 } 24 25 // ReadStatusCode response from a RPC stream. 26 func ReadStatusCode(stream network.Stream, encoding encoder.NetworkEncoding) (uint8, string, error) { 27 // Set ttfb deadline. 28 SetStreamReadDeadline(stream, params.BeaconNetworkConfig().TtfbTimeout) 29 b := make([]byte, 1) 30 _, err := stream.Read(b) 31 if err != nil { 32 return 0, "", err 33 } 34 35 if b[0] == responseCodeSuccess { 36 // Set response deadline on a successful response code. 37 SetStreamReadDeadline(stream, params.BeaconNetworkConfig().RespTimeout) 38 39 return 0, "", nil 40 } 41 42 // Set response deadline, when reading error message. 43 SetStreamReadDeadline(stream, params.BeaconNetworkConfig().RespTimeout) 44 msg := &types.ErrorMessage{} 45 if err := encoding.DecodeWithMaxLength(stream, msg); err != nil { 46 return 0, "", err 47 } 48 49 return b[0], string(*msg), nil 50 } 51 52 func writeErrorResponseToStream(responseCode byte, reason string, stream libp2pcore.Stream, encoder p2p.EncodingProvider) { 53 resp, err := createErrorResponse(responseCode, reason, encoder) 54 if err != nil { 55 log.WithError(err).Debug("Could not generate a response error") 56 } else if _, err := stream.Write(resp); err != nil { 57 log.WithError(err).Debugf("Could not write to stream") 58 } else { 59 // If sending the error message succeeded, close to send an EOF. 60 closeStream(stream, log) 61 } 62 } 63 64 func createErrorResponse(code byte, reason string, encoder p2p.EncodingProvider) ([]byte, error) { 65 buf := bytes.NewBuffer([]byte{code}) 66 errMsg := types.ErrorMessage(reason) 67 if _, err := encoder.Encoding().EncodeWithMaxLength(buf, &errMsg); err != nil { 68 return nil, err 69 } 70 71 return buf.Bytes(), nil 72 } 73 74 // reads data from the stream without applying any timeouts. 75 func readStatusCodeNoDeadline(stream network.Stream, encoding encoder.NetworkEncoding) (uint8, string, error) { 76 b := make([]byte, 1) 77 _, err := stream.Read(b) 78 if err != nil { 79 return 0, "", err 80 } 81 82 if b[0] == responseCodeSuccess { 83 return 0, "", nil 84 } 85 86 msg := &types.ErrorMessage{} 87 if err := encoding.DecodeWithMaxLength(stream, msg); err != nil { 88 return 0, "", err 89 } 90 91 return b[0], string(*msg), nil 92 } 93 94 // only returns true for errors that are valid (no resets or expectedEOF errors). 95 func isValidStreamError(err error) bool { 96 // check the error message itself as well as libp2p doesn't currently 97 // return the correct error type from Close{Read,Write,}. 98 return err != nil && !errors.Is(err, mux.ErrReset) && err.Error() != mux.ErrReset.Error() 99 } 100 101 func closeStream(stream network.Stream, log *logrus.Entry) { 102 if err := stream.Close(); isValidStreamError(err) { 103 log.WithError(err).Debugf("Could not reset stream with protocol %s", stream.Protocol()) 104 } 105 } 106 107 func closeStreamAndWait(stream network.Stream, log *logrus.Entry) { 108 if err := stream.CloseWrite(); err != nil { 109 _err := stream.Reset() 110 _ = _err 111 if isValidStreamError(err) { 112 log.WithError(err).Debugf("Could not reset stream with protocol %s", stream.Protocol()) 113 } 114 return 115 } 116 // Wait for the remote side to respond. 117 // 118 // 1. On success, we expect to read an EOF (remote side received our 119 // response and closed the stream. 120 // 2. On failure (e.g., disconnect), we expect to receive an error. 121 // 3. If the remote side misbehaves, we may receive data. 122 // 123 // However, regardless of what happens, we just close the stream and 124 // walk away. We only read to wait for a response, we close regardless. 125 _, _err := stream.Read([]byte{0}) 126 _ = _err 127 _err = stream.Close() 128 _ = _err 129 }