From 6b9077288aa6c08de75ffa53f35267180e11ce4d Mon Sep 17 00:00:00 2001 From: Evan Lin Date: Thu, 18 Jul 2019 16:36:31 +0800 Subject: [PATCH 1/3] check if structure is non-nil before closing. --- pkg/app/app.go | 5 +- vendor/github.com/skycoin/dmsg/client.go | 10 +- vendor/github.com/skycoin/dmsg/transport.go | 4 + vendor/golang.org/x/net/nettest/conntest.go | 464 ++++++++++++++++++ vendor/golang.org/x/net/nettest/nettest.go | 345 +++++++++++++ .../golang.org/x/net/nettest/nettest_stub.go | 11 + .../golang.org/x/net/nettest/nettest_unix.go | 21 + .../x/net/nettest/nettest_windows.go | 26 + vendor/modules.txt | 1 + 9 files changed, 885 insertions(+), 2 deletions(-) create mode 100644 vendor/golang.org/x/net/nettest/conntest.go create mode 100644 vendor/golang.org/x/net/nettest/nettest.go create mode 100644 vendor/golang.org/x/net/nettest/nettest_stub.go create mode 100644 vendor/golang.org/x/net/nettest/nettest_unix.go create mode 100644 vendor/golang.org/x/net/nettest/nettest_windows.go diff --git a/pkg/app/app.go b/pkg/app/app.go index bf600502f..e2be01015 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -243,7 +243,10 @@ func (app *App) closeConn(data []byte) error { delete(app.conns, loop) app.mu.Unlock() - return conn.Close() + if conn != nil { + return conn.Close() + } + return nil } func (app *App) confirmLoop(data []byte) error { diff --git a/vendor/github.com/skycoin/dmsg/client.go b/vendor/github.com/skycoin/dmsg/client.go index 0ec707809..bd07446ed 100644 --- a/vendor/github.com/skycoin/dmsg/client.go +++ b/vendor/github.com/skycoin/dmsg/client.go @@ -256,14 +256,18 @@ func (c *ClientConn) DialTransport(ctx context.Context, clientPK cipher.PubKey) } func (c *ClientConn) close() (closed bool) { + if c == nil { + return false + } c.once.Do(func() { closed = true c.log.WithField("remoteServer", c.remoteSrv).Infoln("ClosingConnection") close(c.done) c.mx.Lock() for _, tp := range c.tps { + // Nil check is required here to keep 8192 running goroutines limit in tests with -race flag. if tp != nil { - go tp.Close() //nolint:errcheck + go tp.Close() // nolint:errcheck } } _ = c.Conn.Close() //nolint:errcheck @@ -539,6 +543,10 @@ func (c *Client) Type() string { // Close closes the dms_client and associated connections. // TODO(evaninjin): proper error handling. func (c *Client) Close() error { + if c == nil { + return nil + } + c.once.Do(func() { close(c.done) for { diff --git a/vendor/github.com/skycoin/dmsg/transport.go b/vendor/github.com/skycoin/dmsg/transport.go index 990966d0f..cc2724428 100644 --- a/vendor/github.com/skycoin/dmsg/transport.go +++ b/vendor/github.com/skycoin/dmsg/transport.go @@ -85,6 +85,10 @@ func (tp *Transport) serve() (started bool) { // 4. But as, under the mutexes protecting `inCh`/`bufCh`, checking `done` comes first, // and we know that `done` is closed before `inCh`/`bufCh`, we can guarantee that it avoids writing to closed chan. func (tp *Transport) close() (closed bool) { + if tp == nil { + return false + } + tp.doneOnce.Do(func() { closed = true diff --git a/vendor/golang.org/x/net/nettest/conntest.go b/vendor/golang.org/x/net/nettest/conntest.go new file mode 100644 index 000000000..39cc6a631 --- /dev/null +++ b/vendor/golang.org/x/net/nettest/conntest.go @@ -0,0 +1,464 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package nettest + +import ( + "bytes" + "encoding/binary" + "io" + "io/ioutil" + "math/rand" + "net" + "runtime" + "sync" + "testing" + "time" +) + +// MakePipe creates a connection between two endpoints and returns the pair +// as c1 and c2, such that anything written to c1 is read by c2 and vice-versa. +// The stop function closes all resources, including c1, c2, and the underlying +// net.Listener (if there is one), and should not be nil. +type MakePipe func() (c1, c2 net.Conn, stop func(), err error) + +// TestConn tests that a net.Conn implementation properly satisfies the interface. +// The tests should not produce any false positives, but may experience +// false negatives. Thus, some issues may only be detected when the test is +// run multiple times. For maximal effectiveness, run the tests under the +// race detector. +func TestConn(t *testing.T, mp MakePipe) { + t.Run("BasicIO", func(t *testing.T) { timeoutWrapper(t, mp, testBasicIO) }) + t.Run("PingPong", func(t *testing.T) { timeoutWrapper(t, mp, testPingPong) }) + t.Run("RacyRead", func(t *testing.T) { timeoutWrapper(t, mp, testRacyRead) }) + t.Run("RacyWrite", func(t *testing.T) { timeoutWrapper(t, mp, testRacyWrite) }) + t.Run("ReadTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testReadTimeout) }) + t.Run("WriteTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testWriteTimeout) }) + t.Run("PastTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testPastTimeout) }) + t.Run("PresentTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testPresentTimeout) }) + t.Run("FutureTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testFutureTimeout) }) + t.Run("CloseTimeout", func(t *testing.T) { timeoutWrapper(t, mp, testCloseTimeout) }) + t.Run("ConcurrentMethods", func(t *testing.T) { timeoutWrapper(t, mp, testConcurrentMethods) }) +} + +type connTester func(t *testing.T, c1, c2 net.Conn) + +func timeoutWrapper(t *testing.T, mp MakePipe, f connTester) { + t.Helper() + c1, c2, stop, err := mp() + if err != nil { + t.Fatalf("unable to make pipe: %v", err) + } + var once sync.Once + defer once.Do(func() { stop() }) + timer := time.AfterFunc(time.Minute, func() { + once.Do(func() { + t.Error("test timed out; terminating pipe") + stop() + }) + }) + defer timer.Stop() + f(t, c1, c2) +} + +// testBasicIO tests that the data sent on c1 is properly received on c2. +func testBasicIO(t *testing.T, c1, c2 net.Conn) { + want := make([]byte, 1<<20) + rand.New(rand.NewSource(0)).Read(want) + + dataCh := make(chan []byte) + go func() { + rd := bytes.NewReader(want) + if err := chunkedCopy(c1, rd); err != nil { + t.Errorf("unexpected c1.Write error: %v", err) + } + if err := c1.Close(); err != nil { + t.Errorf("unexpected c1.Close error: %v", err) + } + }() + + go func() { + wr := new(bytes.Buffer) + if err := chunkedCopy(wr, c2); err != nil { + t.Errorf("unexpected c2.Read error: %v", err) + } + if err := c2.Close(); err != nil { + t.Errorf("unexpected c2.Close error: %v", err) + } + dataCh <- wr.Bytes() + }() + + if got := <-dataCh; !bytes.Equal(got, want) { + t.Error("transmitted data differs") + } +} + +// testPingPong tests that the two endpoints can synchronously send data to +// each other in a typical request-response pattern. +func testPingPong(t *testing.T, c1, c2 net.Conn) { + var wg sync.WaitGroup + defer wg.Wait() + + pingPonger := func(c net.Conn) { + defer wg.Done() + buf := make([]byte, 8) + var prev uint64 + for { + if _, err := io.ReadFull(c, buf); err != nil { + if err == io.EOF { + break + } + t.Errorf("unexpected Read error: %v", err) + } + + v := binary.LittleEndian.Uint64(buf) + binary.LittleEndian.PutUint64(buf, v+1) + if prev != 0 && prev+2 != v { + t.Errorf("mismatching value: got %d, want %d", v, prev+2) + } + prev = v + if v == 1000 { + break + } + + if _, err := c.Write(buf); err != nil { + t.Errorf("unexpected Write error: %v", err) + break + } + } + if err := c.Close(); err != nil { + t.Errorf("unexpected Close error: %v", err) + } + } + + wg.Add(2) + go pingPonger(c1) + go pingPonger(c2) + + // Start off the chain reaction. + if _, err := c1.Write(make([]byte, 8)); err != nil { + t.Errorf("unexpected c1.Write error: %v", err) + } +} + +// testRacyRead tests that it is safe to mutate the input Read buffer +// immediately after cancelation has occurred. +func testRacyRead(t *testing.T, c1, c2 net.Conn) { + go chunkedCopy(c2, rand.New(rand.NewSource(0))) + + var wg sync.WaitGroup + defer wg.Wait() + + c1.SetReadDeadline(time.Now().Add(time.Millisecond)) + for i := 0; i < 10; i++ { + wg.Add(1) + go func() { + defer wg.Done() + + b1 := make([]byte, 1024) + b2 := make([]byte, 1024) + for j := 0; j < 100; j++ { + _, err := c1.Read(b1) + copy(b1, b2) // Mutate b1 to trigger potential race + if err != nil { + checkForTimeoutError(t, err) + c1.SetReadDeadline(time.Now().Add(time.Millisecond)) + } + } + }() + } +} + +// testRacyWrite tests that it is safe to mutate the input Write buffer +// immediately after cancelation has occurred. +func testRacyWrite(t *testing.T, c1, c2 net.Conn) { + go chunkedCopy(ioutil.Discard, c2) + + var wg sync.WaitGroup + defer wg.Wait() + + c1.SetWriteDeadline(time.Now().Add(time.Millisecond)) + for i := 0; i < 10; i++ { + wg.Add(1) + go func() { + defer wg.Done() + + b1 := make([]byte, 1024) + b2 := make([]byte, 1024) + for j := 0; j < 100; j++ { + _, err := c1.Write(b1) + copy(b1, b2) // Mutate b1 to trigger potential race + if err != nil { + checkForTimeoutError(t, err) + c1.SetWriteDeadline(time.Now().Add(time.Millisecond)) + } + } + }() + } +} + +// testReadTimeout tests that Read timeouts do not affect Write. +func testReadTimeout(t *testing.T, c1, c2 net.Conn) { + go chunkedCopy(ioutil.Discard, c2) + + c1.SetReadDeadline(aLongTimeAgo) + _, err := c1.Read(make([]byte, 1024)) + checkForTimeoutError(t, err) + if _, err := c1.Write(make([]byte, 1024)); err != nil { + t.Errorf("unexpected Write error: %v", err) + } +} + +// testWriteTimeout tests that Write timeouts do not affect Read. +func testWriteTimeout(t *testing.T, c1, c2 net.Conn) { + go chunkedCopy(c2, rand.New(rand.NewSource(0))) + + c1.SetWriteDeadline(aLongTimeAgo) + _, err := c1.Write(make([]byte, 1024)) + checkForTimeoutError(t, err) + if _, err := c1.Read(make([]byte, 1024)); err != nil { + t.Errorf("unexpected Read error: %v", err) + } +} + +// testPastTimeout tests that a deadline set in the past immediately times out +// Read and Write requests. +func testPastTimeout(t *testing.T, c1, c2 net.Conn) { + go chunkedCopy(c2, c2) + + testRoundtrip(t, c1) + + c1.SetDeadline(aLongTimeAgo) + n, err := c1.Write(make([]byte, 1024)) + if n != 0 { + t.Errorf("unexpected Write count: got %d, want 0", n) + } + checkForTimeoutError(t, err) + n, err = c1.Read(make([]byte, 1024)) + if n != 0 { + t.Errorf("unexpected Read count: got %d, want 0", n) + } + checkForTimeoutError(t, err) + + testRoundtrip(t, c1) +} + +// testPresentTimeout tests that a past deadline set while there are pending +// Read and Write operations immediately times out those operations. +func testPresentTimeout(t *testing.T, c1, c2 net.Conn) { + var wg sync.WaitGroup + defer wg.Wait() + wg.Add(3) + + deadlineSet := make(chan bool, 1) + go func() { + defer wg.Done() + time.Sleep(100 * time.Millisecond) + deadlineSet <- true + c1.SetReadDeadline(aLongTimeAgo) + c1.SetWriteDeadline(aLongTimeAgo) + }() + go func() { + defer wg.Done() + n, err := c1.Read(make([]byte, 1024)) + if n != 0 { + t.Errorf("unexpected Read count: got %d, want 0", n) + } + checkForTimeoutError(t, err) + if len(deadlineSet) == 0 { + t.Error("Read timed out before deadline is set") + } + }() + go func() { + defer wg.Done() + var err error + for err == nil { + _, err = c1.Write(make([]byte, 1024)) + } + checkForTimeoutError(t, err) + if len(deadlineSet) == 0 { + t.Error("Write timed out before deadline is set") + } + }() +} + +// testFutureTimeout tests that a future deadline will eventually time out +// Read and Write operations. +func testFutureTimeout(t *testing.T, c1, c2 net.Conn) { + var wg sync.WaitGroup + wg.Add(2) + + c1.SetDeadline(time.Now().Add(100 * time.Millisecond)) + go func() { + defer wg.Done() + _, err := c1.Read(make([]byte, 1024)) + checkForTimeoutError(t, err) + }() + go func() { + defer wg.Done() + var err error + for err == nil { + _, err = c1.Write(make([]byte, 1024)) + } + checkForTimeoutError(t, err) + }() + wg.Wait() + + go chunkedCopy(c2, c2) + resyncConn(t, c1) + testRoundtrip(t, c1) +} + +// testCloseTimeout tests that calling Close immediately times out pending +// Read and Write operations. +func testCloseTimeout(t *testing.T, c1, c2 net.Conn) { + go chunkedCopy(c2, c2) + + var wg sync.WaitGroup + defer wg.Wait() + wg.Add(3) + + // Test for cancelation upon connection closure. + c1.SetDeadline(neverTimeout) + go func() { + defer wg.Done() + time.Sleep(100 * time.Millisecond) + c1.Close() + }() + go func() { + defer wg.Done() + var err error + buf := make([]byte, 1024) + for err == nil { + _, err = c1.Read(buf) + } + }() + go func() { + defer wg.Done() + var err error + buf := make([]byte, 1024) + for err == nil { + _, err = c1.Write(buf) + } + }() +} + +// testConcurrentMethods tests that the methods of net.Conn can safely +// be called concurrently. +func testConcurrentMethods(t *testing.T, c1, c2 net.Conn) { + if runtime.GOOS == "plan9" { + t.Skip("skipping on plan9; see https://golang.org/issue/20489") + } + go chunkedCopy(c2, c2) + + // The results of the calls may be nonsensical, but this should + // not trigger a race detector warning. + var wg sync.WaitGroup + for i := 0; i < 100; i++ { + wg.Add(7) + go func() { + defer wg.Done() + c1.Read(make([]byte, 1024)) + }() + go func() { + defer wg.Done() + c1.Write(make([]byte, 1024)) + }() + go func() { + defer wg.Done() + c1.SetDeadline(time.Now().Add(10 * time.Millisecond)) + }() + go func() { + defer wg.Done() + c1.SetReadDeadline(aLongTimeAgo) + }() + go func() { + defer wg.Done() + c1.SetWriteDeadline(aLongTimeAgo) + }() + go func() { + defer wg.Done() + c1.LocalAddr() + }() + go func() { + defer wg.Done() + c1.RemoteAddr() + }() + } + wg.Wait() // At worst, the deadline is set 10ms into the future + + resyncConn(t, c1) + testRoundtrip(t, c1) +} + +// checkForTimeoutError checks that the error satisfies the Error interface +// and that Timeout returns true. +func checkForTimeoutError(t *testing.T, err error) { + t.Helper() + if nerr, ok := err.(net.Error); ok { + if !nerr.Timeout() { + t.Errorf("err.Timeout() = false, want true") + } + } else { + t.Errorf("got %T, want net.Error", err) + } +} + +// testRoundtrip writes something into c and reads it back. +// It assumes that everything written into c is echoed back to itself. +func testRoundtrip(t *testing.T, c net.Conn) { + t.Helper() + if err := c.SetDeadline(neverTimeout); err != nil { + t.Errorf("roundtrip SetDeadline error: %v", err) + } + + const s = "Hello, world!" + buf := []byte(s) + if _, err := c.Write(buf); err != nil { + t.Errorf("roundtrip Write error: %v", err) + } + if _, err := io.ReadFull(c, buf); err != nil { + t.Errorf("roundtrip Read error: %v", err) + } + if string(buf) != s { + t.Errorf("roundtrip data mismatch: got %q, want %q", buf, s) + } +} + +// resyncConn resynchronizes the connection into a sane state. +// It assumes that everything written into c is echoed back to itself. +// It assumes that 0xff is not currently on the wire or in the read buffer. +func resyncConn(t *testing.T, c net.Conn) { + t.Helper() + c.SetDeadline(neverTimeout) + errCh := make(chan error) + go func() { + _, err := c.Write([]byte{0xff}) + errCh <- err + }() + buf := make([]byte, 1024) + for { + n, err := c.Read(buf) + if n > 0 && bytes.IndexByte(buf[:n], 0xff) == n-1 { + break + } + if err != nil { + t.Errorf("unexpected Read error: %v", err) + break + } + } + if err := <-errCh; err != nil { + t.Errorf("unexpected Write error: %v", err) + } +} + +// chunkedCopy copies from r to w in fixed-width chunks to avoid +// causing a Write that exceeds the maximum packet size for packet-based +// connections like "unixpacket". +// We assume that the maximum packet size is at least 1024. +func chunkedCopy(w io.Writer, r io.Reader) error { + b := make([]byte, 1024) + _, err := io.CopyBuffer(struct{ io.Writer }{w}, struct{ io.Reader }{r}, b) + return err +} diff --git a/vendor/golang.org/x/net/nettest/nettest.go b/vendor/golang.org/x/net/nettest/nettest.go new file mode 100644 index 000000000..717bbb064 --- /dev/null +++ b/vendor/golang.org/x/net/nettest/nettest.go @@ -0,0 +1,345 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package nettest provides utilities for network testing. +package nettest + +import ( + "errors" + "fmt" + "io/ioutil" + "net" + "os" + "os/exec" + "runtime" + "strconv" + "strings" + "sync" + "time" +) + +var ( + stackOnce sync.Once + ipv4Enabled bool + ipv6Enabled bool + rawSocketSess bool + aixTechLvl int + + aLongTimeAgo = time.Unix(233431200, 0) + neverTimeout = time.Time{} + + errNoAvailableInterface = errors.New("no available interface") + errNoAvailableAddress = errors.New("no available address") +) + +func probeStack() { + if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil { + ln.Close() + ipv4Enabled = true + } + if ln, err := net.Listen("tcp6", "[::1]:0"); err == nil { + ln.Close() + ipv6Enabled = true + } + rawSocketSess = supportsRawSocket() + if runtime.GOOS == "aix" { + out, err := exec.Command("oslevel", "-s").Output() + if err == nil { + aixTechLvl, _ = strconv.Atoi(string(out[5:7])) + } + } +} + +func aixTechLevel() int { + stackOnce.Do(probeStack) + return aixTechLvl +} + +// SupportsIPv4 reports whether the platform supports IPv4 networking +// functionality. +func SupportsIPv4() bool { + stackOnce.Do(probeStack) + return ipv4Enabled +} + +// SupportsIPv6 reports whether the platform supports IPv6 networking +// functionality. +func SupportsIPv6() bool { + stackOnce.Do(probeStack) + return ipv6Enabled +} + +// SupportsRawSocket reports whether the current session is available +// to use raw sockets. +func SupportsRawSocket() bool { + stackOnce.Do(probeStack) + return rawSocketSess +} + +// TestableNetwork reports whether network is testable on the current +// platform configuration. +// +// See func Dial of the standard library for the supported networks. +func TestableNetwork(network string) bool { + ss := strings.Split(network, ":") + switch ss[0] { + case "ip+nopriv": + // This is an internal network name for testing on the + // package net of the standard library. + switch runtime.GOOS { + case "android", "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + return false + case "darwin": + // iOS doesn't support it. + if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { + return false + } + } + case "ip", "ip4", "ip6": + switch runtime.GOOS { + case "fuchsia", "hurd", "js", "nacl", "plan9": + return false + default: + if os.Getuid() != 0 { + return false + } + } + case "unix", "unixgram": + switch runtime.GOOS { + case "android", "fuchsia", "hurd", "js", "nacl", "plan9", "windows": + return false + case "aix": + // Unix network isn't properly working on AIX + // 7.2 with Technical Level < 2. + if aixTechLevel() < 2 { + return false + } + return true + case "darwin": + // iOS does not support unix, unixgram. + if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { + return false + } + } + case "unixpacket": + switch runtime.GOOS { + case "aix", "android", "fuchsia", "hurd", "darwin", "js", "nacl", "plan9", "windows": + return false + case "netbsd": + // It passes on amd64 at least. 386 fails + // (Issue 22927). arm is unknown. + if runtime.GOARCH == "386" { + return false + } + } + } + switch ss[0] { + case "tcp4", "udp4", "ip4": + return SupportsIPv4() + case "tcp6", "udp6", "ip6": + return SupportsIPv6() + } + return true +} + +// TestableAddress reports whether address of network is testable on +// the current platform configuration. +func TestableAddress(network, address string) bool { + switch ss := strings.Split(network, ":"); ss[0] { + case "unix", "unixgram", "unixpacket": + // Abstract unix domain sockets, a Linux-ism. + if address[0] == '@' && runtime.GOOS != "linux" { + return false + } + } + return true +} + +// NewLocalListener returns a listener which listens to a loopback IP +// address or local file system path. +// +// The provided network must be "tcp", "tcp4", "tcp6", "unix" or +// "unixpacket". +func NewLocalListener(network string) (net.Listener, error) { + switch network { + case "tcp": + if SupportsIPv4() { + if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil { + return ln, nil + } + } + if SupportsIPv6() { + return net.Listen("tcp6", "[::1]:0") + } + case "tcp4": + if SupportsIPv4() { + return net.Listen("tcp4", "127.0.0.1:0") + } + case "tcp6": + if SupportsIPv6() { + return net.Listen("tcp6", "[::1]:0") + } + case "unix", "unixpacket": + path, err := LocalPath() + if err != nil { + return nil, err + } + return net.Listen(network, path) + } + return nil, fmt.Errorf("%s is not supported on %s/%s", network, runtime.GOOS, runtime.GOARCH) +} + +// NewLocalPacketListener returns a packet listener which listens to a +// loopback IP address or local file system path. +// +// The provided network must be "udp", "udp4", "udp6" or "unixgram". +func NewLocalPacketListener(network string) (net.PacketConn, error) { + switch network { + case "udp": + if SupportsIPv4() { + if c, err := net.ListenPacket("udp4", "127.0.0.1:0"); err == nil { + return c, nil + } + } + if SupportsIPv6() { + return net.ListenPacket("udp6", "[::1]:0") + } + case "udp4": + if SupportsIPv4() { + return net.ListenPacket("udp4", "127.0.0.1:0") + } + case "udp6": + if SupportsIPv6() { + return net.ListenPacket("udp6", "[::1]:0") + } + case "unixgram": + path, err := LocalPath() + if err != nil { + return nil, err + } + return net.ListenPacket(network, path) + } + return nil, fmt.Errorf("%s is not supported on %s/%s", network, runtime.GOOS, runtime.GOARCH) +} + +// LocalPath returns a local path that can be used for Unix-domain +// protocol testing. +func LocalPath() (string, error) { + f, err := ioutil.TempFile("", "go-nettest") + if err != nil { + return "", err + } + path := f.Name() + f.Close() + os.Remove(path) + return path, nil +} + +// MulticastSource returns a unicast IP address on ifi when ifi is an +// IP multicast-capable network interface. +// +// The provided network must be "ip", "ip4" or "ip6". +func MulticastSource(network string, ifi *net.Interface) (net.IP, error) { + switch network { + case "ip", "ip4", "ip6": + default: + return nil, errNoAvailableAddress + } + if ifi == nil || ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 { + return nil, errNoAvailableAddress + } + ip, ok := hasRoutableIP(network, ifi) + if !ok { + return nil, errNoAvailableAddress + } + return ip, nil +} + +// LoopbackInterface returns an available logical network interface +// for loopback test. +func LoopbackInterface() (*net.Interface, error) { + ift, err := net.Interfaces() + if err != nil { + return nil, errNoAvailableInterface + } + for _, ifi := range ift { + if ifi.Flags&net.FlagLoopback != 0 && ifi.Flags&net.FlagUp != 0 { + return &ifi, nil + } + } + return nil, errNoAvailableInterface +} + +// RoutedInterface returns a network interface that can route IP +// traffic and satisfies flags. +// +// The provided network must be "ip", "ip4" or "ip6". +func RoutedInterface(network string, flags net.Flags) (*net.Interface, error) { + switch network { + case "ip", "ip4", "ip6": + default: + return nil, errNoAvailableInterface + } + ift, err := net.Interfaces() + if err != nil { + return nil, errNoAvailableInterface + } + for _, ifi := range ift { + if ifi.Flags&flags != flags { + continue + } + if _, ok := hasRoutableIP(network, &ifi); !ok { + continue + } + return &ifi, nil + } + return nil, errNoAvailableInterface +} + +func hasRoutableIP(network string, ifi *net.Interface) (net.IP, bool) { + ifat, err := ifi.Addrs() + if err != nil { + return nil, false + } + for _, ifa := range ifat { + switch ifa := ifa.(type) { + case *net.IPAddr: + if ip, ok := routableIP(network, ifa.IP); ok { + return ip, true + } + case *net.IPNet: + if ip, ok := routableIP(network, ifa.IP); ok { + return ip, true + } + } + } + return nil, false +} + +func routableIP(network string, ip net.IP) (net.IP, bool) { + if !ip.IsLoopback() && !ip.IsLinkLocalUnicast() && !ip.IsGlobalUnicast() { + return nil, false + } + switch network { + case "ip4": + if ip := ip.To4(); ip != nil { + return ip, true + } + case "ip6": + if ip.IsLoopback() { // addressing scope of the loopback address depends on each implementation + return nil, false + } + if ip := ip.To16(); ip != nil && ip.To4() == nil { + return ip, true + } + default: + if ip := ip.To4(); ip != nil { + return ip, true + } + if ip := ip.To16(); ip != nil { + return ip, true + } + } + return nil, false +} diff --git a/vendor/golang.org/x/net/nettest/nettest_stub.go b/vendor/golang.org/x/net/nettest/nettest_stub.go new file mode 100644 index 000000000..2bb8c0576 --- /dev/null +++ b/vendor/golang.org/x/net/nettest/nettest_stub.go @@ -0,0 +1,11 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows + +package nettest + +func supportsRawSocket() bool { + return false +} diff --git a/vendor/golang.org/x/net/nettest/nettest_unix.go b/vendor/golang.org/x/net/nettest/nettest_unix.go new file mode 100644 index 000000000..afff744e8 --- /dev/null +++ b/vendor/golang.org/x/net/nettest/nettest_unix.go @@ -0,0 +1,21 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris + +package nettest + +import "syscall" + +func supportsRawSocket() bool { + for _, af := range []int{syscall.AF_INET, syscall.AF_INET6} { + s, err := syscall.Socket(af, syscall.SOCK_RAW, 0) + if err != nil { + continue + } + syscall.Close(s) + return true + } + return false +} diff --git a/vendor/golang.org/x/net/nettest/nettest_windows.go b/vendor/golang.org/x/net/nettest/nettest_windows.go new file mode 100644 index 000000000..4939964db --- /dev/null +++ b/vendor/golang.org/x/net/nettest/nettest_windows.go @@ -0,0 +1,26 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package nettest + +import "syscall" + +func supportsRawSocket() bool { + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx: + // Note: To use a socket of type SOCK_RAW requires administrative privileges. + // Users running Winsock applications that use raw sockets must be a member of + // the Administrators group on the local computer, otherwise raw socket calls + // will fail with an error code of WSAEACCES. On Windows Vista and later, access + // for raw sockets is enforced at socket creation. In earlier versions of Windows, + // access for raw sockets is enforced during other socket operations. + for _, af := range []int{syscall.AF_INET, syscall.AF_INET6} { + s, err := syscall.Socket(af, syscall.SOCK_RAW, 0) + if err != nil { + continue + } + syscall.Closesocket(s) + return true + } + return false +} diff --git a/vendor/modules.txt b/vendor/modules.txt index c7c61f234..5d9179f82 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -95,6 +95,7 @@ golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 # golang.org/x/net v0.0.0-20190620200207-3b0461eec859 golang.org/x/net/context +golang.org/x/net/nettest golang.org/x/net/proxy golang.org/x/net/internal/socks # golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb From 94f01d1f8f18516a09251647c6f65391ec8a2502 Mon Sep 17 00:00:00 2001 From: Evan Lin Date: Thu, 18 Jul 2019 17:28:18 +0800 Subject: [PATCH 2/3] Fix data race with err variable. --- pkg/transport/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/transport/manager.go b/pkg/transport/manager.go index 9b9e7650c..d359fac1c 100644 --- a/pkg/transport/manager.go +++ b/pkg/transport/manager.go @@ -336,7 +336,7 @@ func (tm *Manager) acceptTransport(ctx context.Context, factory Factory) (*Manag entry, err := settlementResponderHandshake().Do(tm, tr, 30*time.Second) if err != nil { go func() { - if err = tr.Close(); err != nil { + if err := tr.Close(); err != nil { tm.Logger.Warnf("Failed to close transport: %s", err) } }() From ccaf5d99d4d19cae29436c9a8ac2f02f3622c5fe Mon Sep 17 00:00:00 2001 From: Evan Lin Date: Fri, 19 Jul 2019 18:08:52 +0800 Subject: [PATCH 3/3] update vendor --- go.mod | 2 +- go.sum | 2 + vendor/github.com/skycoin/dmsg/.golangci.yml | 8 +--- vendor/github.com/skycoin/dmsg/README.md | 8 ++-- vendor/github.com/skycoin/dmsg/client.go | 29 +++++++++----- vendor/github.com/skycoin/dmsg/disc/client.go | 31 ++++++++++++--- vendor/github.com/skycoin/dmsg/disc/entry.go | 39 ++++++++++++------- .../skycoin/dmsg/ioutil/ack_waiter.go | 2 +- .../skycoin/dmsg/ioutil/buf_read.go | 4 +- .../github.com/skycoin/dmsg/ioutil/logging.go | 7 ++++ vendor/github.com/skycoin/dmsg/noise/noise.go | 2 - vendor/github.com/skycoin/dmsg/server.go | 20 +++++++--- vendor/github.com/skycoin/dmsg/transport.go | 24 +++++++++--- vendor/modules.txt | 2 +- 14 files changed, 124 insertions(+), 56 deletions(-) create mode 100644 vendor/github.com/skycoin/dmsg/ioutil/logging.go diff --git a/go.mod b/go.mod index 71f84b591..5db14d14e 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/prometheus/client_golang v1.0.0 github.com/prometheus/common v0.4.1 github.com/sirupsen/logrus v1.4.2 - github.com/skycoin/dmsg v0.0.0-20190708174832-eb49a4b802f7 + github.com/skycoin/dmsg v0.0.0-20190719095515-52043626400c github.com/skycoin/skycoin v0.26.0 github.com/spf13/cobra v0.0.5 github.com/stretchr/testify v1.3.0 diff --git a/go.sum b/go.sum index 3862b75d4..2508980af 100644 --- a/go.sum +++ b/go.sum @@ -93,6 +93,8 @@ github.com/skycoin/dmsg v0.0.0-20190628092537-e69f75132be9 h1:Y7CZdMtd5HxkgIaAIL github.com/skycoin/dmsg v0.0.0-20190628092537-e69f75132be9/go.mod h1:AwwGhHjvXpbYVz8oYFaXKWHwscc5nHyHjssQBtQgmZg= github.com/skycoin/dmsg v0.0.0-20190708174832-eb49a4b802f7 h1:4LjXC4C+RJtsyJKlmtaDPhK7uaCImPZTvmVNkVHR2io= github.com/skycoin/dmsg v0.0.0-20190708174832-eb49a4b802f7/go.mod h1:obZYZp8eKR7Xqz+KNhJdUE6Gvp6rEXbDO8YTlW2YXgU= +github.com/skycoin/dmsg v0.0.0-20190719095515-52043626400c h1:ZEE/nDdNWKDoBPAtCZAejJHaaopMbR/+4owT1U+Xa48= +github.com/skycoin/dmsg v0.0.0-20190719095515-52043626400c/go.mod h1:obZYZp8eKR7Xqz+KNhJdUE6Gvp6rEXbDO8YTlW2YXgU= github.com/skycoin/skycoin v0.26.0 h1:xDxe2r8AclMntZ550Y/vUQgwgLtwrf9Wu5UYiYcN5/o= github.com/skycoin/skycoin v0.26.0/go.mod h1:78nHjQzd8KG0jJJVL/j0xMmrihXi70ti63fh8vXScJw= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= diff --git a/vendor/github.com/skycoin/dmsg/.golangci.yml b/vendor/github.com/skycoin/dmsg/.golangci.yml index 8f87242ef..abf0e5593 100644 --- a/vendor/github.com/skycoin/dmsg/.golangci.yml +++ b/vendor/github.com/skycoin/dmsg/.golangci.yml @@ -47,7 +47,7 @@ output: # all available settings of specific linters linters-settings: errcheck: - # report about not checking of errors in type assetions: `a := b.(MyStruct)`; + # report about not checking of errors in type assertions: `a := b.(MyStruct)`; # default is false: such cases aren't reported by default. check-type-assertions: false @@ -169,10 +169,6 @@ issues: # it can be disabled by `exclude-use-default: false`. To list all # excluded by default patterns execute `golangci-lint run --help` exclude: - - "G304: Potential file inclusion via variable" - - "G204: Subprocess launched with variable" - - "G104: Errors unhandled" - - Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked # Independently from option `exclude` we use default exclude patterns, # it can be disabled by this option. To list all @@ -192,4 +188,4 @@ issues: # large codebase. It's not practical to fix all existing issues at the moment # of integration: much better don't allow issues in new code. # Default is false. - new: false \ No newline at end of file + new: false diff --git a/vendor/github.com/skycoin/dmsg/README.md b/vendor/github.com/skycoin/dmsg/README.md index f131334b8..3dd196f9b 100644 --- a/vendor/github.com/skycoin/dmsg/README.md +++ b/vendor/github.com/skycoin/dmsg/README.md @@ -143,9 +143,9 @@ type Client struct { DelegatedServers []cipher.PubKey `json:"delegated_servers"` } -// Server contains the entity's required server meta, if it is to be advertised as a Messaging Server. +// Server contains the entity's required server meta, if it is to be advertised as a dmsg Server. type Server struct { - // IPv4 or IPv6 public address of the Messaging Server. + // IPv4 or IPv6 public address of the dmsg Server. Address string `json:"address"` // Number of connections still available. @@ -155,7 +155,7 @@ type Server struct { **Definition rules:** -- A record **MUST** have either a "Server" field, a "Client" field, or both "Server" and "Client" fields. In other words, a Messaging Node can be a Messaging Server Node, a Messaging Client Node, or both a Messaging Server Node and a Messaging Client Node. +- A record **MUST** have either a "Server" field, a "Client" field, or both "Server" and "Client" fields. In other words, a dmsg node can be a dmsg Server, a dmsg Client, or both a dmsg Server and a dmsg Client. **Iteration rules:** @@ -180,7 +180,7 @@ Only 3 endpoints need to be defined; Get Entry, Post Entry, and Get Available Se #### GET Entry -Obtains a messaging node's entry. +Obtains a dmsg node's entry. > `GET {domain}/discovery/entries/{public_key}` diff --git a/vendor/github.com/skycoin/dmsg/client.go b/vendor/github.com/skycoin/dmsg/client.go index bd07446ed..a3b18d7d1 100644 --- a/vendor/github.com/skycoin/dmsg/client.go +++ b/vendor/github.com/skycoin/dmsg/client.go @@ -9,7 +9,6 @@ import ( "time" "github.com/sirupsen/logrus" - "github.com/skycoin/skycoin/src/util/logging" "github.com/skycoin/dmsg/cipher" @@ -17,6 +16,8 @@ import ( "github.com/skycoin/dmsg/noise" ) +var log = logging.MustGetLogger("dmsg") + const ( clientReconnectInterval = 3 * time.Second ) @@ -159,7 +160,9 @@ func (c *ClientConn) handleRequestFrame(accept chan<- *Transport, id uint16, p [ select { case <-c.done: - _ = tp.Close() //nolint:errcheck + if err := tp.Close(); err != nil { + log.WithError(err).Warn("Failed to close transport") + } return initPK, ErrClientClosed case accept <- tp: @@ -171,7 +174,9 @@ func (c *ClientConn) handleRequestFrame(accept chan<- *Transport, id uint16, p [ return initPK, nil default: - _ = tp.Close() //nolint:errcheck + if err := tp.Close(); err != nil { + log.WithError(err).Warn("Failed to close transport") + } return initPK, ErrClientAcceptMaxed } } @@ -265,12 +270,16 @@ func (c *ClientConn) close() (closed bool) { close(c.done) c.mx.Lock() for _, tp := range c.tps { - // Nil check is required here to keep 8192 running goroutines limit in tests with -race flag. - if tp != nil { - go tp.Close() // nolint:errcheck - } + tp := tp + go func() { + if err := tp.Close(); err != nil { + log.WithError(err).Warn("Failed to close transport") + } + }() + } + if err := c.Conn.Close(); err != nil { + log.WithError(err).Warn("Failed to close connection") } - _ = c.Conn.Close() //nolint:errcheck c.mx.Unlock() }) return closed @@ -561,7 +570,9 @@ func (c *Client) Close() error { c.mx.Lock() for _, conn := range c.conns { - _ = conn.Close() + if err := conn.Close(); err != nil { + log.WithError(err).Warn("Failed to close connection") + } } c.conns = make(map[cipher.PubKey]*ClientConn) c.mx.Unlock() diff --git a/vendor/github.com/skycoin/dmsg/disc/client.go b/vendor/github.com/skycoin/dmsg/disc/client.go index 3bead20da..9f3d4c2ad 100644 --- a/vendor/github.com/skycoin/dmsg/disc/client.go +++ b/vendor/github.com/skycoin/dmsg/disc/client.go @@ -11,9 +11,13 @@ import ( "sync" "time" + "github.com/skycoin/skycoin/src/util/logging" + "github.com/skycoin/dmsg/cipher" ) +var log = logging.MustGetLogger("disc") + // APIClient implements messaging discovery API client. type APIClient interface { Entry(context.Context, cipher.PubKey) (*Entry, error) @@ -50,12 +54,17 @@ func (c *httpClient) Entry(ctx context.Context, publicKey cipher.PubKey) (*Entry req = req.WithContext(ctx) resp, err := c.client.Do(req) + if resp != nil { + defer func() { + if err := resp.Body.Close(); err != nil { + log.WithError(err).Warn("Failed to close response body") + } + }() + } if err != nil { return nil, err } - defer resp.Body.Close() - // if the response is an error it will be codified as an HTTPMessage if resp.StatusCode != http.StatusOK { var message HTTPMessage @@ -92,12 +101,17 @@ func (c *httpClient) SetEntry(ctx context.Context, e *Entry) error { req.Header.Set("Content-Type", "application/json") resp, err := c.client.Do(req) + if resp != nil { + defer func() { + if err := resp.Body.Close(); err != nil { + log.WithError(err).Warn("Failed to close response body") + } + }() + } if err != nil { return err } - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { var httpResponse HTTPMessage @@ -159,12 +173,17 @@ func (c *httpClient) AvailableServers(ctx context.Context) ([]*Entry, error) { req = req.WithContext(ctx) resp, err := c.client.Do(req) + if resp != nil { + defer func() { + if err := resp.Body.Close(); err != nil { + log.WithError(err).Warn("Failed to close response body") + } + }() + } if err != nil { return nil, err } - defer resp.Body.Close() - // if the response is an error it will be codified as an HTTPMessage if resp.StatusCode != http.StatusOK { var message HTTPMessage diff --git a/vendor/github.com/skycoin/dmsg/disc/entry.go b/vendor/github.com/skycoin/dmsg/disc/entry.go index 4cecbfa5e..afebaabcd 100644 --- a/vendor/github.com/skycoin/dmsg/disc/entry.go +++ b/vendor/github.com/skycoin/dmsg/disc/entry.go @@ -4,30 +4,41 @@ import ( "encoding/json" "errors" "fmt" - "time" - "strings" + "time" "github.com/skycoin/dmsg/cipher" ) const currentVersion = "0.0.1" -// nolint var ( - ErrKeyNotFound = errors.New("entry of public key is not found") - ErrUnexpected = errors.New("something unexpected happened") - ErrUnauthorized = errors.New("invalid signature") - ErrBadInput = errors.New("error bad input") - ErrValidationNonZeroSequence = NewEntryValidationError("new entry has non-zero sequence") - ErrValidationNilEphemerals = NewEntryValidationError("entry of client instance has nil ephemeral keys") - ErrValidationNilKeys = NewEntryValidationError("entry Keys is nil") + // ErrKeyNotFound occurs in case when entry of public key is not found + ErrKeyNotFound = errors.New("entry of public key is not found") + // ErrUnexpected occurs in case when something unexpected happened + ErrUnexpected = errors.New("something unexpected happened") + // ErrUnauthorized occurs in case of invalid signature + ErrUnauthorized = errors.New("invalid signature") + // ErrBadInput occurs in case of bad input + ErrBadInput = errors.New("error bad input") + // ErrValidationNonZeroSequence occurs in case when new entry has non-zero sequence + ErrValidationNonZeroSequence = NewEntryValidationError("new entry has non-zero sequence") + // ErrValidationNilEphemerals occurs in case when entry of client instance has nil ephemeral keys + ErrValidationNilEphemerals = NewEntryValidationError("entry of client instance has nil ephemeral keys") + // ErrValidationNilKeys occurs in case when entry Keys is nil + ErrValidationNilKeys = NewEntryValidationError("entry Keys is nil") + // ErrValidationNonNilEphemerals occurs in case when entry of server instance has non nil Keys.Ephemerals field ErrValidationNonNilEphemerals = NewEntryValidationError("entry of server instance has non nil Keys.Ephemerals field") - ErrValidationNoSignature = NewEntryValidationError("entry has no signature") - ErrValidationNoVersion = NewEntryValidationError("entry has no version") + // ErrValidationNoSignature occurs in case when entry has no signature + ErrValidationNoSignature = NewEntryValidationError("entry has no signature") + // ErrValidationNoVersion occurs in case when entry has no version + ErrValidationNoVersion = NewEntryValidationError("entry has no version") + // ErrValidationNoClientOrServer occurs in case when entry has neither client or server field ErrValidationNoClientOrServer = NewEntryValidationError("entry has neither client or server field") - ErrValidationWrongSequence = NewEntryValidationError("sequence field of new entry is not sequence of old entry + 1") - ErrValidationWrongTime = NewEntryValidationError("previous entry timestamp is not set before current entry timestamp") + // ErrValidationWrongSequence occurs in case when sequence field of new entry is not sequence of old entry + 1 + ErrValidationWrongSequence = NewEntryValidationError("sequence field of new entry is not sequence of old entry + 1") + // ErrValidationWrongTime occurs in case when previous entry timestamp is not set before current entry timestamp + ErrValidationWrongTime = NewEntryValidationError("previous entry timestamp is not set before current entry timestamp") errReverseMap = map[string]error{ ErrKeyNotFound.Error(): ErrKeyNotFound, diff --git a/vendor/github.com/skycoin/dmsg/ioutil/ack_waiter.go b/vendor/github.com/skycoin/dmsg/ioutil/ack_waiter.go index 5750aa36d..8257aec8d 100644 --- a/vendor/github.com/skycoin/dmsg/ioutil/ack_waiter.go +++ b/vendor/github.com/skycoin/dmsg/ioutil/ack_waiter.go @@ -61,7 +61,7 @@ func (w *Uint16AckWaiter) stopWaiter(seq Uint16Seq) { func (w *Uint16AckWaiter) StopAll() { w.mx.Lock() for seq := range w.waiters { - w.stopWaiter(Uint16Seq(seq)) + w.stopWaiter(seq) } w.mx.Unlock() } diff --git a/vendor/github.com/skycoin/dmsg/ioutil/buf_read.go b/vendor/github.com/skycoin/dmsg/ioutil/buf_read.go index b6310fd7f..a33054405 100644 --- a/vendor/github.com/skycoin/dmsg/ioutil/buf_read.go +++ b/vendor/github.com/skycoin/dmsg/ioutil/buf_read.go @@ -10,7 +10,9 @@ import ( func BufRead(buf *bytes.Buffer, data, p []byte) (int, error) { n := copy(p, data) if n < len(data) { - buf.Write(data[n:]) + if _, err := buf.Write(data[n:]); err != nil { + log.WithError(err).Warn("Failed to write to buffer") + } } return n, nil } diff --git a/vendor/github.com/skycoin/dmsg/ioutil/logging.go b/vendor/github.com/skycoin/dmsg/ioutil/logging.go new file mode 100644 index 000000000..71c97a40e --- /dev/null +++ b/vendor/github.com/skycoin/dmsg/ioutil/logging.go @@ -0,0 +1,7 @@ +package ioutil + +import ( + "github.com/skycoin/skycoin/src/util/logging" +) + +var log = logging.MustGetLogger("ioutil") diff --git a/vendor/github.com/skycoin/dmsg/noise/noise.go b/vendor/github.com/skycoin/dmsg/noise/noise.go index e605c62ce..3b36cdf79 100644 --- a/vendor/github.com/skycoin/dmsg/noise/noise.go +++ b/vendor/github.com/skycoin/dmsg/noise/noise.go @@ -36,8 +36,6 @@ type Noise struct { seq uint32 // sequence number, used as nonce for both encrypting and decrypting previousSeq uint32 // sequence number last decrypted, check in order to avoid reply attacks highestPrevious uint32 // highest sequence number received from the other end - //encN uint32 // counter to inform encrypting CipherState to re-key - //decN uint32 // counter to inform decrypting CipherState to re-key } // New creates a new Noise with: diff --git a/vendor/github.com/skycoin/dmsg/server.go b/vendor/github.com/skycoin/dmsg/server.go index c557bc00c..37108fdda 100644 --- a/vendor/github.com/skycoin/dmsg/server.go +++ b/vendor/github.com/skycoin/dmsg/server.go @@ -27,7 +27,11 @@ type NextConn struct { func (r *NextConn) writeFrame(ft FrameType, p []byte) error { if err := writeFrame(r.conn.Conn, MakeFrame(ft, r.id, p)); err != nil { - go r.conn.Close() + go func() { + if err := r.conn.Close(); err != nil { + log.WithError(err).Warn("Failed to close connection") + } + }() return err } return nil @@ -109,13 +113,17 @@ type getConnFunc func(pk cipher.PubKey) (*ServerConn, bool) func (c *ServerConn) Serve(ctx context.Context, getConn getConnFunc) (err error) { go func() { <-ctx.Done() - c.Conn.Close() + if err := c.Conn.Close(); err != nil { + log.WithError(err).Warn("Failed to close connection") + } }() log := c.log.WithField("srcClient", c.remoteClient) defer func() { log.WithError(err).WithField("connCount", decrementServeCount()).Infoln("ClosingConn") - c.Conn.Close() + if err := c.Conn.Close(); err != nil { + log.WithError(err).Warn("Failed to close connection") + } }() log.WithField("connCount", incrementServeCount()).Infoln("ServingConn") @@ -187,7 +195,8 @@ func (c *ServerConn) writeOK() error { return nil } -func (c *ServerConn) forwardFrame(ft FrameType, id uint16, p []byte) (*NextConn, byte, bool) { //nolint:unparam +// nolint:unparam +func (c *ServerConn) forwardFrame(ft FrameType, id uint16, p []byte) (*NextConn, byte, bool) { next, ok := c.getNext(id) if !ok { return next, 0, false @@ -198,7 +207,8 @@ func (c *ServerConn) forwardFrame(ft FrameType, id uint16, p []byte) (*NextConn, return next, 0, true } -func (c *ServerConn) handleRequest(ctx context.Context, getLink getConnFunc, id uint16, p []byte) (*NextConn, byte, bool) { //nolint:unparam +// nolint:unparam +func (c *ServerConn) handleRequest(ctx context.Context, getLink getConnFunc, id uint16, p []byte) (*NextConn, byte, bool) { initPK, respPK, ok := splitPKs(p) if !ok || initPK != c.PK() { return nil, 0, false diff --git a/vendor/github.com/skycoin/dmsg/transport.go b/vendor/github.com/skycoin/dmsg/transport.go index cc2724428..7878e49a8 100644 --- a/vendor/github.com/skycoin/dmsg/transport.go +++ b/vendor/github.com/skycoin/dmsg/transport.go @@ -112,7 +112,9 @@ func (tp *Transport) close() (closed bool) { // Close closes the dmsg_tp. func (tp *Transport) Close() error { if tp.close() { - _ = writeFrame(tp.Conn, MakeFrame(CloseType, tp.id, []byte{0})) //nolint:errcheck + if err := writeFrame(tp.Conn, MakeFrame(CloseType, tp.id, []byte{0})); err != nil { + log.WithError(err).Warn("Failed to write frame") + } } return nil } @@ -204,7 +206,9 @@ func (tp *Transport) ReadAccept(ctx context.Context) (err error) { return io.ErrClosedPipe case <-ctx.Done(): - _ = tp.Close() //nolint:errcheck + if err := tp.Close(); err != nil { + log.WithError(err).Warn("Failed to close transport") + } return ctx.Err() case f, ok := <-tp.inCh: @@ -221,7 +225,9 @@ func (tp *Transport) ReadAccept(ctx context.Context) (err error) { // - use an even number with the intermediary dmsg_server. initPK, respPK, ok := splitPKs(p) if !ok || initPK != tp.local || respPK != tp.remote || !isInitiatorID(id) { - _ = tp.Close() //nolint:errcheck + if err := tp.Close(); err != nil { + log.WithError(err).Warn("Failed to close transport") + } return ErrAcceptCheckFailed } return nil @@ -231,7 +237,9 @@ func (tp *Transport) ReadAccept(ctx context.Context) (err error) { return ErrRequestRejected default: - _ = tp.Close() //nolint:errcheck + if err := tp.Close(); err != nil { + log.WithError(err).Warn("Failed to close transport") + } return ErrAcceptCheckFailed } } @@ -248,7 +256,9 @@ func (tp *Transport) Serve() { // also write CLOSE frame if this is the first time 'close' is triggered defer func() { if tp.close() { - _ = writeCloseFrame(tp.Conn, tp.id, 0) //nolint:errcheck + if err := writeCloseFrame(tp.Conn, tp.id, 0); err != nil { + log.WithError(err).Warn("Failed to write close frame") + } } }() @@ -313,7 +323,9 @@ func (tp *Transport) Serve() { case RequestType: log.Warnln("Rejected [REQUEST]: ID already occupied, possibly malicious server.") - _ = tp.Conn.Close() + if err := tp.Conn.Close(); err != nil { + log.WithError(err).Warn("Failed to close connection") + } return default: diff --git a/vendor/modules.txt b/vendor/modules.txt index 5d9179f82..ed363351b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -62,7 +62,7 @@ github.com/prometheus/procfs/internal/fs # github.com/sirupsen/logrus v1.4.2 github.com/sirupsen/logrus/hooks/syslog github.com/sirupsen/logrus -# github.com/skycoin/dmsg v0.0.0-20190708174832-eb49a4b802f7 +# github.com/skycoin/dmsg v0.0.0-20190719095515-52043626400c github.com/skycoin/dmsg/cipher github.com/skycoin/dmsg github.com/skycoin/dmsg/disc