mirror of
https://github.com/apernet/hysteria.git
synced 2025-04-03 20:47:38 +03:00
feat: quic-go v0.40.0
This commit is contained in:
parent
9940ea9dd7
commit
c62dc51017
11 changed files with 54 additions and 41 deletions
|
@ -17,7 +17,7 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/apernet/quic-go v0.39.4-0.20231029220436-0faa281e4a77 // indirect
|
||||
github.com/apernet/quic-go v0.40.1-0.20231112225043-e7f3af208dee // indirect
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
|
@ -36,7 +36,7 @@ require (
|
|||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/spf13/afero v1.9.3 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
|
|
|
@ -40,8 +40,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
|||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f h1:uVh0qpEslrWjgzx9vOcyCqsOY3c9kofDZ1n+qaw35ZY=
|
||||
github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f/go.mod h1:xkkq9D4ygcldQQhKS/w9CadiCKwCngU7K9E3DaKahpM=
|
||||
github.com/apernet/quic-go v0.39.4-0.20231029220436-0faa281e4a77 h1:X45zzYXs02HsYVCi6lQOs4sEvzmCXykxcVvAcQypIqM=
|
||||
github.com/apernet/quic-go v0.39.4-0.20231029220436-0faa281e4a77/go.mod h1:UwsoszQlzTm+dBDuFEwWBYt46K56WqlFEN0RWLvQ0rE=
|
||||
github.com/apernet/quic-go v0.40.1-0.20231112225043-e7f3af208dee h1:S3r63crMLzbjjVJjiR+l6oS7Dzli1mYpxXNNlVc/qCc=
|
||||
github.com/apernet/quic-go v0.40.1-0.20231112225043-e7f3af208dee/go.mod h1:9i0/jnY+4NvJA/wdatko2/I8iRf5R0bvZQ6fbk76tRA=
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
|
@ -194,8 +194,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
|
|
|
@ -162,17 +162,13 @@ func (c *clientImpl) openStream() (quic.Stream, error) {
|
|||
func (c *clientImpl) TCP(addr string) (net.Conn, error) {
|
||||
stream, err := c.openStream()
|
||||
if err != nil {
|
||||
if isQUICClosedError(err) {
|
||||
// Connection is dead
|
||||
return nil, coreErrs.ClosedError{}
|
||||
}
|
||||
return nil, err
|
||||
return nil, maybeWrapQUICClosedError(err)
|
||||
}
|
||||
// Send request
|
||||
err = protocol.WriteTCPRequest(stream, addr)
|
||||
if err != nil {
|
||||
_ = stream.Close()
|
||||
return nil, err
|
||||
return nil, maybeWrapQUICClosedError(err)
|
||||
}
|
||||
if c.config.FastOpen {
|
||||
// Don't wait for the response when fast open is enabled.
|
||||
|
@ -189,7 +185,7 @@ func (c *clientImpl) TCP(addr string) (net.Conn, error) {
|
|||
ok, msg, err := protocol.ReadTCPResponse(stream)
|
||||
if err != nil {
|
||||
_ = stream.Close()
|
||||
return nil, err
|
||||
return nil, maybeWrapQUICClosedError(err)
|
||||
}
|
||||
if !ok {
|
||||
_ = stream.Close()
|
||||
|
@ -216,14 +212,15 @@ func (c *clientImpl) Close() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// isQUICClosedError checks if the error returned by OpenStream
|
||||
// indicates that the QUIC connection is permanently closed.
|
||||
func isQUICClosedError(err error) bool {
|
||||
// maybeWrapQUICClosedError checks if the error returned by quic-go
|
||||
// indicates that the QUIC connection is permanently closed,
|
||||
// and if so, wraps it with coreErrs.ClosedError.
|
||||
func maybeWrapQUICClosedError(err error) error {
|
||||
netErr, ok := err.(net.Error)
|
||||
if !ok {
|
||||
return true
|
||||
if ok && !netErr.Temporary() {
|
||||
return coreErrs.ClosedError{Err: err}
|
||||
} else {
|
||||
return !netErr.Temporary()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,7 +280,7 @@ type udpIOImpl struct {
|
|||
|
||||
func (io *udpIOImpl) ReceiveMessage() (*protocol.UDPMessage, error) {
|
||||
for {
|
||||
msg, err := io.Conn.ReceiveMessage(context.Background())
|
||||
msg, err := io.Conn.ReceiveDatagram(context.Background())
|
||||
if err != nil {
|
||||
// Connection error, this will stop the session manager
|
||||
return nil, err
|
||||
|
@ -303,5 +300,5 @@ func (io *udpIOImpl) SendMessage(buf []byte, msg *protocol.UDPMessage) error {
|
|||
// Message larger than buffer, silent drop
|
||||
return nil
|
||||
}
|
||||
return io.Conn.SendMessage(buf[:msgN])
|
||||
return io.Conn.SendDatagram(buf[:msgN])
|
||||
}
|
||||
|
|
|
@ -48,10 +48,20 @@ func (c DialError) Error() string {
|
|||
}
|
||||
|
||||
// ClosedError is returned when the client attempts to use a closed connection.
|
||||
type ClosedError struct{}
|
||||
type ClosedError struct {
|
||||
Err error // Can be nil
|
||||
}
|
||||
|
||||
func (c ClosedError) Error() string {
|
||||
return "connection closed"
|
||||
if c.Err == nil {
|
||||
return "connection closed"
|
||||
} else {
|
||||
return "connection closed: " + c.Err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func (c ClosedError) Unwrap() error {
|
||||
return c.Err
|
||||
}
|
||||
|
||||
// ProtocolError is returned when the server/client runs into an unexpected
|
||||
|
|
|
@ -3,11 +3,11 @@ module github.com/apernet/hysteria/core
|
|||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/apernet/quic-go v0.39.4-0.20231029220436-0faa281e4a77
|
||||
github.com/apernet/quic-go v0.40.1-0.20231112225043-e7f3af208dee
|
||||
github.com/stretchr/testify v1.8.4
|
||||
go.uber.org/goleak v1.2.1
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db
|
||||
golang.org/x/time v0.3.0
|
||||
golang.org/x/time v0.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -19,7 +19,7 @@ require (
|
|||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/stretchr/objx v0.5.0 // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
|
|
12
core/go.sum
12
core/go.sum
|
@ -1,5 +1,5 @@
|
|||
github.com/apernet/quic-go v0.39.4-0.20231029220436-0faa281e4a77 h1:X45zzYXs02HsYVCi6lQOs4sEvzmCXykxcVvAcQypIqM=
|
||||
github.com/apernet/quic-go v0.39.4-0.20231029220436-0faa281e4a77/go.mod h1:UwsoszQlzTm+dBDuFEwWBYt46K56WqlFEN0RWLvQ0rE=
|
||||
github.com/apernet/quic-go v0.40.1-0.20231112225043-e7f3af208dee h1:S3r63crMLzbjjVJjiR+l6oS7Dzli1mYpxXNNlVc/qCc=
|
||||
github.com/apernet/quic-go v0.40.1-0.20231112225043-e7f3af208dee/go.mod h1:9i0/jnY+4NvJA/wdatko2/I8iRf5R0bvZQ6fbk76tRA=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
|
@ -34,8 +34,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
|
@ -62,8 +62,8 @@ golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
|||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
|
||||
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc=
|
||||
golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
@ -226,17 +226,21 @@ func TestClientServerServerShutdown(t *testing.T) {
|
|||
c, err := client.NewClient(&client.Config{
|
||||
ServerAddr: udpAddr,
|
||||
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
|
||||
QUICConfig: client.QUICConfig{
|
||||
MaxIdleTimeout: 4 * time.Second,
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Close the server - expect the client to return ClosedError for both TCP & UDP calls.
|
||||
_ = s.Close()
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
_, err = c.TCP("whatever")
|
||||
_, ok := err.(errors.ClosedError)
|
||||
assert.True(t, ok)
|
||||
|
||||
time.Sleep(1 * time.Second) // Allow some time for the error to be propagated to the UDP session manager
|
||||
|
||||
_, err = c.UDP()
|
||||
_, ok = err.(errors.ClosedError)
|
||||
assert.True(t, ok)
|
||||
|
|
|
@ -258,7 +258,7 @@ type udpIOImpl struct {
|
|||
|
||||
func (io *udpIOImpl) ReceiveMessage() (*protocol.UDPMessage, error) {
|
||||
for {
|
||||
msg, err := io.Conn.ReceiveMessage(context.Background())
|
||||
msg, err := io.Conn.ReceiveDatagram(context.Background())
|
||||
if err != nil {
|
||||
// Connection error, this will stop the session manager
|
||||
return nil, err
|
||||
|
@ -294,7 +294,7 @@ func (io *udpIOImpl) SendMessage(buf []byte, msg *protocol.UDPMessage) error {
|
|||
// Message larger than buffer, silent drop
|
||||
return nil
|
||||
}
|
||||
return io.Conn.SendMessage(buf[:msgN])
|
||||
return io.Conn.SendDatagram(buf[:msgN])
|
||||
}
|
||||
|
||||
func (io *udpIOImpl) UDP(reqAddr string) (UDPConn, error) {
|
||||
|
|
|
@ -15,7 +15,7 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/apernet/quic-go v0.39.4-0.20231029220436-0faa281e4a77 // indirect
|
||||
github.com/apernet/quic-go v0.40.1-0.20231112225043-e7f3af208dee // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
|
@ -23,7 +23,7 @@ require (
|
|||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/stretchr/objx v0.5.0 // indirect
|
||||
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
github.com/apernet/quic-go v0.39.4-0.20231029220436-0faa281e4a77 h1:X45zzYXs02HsYVCi6lQOs4sEvzmCXykxcVvAcQypIqM=
|
||||
github.com/apernet/quic-go v0.39.4-0.20231029220436-0faa281e4a77/go.mod h1:UwsoszQlzTm+dBDuFEwWBYt46K56WqlFEN0RWLvQ0rE=
|
||||
github.com/apernet/quic-go v0.40.1-0.20231112225043-e7f3af208dee h1:S3r63crMLzbjjVJjiR+l6oS7Dzli1mYpxXNNlVc/qCc=
|
||||
github.com/apernet/quic-go v0.40.1-0.20231112225043-e7f3af208dee/go.mod h1:9i0/jnY+4NvJA/wdatko2/I8iRf5R0bvZQ6fbk76tRA=
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
|
||||
github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
|
@ -40,8 +40,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||
|
|
|
@ -282,6 +282,8 @@ golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
|||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue