diff --git a/.golangci.yml b/.golangci.yml index a3235be..178b3f3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,17 +25,32 @@ linters-settings: - ^os.Exit$ - ^panic$ - ^print(ln)?$ + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte linters: enable: - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity - decorder # check declaration order and count of types, constants, variables and functions - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. @@ -46,18 +61,17 @@ linters: - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - gocognit # Computes and checks the cognitive complexity of functions - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period - godox # Tool for detection of FIXME, TODO and other comment keywords - - err113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - goprintffuncname # Checks that printf-like functions are named with `f` at the end - gosec # Inspects source code for security problems - gosimple # Linter for Go source code that specializes in simplifying a code @@ -65,9 +79,15 @@ linters: - grouper # An analyzer to analyze expression groups. - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length - misspell # Finds commonly misspelled English words in comments + - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - noctx # noctx finds sending http request without context.Context - predeclared # find code that shadows one of Go's predeclared identifiers - revive # golint replacement, finds style mistakes @@ -75,28 +95,22 @@ linters: - stylecheck # Stylecheck is a replacement for golint - tagliatelle # Checks the struct tags. - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types + - varnamelen # checks that the length of a variable's name matches its scope - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: - depguard # Go linter that checks if package imports are in a list of acceptable packages - - containedctx # containedctx is a linter that detects struct contained context.Context field - - cyclop # checks function and package cyclomatic complexity - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. - ireturn # Accept Interfaces, Return Concrete Types - - lll # Reports long lines - - maintidx # maintidx measures the maintainability index of each function. - - makezero # Finds slice declarations with non-zero initial length - - nakedret # Finds naked returns in functions greater than a specified function length - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - mnd # An analyzer to detect magic numbers - nolintlint # Reports ill-formed or insufficient nolint directives - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - prealloc # Finds slice declarations that could potentially be preallocated @@ -104,8 +118,7 @@ linters: - rowserrcheck # checks whether Err of rows is checked successfully - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - testpackage # linter that makes you use a separate _test package - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - varnamelen # checks that the length of a variable's name matches its scope + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - wrapcheck # Checks that errors returned from external packages are wrapped - wsl # Whitespace Linter - Forces you to use empty lines! @@ -123,3 +136,6 @@ issues: - path: cmd linters: - forbidigo + max-issues-per-linter: 0 + max-same-issues: 0 + \ No newline at end of file diff --git a/connctx/connctx.go b/connctx/connctx.go index 4869b9c..8e61b44 100644 --- a/connctx/connctx.go +++ b/connctx/connctx.go @@ -61,10 +61,11 @@ func New(conn net.Conn) ConnCtx { nextConn: conn, closed: make(chan struct{}), } + return c } -func (c *connCtx) ReadContext(ctx context.Context, b []byte) (int, error) { +func (c *connCtx) ReadContext(ctx context.Context, b []byte) (int, error) { //nolint:cyclop c.readMu.Lock() defer c.readMu.Unlock() @@ -85,6 +86,7 @@ func (c *connCtx) ReadContext(ctx context.Context, b []byte) (int, error) { // context canceled if err := c.nextConn.SetReadDeadline(veryOld); err != nil { errSetDeadline.Store(err) + return } <-done @@ -105,10 +107,11 @@ func (c *connCtx) ReadContext(ctx context.Context, b []byte) (int, error) { if err2, ok := errSetDeadline.Load().(error); ok && err == nil && err2 != nil { err = err2 } + return n, err } -func (c *connCtx) WriteContext(ctx context.Context, b []byte) (int, error) { +func (c *connCtx) WriteContext(ctx context.Context, b []byte) (int, error) { //nolint:cyclop c.writeMu.Lock() defer c.writeMu.Unlock() @@ -129,6 +132,7 @@ func (c *connCtx) WriteContext(ctx context.Context, b []byte) (int, error) { // context canceled if err := c.nextConn.SetWriteDeadline(veryOld); err != nil { errSetDeadline.Store(err) + return } <-done @@ -149,6 +153,7 @@ func (c *connCtx) WriteContext(ctx context.Context, b []byte) (int, error) { if err2, ok := errSetDeadline.Load().(error); ok && err == nil && err2 != nil { err = err2 } + return n, err } @@ -161,6 +166,7 @@ func (c *connCtx) Close() error { c.readMu.Unlock() c.writeMu.Unlock() }) + return err } diff --git a/connctx/connctx_test.go b/connctx/connctx_test.go index 910f122..95fb74e 100644 --- a/connctx/connctx_test.go +++ b/connctx/connctx_test.go @@ -200,7 +200,7 @@ func TestWriteClosed(t *testing.T) { } } -// Test for TestLocalAddrAndRemoteAddr +// Test for TestLocalAddrAndRemoteAddr. type stringAddr struct { network string addr string @@ -262,6 +262,7 @@ func BenchmarkBase(b *testing.B) { if !errors.Is(err, io.EOF) { b.Fatal(err) } + break } if n != len(data) { @@ -304,6 +305,7 @@ func BenchmarkWrite(b *testing.B) { if !errors.Is(err, io.EOF) { b.Fatal(err) } + break } if n != len(data) { @@ -346,6 +348,7 @@ func BenchmarkRead(b *testing.B) { if !errors.Is(err, io.EOF) { b.Fatal(err) } + break } if n != len(data) { diff --git a/connctx/pipe.go b/connctx/pipe.go index 96b802e..11e7a4e 100644 --- a/connctx/pipe.go +++ b/connctx/pipe.go @@ -10,5 +10,6 @@ import ( // Pipe creates piped pair of ConnCtx. func Pipe() (ConnCtx, ConnCtx) { ca, cb := net.Pipe() + return New(ca), New(cb) } diff --git a/deadline/deadline.go b/deadline/deadline.go index f49b908..9432ff6 100644 --- a/deadline/deadline.go +++ b/deadline/deadline.go @@ -43,6 +43,7 @@ func (d *Deadline) timeout() { d.mu.Lock() if d.pending--; d.pending != 0 || d.state != deadlineStarted { d.mu.Unlock() + return } @@ -54,7 +55,7 @@ func (d *Deadline) timeout() { } // Set new deadline. Zero value means no deadline. -func (d *Deadline) Set(t time.Time) { +func (d *Deadline) Set(setTo time.Time) { d.mu.Lock() defer d.mu.Unlock() @@ -62,26 +63,28 @@ func (d *Deadline) Set(t time.Time) { d.pending-- } - d.deadline = t + d.deadline = setTo d.pending++ if d.state == deadlineExceeded { d.done = make(chan struct{}) } - if t.IsZero() { + if setTo.IsZero() { d.pending-- d.state = deadlineStopped + return } - if dur := time.Until(t); dur > 0 { + if dur := time.Until(setTo); dur > 0 { d.state = deadlineStarted if d.timer == nil { d.timer = afterFunc(dur, d.timeout) } else { d.timer.Reset(dur) } + return } @@ -94,6 +97,7 @@ func (d *Deadline) Set(t time.Time) { func (d *Deadline) Done() <-chan struct{} { d.mu.RLock() defer d.mu.RUnlock() + return d.done } @@ -105,6 +109,7 @@ func (d *Deadline) Err() error { if d.state == deadlineExceeded { return context.DeadlineExceeded } + return nil } @@ -115,6 +120,7 @@ func (d *Deadline) Deadline() (time.Time, bool) { if d.deadline.IsZero() { return d.deadline, false } + return d.deadline, true } diff --git a/deadline/deadline_test.go b/deadline/deadline_test.go index 31dbdf0..7b21077 100644 --- a/deadline/deadline_test.go +++ b/deadline/deadline_test.go @@ -124,27 +124,29 @@ func collectCh(ch <-chan byte, n int, timeout time.Duration) []byte { return calls } } + return calls } -func TestContext(t *testing.T) { +func TestContext(t *testing.T) { //nolint:cyclop t.Run("Cancel", func(t *testing.T) { - d := New() + deadline := New() + select { - case <-d.Done(): + case <-deadline.Done(): t.Fatal("Deadline unexpectedly done") case <-time.After(50 * time.Millisecond): } - if err := d.Err(); err != nil { + if err := deadline.Err(); err != nil { t.Errorf("Wrong Err(), expected: nil, got: %v", err) } - d.Set(time.Unix(0, 1)) // exceeded + deadline.Set(time.Unix(0, 1)) // exceeded select { - case <-d.Done(): + case <-deadline.Done(): case <-time.After(50 * time.Millisecond): t.Fatal("Timeout") } - if err := d.Err(); !errors.Is(err, context.DeadlineExceeded) { + if err := deadline.Err(); !errors.Is(err, context.DeadlineExceeded) { t.Errorf("Wrong Err(), expected: %v, got: %v", context.DeadlineExceeded, err) } }) diff --git a/dpipe/dpipe.go b/dpipe/dpipe.go index 3131230..0dc71d4 100644 --- a/dpipe/dpipe.go +++ b/dpipe/dpipe.go @@ -21,6 +21,7 @@ import ( func Pipe() (net.Conn, net.Conn) { ch0 := make(chan []byte, 1000) ch1 := make(chan []byte, 1000) + return &conn{ rCh: ch0, wCh: ch1, @@ -60,20 +61,23 @@ func (*conn) RemoteAddr() net.Addr { return pipeAddr{} } func (c *conn) SetDeadline(t time.Time) error { c.readDeadline.Set(t) c.writeDeadline.Set(t) + return nil } func (c *conn) SetReadDeadline(t time.Time) error { c.readDeadline.Set(t) + return nil } func (c *conn) SetWriteDeadline(t time.Time) error { c.writeDeadline.Set(t) + return nil } -func (c *conn) Read(data []byte) (n int, err error) { +func (c *conn) Read(data []byte) (n int, err error) { //nolint:cyclop select { case <-c.closed: return 0, io.EOF @@ -91,9 +95,11 @@ func (c *conn) Read(data []byte) (n int, err error) { case d := <-c.rCh: if len(d) <= len(data) { copy(data, d) + return len(d), nil } copy(data, d[:len(data)]) + return len(data), nil case <-c.closed: return 0, io.EOF @@ -123,6 +129,7 @@ func (c *conn) Write(data []byte) (n int, err error) { return 0, io.ErrClosedPipe case <-c.writeDeadline.Done(): c.cleanWriteBuffer() + return 0, context.DeadlineExceeded default: } @@ -135,6 +142,7 @@ func (c *conn) Write(data []byte) (n int, err error) { return 0, io.ErrClosedPipe case <-c.writeDeadline.Done(): c.cleanWriteBuffer() + return 0, context.DeadlineExceeded case c.wCh <- cData: return len(cData), nil @@ -145,5 +153,6 @@ func (c *conn) Close() error { c.closeOnce.Do(func() { close(c.closed) }) + return nil } diff --git a/dpipe/dpipe_test.go b/dpipe/dpipe_test.go index 78692ac..efc7c24 100644 --- a/dpipe/dpipe_test.go +++ b/dpipe/dpipe_test.go @@ -49,10 +49,11 @@ type closePropagator struct { func (c *closePropagator) Close() error { close(c.otherEnd.closing) + return c.conn.Close() } -func TestPipe(t *testing.T) { +func TestPipe(t *testing.T) { //nolint:cyclop ca, cb := Pipe() testData := []byte{0x01, 0x02} diff --git a/examples/vnet-udpproxy/main.go b/examples/vnet-udpproxy/main.go index 81c7b48..2139d9b 100644 --- a/examples/vnet-udpproxy/main.go +++ b/examples/vnet-udpproxy/main.go @@ -14,7 +14,7 @@ import ( "github.com/pion/transport/v3/vnet" ) -func main() { +func main() { //nolint:cyclop address := flag.String("address", "", "Destination address that three separate vnet clients will send too") flag.Parse() diff --git a/net.go b/net.go index 86d3468..5fe3783 100644 --- a/net.go +++ b/net.go @@ -390,13 +390,13 @@ type TCPListener interface { SetDeadline(t time.Time) error } -// Interface wraps a standard net.Interfaces and its assigned addresses +// Interface wraps a standard net.Interfaces and its assigned addresses. type Interface struct { net.Interface addrs []net.Addr } -// NewInterface creates a new interface based of a standard net.Interface +// NewInterface creates a new interface based of a standard net.Interface. func NewInterface(ifc net.Interface) *Interface { return &Interface{ Interface: ifc, @@ -404,15 +404,16 @@ func NewInterface(ifc net.Interface) *Interface { } } -// AddAddress adds a new address to the interface +// AddAddress adds a new address to the interface. func (ifc *Interface) AddAddress(addr net.Addr) { ifc.addrs = append(ifc.addrs, addr) } -// Addrs returns a slice of configured addresses on the interface +// Addrs returns a slice of configured addresses on the interface. func (ifc *Interface) Addrs() ([]net.Addr, error) { if len(ifc.addrs) == 0 { return nil, ErrNoAddressAssigned } + return ifc.addrs, nil } diff --git a/netctx/conn.go b/netctx/conn.go index 823107c..79506c2 100644 --- a/netctx/conn.go +++ b/netctx/conn.go @@ -59,12 +59,13 @@ func NewConn(netConn net.Conn) Conn { nextConn: netConn, closed: make(chan struct{}), } + return c } // ReadContext reads data from the connection. // Unlike net.Conn.Read(), the provided context is used to control timeout. -func (c *conn) ReadContext(ctx context.Context, b []byte) (int, error) { +func (c *conn) ReadContext(ctx context.Context, b []byte) (int, error) { //nolint:cyclop c.readMu.Lock() defer c.readMu.Unlock() @@ -85,6 +86,7 @@ func (c *conn) ReadContext(ctx context.Context, b []byte) (int, error) { // context canceled if err := c.nextConn.SetReadDeadline(veryOld); err != nil { errSetDeadline.Store(err) + return } <-done @@ -105,12 +107,13 @@ func (c *conn) ReadContext(ctx context.Context, b []byte) (int, error) { if err2, ok := errSetDeadline.Load().(error); ok && err == nil && err2 != nil { err = err2 } + return n, err } // WriteContext writes data to the connection. // Unlike net.Conn.Write(), the provided context is used to control timeout. -func (c *conn) WriteContext(ctx context.Context, b []byte) (int, error) { +func (c *conn) WriteContext(ctx context.Context, b []byte) (int, error) { //nolint:cyclop c.writeMu.Lock() defer c.writeMu.Unlock() @@ -131,6 +134,7 @@ func (c *conn) WriteContext(ctx context.Context, b []byte) (int, error) { // context canceled if err := c.nextConn.SetWriteDeadline(veryOld); err != nil { errSetDeadline.Store(err) + return } <-done @@ -151,6 +155,7 @@ func (c *conn) WriteContext(ctx context.Context, b []byte) (int, error) { if err2, ok := errSetDeadline.Load().(error); ok && err == nil && err2 != nil { err = err2 } + return n, err } @@ -166,6 +171,7 @@ func (c *conn) Close() error { c.readMu.Unlock() c.writeMu.Unlock() }) + return err } diff --git a/netctx/conn_test.go b/netctx/conn_test.go index 4c920c2..3523e34 100644 --- a/netctx/conn_test.go +++ b/netctx/conn_test.go @@ -200,7 +200,7 @@ func TestWriteClosed(t *testing.T) { } } -// Test for TestLocalAddrAndRemoteAddr +// Test for TestLocalAddrAndRemoteAddr. type stringAddr struct { network string addr string @@ -262,6 +262,7 @@ func BenchmarkBase(b *testing.B) { if !errors.Is(err, io.EOF) { b.Fatal(err) } + break } if n != len(data) { @@ -304,6 +305,7 @@ func BenchmarkWrite(b *testing.B) { if !errors.Is(err, io.EOF) { b.Fatal(err) } + break } if n != len(data) { @@ -346,6 +348,7 @@ func BenchmarkRead(b *testing.B) { if !errors.Is(err, io.EOF) { b.Fatal(err) } + break } if n != len(data) { diff --git a/netctx/packetconn.go b/netctx/packetconn.go index a4ce22d..feb5910 100644 --- a/netctx/packetconn.go +++ b/netctx/packetconn.go @@ -45,6 +45,7 @@ func NewPacketConn(pconn net.PacketConn) PacketConn { nextConn: pconn, closed: make(chan struct{}), } + return p } @@ -57,7 +58,7 @@ func NewPacketConn(pconn net.PacketConn) PacketConn { // the n > 0 bytes returned before considering the error err. // Unlike net.PacketConn.ReadFrom(), the provided context is // used to control timeout. -func (p *packetConn) ReadFromContext(ctx context.Context, b []byte) (int, net.Addr, error) { +func (p *packetConn) ReadFromContext(ctx context.Context, b []byte) (int, net.Addr, error) { //nolint:cyclop p.readMu.Lock() defer p.readMu.Unlock() @@ -78,6 +79,7 @@ func (p *packetConn) ReadFromContext(ctx context.Context, b []byte) (int, net.Ad // context canceled if err := p.nextConn.SetReadDeadline(veryOld); err != nil { errSetDeadline.Store(err) + return } <-done @@ -98,6 +100,7 @@ func (p *packetConn) ReadFromContext(ctx context.Context, b []byte) (int, net.Ad if err2, ok := errSetDeadline.Load().(error); ok && err == nil && err2 != nil { err = err2 } + return n, raddr, err } @@ -105,7 +108,7 @@ func (p *packetConn) ReadFromContext(ctx context.Context, b []byte) (int, net.Ad // Unlike net.PacketConn.WriteTo(), the provided context // is used to control timeout. // On packet-oriented connections, write timeouts are rare. -func (p *packetConn) WriteToContext(ctx context.Context, b []byte, raddr net.Addr) (int, error) { +func (p *packetConn) WriteToContext(ctx context.Context, b []byte, raddr net.Addr) (int, error) { //nolint:cyclop p.writeMu.Lock() defer p.writeMu.Unlock() @@ -126,6 +129,7 @@ func (p *packetConn) WriteToContext(ctx context.Context, b []byte, raddr net.Add // context canceled if err := p.nextConn.SetWriteDeadline(veryOld); err != nil { errSetDeadline.Store(err) + return } <-done @@ -146,6 +150,7 @@ func (p *packetConn) WriteToContext(ctx context.Context, b []byte, raddr net.Add if err2, ok := errSetDeadline.Load().(error); ok && err == nil && err2 != nil { err = err2 } + return n, err } @@ -161,6 +166,7 @@ func (p *packetConn) Close() error { p.readMu.Unlock() p.writeMu.Unlock() }) + return err } diff --git a/netctx/packetconn_test.go b/netctx/packetconn_test.go index f1fd571..bc7950a 100644 --- a/netctx/packetconn_test.go +++ b/netctx/packetconn_test.go @@ -21,6 +21,7 @@ type wrapConn struct { func (w wrapConn) ReadFrom(p []byte) (int, net.Addr, error) { n, err := w.c.Read(p) + return n, nil, err } @@ -54,6 +55,7 @@ func (w wrapConn) SetWriteDeadline(t time.Time) error { func pipe() (net.PacketConn, net.PacketConn) { a, b := net.Pipe() + return wrapConn{a}, wrapConn{b} } @@ -292,6 +294,7 @@ func BenchmarkPacketConnBase(b *testing.B) { if !errors.Is(err, io.EOF) { b.Fatal(err) } + break } if n != len(data) { @@ -334,6 +337,7 @@ func BenchmarkWriteTo(b *testing.B) { if !errors.Is(err, io.EOF) { b.Fatal(err) } + break } if n != len(data) { @@ -376,6 +380,7 @@ func BenchmarkReadFrom(b *testing.B) { if !errors.Is(err, io.EOF) { b.Fatal(err) } + break } if n != len(data) { diff --git a/netctx/pipe.go b/netctx/pipe.go index 7deae66..12d4f72 100644 --- a/netctx/pipe.go +++ b/netctx/pipe.go @@ -10,5 +10,6 @@ import ( // Pipe creates piped pair of Conn. func Pipe() (Conn, Conn) { ca, cb := net.Pipe() + return NewConn(ca), NewConn(cb) } diff --git a/packetio/buffer.go b/packetio/buffer.go index cdd39d7..3ac68d5 100644 --- a/packetio/buffer.go +++ b/packetio/buffer.go @@ -19,9 +19,9 @@ var errPacketTooBig = errors.New("packet too big") type BufferPacketType int const ( - // RTPBufferPacket indicates the Buffer that is handling RTP packets + // RTPBufferPacket indicates the Buffer that is handling RTP packets. RTPBufferPacket BufferPacketType = 1 - // RTCPBufferPacket indicates the Buffer that is handling RTCP packets + // RTCPBufferPacket indicates the Buffer that is handling RTCP packets. RTCPBufferPacket BufferPacketType = 2 ) @@ -123,7 +123,7 @@ func (b *Buffer) grow() error { // Returns ErrFull if the packet doesn't fit. // // Note that the packet size is limited to 65536 bytes since v0.11.0 due to the internal data structure. -func (b *Buffer) Write(packet []byte) (int, error) { +func (b *Buffer) Write(packet []byte) (int, error) { //nolint:cyclop if len(packet) >= 0x10000 { return 0, errPacketTooBig } @@ -132,12 +132,14 @@ func (b *Buffer) Write(packet []byte) (int, error) { if b.closed { b.mutex.Unlock() + return 0, io.ErrClosedPipe } if (b.limitCount > 0 && b.count >= b.limitCount) || (b.limitSize > 0 && b.size()+2+len(packet) > b.limitSize) { b.mutex.Unlock() + return 0, ErrFull } @@ -146,17 +148,18 @@ func (b *Buffer) Write(packet []byte) (int, error) { err := b.grow() if err != nil { b.mutex.Unlock() + return 0, err } } // store the length of the packet - b.data[b.tail] = uint8(len(packet) >> 8) + b.data[b.tail] = uint8(len(packet) >> 8) //nolint:gosec b.tail++ if b.tail >= len(b.data) { b.tail = 0 } - b.data[b.tail] = uint8(len(packet)) + b.data[b.tail] = uint8(len(packet)) //nolint:gosec b.tail++ if b.tail >= len(b.data) { b.tail = 0 @@ -185,7 +188,7 @@ func (b *Buffer) Write(packet []byte) (int, error) { // Blocks until data is available or the buffer is closed. // Returns io.ErrShortBuffer is the packet is too small to copy the Write. // Returns io.EOF if the buffer is closed. -func (b *Buffer) Read(packet []byte) (n int, err error) { //nolint:gocognit +func (b *Buffer) Read(packet []byte) (n int, err error) { //nolint:gocognit,cyclop // Return immediately if the deadline is already exceeded. select { case <-b.readDeadline.Done(): @@ -196,7 +199,7 @@ func (b *Buffer) Read(packet []byte) (n int, err error) { //nolint:gocognit for { b.mutex.Lock() - if b.head != b.tail { + if b.head != b.tail { //nolint:nestif // decode the packet size n1 := b.data[b.head] b.head++ @@ -243,11 +246,13 @@ func (b *Buffer) Read(packet []byte) (n int, err error) { //nolint:gocognit if copied < count { return copied, io.ErrShortBuffer } + return copied, nil } if b.closed { b.mutex.Unlock() + return 0, io.EOF } b.mutex.Unlock() @@ -267,6 +272,7 @@ func (b *Buffer) Close() (err error) { if b.closed { b.mutex.Unlock() + return nil } @@ -281,6 +287,7 @@ func (b *Buffer) Close() (err error) { func (b *Buffer) Count() int { b.mutex.Lock() defer b.mutex.Unlock() + return b.count } @@ -308,6 +315,7 @@ func (b *Buffer) size() int { if size < 0 { size += len(b.data) } + return size } @@ -329,5 +337,6 @@ func (b *Buffer) SetLimitSize(limit int) { // Setting to zero means no deadline. func (b *Buffer) SetReadDeadline(t time.Time) error { b.readDeadline.Set(t) + return nil } diff --git a/packetio/buffer_test.go b/packetio/buffer_test.go index 2f35a4a..ce9d2b6 100644 --- a/packetio/buffer_test.go +++ b/packetio/buffer_test.go @@ -91,6 +91,8 @@ func TestBuffer(t *testing.T) { } func testWraparound(t *testing.T, grow bool) { + t.Helper() + assert := assert.New(t) buffer := NewBuffer() @@ -112,30 +114,30 @@ func testWraparound(t *testing.T, grow bool) { _, err = buffer.Write(p3) assert.NoError(err) - p := make([]byte, 10) + packet := make([]byte, 10) - n, err := buffer.Read(p) + n, err := buffer.Read(packet) assert.NoError(err) - assert.Equal(p1, p[:n]) + assert.Equal(p1, packet[:n]) if grow { err = buffer.grow() assert.NoError(err) } - n, err = buffer.Read(p) + n, err = buffer.Read(packet) assert.NoError(err) - assert.Equal(p2, p[:n]) + assert.Equal(p2, packet[:n]) _, err = buffer.Write(p4) assert.NoError(err) - n, err = buffer.Read(p) + n, err = buffer.Read(packet) assert.NoError(err) - assert.Equal(p3, p[:n]) - n, err = buffer.Read(p) + assert.Equal(p3, packet[:n]) + n, err = buffer.Read(packet) assert.NoError(err) - assert.Equal(p4, p[:n]) + assert.Equal(p4, packet[:n]) if !grow { assert.Equal(len(buffer.data), minSize) @@ -410,6 +412,8 @@ func TestBufferAlloc(t *testing.T) { test := func(f func(count int) func(), count int, maxVal float64) func(t *testing.T) { return func(t *testing.T) { + t.Helper() + allocs := testing.AllocsPerRun(3, f(count)) if allocs > maxVal { t.Errorf("count=%v, max=%v, got %v", @@ -419,23 +423,24 @@ func TestBufferAlloc(t *testing.T) { } } - w := func(count int) func() { + writer := func(count int) func() { return func() { buffer := NewBuffer() for i := 0; i < count; i++ { _, err := buffer.Write(packet) if err != nil { t.Errorf("Write: %v", err) + break } } } } - t.Run("100 writes", test(w, 100, 11)) - t.Run("200 writes", test(w, 200, 14)) - t.Run("400 writes", test(w, 400, 17)) - t.Run("1000 writes", test(w, 1000, 21)) + t.Run("100 writes", test(writer, 100, 11)) + t.Run("200 writes", test(writer, 200, 14)) + t.Run("400 writes", test(writer, 400, 17)) + t.Run("1000 writes", test(writer, 1000, 21)) wr := func(count int) func() { return func() { @@ -459,6 +464,7 @@ func TestBufferAlloc(t *testing.T) { } func benchmarkBufferWR(b *testing.B, size int64, write bool, grow int) { // nolint:unparam + b.Helper() buffer := NewBuffer() packet := make([]byte, size) @@ -513,7 +519,7 @@ func BenchmarkBufferWR1400(b *testing.B) { benchmarkBufferWR(b, 1400, false, 128000) } -// Here, the buffer never becomes empty, which forces wraparound +// Here, the buffer never becomes empty, which forces wraparound. func BenchmarkBufferWWR14(b *testing.B) { benchmarkBufferWR(b, 14, true, 128000) } @@ -527,6 +533,8 @@ func BenchmarkBufferWWR1400(b *testing.B) { } func benchmarkBuffer(b *testing.B, size int64) { + b.Helper() + buffer := NewBuffer() b.SetBytes(size) @@ -540,6 +548,7 @@ func benchmarkBuffer(b *testing.B, size int64) { break } else if err != nil { b.Error(err) + break } } @@ -647,8 +656,9 @@ func TestBufferConcurrentReadWrite(t *testing.T) { if readErr != nil { return } - if atomic.AddUint64(&numRead, 1) == uint64(numPkts) { + if atomic.AddUint64(&numRead, 1) == uint64(numPkts) { //nolint:gosec close(allRead) + return } } diff --git a/packetio/errors.go b/packetio/errors.go index 4974a10..eb45a78 100644 --- a/packetio/errors.go +++ b/packetio/errors.go @@ -7,7 +7,7 @@ import ( "errors" ) -// netError implements net.Error +// netError implements net.Error. type netError struct { error timeout, temporary bool @@ -25,6 +25,6 @@ var ( // ErrFull is returned when the buffer has hit the configured limits. ErrFull = errors.New("packetio.Buffer is full, discarding write") - // ErrTimeout is returned when a deadline has expired + // ErrTimeout is returned when a deadline has expired. ErrTimeout = errors.New("i/o timeout") ) diff --git a/replaydetector/fixedbig.go b/replaydetector/fixedbig.go index 80cb6b3..8a5655d 100644 --- a/replaydetector/fixedbig.go +++ b/replaydetector/fixedbig.go @@ -20,6 +20,7 @@ func newFixedBigInt(n uint) *fixedBigInt { if chunkSize == 0 { chunkSize = 1 } + return &fixedBigInt{ bits: make([]uint64, chunkSize), n: n, @@ -28,11 +29,11 @@ func newFixedBigInt(n uint) *fixedBigInt { } // Lsh is the left shift operation. -func (s *fixedBigInt) Lsh(n uint) { +func (s *fixedBigInt) Lsh(n uint) { //nolint:varnamelen if n == 0 { return } - nChunk := int(n / 64) + nChunk := int(n / 64) //nolint:gosec nN := n % 64 for i := len(s.bits) - 1; i >= 0; i-- { @@ -58,6 +59,7 @@ func (s *fixedBigInt) Bit(i uint) uint { if s.bits[chunk]&(1<= 0; i-- { out += fmt.Sprintf("%016X", s.bits[i]) } + return out } diff --git a/replaydetector/replaydetector.go b/replaydetector/replaydetector.go index d407995..58ace65 100644 --- a/replaydetector/replaydetector.go +++ b/replaydetector/replaydetector.go @@ -63,6 +63,7 @@ func (d *slidingWindowDetector) Check(seq uint64) (func() bool, bool) { } diff := (d.latestSeq - seq) % d.maxSeq d.mask.SetBit(uint(diff)) + return latest }, true } @@ -99,15 +100,15 @@ func (d *wrappedSlidingWindowDetector) Check(seq uint64) (func() bool, bool) { d.init = true } - diff := int64(d.latestSeq) - int64(seq) + diff := int64(d.latestSeq) - int64(seq) //nolint:gosec // GG115 TODO check // Wrap the number. - if diff > int64(d.maxSeq)/2 { - diff -= int64(d.maxSeq + 1) - } else if diff <= -int64(d.maxSeq)/2 { - diff += int64(d.maxSeq + 1) + if diff > int64(d.maxSeq)/2 { //nolint:gosec // GG115 TODO check + diff -= int64(d.maxSeq + 1) //nolint:gosec // GG115 TODO check + } else if diff <= -int64(d.maxSeq)/2 { //nolint:gosec // GG115 TODO check + diff += int64(d.maxSeq + 1) //nolint:gosec // GG115 TODO check } - if diff >= int64(d.windowSize) { + if diff >= int64(d.windowSize) { //nolint:gosec // GG115 TODO check // Too old. return nop, false } @@ -127,6 +128,7 @@ func (d *wrappedSlidingWindowDetector) Check(seq uint64) (func() bool, bool) { latest = true } d.mask.SetBit(uint(d.latestSeq - seq)) + return latest }, true } diff --git a/replaydetector/replaydetector_test.go b/replaydetector/replaydetector_test.go index f19836e..0ff80f8 100644 --- a/replaydetector/replaydetector_test.go +++ b/replaydetector/replaydetector_test.go @@ -189,26 +189,26 @@ var commonCases = map[string]testCase{ //nolint:gochecknoglobals } func TestReplayDetector(t *testing.T) { - for name, c := range commonCases { - c := c + for name, testCase := range commonCases { + testCase := testCase t.Run(name, func(t *testing.T) { - det := New(c.windowSize, c.maxSeq) + det := New(testCase.windowSize, testCase.maxSeq) var out []uint64 - for i, seq := range c.input { + for i, seq := range testCase.input { accept, ok := det.Check(seq) - if ok != c.valid[i] { - t.Errorf("Unexpected validity (%d):\nexpected: %v\ngot: %v", seq, c.valid[i], ok) + if ok != testCase.valid[i] { + t.Errorf("Unexpected validity (%d):\nexpected: %v\ngot: %v", seq, testCase.valid[i], ok) } if ok { out = append(out, seq) } - if latest := accept(); latest != c.latest[i] { - t.Errorf("Unexpected sequence latest status (%d):\nexpected: %v\ngot: %v", seq, c.latest[i], latest) + if latest := accept(); latest != testCase.latest[i] { + t.Errorf("Unexpected sequence latest status (%d):\nexpected: %v\ngot: %v", seq, testCase.latest[i], latest) } } - if !reflect.DeepEqual(c.expected, out) { + if !reflect.DeepEqual(testCase.expected, out) { t.Errorf("Wrong replay detection result:\nexpected: %v\ngot: %v", - c.expected, out, + testCase.expected, out, ) } }) @@ -258,25 +258,25 @@ func TestReplayDetectorWrapped(t *testing.T) { cases[name] = c } for name, c := range cases { - c := c + testCase := c t.Run(name, func(t *testing.T) { - det := WithWrap(c.windowSize, c.maxSeq) + det := WithWrap(testCase.windowSize, testCase.maxSeq) var out []uint64 - for i, seq := range c.input { + for i, seq := range testCase.input { accept, ok := det.Check(seq) - if ok != c.valid[i] { - t.Errorf("Unexpected validity (%d):\nexpected: %v\ngot: %v", seq, c.valid[i], ok) + if ok != testCase.valid[i] { + t.Errorf("Unexpected validity (%d):\nexpected: %v\ngot: %v", seq, testCase.valid[i], ok) } if ok { out = append(out, seq) } - if latest := accept(); latest != c.latest[i] { - t.Errorf("Unexpected sequence latest status (%d):\nexpected: %v\ngot: %v", seq, c.latest[i], latest) + if latest := accept(); latest != testCase.latest[i] { + t.Errorf("Unexpected sequence latest status (%d):\nexpected: %v\ngot: %v", seq, testCase.latest[i], latest) } } - if !reflect.DeepEqual(c.expected, out) { + if !reflect.DeepEqual(testCase.expected, out) { t.Errorf("Wrong replay detection result:\nexpected: %v\ngot: %v", - c.expected, out, + testCase.expected, out, ) } }) diff --git a/stdnet/net.go b/stdnet/net.go index 3d2a6e8..406b1e4 100644 --- a/stdnet/net.go +++ b/stdnet/net.go @@ -31,7 +31,7 @@ func NewNet() (*Net, error) { return n, n.UpdateInterfaces() } -// Compile-time assertion +// Compile-time assertion. var _ transport.Net = &Net{} // UpdateInterfaces updates the internal list of network interfaces @@ -65,7 +65,7 @@ func (n *Net) UpdateInterfaces() error { } // Interfaces returns a slice of interfaces which are available on the -// system +// system. func (n *Net) Interfaces() ([]*transport.Interface, error) { return n.interfaces, nil } @@ -162,7 +162,7 @@ func (d stdDialer) Dial(network, address string) (net.Conn, error) { return d.Dialer.Dial(network, address) } -// CreateDialer creates an instance of vnet.Dialer +// CreateDialer creates an instance of vnet.Dialer. func (n *Net) CreateDialer(d *net.Dialer) transport.Dialer { return stdDialer{d} } diff --git a/stdnet/net_test.go b/stdnet/net_test.go index a1b619e..db1c69f 100644 --- a/stdnet/net_test.go +++ b/stdnet/net_test.go @@ -14,7 +14,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestStdNet(t *testing.T) { +func TestStdNet(t *testing.T) { //nolint:cyclop log := logging.NewDefaultLoggerFactory().NewLogger("test") t.Run("Interfaces", func(t *testing.T) { @@ -202,6 +202,7 @@ func TestStdNet(t *testing.T) { for _, ifc := range ifs { if ifc.Flags&net.FlagLoopback != 0 { loName = ifc.Name + break } } diff --git a/test/bridge.go b/test/bridge.go index 721dec7..fa4c19f 100644 --- a/test/bridge.go +++ b/test/bridge.go @@ -79,6 +79,7 @@ func (conn *bridgeConn) Read(b []byte) (int, error) { return 0, io.EOF } n := copy(b, data) + return n, nil case <-conn.readDeadline.Done(): return 0, &netError{errIOTimeout, true, true} @@ -100,6 +101,7 @@ func (conn *bridgeConn) Write(b []byte) (int, error) { if !conn.br.Push(b, conn.id) { return 0, &netError{errBridgeConnClosed, false, false} } + return len(b), nil } @@ -114,15 +116,16 @@ func (conn *bridgeConn) Close() error { conn.closeReq = true conn.closing = true + return nil } -// LocalAddr is not used +// LocalAddr is not used. func (conn *bridgeConn) LocalAddr() net.Addr { return bridgeConnAddr(conn.id) } -// RemoteAddr is not used +// RemoteAddr is not used. func (conn *bridgeConn) RemoteAddr() net.Addr { return nil } // SetDeadline sets deadline of Read/Write operation. @@ -130,6 +133,7 @@ func (conn *bridgeConn) RemoteAddr() net.Addr { return nil } func (conn *bridgeConn) SetDeadline(t time.Time) error { conn.writeDeadline.Set(t) conn.readDeadline.Set(t) + return nil } @@ -137,6 +141,7 @@ func (conn *bridgeConn) SetDeadline(t time.Time) error { // Setting zero means no deadline. func (conn *bridgeConn) SetReadDeadline(t time.Time) error { conn.readDeadline.Set(t) + return nil } @@ -144,6 +149,7 @@ func (conn *bridgeConn) SetReadDeadline(t time.Time) error { // Setting zero means no deadline. func (conn *bridgeConn) SetWriteDeadline(t time.Time) error { conn.writeDeadline.Set(t) + return nil } @@ -182,14 +188,16 @@ func inverse(s [][]byte) error { for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] } + return nil } -// drop n packets from the slice starting from offset +// drop n packets from the slice starting from offset. func drop(s [][]byte, offset, n int) [][]byte { if offset+n > len(s) { n = len(s) - offset } + return append(s[:offset], s[offset+n:]...) } @@ -236,13 +244,14 @@ func (br *Bridge) Len(fromID int) int { if fromID == 0 { return len(br.queue0to1) } + return len(br.queue1to0) } // Push pushes a packet into the specified queue. -func (br *Bridge) Push(packet []byte, fromID int) bool { //nolint:gocognit - d := make([]byte, len(packet)) - copy(d, packet) +func (br *Bridge) Push(packet []byte, fromID int) bool { //nolint:gocognit,cyclop + data := make([]byte, len(packet)) + copy(data, packet) // Push rate should be limited as same as Tick rate. // Otherwise, queue grows too fast on free running Write. @@ -265,17 +274,18 @@ func (br *Bridge) Push(packet []byte, fromID int) bool { //nolint:gocognit if fromID == 1 && closing1 { return false } + return true } - if fromID == 0 { + if fromID == 0 { //nolint:nestif switch { case br.dropNWrites0 > 0: br.dropNWrites0-- // fmt.Printf("br: dropped a packet of size %d (rem: %d for q0)\n", len(d), br.dropNWrites0) // nolint case br.reorderNWrites0 > 0: br.reorderNWrites0-- - br.stack0 = append(br.stack0, d) + br.stack0 = append(br.stack0, data) // fmt.Printf("stack0 size: %d\n", len(br.stack0)) // nolint if br.reorderNWrites0 == 0 { if err := inverse(br.stack0); err == nil { @@ -285,11 +295,11 @@ func (br *Bridge) Push(packet []byte, fromID int) bool { //nolint:gocognit br.err = err } } - case br.filterCB0 != nil && !br.filterCB0(d): + case br.filterCB0 != nil && !br.filterCB0(data): // fmt.Printf("br: filtered out a packet of size %d (q0)\n", len(d)) // nolint default: // fmt.Printf("br: routed a packet of size %d (q0)\n", len(d)) // nolint - br.queue0to1 = append(br.queue0to1, d) + br.queue0to1 = append(br.queue0to1, data) } } else { switch { @@ -298,20 +308,21 @@ func (br *Bridge) Push(packet []byte, fromID int) bool { //nolint:gocognit // fmt.Printf("br: dropped a packet of size %d (rem: %d for q1)\n", len(d), br.dropNWrites0) // nolint case br.reorderNWrites1 > 0: br.reorderNWrites1-- - br.stack1 = append(br.stack1, d) + br.stack1 = append(br.stack1, data) if br.reorderNWrites1 == 0 { if err := inverse(br.stack1); err != nil { br.err = err } br.queue1to0 = append(br.queue1to0, br.stack1...) } - case br.filterCB1 != nil && !br.filterCB1(d): + case br.filterCB1 != nil && !br.filterCB1(data): // fmt.Printf("br: filtered out a packet of size %d (q1)\n", len(d)) // nolint default: // fmt.Printf("br: routed a packet of size %d (q1)\n", len(d)) // nolint - br.queue1to0 = append(br.queue1to0, d) + br.queue1to0 = append(br.queue1to0, data) } } + return true } @@ -323,6 +334,7 @@ func (br *Bridge) Reorder(fromID int) error { if fromID == 0 { return inverse(br.queue0to1) } + return inverse(br.queue1to0) } @@ -376,7 +388,7 @@ func (br *Bridge) clear() { // Tick attempts to hand a packet from the queue for each directions, to readers, // if there are waiting on the queue. If there's no reader, it will return // immediately. -func (br *Bridge) Tick() int { +func (br *Bridge) Tick() int { //nolint:cyclop br.mutex.Lock() defer br.mutex.Unlock() @@ -428,7 +440,8 @@ func (br *Bridge) Process() { } } -// SetLossChance sets the probability of writes being discard (to introduce artificial loss) +// SetLossChance sets the probability of writes being discard +// ( to introduce artificial loss). func (br *Bridge) SetLossChance(chance int) error { if chance > 100 || chance < 0 { return errBadLossChanceRange @@ -437,6 +450,7 @@ func (br *Bridge) SetLossChance(chance int) error { rand.Seed(time.Now().UTC().UnixNano()) br.conn0.lossChance = chance br.conn1.lossChance = chance + return nil } diff --git a/test/bridge_test.go b/test/bridge_test.go index 2ddfbb1..a819b99 100644 --- a/test/bridge_test.go +++ b/test/bridge_test.go @@ -18,7 +18,7 @@ const ( msg2 = `DEFG` ) -// helper to close both conns +// helper to close both conns. func closeBridge(br *Bridge) error { if err := br.conn0.Close(); err != nil { return err @@ -33,7 +33,7 @@ type AsyncResult struct { msg string } -func TestBridge(t *testing.T) { +func TestBridge(t *testing.T) { //nolint:gocyclo,cyclop,maintidx tt := TimeOut(30 * time.Second) defer tt.Stop() @@ -364,6 +364,7 @@ func TestBridge(t *testing.T) { t.Run("drop next N packets", func(t *testing.T) { testFrom := func(t *testing.T, fromID int) { + t.Helper() readRes := make(chan AsyncResult, 5) br := NewBridge() conn0 := br.GetConn0() @@ -450,6 +451,7 @@ func (c *closePropagator) Close() error { c.otherEnd.mutex.Lock() c.otherEnd.closing = true c.otherEnd.mutex.Unlock() + return c.bridgeConn.Close() } @@ -465,10 +467,12 @@ func TestNetTest(t *testing.T) { br.Process() if conn0.isClosed() && conn1.isClosed() { wg.Done() + return } } }() + return &closePropagator{conn0, conn1}, &closePropagator{conn1, conn0}, func() { // RacyRead test leave receive buffer filled. diff --git a/test/rand.go b/test/rand.go index a395f68..bbf3fda 100644 --- a/test/rand.go +++ b/test/rand.go @@ -22,6 +22,7 @@ func initRand() randomizer { if _, err := crand.Read(randomness); err != nil { fmt.Println("Failed to initiate randomness:", err) // nolint } + return randomizer{ randomness: randomness, } @@ -34,5 +35,6 @@ func (r *randomizer) randBuf(size int) ([]byte, error) { } start := mrand.Intn(n) //nolint:gosec + return r.randomness[start : start+size], nil } diff --git a/test/stress.go b/test/stress.go index c3c7e32..418dfda 100644 --- a/test/stress.go +++ b/test/stress.go @@ -16,7 +16,7 @@ import ( var errByteSequenceChanged = errors.New("byte sequence changed") -// Options represents the configuration of the stress test +// Options represents the configuration of the stress test. type Options struct { MsgSize int MsgCount int @@ -113,5 +113,6 @@ func write(ctx context.Context, c netctx.Writer, bufs chan []byte, opt Options) return err } } + return nil } diff --git a/test/util.go b/test/util.go index b320108..69d46cd 100644 --- a/test/util.go +++ b/test/util.go @@ -29,6 +29,8 @@ func TimeOut(t time.Duration) *time.Timer { } func tryCheckRoutinesLoop(tb testing.TB, failMessage string) { + tb.Helper() + try := 0 ticker := time.NewTicker(200 * time.Millisecond) defer ticker.Stop() @@ -45,9 +47,11 @@ func tryCheckRoutinesLoop(tb testing.TB, failMessage string) { } } -// CheckRoutines is used to check for leaked go-routines +// CheckRoutines is used to check for leaked go-routines. func CheckRoutines(t *testing.T) func() { + t.Helper() tryCheckRoutinesLoop(t, "Unexpected routines on test startup") + return func() { tryCheckRoutinesLoop(t, "Unexpected routines on test end") } @@ -68,7 +72,10 @@ func CheckRoutines(t *testing.T) func() { // best we can do is sleep a little bit and try to encourage the runtime // to run that goroutine (G) on the machine (M) it belongs to. func CheckRoutinesStrict(tb testing.TB) func() { + tb.Helper() + tryCheckRoutinesLoop(tb, "Unexpected routines on test startup") + return func() { runtime.Gosched() runtime.GC() @@ -94,6 +101,7 @@ func CheckRoutinesStrict(tb testing.TB) func() { func getRoutines() []string { buf := make([]byte, 2<<20) buf = buf[:runtime.Stack(buf, true)] + return filterRoutines(strings.Split(string(buf), "\n\n")) } @@ -109,6 +117,7 @@ func filterRoutines(routines []string) []string { } result = append(result, stack) } + return result } @@ -124,7 +133,7 @@ func GatherErrs(c chan error) []error { return errs } -// FlattenErrs flattens a slice of errors into a single error +// FlattenErrs flattens a slice of errors into a single error. func FlattenErrs(errs []error) error { var errStrings []string diff --git a/udp/batchconn.go b/udp/batchconn.go index 54bdab6..b31da2a 100644 --- a/udp/batchconn.go +++ b/udp/batchconn.go @@ -15,17 +15,17 @@ import ( "golang.org/x/net/ipv6" ) -// BatchWriter represents conn can write messages in batch +// BatchWriter represents conn can write messages in batch. type BatchWriter interface { WriteBatch(ms []ipv4.Message, flags int) (int, error) } -// BatchReader represents conn can read messages in batch +// BatchReader represents conn can read messages in batch. type BatchReader interface { ReadBatch(msg []ipv4.Message, flags int) (int, error) } -// BatchPacketConn represents conn can read/write messages in batch +// BatchPacketConn represents conn can read/write messages in batch. type BatchPacketConn interface { BatchWriter BatchReader @@ -90,7 +90,7 @@ func NewBatchConn(conn net.PacketConn, batchWriteSize int, batchWriteInterval ti return bc } -// Close batchConn and the underlying PacketConn +// Close batchConn and the underlying PacketConn. func (c *BatchConn) Close() error { atomic.StoreInt32(&c.closed, 1) c.batchWriteMutex.Lock() @@ -101,6 +101,7 @@ func (c *BatchConn) Close() error { if c.batchConn != nil { return c.batchConn.Close() } + return c.PacketConn.Close() } @@ -109,6 +110,7 @@ func (c *BatchConn) WriteTo(b []byte, addr net.Addr) (int, error) { if c.batchConn == nil { return c.PacketConn.WriteTo(b, addr) } + return c.enqueueMessage(b, addr) } @@ -136,6 +138,7 @@ func (c *BatchConn) enqueueMessage(buf []byte, raddr net.Addr) (int, error) { if c.batchWritePos == c.batchWriteSize { err = c.flush() } + return len(buf), err } @@ -146,10 +149,13 @@ func (c *BatchConn) ReadBatch(msgs []ipv4.Message, flags int) (int, error) { if err == nil { msgs[0].N = n msgs[0].Addr = addr + return 1, nil } + return 0, err } + return c.batchConn.ReadBatch(msgs, flags) } @@ -160,11 +166,13 @@ func (c *BatchConn) flush() error { n, err := c.batchConn.WriteBatch(c.batchWriteMessages[txN:c.batchWritePos], 0) if err != nil { writeErr = err + break } txN += n } c.batchWritePos = 0 c.batchWriteLast = time.Now() + return writeErr } diff --git a/udp/conn.go b/udp/conn.go index 071b30e..f4dd199 100644 --- a/udp/conn.go +++ b/udp/conn.go @@ -23,14 +23,14 @@ const ( defaultListenBacklog = 128 // same as Linux default ) -// Typed errors +// Typed errors. var ( ErrClosedListener = errors.New("udp: listener closed") ErrListenQueueExceeded = errors.New("udp: listen queue exceeded") ErrInvalidBatchConfig = errors.New("udp: invalid batch config") ) -// listener augments a connection-oriented Listener over a UDP PacketConn +// listener augments a connection-oriented Listener over a UDP PacketConn. type listener struct { pConn net.PacketConn @@ -58,10 +58,12 @@ func (l *listener) Accept() (net.Conn, error) { select { case c := <-l.acceptCh: l.connWG.Add(1) + return c, nil case <-l.readDoneCh: err, _ := l.errRead.Load().(error) + return nil, err case <-l.doneCh: @@ -175,7 +177,7 @@ func (lc *ListenConfig) Listen(network string, laddr *net.UDPAddr) (net.Listener _ = conn.SetWriteBuffer(lc.WriteBufferSize) } - l := &listener{ + listnerer := &listener{ pConn: conn, acceptCh: make(chan *Conn, lc.Backlog), conns: make(map[string]*Conn), @@ -186,24 +188,24 @@ func (lc *ListenConfig) Listen(network string, laddr *net.UDPAddr) (net.Listener } if lc.Batch.Enable { - l.pConn = NewBatchConn(conn, lc.Batch.WriteBatchSize, lc.Batch.WriteBatchInterval) - l.readBatchSize = lc.Batch.ReadBatchSize + listnerer.pConn = NewBatchConn(conn, lc.Batch.WriteBatchSize, lc.Batch.WriteBatchInterval) + listnerer.readBatchSize = lc.Batch.ReadBatchSize } - l.accepting.Store(true) - l.connWG.Add(1) - l.readWG.Add(2) // wait readLoop and Close execution routine + listnerer.accepting.Store(true) + listnerer.connWG.Add(1) + listnerer.readWG.Add(2) // wait readLoop and Close execution routine - go l.readLoop() + go listnerer.readLoop() go func() { - l.connWG.Wait() - if err := l.pConn.Close(); err != nil { - l.errClose.Store(err) + listnerer.connWG.Wait() + if err := listnerer.pConn.Close(); err != nil { + listnerer.errClose.Store(err) } - l.readWG.Done() + listnerer.readWG.Done() }() - return l, nil + return listnerer, nil } // Listen creates a new listener using default ListenConfig. @@ -237,6 +239,7 @@ func (l *listener) readBatch(br BatchReader) { n, err := br.ReadBatch(msgs, 0) if err != nil { l.errRead.Store(err) + return } for i := 0; i < n; i++ { @@ -251,6 +254,7 @@ func (l *listener) read() { n, raddr, err := l.pConn.ReadFrom(buf) if err != nil { l.errRead.Store(err) + return } l.dispatchMsg(raddr, buf[:n]) @@ -288,10 +292,11 @@ func (l *listener) getConn(raddr net.Addr, buf []byte) (*Conn, bool, error) { return nil, false, ErrListenQueueExceeded } } + return conn, true, nil } -// Conn augments a connection-oriented connection over a UDP PacketConn +// Conn augments a connection-oriented connection over a UDP PacketConn. type Conn struct { listener *listener @@ -315,22 +320,23 @@ func (l *listener) newConn(rAddr net.Addr) *Conn { } } -// Read reads from c into p +// Read reads from c into p. func (c *Conn) Read(p []byte) (int, error) { return c.buffer.Read(p) } -// Write writes len(p) bytes from p to the DTLS connection +// Write writes len(p) bytes from p to the DTLS connection. func (c *Conn) Write(p []byte) (n int, err error) { select { case <-c.writeDeadline.Done(): return 0, context.DeadlineExceeded default: } + return c.listener.pConn.WriteTo(p, c.rAddr) } -// Close closes the conn and releases any Read calls +// Close closes the conn and releases any Read calls. func (c *Conn) Close() error { var err error c.doneOnce.Do(func() { @@ -359,28 +365,29 @@ func (c *Conn) Close() error { return err } -// LocalAddr implements net.Conn.LocalAddr +// LocalAddr implements net.Conn.LocalAddr. func (c *Conn) LocalAddr() net.Addr { return c.listener.pConn.LocalAddr() } -// RemoteAddr implements net.Conn.RemoteAddr +// RemoteAddr implements net.Conn.RemoteAddr. func (c *Conn) RemoteAddr() net.Addr { return c.rAddr } -// SetDeadline implements net.Conn.SetDeadline +// SetDeadline implements net.Conn.SetDeadline. func (c *Conn) SetDeadline(t time.Time) error { c.writeDeadline.Set(t) + return c.SetReadDeadline(t) } -// SetReadDeadline implements net.Conn.SetDeadline +// SetReadDeadline implements net.Conn.SetDeadline. func (c *Conn) SetReadDeadline(t time.Time) error { return c.buffer.SetReadDeadline(t) } -// SetWriteDeadline implements net.Conn.SetDeadline +// SetWriteDeadline implements net.Conn.SetDeadline. func (c *Conn) SetWriteDeadline(t time.Time) error { c.writeDeadline.Set(t) // Write deadline of underlying connection should not be changed diff --git a/udp/conn_test.go b/udp/conn_test.go index 0f30de8..8a9f3a3 100644 --- a/udp/conn_test.go +++ b/udp/conn_test.go @@ -56,6 +56,8 @@ func TestStressDuplex(t *testing.T) { } func stressDuplex(t *testing.T) { + t.Helper() + listener, ca, cb, err := pipe() if err != nil { t.Fatal(err) @@ -136,6 +138,7 @@ func TestListenerCloseUnaccepted(t *testing.T) { conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) if dErr != nil { t.Error(dErr) + continue } if _, wErr := conn.Write([]byte{byte(i)}); wErr != nil { @@ -154,7 +157,7 @@ func TestListenerCloseUnaccepted(t *testing.T) { } } -func TestListenerAcceptFilter(t *testing.T) { +func TestListenerAcceptFilter(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -221,6 +224,7 @@ func TestListenerAcceptFilter(t *testing.T) { if !errors.Is(aArr, ErrClosedListener) { t.Error(aArr) } + return } close(chAccepted) @@ -247,7 +251,7 @@ func TestListenerAcceptFilter(t *testing.T) { } } -func TestListenerConcurrent(t *testing.T) { +func TestListenerConcurrent(t *testing.T) { //nolint:cyclop // Limit runtime in case of deadlocks lim := test.TimeOut(time.Second * 20) defer lim.Stop() @@ -270,6 +274,7 @@ func TestListenerConcurrent(t *testing.T) { conn, dErr := net.DialUDP(network, nil, listener.Addr().(*net.UDPAddr)) if dErr != nil { t.Error(dErr) + continue } if _, wErr := conn.Write([]byte{byte(i)}); wErr != nil { @@ -286,6 +291,7 @@ func TestListenerConcurrent(t *testing.T) { conn, lErr := listener.Accept() if lErr != nil { t.Error(lErr) + continue } b := make([]byte, 1) @@ -368,7 +374,7 @@ func getConfig() (string, *net.UDPAddr) { return "udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 0} } -func TestConnClose(t *testing.T) { +func TestConnClose(t *testing.T) { //nolint:cyclop lim := test.TimeOut(time.Second * 5) defer lim.Stop() @@ -396,12 +402,12 @@ func TestConnClose(t *testing.T) { report := test.CheckRoutines(t) defer report() - l, ca, cb, errPipe := pipe() + listn, ca, cb, errPipe := pipe() if errPipe != nil { t.Fatal(errPipe) } // Close l.pConn to inject error. - if err := l.(*listener).pConn.Close(); err != nil { //nolint:forcetypeassert + if err := listn.(*listener).pConn.Close(); err != nil { //nolint:forcetypeassert t.Error(err) } @@ -411,7 +417,7 @@ func TestConnClose(t *testing.T) { if err := ca.Close(); err != nil { t.Errorf("Failed to close B side: %v", err) } - if err := l.Close(); err == nil { + if err := listn.Close(); err == nil { t.Errorf("Error is not propagated to Listener.Close") } }) @@ -448,7 +454,7 @@ func TestConnClose(t *testing.T) { report := test.CheckRoutines(t) defer report() - l, ca, cb, errPipe := pipe() + listn, ca, cb, errPipe := pipe() if errPipe != nil { t.Fatal(errPipe) } @@ -475,7 +481,7 @@ func TestConnClose(t *testing.T) { if err := cb.Close(); err != nil { t.Errorf("Failed to close A side: %v", err) } - if err := l.Close(); err != nil { + if err := listn.Close(); err != nil { t.Errorf("Failed to close listener: %v", err) } }) diff --git a/utils/xor/xor_test.go b/utils/xor/xor_test.go index a694359..6dadba2 100644 --- a/utils/xor/xor_test.go +++ b/utils/xor/xor_test.go @@ -11,16 +11,16 @@ import ( "testing" ) -func TestXOR(t *testing.T) { - for j := 1; j <= 1024; j++ { +func TestXOR(t *testing.T) { //nolint:cyclop + for j := 1; j <= 1024; j++ { //nolint:varnamelen if testing.Short() && j > 16 { break } for alignP := 0; alignP < 2; alignP++ { for alignQ := 0; alignQ < 2; alignQ++ { for alignD := 0; alignD < 2; alignD++ { - p := make([]byte, j)[alignP:] - q := make([]byte, j)[alignQ:] + p := make([]byte, j)[alignP:] //nolint:varnamelen + q := make([]byte, j)[alignQ:] //nolint:varnamelen d0 := make([]byte, j+alignD+1) d0[j+alignD] = 42 d1 := d0[alignD : j+alignD] @@ -58,6 +58,7 @@ func minInt(a, b []byte) int { if len(b) < n { n = len(b) } + return n } diff --git a/vnet/chunk.go b/vnet/chunk.go index 9f59c9c..dde136c 100644 --- a/vnet/chunk.go +++ b/vnet/chunk.go @@ -50,11 +50,12 @@ var assignChunkTag = func() func() string { //nolint:gochecknoglobals return func() string { n := atomic.AddUint64(&tagCtr, 1) + return strconv.FormatUint(n, 36) } }() -// Chunk represents a packet passed around in the vnet +// Chunk represents a packet passed around in the vnet. type Chunk interface { setTimestamp() time.Time // used by router getTimestamp() time.Time // used by router @@ -81,6 +82,7 @@ type chunkIP struct { func (c *chunkIP) setTimestamp() time.Time { c.timestamp = time.Now() + return c.timestamp } @@ -164,6 +166,7 @@ func (c *chunkUDP) Network() string { func (c *chunkUDP) String() string { src := c.SourceAddr() dst := c.DestinationAddr() + return fmt.Sprintf("%s chunk %s %s => %s", src.Network(), c.tag, @@ -179,6 +182,7 @@ func (c *chunkUDP) setSourceAddr(address string) error { } c.sourceIP = addr.IP c.sourcePort = addr.Port + return nil } @@ -189,6 +193,7 @@ func (c *chunkUDP) setDestinationAddr(address string) error { } c.destinationIP = addr.IP c.destinationPort = addr.Port + return nil } @@ -256,6 +261,7 @@ func (c *chunkTCP) Network() string { func (c *chunkTCP) String() string { src := c.SourceAddr() dst := c.DestinationAddr() + return fmt.Sprintf("%s %s chunk %s %s => %s", src.Network(), c.flags.String(), @@ -272,6 +278,7 @@ func (c *chunkTCP) setSourceAddr(address string) error { } c.sourceIP = addr.IP c.sourcePort = addr.Port + return nil } @@ -282,5 +289,6 @@ func (c *chunkTCP) setDestinationAddr(address string) error { } c.destinationIP = addr.IP c.destinationPort = addr.Port + return nil } diff --git a/vnet/chunk_queue.go b/vnet/chunk_queue.go index 2393254..f9cd811 100644 --- a/vnet/chunk_queue.go +++ b/vnet/chunk_queue.go @@ -38,6 +38,7 @@ func (q *chunkQueue) push(c Chunk) bool { q.currentBytes += len(c.UserData()) q.chunks = append(q.chunks, c) + return true } diff --git a/vnet/chunk_queue_test.go b/vnet/chunk_queue_test.go index bcf2397..a525e6c 100644 --- a/vnet/chunk_queue_test.go +++ b/vnet/chunk_queue_test.go @@ -11,52 +11,52 @@ import ( ) func TestChunkQueue(t *testing.T) { - c := newChunkUDP(&net.UDPAddr{ + chunk := newChunkUDP(&net.UDPAddr{ IP: net.ParseIP("192.188.0.2"), Port: 1234, }, &net.UDPAddr{ IP: net.ParseIP(demoIP), Port: 5678, }) - c.userData = make([]byte, 1200) + chunk.userData = make([]byte, 1200) var ok bool - var q *chunkQueue - var d Chunk + var queue *chunkQueue + var chunk2 Chunk - q = newChunkQueue(0, 0) + queue = newChunkQueue(0, 0) - d = q.peek() - assert.Nil(t, d, "should return nil") + chunk2 = queue.peek() + assert.Nil(t, chunk2, "should return nil") - ok = q.push(c) + ok = queue.push(chunk) assert.True(t, ok, "should succeed") - d, ok = q.pop() + chunk2, ok = queue.pop() assert.True(t, ok, "should succeed") - assert.Equal(t, c, d, "should be the same") + assert.Equal(t, chunk, chunk2, "should be the same") - d, ok = q.pop() + chunk2, ok = queue.pop() assert.False(t, ok, "should fail") - assert.Nil(t, d, "should be nil") + assert.Nil(t, chunk2, "should be nil") - q = newChunkQueue(1, 0) - ok = q.push(c) + queue = newChunkQueue(1, 0) + ok = queue.push(chunk) assert.True(t, ok, "should succeed") - ok = q.push(c) + ok = queue.push(chunk) assert.False(t, ok, "should fail") - d = q.peek() - assert.Equal(t, c, d, "should be the same") + chunk2 = queue.peek() + assert.Equal(t, chunk, chunk2, "should be the same") - q = newChunkQueue(0, 1500) - ok = q.push(c) + queue = newChunkQueue(0, 1500) + ok = queue.push(chunk) assert.True(t, ok, "should succeed") - ok = q.push(c) + ok = queue.push(chunk) assert.False(t, ok, "should fail") - d = q.peek() - assert.Equal(t, c, d, "should be the same") + chunk2 = queue.peek() + assert.Equal(t, chunk, chunk2, "should be the same") } diff --git a/vnet/chunk_test.go b/vnet/chunk_test.go index 4248763..be22d71 100644 --- a/vnet/chunk_test.go +++ b/vnet/chunk_test.go @@ -41,24 +41,24 @@ func TestChunk(t *testing.T) { Port: 5678, } - var c Chunk = newChunkUDP(src, dst) - str := c.String() + var chunk Chunk = newChunkUDP(src, dst) + str := chunk.String() log.Debugf("chunk: %s", str) - assert.Equal(t, udp, c.Network(), "should match") + assert.Equal(t, udp, chunk.Network(), "should match") assert.True(t, strings.Contains(str, src.Network()), "should include network type") assert.True(t, strings.Contains(str, src.String()), "should include address") assert.True(t, strings.Contains(str, dst.String()), "should include address") - assert.True(t, c.getSourceIP().Equal(src.IP), "ip should match") - assert.True(t, c.getDestinationIP().Equal(dst.IP), "ip should match") + assert.True(t, chunk.getSourceIP().Equal(src.IP), "ip should match") + assert.True(t, chunk.getDestinationIP().Equal(dst.IP), "ip should match") // Test timestamp - ts := c.setTimestamp() - assert.Equal(t, ts, c.getTimestamp(), "timestamp should match") + ts := chunk.setTimestamp() + assert.Equal(t, ts, chunk.getTimestamp(), "timestamp should match") - uc := c.(*chunkUDP) //nolint:forcetypeassert + uc := chunk.(*chunkUDP) //nolint:forcetypeassert uc.userData = []byte("Hello") - cloned := c.Clone().(*chunkUDP) //nolint:forcetypeassert + cloned := chunk.Clone().(*chunkUDP) //nolint:forcetypeassert // Test setSourceAddr err := uc.setSourceAddr("2.3.4.5:4000") @@ -87,28 +87,28 @@ func TestChunk(t *testing.T) { Port: 5678, } - var c Chunk = newChunkTCP(src, dst, tcpSYN) - str := c.String() + var chunk Chunk = newChunkTCP(src, dst, tcpSYN) + str := chunk.String() log.Debugf("chunk: %s", str) - assert.Equal(t, "tcp", c.Network(), "should match") + assert.Equal(t, "tcp", chunk.Network(), "should match") assert.True(t, strings.Contains(str, src.Network()), "should include network type") assert.True(t, strings.Contains(str, src.String()), "should include address") assert.True(t, strings.Contains(str, dst.String()), "should include address") - assert.True(t, c.getSourceIP().Equal(src.IP), "ip should match") - assert.True(t, c.getDestinationIP().Equal(dst.IP), "ip should match") + assert.True(t, chunk.getSourceIP().Equal(src.IP), "ip should match") + assert.True(t, chunk.getDestinationIP().Equal(dst.IP), "ip should match") - tcp, ok := c.(*chunkTCP) + tcp, ok := chunk.(*chunkTCP) assert.True(t, ok, "type should match") assert.Equal(t, tcp.flags, tcpSYN, "flags should match") // Test timestamp - ts := c.setTimestamp() - assert.Equal(t, ts, c.getTimestamp(), "timestamp should match") + ts := chunk.setTimestamp() + assert.Equal(t, ts, chunk.getTimestamp(), "timestamp should match") - tc := c.(*chunkTCP) //nolint:forcetypeassert + tc := chunk.(*chunkTCP) //nolint:forcetypeassert tc.userData = []byte("Hello") - cloned := c.Clone().(*chunkTCP) //nolint:forcetypeassert + cloned := chunk.Clone().(*chunkTCP) //nolint:forcetypeassert // Test setSourceAddr err := tc.setSourceAddr("2.3.4.5:4000") diff --git a/vnet/conn.go b/vnet/conn.go index a407f72..6f42339 100644 --- a/vnet/conn.go +++ b/vnet/conn.go @@ -28,7 +28,7 @@ var ( errNoRemAddr = errors.New("no remAddr defined") ) -// vNet implements this +// vNet implements this. type connObserver interface { write(c Chunk) error onClosed(addr net.Addr) @@ -36,7 +36,7 @@ type connObserver interface { } // UDPConn is the implementation of the Conn and PacketConn interfaces for UDP network connections. -// compatible with net.PacketConn and net.Conn +// compatible with net.PacketConn and net.Conn. type UDPConn struct { locAddr *net.UDPAddr // read-only remAddr *net.UDPAddr // read-only @@ -76,6 +76,7 @@ func (c *UDPConn) Close() error { close(c.readCh) c.obs.onClosed(c.locAddr) + return nil } @@ -120,6 +121,7 @@ func (c *UDPConn) SetReadDeadline(t time.Time) error { d = time.Until(t) } c.readTimer.Reset(d) + return nil } @@ -138,6 +140,7 @@ func (c *UDPConn) SetWriteDeadline(time.Time) error { // after a fixed time limit; see SetDeadline and SetReadDeadline. func (c *UDPConn) Read(b []byte) (int, error) { n, _, err := c.ReadFrom(b) + return n, err } @@ -171,6 +174,7 @@ loop: break // discard (shouldn't happen) } } + return n, addr, err case <-c.readTimer.C: @@ -225,12 +229,12 @@ func (c *UDPConn) Write(b []byte) (int, error) { return c.WriteTo(b, c.remAddr) } -// WriteTo writes a packet with payload p to addr. +// WriteTo writes a packet with payload to addr. // WriteTo can be made to time out and return // an Error with Timeout() == true after a fixed time limit; // see SetDeadline and SetWriteDeadline. // On packet-oriented connections, write timeouts are rare. -func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { +func (c *UDPConn) WriteTo(payload []byte, addr net.Addr) (n int, err error) { dstAddr, ok := addr.(*net.UDPAddr) if !ok { return 0, errAddrNotUDPAddr @@ -246,12 +250,13 @@ func (c *UDPConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { } chunk := newChunkUDP(srcAddr, dstAddr) - chunk.userData = make([]byte, len(p)) - copy(chunk.userData, p) + chunk.userData = make([]byte, len(payload)) + copy(chunk.userData, payload) if err := c.obs.write(chunk); err != nil { return 0, err } - return len(p), nil + + return len(payload), nil } // WriteToUDP acts like WriteTo but takes a UDPAddr. diff --git a/vnet/conn_map.go b/vnet/conn_map.go index da22483..5e9a1ed 100644 --- a/vnet/conn_map.go +++ b/vnet/conn_map.go @@ -52,6 +52,7 @@ func (m *udpConnMap) insert(conn *UDPConn) error { } m.portMap[udpAddr.Port] = conns + return nil } @@ -67,8 +68,10 @@ func (m *udpConnMap) find(addr net.Addr) (*UDPConn, bool) { if len(conns) == 0 { // This can't happen! delete(m.portMap, udpAddr.Port) + return nil, false } + return conns[0], true } @@ -97,6 +100,7 @@ func (m *udpConnMap) delete(addr net.Addr) error { if udpAddr.IP.IsUnspecified() { // remove all from this port delete(m.portMap, udpAddr.Port) + return nil } @@ -125,7 +129,7 @@ func (m *udpConnMap) delete(addr net.Addr) error { return nil } -// size returns the number of UDPConns (UDP listeners) +// size returns the number of UDPConns (UDP listeners). func (m *udpConnMap) size() int { m.mutex.RLock() defer m.mutex.RUnlock() diff --git a/vnet/conn_test.go b/vnet/conn_test.go index e39b009..a94ad93 100644 --- a/vnet/conn_test.go +++ b/vnet/conn_test.go @@ -33,7 +33,7 @@ func (o *dummyObserver) determineSourceIP(locIP, _ net.IP) net.IP { return locIP } -func TestUDPConn(t *testing.T) { +func TestUDPConn(t *testing.T) { //nolint:cyclop,maintidx log := logging.NewDefaultLoggerFactory().NewLogger("test") t.Run("WriteTo ReadFrom", func(t *testing.T) { @@ -60,6 +60,7 @@ func TestUDPConn(t *testing.T) { chunk.userData = make([]byte, len(uc.userData)) copy(chunk.userData, uc.userData) conn.readCh <- chunk // echo back + return nil }, onOnClosed: func(net.Addr) { @@ -79,6 +80,7 @@ func TestUDPConn(t *testing.T) { n, addr, err2 := conn.ReadFrom(buf) if err2 != nil { log.Debug("conn closed. exiting the read loop") + break } log.Debug("read data") @@ -141,6 +143,7 @@ func TestUDPConn(t *testing.T) { chunk.userData = make([]byte, len(uc.userData)) copy(chunk.userData, uc.userData) conn.readCh <- chunk // echo back + return nil }, onOnClosed: func(net.Addr) { @@ -161,6 +164,7 @@ func TestUDPConn(t *testing.T) { n, err2 := conn.Read(buf) if err2 != nil { log.Debug("conn closed. exiting the read loop") + break } log.Debug("read data") @@ -196,6 +200,8 @@ func TestUDPConn(t *testing.T) { }) deadlineTest := func(t *testing.T, readOnly bool) { + t.Helper() + var nClosed int32 var conn *UDPConn var err error diff --git a/vnet/delay_filter.go b/vnet/delay_filter.go index 119e34e..3200af4 100644 --- a/vnet/delay_filter.go +++ b/vnet/delay_filter.go @@ -43,7 +43,7 @@ func (f *DelayFilter) onInboundChunk(c Chunk) { // Run starts forwarding of packets. Packets will be forwarded if they spent // >delay time in the internal queue. Must be called before any packet will be // forwarded. -func (f *DelayFilter) Run(ctx context.Context) { +func (f *DelayFilter) Run(ctx context.Context) { //nolint:cyclop timer := time.NewTimer(0) for { select { @@ -59,6 +59,7 @@ func (f *DelayFilter) Run(ctx context.Context) { next := f.queue.peek() if next == nil { timer.Reset(time.Minute) + continue } if n, ok := next.(timedChunk); ok && n.deadline.Before(now) { @@ -68,6 +69,7 @@ func (f *DelayFilter) Run(ctx context.Context) { next = f.queue.peek() if next == nil { timer.Reset(time.Minute) + continue } if n, ok := next.(timedChunk); ok { diff --git a/vnet/loss_filter.go b/vnet/loss_filter.go index 4b2d75f..a63bf56 100644 --- a/vnet/loss_filter.go +++ b/vnet/loss_filter.go @@ -9,7 +9,7 @@ import ( ) // LossFilter is a wrapper around NICs, that drops some of the packets passed to -// onInboundChunk +// onInboundChunk. type LossFilter struct { NIC chance int @@ -24,6 +24,7 @@ func NewLossFilter(nic NIC, chance int) (*LossFilter, error) { chance: chance, } rand.Seed(time.Now().UTC().UnixNano()) + return f, nil } diff --git a/vnet/loss_filter_test.go b/vnet/loss_filter_test.go index ac87c8c..41efb4d 100644 --- a/vnet/loss_filter_test.go +++ b/vnet/loss_filter_test.go @@ -35,9 +35,12 @@ func (n *mockNIC) setRouter(r *Router) error { } func newMockNIC(t *testing.T) *mockNIC { + t.Helper() + return &mockNIC{ mockGetInterface: func(string) (*transport.Interface, error) { assert.Fail(t, "unexpected call to mockGetInterface") + return nil, nil }, mockOnInboundChunk: func(Chunk) { @@ -45,10 +48,12 @@ func newMockNIC(t *testing.T) *mockNIC { }, mockGetStaticIPs: func() []net.IP { assert.Fail(t, "unexpected call to mockGetStaticIPs") + return nil }, mockSetRouter: func(*Router) error { assert.Fail(t, "unexpected call to mockSetRouter") + return nil }, } diff --git a/vnet/nat.go b/vnet/nat.go index a4be36e..f4722af 100644 --- a/vnet/nat.go +++ b/vnet/nat.go @@ -32,15 +32,15 @@ var ( type EndpointDependencyType uint8 const ( - // EndpointIndependent means the behavior is independent of the endpoint's address or port + // EndpointIndependent means the behavior is independent of the endpoint's address or port. EndpointIndependent EndpointDependencyType = iota - // EndpointAddrDependent means the behavior is dependent on the endpoint's address + // EndpointAddrDependent means the behavior is dependent on the endpoint's address. EndpointAddrDependent - // EndpointAddrPortDependent means the behavior is dependent on the endpoint's address and port + // EndpointAddrPortDependent means the behavior is dependent on the endpoint's address and port. EndpointAddrPortDependent ) -// NATMode defines basic behavior of the NAT +// NATMode defines basic behavior of the NAT. type NATMode uint8 const ( @@ -137,6 +137,7 @@ func (n *networkAddressTranslator) getPairedMappedIP(locIP net.IP) net.IP { return n.mappedIPs[i] } } + return nil } @@ -146,22 +147,24 @@ func (n *networkAddressTranslator) getPairedLocalIP(mappedIP net.IP) net.IP { return n.localIPs[i] } } + return nil } -func (n *networkAddressTranslator) translateOutbound(from Chunk) (Chunk, error) { +func (n *networkAddressTranslator) translateOutbound(from Chunk) (Chunk, error) { //nolint:cyclop n.mutex.Lock() defer n.mutex.Unlock() to := from.Clone() - if from.Network() == udp { + if from.Network() == udp { //nolint:nestif if n.natType.Mode == NATModeNAT1To1 { // 1:1 NAT behavior srcAddr := from.SourceAddr().(*net.UDPAddr) //nolint:forcetypeassert srcIP := n.getPairedMappedIP(srcAddr.IP) if srcIP == nil { n.log.Debugf("[%s] drop outbound chunk %s with not route", n.name, from.String()) + return nil, nil // nolint:nilnil } srcPort := srcAddr.Port @@ -191,13 +194,13 @@ func (n *networkAddressTranslator) translateOutbound(from Chunk) (Chunk, error) oKey := fmt.Sprintf("udp:%s:%s", from.SourceAddr().String(), bound) - m := n.findOutboundMapping(oKey) - if m == nil { + mapp := n.findOutboundMapping(oKey) + if mapp == nil { // Create a new mapping mappedPort := 0xC000 + n.udpPortCounter n.udpPortCounter++ - m = &mapping{ + mapp = &mapping{ proto: from.SourceAddr().Network(), local: from.SourceAddr().String(), bound: bound, @@ -206,24 +209,24 @@ func (n *networkAddressTranslator) translateOutbound(from Chunk) (Chunk, error) expires: time.Now().Add(n.natType.MappingLifeTime), } - n.outboundMap[oKey] = m + n.outboundMap[oKey] = mapp - iKey := fmt.Sprintf("udp:%s", m.mapped) + iKey := fmt.Sprintf("udp:%s", mapp.mapped) n.log.Debugf("[%s] created a new NAT binding oKey=%s iKey=%s", n.name, oKey, iKey) - m.filters[filterKey] = struct{}{} - n.log.Debugf("[%s] permit access from %s to %s", n.name, filterKey, m.mapped) - n.inboundMap[iKey] = m - } else if _, ok := m.filters[filterKey]; !ok { - n.log.Debugf("[%s] permit access from %s to %s", n.name, filterKey, m.mapped) - m.filters[filterKey] = struct{}{} + mapp.filters[filterKey] = struct{}{} + n.log.Debugf("[%s] permit access from %s to %s", n.name, filterKey, mapp.mapped) + n.inboundMap[iKey] = mapp + } else if _, ok := mapp.filters[filterKey]; !ok { + n.log.Debugf("[%s] permit access from %s to %s", n.name, filterKey, mapp.mapped) + mapp.filters[filterKey] = struct{}{} } - if err := to.setSourceAddr(m.mapped); err != nil { + if err := to.setSourceAddr(mapp.mapped); err != nil { return nil, err } } @@ -236,13 +239,13 @@ func (n *networkAddressTranslator) translateOutbound(from Chunk) (Chunk, error) return nil, errNonUDPTranslationNotSupported } -func (n *networkAddressTranslator) translateInbound(from Chunk) (Chunk, error) { +func (n *networkAddressTranslator) translateInbound(from Chunk) (Chunk, error) { //nolint:cyclop n.mutex.Lock() defer n.mutex.Unlock() to := from.Clone() - if from.Network() == udp { + if from.Network() == udp { //nolint:nestif if n.natType.Mode == NATModeNAT1To1 { // 1:1 NAT behavior dstAddr := from.DestinationAddr().(*net.UDPAddr) //nolint:forcetypeassert @@ -257,8 +260,8 @@ func (n *networkAddressTranslator) translateInbound(from Chunk) (Chunk, error) { } else { // Normal (NAPT) behavior iKey := fmt.Sprintf("udp:%s", from.DestinationAddr().String()) - m := n.findInboundMapping(iKey) - if m == nil { + mapping := n.findInboundMapping(iKey) + if mapping == nil { return nil, fmt.Errorf("drop %s as %w", from.String(), errNoNATBindingFound) } @@ -272,7 +275,7 @@ func (n *networkAddressTranslator) translateInbound(from Chunk) (Chunk, error) { filterKey = from.SourceAddr().String() } - if _, ok := m.filters[filterKey]; !ok { + if _, ok := mapping.filters[filterKey]; !ok { return nil, fmt.Errorf("drop %s as the remote %s %w", from.String(), filterKey, errHasNoPermission) } @@ -284,7 +287,7 @@ func (n *networkAddressTranslator) translateInbound(from Chunk) (Chunk, error) { // process is repeated with different ports, over time, it could // use up all the ports on the NAT. - if err := to.setDestinationAddr(m.local); err != nil { + if err := to.setDestinationAddr(mapping.local); err != nil { return nil, err } } @@ -297,7 +300,7 @@ func (n *networkAddressTranslator) translateInbound(from Chunk) (Chunk, error) { return nil, errNonUDPTranslationNotSupported } -// caller must hold the mutex +// caller must hold the mutex. func (n *networkAddressTranslator) findOutboundMapping(oKey string) *mapping { now := time.Now() @@ -315,7 +318,7 @@ func (n *networkAddressTranslator) findOutboundMapping(oKey string) *mapping { return m } -// caller must hold the mutex +// caller must hold the mutex. func (n *networkAddressTranslator) findInboundMapping(iKey string) *mapping { now := time.Now() m, ok := n.inboundMap[iKey] @@ -326,13 +329,14 @@ func (n *networkAddressTranslator) findInboundMapping(iKey string) *mapping { // check if this mapping is expired if now.After(m.expires) { n.removeMapping(m) + return nil } return m } -// caller must hold the mutex +// caller must hold the mutex. func (n *networkAddressTranslator) removeMapping(m *mapping) { oKey := fmt.Sprintf("%s:%s:%s", m.proto, m.local, m.bound) iKey := fmt.Sprintf("%s:%s", m.proto, m.mapped) diff --git a/vnet/nat_test.go b/vnet/nat_test.go index b70f539..8f81eb0 100644 --- a/vnet/nat_test.go +++ b/vnet/nat_test.go @@ -35,7 +35,7 @@ func TestNATTypeDefaults(t *testing.T) { assert.Equal(t, defaultNATMappingLifeTime, nat.natType.MappingLifeTime, "should be false") } -func TestNATMappingBehavior(t *testing.T) { +func TestNATMappingBehavior(t *testing.T) { //nolint:maintidx loggerFactory := logging.NewDefaultLoggerFactory() log := loggerFactory.NewLogger("test") @@ -442,8 +442,18 @@ func TestNATMappingBehavior(t *testing.T) { log.Debugf("o-translated: %s", oec2.String()) log.Debugf("o-translated: %s", oec3.String()) - assert.NotEqual(t, oec1.(*chunkUDP).sourcePort, oec2.(*chunkUDP).sourcePort, "should not match") //nolint:forcetypeassert - assert.Equal(t, oec1.(*chunkUDP).sourcePort, oec3.(*chunkUDP).sourcePort, "should match") //nolint:forcetypeassert + assert.NotEqual( + t, + oec1.(*chunkUDP).sourcePort, //nolint:forcetypeassert + oec2.(*chunkUDP).sourcePort, //nolint:forcetypeassert + "should not match", + ) + assert.Equal( + t, + oec1.(*chunkUDP).sourcePort, //nolint:forcetypeassert + oec3.(*chunkUDP).sourcePort, //nolint:forcetypeassert + "should match", + ) }) t.Run("symmetric NAT port dependent mapping", func(t *testing.T) { //nolint:dupl @@ -512,8 +522,18 @@ func TestNATMappingBehavior(t *testing.T) { log.Debugf("o-translated: %s", oec2.String()) log.Debugf("o-translated: %s", oec3.String()) - assert.NotEqual(t, oec1.(*chunkUDP).sourcePort, oec2.(*chunkUDP).sourcePort, "should not match") //nolint:forcetypeassert - assert.NotEqual(t, oec1.(*chunkUDP).sourcePort, oec3.(*chunkUDP).sourcePort, "should match") //nolint:forcetypeassert + assert.NotEqual( + t, + oec1.(*chunkUDP).sourcePort, //nolint:forcetypeassert + oec2.(*chunkUDP).sourcePort, //nolint:forcetypeassert + "should not match", + ) + assert.NotEqual( + t, + oec1.(*chunkUDP).sourcePort, //nolint:forcetypeassert + oec3.(*chunkUDP).sourcePort, //nolint:forcetypeassert + "should match", + ) }) } @@ -581,7 +601,12 @@ func TestNATMappingTimeout(t *testing.T) { log.Debugf("o-original : %s", oic.String()) log.Debugf("o-translated: %s", oec.String()) - assert.NotEqual(t, mapped, oec.(*chunkUDP).SourceAddr().String(), "mapped addr should not match") //nolint:forcetypeassert + assert.NotEqual( + t, + mapped, + oec.(*chunkUDP).SourceAddr().String(), //nolint:forcetypeassert + "mapped addr should not match", + ) }) t.Run("outbound detects timeout", func(t *testing.T) { diff --git a/vnet/net.go b/vnet/net.go index 08fd1f5..157c2b4 100644 --- a/vnet/net.go +++ b/vnet/net.go @@ -40,6 +40,7 @@ func newMACAddress() net.HardwareAddr { b := make([]byte, 8) binary.BigEndian.PutUint64(b, macAddrCounter) macAddrCounter++ + return b[2:] } @@ -53,7 +54,7 @@ type Net struct { mutex sync.RWMutex } -// Compile-time assertion +// Compile-time assertion. var _ transport.Net = &Net{} func (v *Net) _getInterfaces() ([]*transport.Interface, error) { @@ -72,7 +73,7 @@ func (v *Net) Interfaces() ([]*transport.Interface, error) { return v._getInterfaces() } -// caller must hold the mutex (read) +// caller must hold the mutex (read). func (v *Net) _getInterface(ifName string) (*transport.Interface, error) { ifs, err := v._getInterfaces() if err != nil { @@ -114,7 +115,7 @@ func (v *Net) InterfaceByName(ifName string) (*transport.Interface, error) { return v.getInterface(ifName) } -// caller must hold the mutex +// caller must hold the mutex. func (v *Net) getAllIPAddrs(ipv6 bool) []net.IP { ips := []net.IP{} @@ -150,6 +151,7 @@ func (v *Net) setRouter(r *Router) error { defer v.mutex.Unlock() v.router = r + return nil } @@ -164,8 +166,8 @@ func (v *Net) onInboundChunk(c Chunk) { } } -// caller must hold the mutex -func (v *Net) _dialUDP(network string, locAddr, remAddr *net.UDPAddr) (transport.UDPConn, error) { +// caller must hold the mutex. +func (v *Net) _dialUDP(network string, locAddr, remAddr *net.UDPAddr) (transport.UDPConn, error) { //nolint:cyclop // validate network if network != udp && network != udp4 { return nil, fmt.Errorf("%w: %s", errUnexpectedNetwork, network) @@ -276,7 +278,7 @@ func (v *Net) ResolveIPAddr(_, address string) (*net.IPAddr, error) { // Check if host is a domain name ip := net.ParseIP(address) - if ip == nil { + if ip == nil { //nolint:nestif address = strings.ToLower(address) if address == "localhost" { ip = net.IPv4(127, 0, 0, 1) @@ -358,13 +360,14 @@ func (v *Net) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) { return udpAddr, nil } -func (v *Net) write(c Chunk) error { - if c.Network() == udp { - if udp, ok := c.(*chunkUDP); ok { - if c.getDestinationIP().IsLoopback() { +func (v *Net) write(chunk Chunk) error { + if chunk.Network() == udp { //nolint:nestif + if udp, ok := chunk.(*chunkUDP); ok { + if chunk.getDestinationIP().IsLoopback() { if conn, ok := v.udpConns.find(udp.DestinationAddr()); ok { conn.onInboundChunk(udp) } + return nil } } else { @@ -376,7 +379,8 @@ func (v *Net) write(c Chunk) error { return errNoRouterLinked } - v.router.push(c) + v.router.push(chunk) + return nil } @@ -390,15 +394,15 @@ func (v *Net) onClosed(addr net.Addr) { // This method determines the srcIP based on the dstIP when locIP // is any IP address ("0.0.0.0" or "::"). If locIP is a non-any addr, // this method simply returns locIP. -// caller must hold the mutex -func (v *Net) determineSourceIP(locIP, dstIP net.IP) net.IP { +// caller must hold the mutex. +func (v *Net) determineSourceIP(locIP, dstIP net.IP) net.IP { //nolint:cyclop if locIP != nil && !locIP.IsUnspecified() { return locIP } var srcIP net.IP - if dstIP.IsLoopback() { + if dstIP.IsLoopback() { //nolint:nestif srcIP = net.ParseIP("127.0.0.1") } else { ifc, err2 := v._getInterface("eth0") @@ -427,11 +431,13 @@ func (v *Net) determineSourceIP(locIP, dstIP net.IP) net.IP { if findIPv4 { if ip.To4() != nil { srcIP = ip + break } } else { if ip.To4() == nil { srcIP = ip + break } } @@ -441,10 +447,10 @@ func (v *Net) determineSourceIP(locIP, dstIP net.IP) net.IP { return srcIP } -// caller must hold the mutex -func (v *Net) hasIPAddr(ip net.IP) bool { //nolint:gocognit +// caller must hold the mutex. +func (v *Net) hasIPAddr(ip net.IP) bool { //nolint:gocognit,cyclop for _, ifc := range v.interfaces { - if addrs, err := ifc.Addrs(); err == nil { + if addrs, err := ifc.Addrs(); err == nil { //nolint:nestif for _, addr := range addrs { var locIP net.IP if ipNet, ok := addr.(*net.IPNet); ok { @@ -476,7 +482,7 @@ func (v *Net) hasIPAddr(ip net.IP) bool { //nolint:gocognit return false } -// caller must hold the mutex +// caller must hold the mutex. func (v *Net) allocateLocalAddr(ip net.IP, port int) error { // gather local IP addresses to bind var ips []net.IP @@ -509,7 +515,7 @@ func (v *Net) allocateLocalAddr(ip net.IP, port int) error { return nil } -// caller must hold the mutex +// caller must hold the mutex. func (v *Net) assignPort(ip net.IP, start, end int) (int, error) { // choose randomly from the range between start and end (inclusive) if end < start { @@ -600,7 +606,7 @@ func (v *Net) ListenTCP(string, *net.TCPAddr) (transport.TCPListener, error) { return nil, transport.ErrNotSupported } -// CreateDialer creates an instance of vnet.Dialer +// CreateDialer creates an instance of vnet.Dialer. func (v *Net) CreateDialer(d *net.Dialer) transport.Dialer { return &dialer{ dialer: d, diff --git a/vnet/net_test.go b/vnet/net_test.go index 4a467bb..7737492 100644 --- a/vnet/net_test.go +++ b/vnet/net_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestNetVirtual(t *testing.T) { +func TestNetVirtual(t *testing.T) { //nolint:gocyclo,cyclop,maintidx loggerFactory := logging.NewDefaultLoggerFactory() log := logging.NewDefaultLoggerFactory().NewLogger("test") @@ -518,14 +518,14 @@ func TestNetVirtual(t *testing.T) { laddr := conn.LocalAddr() assert.Equal(t, "127.0.0.1:50916", laddr.String(), "should match") - c := newChunkUDP(&net.UDPAddr{ + chunk := newChunkUDP(&net.UDPAddr{ IP: net.ParseIP("127.0.0.1"), Port: 4000, }, &net.UDPAddr{ IP: net.ParseIP("127.0.0.1"), Port: 50916, }) - c.userData = []byte("Hello!") + chunk.userData = []byte("Hello!") var hasReceived bool recvdCh := make(chan bool) @@ -540,10 +540,11 @@ func TestNetVirtual(t *testing.T) { n, addr, err = conn.ReadFrom(buf) if err != nil { log.Debugf("ReadFrom returned: %v", err) + break } - assert.Equal(t, 6, len(c.userData), "should match") + assert.Equal(t, 6, len(chunk.userData), "should match") assert.Equal(t, "127.0.0.1:4000", addr.String(), "should match") assert.Equal(t, "Hello!", string(buf[:n]), "should match") @@ -553,7 +554,7 @@ func TestNetVirtual(t *testing.T) { close(doneCh) }() - nw.onInboundChunk(c) + nw.onInboundChunk(chunk) loop: for { @@ -626,6 +627,7 @@ func TestNetVirtual(t *testing.T) { n, _, err2 := conn1.ReadFrom(buf) if err2 != nil { log.Debugf("ReadFrom returned: %v", err2) + break } @@ -643,6 +645,7 @@ func TestNetVirtual(t *testing.T) { n, addr, err2 := conn2.ReadFrom(buf) if err2 != nil { log.Debugf("ReadFrom returned: %v", err2) + break } @@ -752,6 +755,7 @@ func TestNetVirtual(t *testing.T) { n, _, err2 := conn1.ReadFrom(buf) if err2 != nil { log.Debugf("ReadFrom returned: %v", err2) + break } @@ -769,6 +773,7 @@ func TestNetVirtual(t *testing.T) { n, addr, err2 := conn2.ReadFrom(buf) if err2 != nil { log.Debugf("ReadFrom returned: %v", err2) + break } diff --git a/vnet/resolver.go b/vnet/resolver.go index a391cc7..3054a4d 100644 --- a/vnet/resolver.go +++ b/vnet/resolver.go @@ -37,6 +37,7 @@ func newResolver(config *resolverConfig) *resolver { if err := r.addHost("localhost", "127.0.0.1"); err != nil { r.log.Warn("failed to add localhost to resolver") } + return r } @@ -59,6 +60,7 @@ func (r *resolver) addHost(name string, ipAddr string) error { return fmt.Errorf("%w \"%s\"", errFailedToParseIPAddr, ipAddr) } r.hosts[name] = ip + return nil } @@ -70,6 +72,7 @@ func (r *resolver) lookUp(hostName string) (net.IP, error) { if ip2, ok := r.hosts[hostName]; ok { return ip2 } + return nil }() if ip != nil { diff --git a/vnet/resolver_test.go b/vnet/resolver_test.go index 2617b45..4eebb1b 100644 --- a/vnet/resolver_test.go +++ b/vnet/resolver_test.go @@ -16,7 +16,7 @@ func TestResolver(t *testing.T) { log := loggerFactory.NewLogger("test") t.Run("Standalone", func(t *testing.T) { - r := newResolver(&resolverConfig{ + resolver := newResolver(&resolverConfig{ LoggerFactory: loggerFactory, }) @@ -25,7 +25,7 @@ func TestResolver(t *testing.T) { ipAddr := "127.0.0.1" ip := net.ParseIP(ipAddr) - resolved, err := r.lookUp(name) + resolved, err := resolver.lookUp(name) assert.NoError(t, err, "should succeed") assert.True(t, resolved.Equal(ip), "should match") @@ -34,10 +34,10 @@ func TestResolver(t *testing.T) { ip = net.ParseIP(ipAddr) log.Debugf("adding %s %s", name, ipAddr) - err = r.addHost(name, ipAddr) + err = resolver.addHost(name, ipAddr) assert.NoError(t, err, "should succeed") - resolved, err = r.lookUp(name) + resolved, err = resolver.lookUp(name) assert.NoError(t, err, "should succeed") assert.True(t, resolved.Equal(ip), "should match") }) diff --git a/vnet/router.go b/vnet/router.go index cfa4211..321b595 100644 --- a/vnet/router.go +++ b/vnet/router.go @@ -32,12 +32,13 @@ var ( errNoIPAddrEth0 = errors.New("no IP address is assigned for eth0") ) -// Generate a unique router name +// Generate a unique router name. var assignRouterName = func() func() string { //nolint:gochecknoglobals var routerIDCtr uint64 return func() string { n := atomic.AddUint64(&routerIDCtr, 1) + return fmt.Sprintf("router%d", n) } }() @@ -67,7 +68,7 @@ type RouterConfig struct { LoggerFactory logging.LoggerFactory } -// NIC is a network interface controller that interfaces Router +// NIC is a network interface controller that interfaces Router. type NIC interface { getInterface(ifName string) (*transport.Interface, error) onInboundChunk(c Chunk) @@ -105,7 +106,7 @@ type Router struct { } // NewRouter ... -func NewRouter(config *RouterConfig) (*Router, error) { +func NewRouter(config *RouterConfig) (*Router, error) { //nolint:cyclop loggerFactory := config.LoggerFactory log := loggerFactory.NewLogger("vnet") @@ -152,7 +153,7 @@ func NewRouter(config *RouterConfig) (*Router, error) { staticLocalIPs := map[string]net.IP{} for _, ipStr := range config.StaticIPs { ipPair := strings.Split(ipStr, "/") - if ip := net.ParseIP(ipPair[0]); ip != nil { + if ip := net.ParseIP(ipPair[0]); ip != nil { //nolint:nestif if len(ipPair) > 1 { locIP := net.ParseIP(ipPair[1]) if locIP == nil { @@ -197,7 +198,7 @@ func NewRouter(config *RouterConfig) (*Router, error) { }, nil } -// caller must hold the mutex +// caller must hold the mutex. func (r *Router) getInterfaces() ([]*transport.Interface, error) { if len(r.interfaces) == 0 { return nil, fmt.Errorf("%w is available", errNoInterface) @@ -224,7 +225,7 @@ func (r *Router) getInterface(ifName string) (*transport.Interface, error) { } // Start ... -func (r *Router) Start() error { +func (r *Router) Start() error { //nolint:cyclop r.mutex.Lock() defer r.mutex.Unlock() @@ -237,20 +238,21 @@ func (r *Router) Start() error { go func() { loop: for { - d, err := r.processChunks() + duration, err := r.processChunks() if err != nil { r.log.Errorf("[%s] %s", r.name, err.Error()) + break } - if d <= 0 { + if duration <= 0 { select { case <-r.pushCh: case <-cancelCh: break loop } } else { - t := time.NewTimer(d) + t := time.NewTimer(duration) select { case <-t.C: case <-cancelCh: @@ -294,10 +296,11 @@ func (r *Router) Stop() error { r.stopFunc() r.stopFunc = nil + return nil } -// caller must hold the mutex +// caller must hold the mutex. func (r *Router) addNIC(nic NIC) error { ifc, err := nic.getInterface("eth0") if err != nil { @@ -348,6 +351,7 @@ func (r *Router) AddRouter(router *Router) error { } r.children = append(r.children, router) + return nil } @@ -363,6 +367,7 @@ func (r *Router) AddChildRouter(router *Router) error { } r.children = append(r.children, router) + return nil } @@ -389,7 +394,7 @@ func (r *Router) AddChunkFilter(filter ChunkFilter) { r.chunkFilters = append(r.chunkFilters, filter) } -// caller should hold the mutex +// caller should hold the mutex. func (r *Router) assignIPAddress() (net.IP, error) { // See: https://stackoverflow.com/questions/14915188/ip-address-ending-with-zero @@ -401,6 +406,7 @@ func (r *Router) assignIPAddress() (net.IP, error) { copy(ip, r.ipv4Net.IP[:3]) r.lastID++ ip[3] = r.lastID + return ip, nil } @@ -422,7 +428,7 @@ func (r *Router) push(c Chunk) { } } -func (r *Router) processChunks() (time.Duration, error) { +func (r *Router) processChunks() (time.Duration, error) { //nolint:cyclop r.mutex.Lock() defer r.mutex.Unlock() @@ -444,35 +450,37 @@ func (r *Router) processChunks() (time.Duration, error) { enteredAt := time.Now() cutOff := enteredAt.Add(-r.minDelay) - var d time.Duration // the next sleep duration + var duration time.Duration // the next sleep duration for { - d = 0 + duration = 0 - c := r.queue.peek() - if c == nil { + chunk := r.queue.peek() + if chunk == nil { break // no more chunk in the queue } // check timestamp to find if the chunk is due - if c.getTimestamp().After(cutOff) { + if chunk.getTimestamp().After(cutOff) { // There is one or more chunk in the queue but none of them are due. // Calculate the next sleep duration here. - nextExpire := c.getTimestamp().Add(r.minDelay) - d = nextExpire.Sub(enteredAt) + nextExpire := chunk.getTimestamp().Add(r.minDelay) + duration = nextExpire.Sub(enteredAt) + break } var ok bool - if c, ok = r.queue.pop(); !ok { + if chunk, ok = r.queue.pop(); !ok { break // no more chunk in the queue } blocked := false for i := 0; i < len(r.chunkFilters); i++ { filter := r.chunkFilters[i] - if !filter(c) { + if !filter(chunk) { blocked = true + break } } @@ -480,7 +488,7 @@ func (r *Router) processChunks() (time.Duration, error) { continue // discard } - dstIP := c.getDestinationIP() + dstIP := chunk.getDestinationIP() // check if the destination is in our subnet if r.ipv4Net.Contains(dstIP) { @@ -488,15 +496,17 @@ func (r *Router) processChunks() (time.Duration, error) { var nic NIC if nic, ok = r.nics[dstIP.String()]; !ok { // NIC not found. drop it. - r.log.Debugf("[%s] %s unreachable", r.name, c.String()) + r.log.Debugf("[%s] %s unreachable", r.name, chunk.String()) + continue } // found the NIC, forward the chunk to the NIC. // call to NIC must unlock mutex r.mutex.Unlock() - nic.onInboundChunk(c) + nic.onInboundChunk(chunk) r.mutex.Lock() + continue } @@ -504,12 +514,13 @@ func (r *Router) processChunks() (time.Duration, error) { // is this WAN? if r.parent == nil { // this WAN. No route for this chunk - r.log.Debugf("[%s] no route found for %s", r.name, c.String()) + r.log.Debugf("[%s] no route found for %s", r.name, chunk.String()) + continue } // Pass it to the parent via NAT - toParent, err := r.nat.translateOutbound(c) + toParent, err := r.nat.translateOutbound(chunk) if err != nil { return 0, err } @@ -538,11 +549,11 @@ func (r *Router) processChunks() (time.Duration, error) { r.mutex.Lock() } - return d, nil + return duration, nil } -// caller must hold the mutex -func (r *Router) setRouter(parent *Router) error { +// caller must hold the mutex. +func (r *Router) setRouter(parent *Router) error { //nolint:cyclop r.parent = parent r.resolver.setParent(parent.resolver) @@ -610,6 +621,7 @@ func (r *Router) onInboundChunk(c Chunk) { fromParent, err := r.nat.translateInbound(c) if err != nil { r.log.Warnf("[%s] %s", r.name, err.Error()) + return } diff --git a/vnet/router_test.go b/vnet/router_test.go index 881096f..18bca93 100644 --- a/vnet/router_test.go +++ b/vnet/router_test.go @@ -21,7 +21,7 @@ type dummyNIC struct { onInboundChunkHandler func(Chunk) } -// hijack onInboundChunk +// hijack onInboundChunk. func (v *dummyNIC) onInboundChunk(c Chunk) { v.onInboundChunkHandler(c) } @@ -44,7 +44,7 @@ func getIPAddr(n NIC) (string, error) { return addrs[0].(*net.IPNet).IP.String(), nil //nolint:forcetypeassert } -func TestRouterStandalone(t *testing.T) { +func TestRouterStandalone(t *testing.T) { //nolint:cyclop,maintidx loggerFactory := logging.NewDefaultLoggerFactory() log := loggerFactory.NewLogger("test") @@ -62,7 +62,7 @@ func TestRouterStandalone(t *testing.T) { }) t.Run("assignIPAddress", func(t *testing.T) { - r, err := NewRouter(&RouterConfig{ + router, err := NewRouter(&RouterConfig{ CIDR: "1.2.3.0/24", LoggerFactory: loggerFactory, }) @@ -71,7 +71,7 @@ func TestRouterStandalone(t *testing.T) { } for i := 1; i < 255; i++ { - ip, err2 := r.assignIPAddress() + ip, err2 := router.assignIPAddress() assert.Nil(t, err2, "should succeed") assert.Equal(t, byte(1), ip[0], "should match") assert.Equal(t, byte(2), ip[1], "should match") @@ -79,12 +79,12 @@ func TestRouterStandalone(t *testing.T) { assert.Equal(t, byte(i), ip[3], "should match") } - _, err = r.assignIPAddress() + _, err = router.assignIPAddress() assert.NotNil(t, err, "should fail") }) t.Run("AddNet", func(t *testing.T) { - r, err := NewRouter(&RouterConfig{ + router, err := NewRouter(&RouterConfig{ CIDR: "1.2.3.0/24", LoggerFactory: loggerFactory, }) @@ -97,7 +97,7 @@ func TestRouterStandalone(t *testing.T) { return } - err = r.AddNet(nic) + err = router.AddNet(nic) assert.Nil(t, err, "should succeed") // Now, eth0 must have one address assigned @@ -143,7 +143,7 @@ func TestRouterStandalone(t *testing.T) { t.Run("routing", func(t *testing.T) { var nCbs0 int32 doneCh := make(chan struct{}) - r, err := NewRouter(&RouterConfig{ + router, err := NewRouter(&RouterConfig{ CIDR: "1.2.3.0/24", LoggerFactory: loggerFactory, }) @@ -164,7 +164,7 @@ func TestRouterStandalone(t *testing.T) { Net: anic, } - err2 := r.AddNet(nic[i]) + err2 := router.AddNet(nic[i]) assert.Nil(t, err2, "should succeed") // Now, eth0 must have one address assigned @@ -190,14 +190,14 @@ func TestRouterStandalone(t *testing.T) { close(doneCh) } - err = r.Start() + err = router.Start() assert.Nil(t, err, "should succeed") c := newChunkUDP(ip[0], ip[1]) - r.push(c) + router.push(c) <-doneCh - err = r.Stop() + err = router.Stop() assert.Nil(t, err, "should succeed") assert.Equal(t, int32(0), atomic.LoadInt32(&nCbs0), "should be zero") }) @@ -205,7 +205,7 @@ func TestRouterStandalone(t *testing.T) { t.Run("AddChunkFilter", func(t *testing.T) { var nCbs0 int32 var nCbs1 int32 - r, err := NewRouter(&RouterConfig{ + router, err := NewRouter(&RouterConfig{ CIDR: "1.2.3.0/24", LoggerFactory: loggerFactory, }) @@ -226,7 +226,7 @@ func TestRouterStandalone(t *testing.T) { Net: anic, } - err2 := r.AddNet(nic[i]) + err2 := router.AddNet(nic[i]) assert.Nil(t, err2, "should succeed") // Now, eth0 must have one address assigned @@ -257,6 +257,7 @@ func TestRouterStandalone(t *testing.T) { // this creates a filter that block the first chunk makeFilter := func(name string) func(c Chunk) bool { n := 0 + return func(c Chunk) bool { pass := (n > 0) if pass { @@ -265,17 +266,18 @@ func TestRouterStandalone(t *testing.T) { log.Debugf("%s blocked %s", name, c.String()) } n++ + return pass } } // filter 1: block first one - r.AddChunkFilter(makeFilter("filter1")) + router.AddChunkFilter(makeFilter("filter1")) // filter 2: block first one - r.AddChunkFilter(makeFilter("filter2")) + router.AddChunkFilter(makeFilter("filter2")) - err = r.Start() + err = router.Start() assert.Nil(t, err, "should succeed") // send 3 packets @@ -283,12 +285,12 @@ func TestRouterStandalone(t *testing.T) { c := newChunkUDP(ip[0], ip[1]) c.userData = make([]byte, 1) c.userData[0] = byte(i) // 1-byte seq num - r.push(c) + router.push(c) } time.Sleep(50 * time.Millisecond) - err = r.Stop() + err = router.Stop() assert.Nil(t, err, "should succeed") assert.Equal(t, int32(0), atomic.LoadInt32(&nCbs0), "should be zero") @@ -302,11 +304,13 @@ func TestRouterDelay(t *testing.T) { log := loggerFactory.NewLogger("test") subTest := func(t *testing.T, title string, minDelay, maxJitter time.Duration) { + t.Helper() + t.Run(title, func(t *testing.T) { const margin = 8 * time.Millisecond var nCBs int32 doneCh := make(chan struct{}) - r, err := NewRouter(&RouterConfig{ + router, err := NewRouter(&RouterConfig{ CIDR: "1.2.3.0/24", MinDelay: minDelay, MaxJitter: maxJitter, @@ -329,7 +333,7 @@ func TestRouterDelay(t *testing.T) { Net: anic, } - err2 := r.AddNet(nic[i]) + err2 := router.AddNet(nic[i]) assert.Nil(t, err2, "should succeed") // Now, eth0 must have one address assigned @@ -354,22 +358,22 @@ func TestRouterDelay(t *testing.T) { delay := time.Since(c.getTimestamp()) delayRes = append(delayRes, delay) n := atomic.AddInt32(&nCBs, 1) - if n == int32(nPkts) { + if n == int32(nPkts) { //nolint:gosec // nPkts is a constant close(doneCh) } } - err = r.Start() + err = router.Start() assert.Nil(t, err, "should succeed") for i := 0; i < nPkts; i++ { c := newChunkUDP(ip[0], ip[1]) - r.push(c) + router.push(c) time.Sleep(50 * time.Millisecond) } <-doneCh - err = r.Stop() + err = router.Stop() assert.Nil(t, err, "should succeed") // Validate the amount of delays @@ -478,7 +482,7 @@ func TestRouterOneChild(t *testing.T) { err = wan.Start() assert.Nil(t, err, "should succeed") - c := newChunkUDP( + chunk := newChunkUDP( &net.UDPAddr{ IP: net.ParseIP(lanIP), Port: 1234, @@ -489,9 +493,9 @@ func TestRouterOneChild(t *testing.T) { }, ) - log.Debugf("sending %s", c.String()) + log.Debugf("sending %s", chunk.String()) - lan.push(c) + lan.push(chunk) <-doneCh err = wan.Stop() @@ -662,7 +666,7 @@ func TestRouterFailures(t *testing.T) { }) t.Run("AddNet", func(t *testing.T) { - r, err := NewRouter(&RouterConfig{ + router, err := NewRouter(&RouterConfig{ CIDR: "1.2.3.0/24", LoggerFactory: loggerFactory, }) @@ -679,7 +683,7 @@ func TestRouterFailures(t *testing.T) { return } - err = r.AddNet(nic) + err = router.AddNet(nic) assert.Error(t, err, "should fail") }) diff --git a/vnet/stress_test.go b/vnet/stress_test.go index f20af64..b209628 100644 --- a/vnet/stress_test.go +++ b/vnet/stress_test.go @@ -15,7 +15,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestStressTestUDP(t *testing.T) { +func TestStressTestUDP(t *testing.T) { //nolint:cyclop loggerFactory := logging.NewDefaultLoggerFactory() log := loggerFactory.NewLogger("test") @@ -95,9 +95,11 @@ func TestStressTestUDP(t *testing.T) { switch addr := addr.(type) { case *net.IPNet: echoServerIP = addr.IP + break loop case *net.IPAddr: echoServerIP = addr.IP + break loop } } diff --git a/vnet/tbf.go b/vnet/tbf.go index e6188e3..087f089 100644 --- a/vnet/tbf.go +++ b/vnet/tbf.go @@ -12,11 +12,11 @@ import ( ) const ( - // Bit is a single bit + // Bit is a single bit. Bit = 1 - // KBit is a kilobit + // KBit is a kilobit. KBit = 1000 * Bit - // MBit is a Megabit + // MBit is a Megabit. MBit = 1000 * KBit ) @@ -39,7 +39,7 @@ type TokenBucketFilter struct { log logging.LeveledLogger } -// TBFOption is the option type to configure a TokenBucketFilter +// TBFOption is the option type to configure a TokenBucketFilter. type TBFOption func(*TokenBucketFilter) TBFOption // TBFQueueSizeInBytes sets the max number of bytes waiting in the queue. Can @@ -48,17 +48,19 @@ func TBFQueueSizeInBytes(bytes int) TBFOption { return func(t *TokenBucketFilter) TBFOption { prev := t.queueSize t.queueSize = bytes + return TBFQueueSizeInBytes(prev) } } -// TBFRate sets the bit rate of a TokenBucketFilter +// TBFRate sets the bit rate of a TokenBucketFilter. func TBFRate(rate int) TBFOption { return func(t *TokenBucketFilter) TBFOption { t.mutex.Lock() defer t.mutex.Unlock() previous := t.rate t.rate = rate + return TBFRate(previous) } } @@ -71,19 +73,21 @@ func TBFMaxBurst(size int) TBFOption { defer t.mutex.Unlock() previous := t.maxBurst t.maxBurst = size + return TBFMaxBurst(previous) } } -// Set updates a setting on the token bucket filter +// Set updates a setting on the token bucket filter. func (t *TokenBucketFilter) Set(opts ...TBFOption) (previous TBFOption) { for _, opt := range opts { previous = opt(t) } + return previous } -// NewTokenBucketFilter creates and starts a new TokenBucketFilter +// NewTokenBucketFilter creates and starts a new TokenBucketFilter. func NewTokenBucketFilter(n NIC, opts ...TBFOption) (*TokenBucketFilter, error) { tbf := &TokenBucketFilter{ NIC: n, @@ -103,6 +107,7 @@ func NewTokenBucketFilter(n NIC, opts ...TBFOption) (*TokenBucketFilter, error) tbf.queue = newChunkQueue(0, tbf.queueSize) tbf.wg.Add(1) go tbf.run() + return tbf, nil } @@ -120,6 +125,7 @@ func (t *TokenBucketFilter) run() { select { case <-t.done: t.drainQueue() + return case chunk := <-t.c: if time.Since(lastRefill) > t.minRefillDuration { @@ -138,7 +144,14 @@ func (t *TokenBucketFilter) refillTokens(dt time.Duration) { t.mutex.Lock() defer t.mutex.Unlock() t.currentTokensInBucket = math.Min(float64(t.maxBurst), t.currentTokensInBucket+add) - t.log.Tracef("add=(%v / %v) / 8 = %v, currentTokensInBucket=%v, maxBurst=%v", t.rate, m, add, t.currentTokensInBucket, t.maxBurst) + t.log.Tracef( + "add=(%v / %v) / 8 = %v, currentTokensInBucket=%v, maxBurst=%v", + t.rate, + m, + add, + t.currentTokensInBucket, + t.maxBurst, + ) } func (t *TokenBucketFilter) drainQueue() { @@ -150,6 +163,7 @@ func (t *TokenBucketFilter) drainQueue() { tokens := float64(len(next.UserData())) if t.currentTokensInBucket < tokens { t.log.Tracef("currentTokensInBucket=%v, tokens=%v, stop drain", t.currentTokensInBucket, tokens) + break } t.log.Tracef("currentTokensInBucket=%v, tokens=%v, pop chunk", t.currentTokensInBucket, tokens) @@ -159,9 +173,10 @@ func (t *TokenBucketFilter) drainQueue() { } } -// Close closes and stops the token bucket filter queue +// Close closes and stops the token bucket filter queue. func (t *TokenBucketFilter) Close() error { close(t.done) t.wg.Wait() + return nil } diff --git a/vnet/tbf_test.go b/vnet/tbf_test.go index 3292f8c..080b848 100644 --- a/vnet/tbf_test.go +++ b/vnet/tbf_test.go @@ -43,6 +43,8 @@ func TestTokenBucketFilter(t *testing.T) { }) subTest := func(t *testing.T, capacity int, maxBurst int, duration time.Duration) { + t.Helper() + log := logging.NewDefaultLoggerFactory().NewLogger("test") mnic := newMockNIC(t) @@ -83,16 +85,28 @@ func TestTokenBucketFilter(t *testing.T) { assert.Less(t, rate, 1.05*float64(capacity)) assert.Greater(t, rate, 0.9*float64(capacity)) - log.Infof("duration=%v, bytesReceived=%v, packetsReceived=%v throughput=%.2f Mb/s", time.Since(start), bytesReceived, packetsReceived, mBitPerSecond) - return + log.Infof( + "duration=%v, bytesReceived=%v, packetsReceived=%v throughput=%.2f Mb/s", + time.Since(start), + bytesReceived, + packetsReceived, + mBitPerSecond, + ) + return case now := <-ticker.C: delta := now.Sub(last) last = now bits := float64(bytesReceived) * 8.0 rate := bits / delta.Seconds() mBitPerSecond := rate / float64(MBit) - log.Infof("duration=%v, bytesReceived=%v, packetsReceived=%v throughput=%.2f Mb/s", delta, bytesReceived, packetsReceived, mBitPerSecond) + log.Infof( + "duration=%v, bytesReceived=%v, packetsReceived=%v throughput=%.2f Mb/s", + delta, + bytesReceived, + packetsReceived, + mBitPerSecond, + ) // Allow 10% more than capacity due to max bursts assert.Less(t, rate, 1.10*float64(capacity)) assert.Greater(t, rate, 0.9*float64(capacity)) @@ -125,7 +139,13 @@ func TestTokenBucketFilter(t *testing.T) { bits := float64(bytesSent) * 8.0 rate := bits / time.Since(start).Seconds() mBitPerSecond := rate / float64(MBit) - log.Infof("duration=%v, bytesSent=%v, packetsSent=%v throughput=%.2f Mb/s", time.Since(start), bytesSent, packetsSent, mBitPerSecond) + log.Infof( + "duration=%v, bytesSent=%v, packetsSent=%v throughput=%.2f Mb/s", + time.Since(start), + bytesSent, + packetsSent, + mBitPerSecond, + ) assert.NoError(t, tbf.Close()) }() diff --git a/vnet/udpproxy.go b/vnet/udpproxy.go index 6de9ceb..5bac62d 100644 --- a/vnet/udpproxy.go +++ b/vnet/udpproxy.go @@ -50,6 +50,7 @@ type UDPProxy struct { // vnet.Net in this router and proxy all packets. func NewProxy(router *Router) (*UDPProxy, error) { v := &UDPProxy{router: router, timeout: 2 * time.Minute} + return v, nil } @@ -57,8 +58,10 @@ func NewProxy(router *Router) (*UDPProxy, error) { func (v *UDPProxy) Close() error { v.workers.Range(func(_, value interface{}) bool { _ = value.(*aUDPProxyWorker).Close() //nolint:forcetypeassert + return true }) + return nil } @@ -111,7 +114,7 @@ func (v *aUDPProxyWorker) Close() error { return nil } -func (v *aUDPProxyWorker) Proxy(ctx context.Context, _ *Net, serverAddr *net.UDPAddr) error { // nolint:gocognit +func (v *aUDPProxyWorker) Proxy(ctx context.Context, _ *Net, serverAddr *net.UDPAddr) error { // nolint:gocognit,cyclop // Create vnet for real server by serverAddr. nw, err := NewNet(&NetConfig{ StaticIP: serverAddr.IP.String(), diff --git a/vnet/udpproxy_direct.go b/vnet/udpproxy_direct.go index 35d815d..f5ebb90 100644 --- a/vnet/udpproxy_direct.go +++ b/vnet/udpproxy_direct.go @@ -20,6 +20,7 @@ func (v *UDPProxy) Deliver(sourceAddr, destAddr net.Addr, b []byte) (nn int, err return true // Deliver by next worker. }) + return } diff --git a/vnet/udpproxy_direct_test.go b/vnet/udpproxy_direct_test.go index 896ad9c..141e938 100644 --- a/vnet/udpproxy_direct_test.go +++ b/vnet/udpproxy_direct_test.go @@ -27,7 +27,7 @@ import ( // 192.168.1.10:8000 // // We should get a reply if directly deliver to proxy. -func TestUDPProxyDirectDeliverTypical(t *testing.T) { +func TestUDPProxyDirectDeliverTypical(t *testing.T) { //nolint:cyclop ctx, cancel := context.WithCancel(context.Background()) var r0, r1, r2 error @@ -146,6 +146,7 @@ func TestUDPProxyDirectDeliverTypical(t *testing.T) { if errors.Is(selfKill.Err(), context.Canceled) { return nil } + return err } else if n != 5 || addr == nil { return fmt.Errorf("n=%v, addr=%v", n, addr) // nolint:goerr113 @@ -163,6 +164,7 @@ func TestUDPProxyDirectDeliverTypical(t *testing.T) { if errors.Is(selfKill.Err(), context.Canceled) { return nil } + return err } else if n != 5 || addr == nil { return fmt.Errorf("n=%v, addr=%v", n, addr) // nolint:goerr113 @@ -180,7 +182,7 @@ func TestUDPProxyDirectDeliverTypical(t *testing.T) { } // Error if deliver to invalid address. -func TestUDPProxyDirectDeliverBadCase(t *testing.T) { +func TestUDPProxyDirectDeliverBadCase(t *testing.T) { //nolint:cyclop ctx, cancel := context.WithCancel(context.Background()) var r0, r1, r2 error @@ -299,6 +301,7 @@ func TestUDPProxyDirectDeliverBadCase(t *testing.T) { if errors.Is(selfKill.Err(), context.Canceled) { return nil } + return err } else if n != 5 || addr == nil { return fmt.Errorf("n=%v, addr=%v", n, addr) // nolint:goerr113 @@ -333,8 +336,10 @@ func TestUDPProxyDirectDeliverBadCase(t *testing.T) { //nolint:forcetypeassert value.(*aUDPProxyWorker).endpoints.Range(func(_, value interface{}) bool { _ = value.(*net.UDPConn).Close() //nolint:forcetypeassert + return true }) + return true }) diff --git a/vnet/udpproxy_test.go b/vnet/udpproxy_test.go index f7541dc..14b8c0a 100644 --- a/vnet/udpproxy_test.go +++ b/vnet/udpproxy_test.go @@ -22,17 +22,18 @@ import ( type MockUDPEchoServer struct { realServerAddr *net.UDPAddr - realServerReady context.Context + realServerReady context.Context //nolint:containedctx // this is a test context... realServerReadyCancel context.CancelFunc } func NewMockUDPEchoServer() *MockUDPEchoServer { v := &MockUDPEchoServer{} v.realServerReady, v.realServerReadyCancel = context.WithCancel(context.Background()) + return v } -func (v *MockUDPEchoServer) doMockUDPServer(ctx context.Context) error { +func (v *MockUDPEchoServer) doMockUDPServer(ctx context.Context) error { //nolint:cyclop // Listen to a random port. laddr, err := net.ResolveUDPAddr("udp4", "127.0.0.1:0") if err != nil { @@ -66,6 +67,7 @@ func (v *MockUDPEchoServer) doMockUDPServer(ctx context.Context) error { if errors.Is(selfKill.Err(), context.Canceled) { return nil } + return err } else if n == 0 || addr == nil { return fmt.Errorf("n=%v, addr=%v", n, addr) // nolint:goerr113 @@ -100,7 +102,9 @@ func TestMain(m *testing.M) { // proxy to real server: // // 192.168.1.10:8000 -func TestUDPProxyOne2One(t *testing.T) { +// +// . +func TestUDPProxyOne2One(t *testing.T) { //nolint:gocyclo,cyclop ctx, cancel := context.WithCancel(context.Background()) var r0, r1, r2 error @@ -221,6 +225,7 @@ func TestUDPProxyOne2One(t *testing.T) { if errors.Is(selfKill.Err(), context.Canceled) { return nil } + return err } else if n != 5 || addr == nil { return fmt.Errorf("n=%v, addr=%v", n, addr) // nolint:goerr113 @@ -253,7 +258,7 @@ func TestUDPProxyOne2One(t *testing.T) { // proxy to real server: // // 192.168.1.10:8000 -func TestUDPProxyTwo2One(t *testing.T) { +func TestUDPProxyTwo2One(t *testing.T) { //nolint:gocyclo,cyclop ctx, cancel := context.WithCancel(context.Background()) var r0, r1, r2, r3 error @@ -375,6 +380,7 @@ func TestUDPProxyTwo2One(t *testing.T) { if errors.Is(selfKill.Err(), context.Canceled) { return nil } + return err } else if n != len(echoData) || addr == nil { return fmt.Errorf("n=%v, addr=%v", n, addr) // nolint:goerr113 @@ -441,7 +447,7 @@ func TestUDPProxyTwo2One(t *testing.T) { // proxy to real server: // // 192.168.1.10:8000 -func TestUDPProxyProxyTwice(t *testing.T) { +func TestUDPProxyProxyTwice(t *testing.T) { //nolint:gocyclo,cyclop ctx, cancel := context.WithCancel(context.Background()) var r0, r1, r2, r3 error @@ -563,6 +569,7 @@ func TestUDPProxyProxyTwice(t *testing.T) { if errors.Is(selfKill.Err(), context.Canceled) { return nil } + return handClientErr } else if n != len(echoData) || addr == nil { return fmt.Errorf("n=%v, addr=%v", n, addr) // nolint:goerr113