mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 07:16:38 +00:00
[management,proxy,client] Add L4 capabilities (TLS/TCP/UDP) (#5530)
This commit is contained in:
40
proxy/internal/netutil/errors.go
Normal file
40
proxy/internal/netutil/errors.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ValidatePort converts an int32 proto port to uint16, returning an error
|
||||
// if the value is out of the valid 1–65535 range.
|
||||
func ValidatePort(port int32) (uint16, error) {
|
||||
if port <= 0 || port > math.MaxUint16 {
|
||||
return 0, fmt.Errorf("invalid port %d: must be 1–65535", port)
|
||||
}
|
||||
return uint16(port), nil
|
||||
}
|
||||
|
||||
// IsExpectedError returns true for errors that are normal during
|
||||
// connection teardown and should not be logged as warnings.
|
||||
func IsExpectedError(err error) bool {
|
||||
return errors.Is(err, net.ErrClosed) ||
|
||||
errors.Is(err, context.Canceled) ||
|
||||
errors.Is(err, io.EOF) ||
|
||||
errors.Is(err, syscall.ECONNRESET) ||
|
||||
errors.Is(err, syscall.EPIPE) ||
|
||||
errors.Is(err, syscall.ECONNABORTED)
|
||||
}
|
||||
|
||||
// IsTimeout checks whether the error is a network timeout.
|
||||
func IsTimeout(err error) bool {
|
||||
var netErr net.Error
|
||||
if errors.As(err, &netErr) {
|
||||
return netErr.Timeout()
|
||||
}
|
||||
return false
|
||||
}
|
||||
92
proxy/internal/netutil/errors_test.go
Normal file
92
proxy/internal/netutil/errors_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"syscall"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidatePort(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
port int32
|
||||
want uint16
|
||||
wantErr bool
|
||||
}{
|
||||
{"valid min", 1, 1, false},
|
||||
{"valid mid", 8080, 8080, false},
|
||||
{"valid max", 65535, 65535, false},
|
||||
{"zero", 0, 0, true},
|
||||
{"negative", -1, 0, true},
|
||||
{"too large", 65536, 0, true},
|
||||
{"way too large", 100000, 0, true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := ValidatePort(tt.port)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
assert.Zero(t, got)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsExpectedError(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
err error
|
||||
want bool
|
||||
}{
|
||||
{"net.ErrClosed", net.ErrClosed, true},
|
||||
{"context.Canceled", context.Canceled, true},
|
||||
{"io.EOF", io.EOF, true},
|
||||
{"ECONNRESET", syscall.ECONNRESET, true},
|
||||
{"EPIPE", syscall.EPIPE, true},
|
||||
{"ECONNABORTED", syscall.ECONNABORTED, true},
|
||||
{"wrapped expected", fmt.Errorf("wrap: %w", net.ErrClosed), true},
|
||||
{"unexpected EOF", io.ErrUnexpectedEOF, false},
|
||||
{"generic error", errors.New("something"), false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.want, IsExpectedError(tt.err))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type timeoutErr struct{ timeout bool }
|
||||
|
||||
func (e *timeoutErr) Error() string { return "timeout" }
|
||||
func (e *timeoutErr) Timeout() bool { return e.timeout }
|
||||
func (e *timeoutErr) Temporary() bool { return false }
|
||||
|
||||
func TestIsTimeout(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
err error
|
||||
want bool
|
||||
}{
|
||||
{"net timeout", &timeoutErr{timeout: true}, true},
|
||||
{"net non-timeout", &timeoutErr{timeout: false}, false},
|
||||
{"wrapped timeout", fmt.Errorf("wrap: %w", &timeoutErr{timeout: true}), true},
|
||||
{"generic error", errors.New("not a timeout"), false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.want, IsTimeout(tt.err))
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user