diff --git a/.github/workflows/golangci.yml b/.github/workflows/golangci.yml new file mode 100644 index 00000000..07466b71 --- /dev/null +++ b/.github/workflows/golangci.yml @@ -0,0 +1,26 @@ +name: golangci-lint +on: + push: + tags: + - v* + branches: + - main + pull_request: +permissions: + contents: read + # Optional: allow read access to pull request. Use with `only-new-issues` option. + # pull-requests: read +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/setup-go@v5 + with: + go-version: '1.21' + - uses: actions/checkout@v4 + - name: golangci-lint + uses: golangci/golangci-lint-action@v3.7.0 + with: + version: v1.54.2 + args: --timeout 10m diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..f35b1bd6 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,18 @@ + + + +on: [push, pull_request] +name: Test +jobs: + test: + strategy: + matrix: + go-version: [1.21.x] + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go-version }} + - run: go test ./... \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..8685ac2e --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,113 @@ +run: + tests: true + timeout: 10m + +linters: + disable-all: true + enable: + - exportloopref + # - errcheck # use revive's instead + - gci + - goconst + - gocritic + - gofumpt + - gosec + - gosimple + - govet + - ineffassign + - misspell + - nakedret + - staticcheck + - thelper + - typecheck + - stylecheck + - revive + - typecheck + - tenv + - unconvert + # Prefer unparam over revive's unused param. It is more thorough in its checking. + - unparam + - unused + - misspell + +issues: + exclude-rules: + - text: 'differs only by capitalization to method' + linters: + - revive + - text: 'Use of weak random number generator' + linters: + - gosec + - linters: + - staticcheck + text: "SA1019:" # silence errors on usage of deprecated funcs + + max-issues-per-linter: 10000 + max-same-issues: 10000 + +linters-settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - blank # blank imports + - dot # dot imports + - prefix(github.com/xtaci/kcp-go) + custom-order: true + revive: + enable-all-rules: true + # Do NOT whine about the following, full explanation found in: + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#description-of-available-rules + rules: + - name: use-any + disabled: true + - name: if-return + disabled: true + - name: max-public-structs + disabled: true + - name: cognitive-complexity + disabled: true + - name: argument-limit + disabled: true + - name: cyclomatic + disabled: true + - name: file-header + disabled: true + - name: function-length + disabled: true + - name: function-result-limit + disabled: true + - name: line-length-limit + disabled: true + - name: flag-parameter + disabled: true + - name: add-constant + disabled: true + - name: empty-lines + disabled: true + - name: banned-characters + disabled: true + - name: deep-exit + disabled: true + - name: confusing-results + disabled: true + - name: unused-parameter + disabled: true + - name: modifies-value-receiver + disabled: true + - name: early-return + disabled: true + - name: confusing-naming + disabled: true + - name: defer + disabled: true + # Disabled in favour of unparam. + - name: unused-parameter + disabled: true + - name: unhandled-error + disabled: true + arguments: + - 'fmt.Printf' + - 'fmt.Print' + - 'fmt.Println' + - 'myFunction' diff --git a/autotune.go b/autotune.go index 1f85be33..7c189951 100644 --- a/autotune.go +++ b/autotune.go @@ -21,11 +21,11 @@ func (tune *autoTune) Sample(bit bool, seq uint32) { // Find a period for a given signal // returns -1 if not found // -// --- ------ -// | | -// |______________| -// Period -// Falling Edge Rising Edge +// --- ------ +// | | +// |______________| +// Period +// Falling Edge Rising Edge func (tune *autoTune) FindPeriod(bit bool) int { // last pulse and initial index setup lastPulse := tune.pulses[0] diff --git a/batchconn.go b/batchconn.go index 6c307010..52ff705f 100644 --- a/batchconn.go +++ b/batchconn.go @@ -2,10 +2,6 @@ package kcp import "golang.org/x/net/ipv4" -const ( - batchSize = 16 -) - type batchConn interface { WriteBatch(ms []ipv4.Message, flags int) (int, error) ReadBatch(ms []ipv4.Message, flags int) (int, error) diff --git a/crypt.go b/crypt.go index d8828522..10d337ff 100644 --- a/crypt.go +++ b/crypt.go @@ -3,20 +3,15 @@ package kcp import ( "crypto/aes" "crypto/cipher" - "crypto/des" - "crypto/sha1" + "crypto/sha256" "unsafe" xor "github.com/templexxx/xorsimd" "github.com/tjfoc/gmsm/sm4" - - "golang.org/x/crypto/blowfish" "golang.org/x/crypto/cast5" "golang.org/x/crypto/pbkdf2" "golang.org/x/crypto/salsa20" "golang.org/x/crypto/tea" - "golang.org/x/crypto/twofish" - "golang.org/x/crypto/xtea" ) var ( @@ -52,6 +47,7 @@ func (c *salsa20BlockCrypt) Encrypt(dst, src []byte) { salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key) copy(dst[:8], src[:8]) } + func (c *salsa20BlockCrypt) Decrypt(dst, src []byte) { salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key) copy(dst[:8], src[:8]) @@ -77,46 +73,6 @@ func NewSM4BlockCrypt(key []byte) (BlockCrypt, error) { func (c *sm4BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } func (c *sm4BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } -type twofishBlockCrypt struct { - encbuf [twofish.BlockSize]byte - decbuf [2 * twofish.BlockSize]byte - block cipher.Block -} - -// NewTwofishBlockCrypt https://en.wikipedia.org/wiki/Twofish -func NewTwofishBlockCrypt(key []byte) (BlockCrypt, error) { - c := new(twofishBlockCrypt) - block, err := twofish.NewCipher(key) - if err != nil { - return nil, err - } - c.block = block - return c, nil -} - -func (c *twofishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } -func (c *twofishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } - -type tripleDESBlockCrypt struct { - encbuf [des.BlockSize]byte - decbuf [2 * des.BlockSize]byte - block cipher.Block -} - -// NewTripleDESBlockCrypt https://en.wikipedia.org/wiki/Triple_DES -func NewTripleDESBlockCrypt(key []byte) (BlockCrypt, error) { - c := new(tripleDESBlockCrypt) - block, err := des.NewTripleDESCipher(key) - if err != nil { - return nil, err - } - c.block = block - return c, nil -} - -func (c *tripleDESBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } -func (c *tripleDESBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } - type cast5BlockCrypt struct { encbuf [cast5.BlockSize]byte decbuf [2 * cast5.BlockSize]byte @@ -137,26 +93,6 @@ func NewCast5BlockCrypt(key []byte) (BlockCrypt, error) { func (c *cast5BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } func (c *cast5BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } -type blowfishBlockCrypt struct { - encbuf [blowfish.BlockSize]byte - decbuf [2 * blowfish.BlockSize]byte - block cipher.Block -} - -// NewBlowfishBlockCrypt https://en.wikipedia.org/wiki/Blowfish_(cipher) -func NewBlowfishBlockCrypt(key []byte) (BlockCrypt, error) { - c := new(blowfishBlockCrypt) - block, err := blowfish.NewCipher(key) - if err != nil { - return nil, err - } - c.block = block - return c, nil -} - -func (c *blowfishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } -func (c *blowfishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } - type aesBlockCrypt struct { encbuf [aes.BlockSize]byte decbuf [2 * aes.BlockSize]byte @@ -197,26 +133,6 @@ func NewTEABlockCrypt(key []byte) (BlockCrypt, error) { func (c *teaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } func (c *teaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } -type xteaBlockCrypt struct { - encbuf [xtea.BlockSize]byte - decbuf [2 * xtea.BlockSize]byte - block cipher.Block -} - -// NewXTEABlockCrypt https://en.wikipedia.org/wiki/XTEA -func NewXTEABlockCrypt(key []byte) (BlockCrypt, error) { - c := new(xteaBlockCrypt) - block, err := xtea.NewCipher(key) - if err != nil { - return nil, err - } - c.block = block - return c, nil -} - -func (c *xteaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } -func (c *xteaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } - type simpleXORBlockCrypt struct { xortbl []byte } @@ -224,7 +140,7 @@ type simpleXORBlockCrypt struct { // NewSimpleXORBlockCrypt simple xor with key expanding func NewSimpleXORBlockCrypt(key []byte) (BlockCrypt, error) { c := new(simpleXORBlockCrypt) - c.xortbl = pbkdf2.Key(key, []byte(saltxor), 32, mtuLimit, sha1.New) + c.xortbl = pbkdf2.Key(key, []byte(saltxor), 32, mtuLimit, sha256.New) return c, nil } @@ -238,8 +154,8 @@ func NewNoneBlockCrypt(key []byte) (BlockCrypt, error) { return new(noneBlockCrypt), nil } -func (c *noneBlockCrypt) Encrypt(dst, src []byte) { copy(dst, src) } -func (c *noneBlockCrypt) Decrypt(dst, src []byte) { copy(dst, src) } +func (*noneBlockCrypt) Encrypt(dst, src []byte) { copy(dst, src) } +func (*noneBlockCrypt) Decrypt(dst, src []byte) { copy(dst, src) } // packet encryption with local CFB mode func encrypt(block cipher.Block, dst, src, buf []byte) { @@ -261,71 +177,71 @@ func encrypt8(block cipher.Block, dst, src, buf []byte) { base := 0 repeat := n / 8 left := n % 8 - ptr_tbl := (*uint64)(unsafe.Pointer(&tbl[0])) + ptrTbl := (*uint64)(unsafe.Pointer(&tbl[0])) for i := 0; i < repeat; i++ { s := src[base:][0:64] d := dst[base:][0:64] // 1 - *(*uint64)(unsafe.Pointer(&d[0])) = *(*uint64)(unsafe.Pointer(&s[0])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[0])) = *(*uint64)(unsafe.Pointer(&s[0])) ^ *ptrTbl block.Encrypt(tbl, d[0:8]) // 2 - *(*uint64)(unsafe.Pointer(&d[8])) = *(*uint64)(unsafe.Pointer(&s[8])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[8])) = *(*uint64)(unsafe.Pointer(&s[8])) ^ *ptrTbl block.Encrypt(tbl, d[8:16]) // 3 - *(*uint64)(unsafe.Pointer(&d[16])) = *(*uint64)(unsafe.Pointer(&s[16])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[16])) = *(*uint64)(unsafe.Pointer(&s[16])) ^ *ptrTbl block.Encrypt(tbl, d[16:24]) // 4 - *(*uint64)(unsafe.Pointer(&d[24])) = *(*uint64)(unsafe.Pointer(&s[24])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[24])) = *(*uint64)(unsafe.Pointer(&s[24])) ^ *ptrTbl block.Encrypt(tbl, d[24:32]) // 5 - *(*uint64)(unsafe.Pointer(&d[32])) = *(*uint64)(unsafe.Pointer(&s[32])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[32])) = *(*uint64)(unsafe.Pointer(&s[32])) ^ *ptrTbl block.Encrypt(tbl, d[32:40]) // 6 - *(*uint64)(unsafe.Pointer(&d[40])) = *(*uint64)(unsafe.Pointer(&s[40])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[40])) = *(*uint64)(unsafe.Pointer(&s[40])) ^ *ptrTbl block.Encrypt(tbl, d[40:48]) // 7 - *(*uint64)(unsafe.Pointer(&d[48])) = *(*uint64)(unsafe.Pointer(&s[48])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[48])) = *(*uint64)(unsafe.Pointer(&s[48])) ^ *ptrTbl block.Encrypt(tbl, d[48:56]) // 8 - *(*uint64)(unsafe.Pointer(&d[56])) = *(*uint64)(unsafe.Pointer(&s[56])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[56])) = *(*uint64)(unsafe.Pointer(&s[56])) ^ *ptrTbl block.Encrypt(tbl, d[56:64]) base += 64 } switch left { case 7: - *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptrTbl block.Encrypt(tbl, dst[base:]) base += 8 fallthrough case 6: - *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptrTbl block.Encrypt(tbl, dst[base:]) base += 8 fallthrough case 5: - *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptrTbl block.Encrypt(tbl, dst[base:]) base += 8 fallthrough case 4: - *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptrTbl block.Encrypt(tbl, dst[base:]) base += 8 fallthrough case 3: - *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptrTbl block.Encrypt(tbl, dst[base:]) base += 8 fallthrough case 2: - *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptrTbl block.Encrypt(tbl, dst[base:]) base += 8 fallthrough case 1: - *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptrTbl block.Encrypt(tbl, dst[base:]) base += 8 fallthrough @@ -434,36 +350,36 @@ func decrypt8(block cipher.Block, dst, src, buf []byte) { base := 0 repeat := n / 8 left := n % 8 - ptr_tbl := (*uint64)(unsafe.Pointer(&tbl[0])) - ptr_next := (*uint64)(unsafe.Pointer(&next[0])) + ptrTbl := (*uint64)(unsafe.Pointer(&tbl[0])) + ptrNext := (*uint64)(unsafe.Pointer(&next[0])) for i := 0; i < repeat; i++ { s := src[base:][0:64] d := dst[base:][0:64] // 1 block.Encrypt(next, s[0:8]) - *(*uint64)(unsafe.Pointer(&d[0])) = *(*uint64)(unsafe.Pointer(&s[0])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[0])) = *(*uint64)(unsafe.Pointer(&s[0])) ^ *ptrTbl // 2 block.Encrypt(tbl, s[8:16]) - *(*uint64)(unsafe.Pointer(&d[8])) = *(*uint64)(unsafe.Pointer(&s[8])) ^ *ptr_next + *(*uint64)(unsafe.Pointer(&d[8])) = *(*uint64)(unsafe.Pointer(&s[8])) ^ *ptrNext // 3 block.Encrypt(next, s[16:24]) - *(*uint64)(unsafe.Pointer(&d[16])) = *(*uint64)(unsafe.Pointer(&s[16])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[16])) = *(*uint64)(unsafe.Pointer(&s[16])) ^ *ptrTbl // 4 block.Encrypt(tbl, s[24:32]) - *(*uint64)(unsafe.Pointer(&d[24])) = *(*uint64)(unsafe.Pointer(&s[24])) ^ *ptr_next + *(*uint64)(unsafe.Pointer(&d[24])) = *(*uint64)(unsafe.Pointer(&s[24])) ^ *ptrNext // 5 block.Encrypt(next, s[32:40]) - *(*uint64)(unsafe.Pointer(&d[32])) = *(*uint64)(unsafe.Pointer(&s[32])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[32])) = *(*uint64)(unsafe.Pointer(&s[32])) ^ *ptrTbl // 6 block.Encrypt(tbl, s[40:48]) - *(*uint64)(unsafe.Pointer(&d[40])) = *(*uint64)(unsafe.Pointer(&s[40])) ^ *ptr_next + *(*uint64)(unsafe.Pointer(&d[40])) = *(*uint64)(unsafe.Pointer(&s[40])) ^ *ptrNext // 7 block.Encrypt(next, s[48:56]) - *(*uint64)(unsafe.Pointer(&d[48])) = *(*uint64)(unsafe.Pointer(&s[48])) ^ *ptr_tbl + *(*uint64)(unsafe.Pointer(&d[48])) = *(*uint64)(unsafe.Pointer(&s[48])) ^ *ptrTbl // 8 block.Encrypt(tbl, s[56:64]) - *(*uint64)(unsafe.Pointer(&d[56])) = *(*uint64)(unsafe.Pointer(&s[56])) ^ *ptr_next + *(*uint64)(unsafe.Pointer(&d[56])) = *(*uint64)(unsafe.Pointer(&s[56])) ^ *ptrNext base += 64 } @@ -593,7 +509,7 @@ func decrypt16(block cipher.Block, dst, src, buf []byte) { case 1: block.Encrypt(next, src[base:]) xor.Bytes16Align(dst[base:], src[base:], tbl) - tbl, next = next, tbl + tbl = next base += 16 fallthrough case 0: diff --git a/crypt_test.go b/crypt_test.go index 2ef4dc8a..bfdb17f2 100644 --- a/crypt_test.go +++ b/crypt_test.go @@ -3,9 +3,8 @@ package kcp import ( "bytes" "crypto/aes" - "crypto/md5" "crypto/rand" - "crypto/sha1" + "crypto/sha256" "hash/crc32" "io" "testing" @@ -43,14 +42,6 @@ func TestXOR(t *testing.T) { cryptTest(t, bc) } -func TestBlowfish(t *testing.T) { - bc, err := NewBlowfishBlockCrypt(pass[:32]) - if err != nil { - t.Fatal(err) - } - cryptTest(t, bc) -} - func TestNone(t *testing.T) { bc, err := NewNoneBlockCrypt(pass[:32]) if err != nil { @@ -67,30 +58,6 @@ func TestCast5(t *testing.T) { cryptTest(t, bc) } -func Test3DES(t *testing.T) { - bc, err := NewTripleDESBlockCrypt(pass[:24]) - if err != nil { - t.Fatal(err) - } - cryptTest(t, bc) -} - -func TestTwofish(t *testing.T) { - bc, err := NewTwofishBlockCrypt(pass[:32]) - if err != nil { - t.Fatal(err) - } - cryptTest(t, bc) -} - -func TestXTEA(t *testing.T) { - bc, err := NewXTEABlockCrypt(pass[:16]) - if err != nil { - t.Fatal(err) - } - cryptTest(t, bc) -} - func TestSalsa20(t *testing.T) { bc, err := NewSalsa20BlockCrypt(pass[:32]) if err != nil { @@ -100,6 +67,7 @@ func TestSalsa20(t *testing.T) { } func cryptTest(t *testing.T, bc BlockCrypt) { + t.Helper() data := make([]byte, mtuLimit) io.ReadFull(rand.Reader, data) dec := make([]byte, mtuLimit) @@ -162,14 +130,6 @@ func BenchmarkXOR(b *testing.B) { benchCrypt(b, bc) } -func BenchmarkBlowfish(b *testing.B) { - bc, err := NewBlowfishBlockCrypt(pass[:32]) - if err != nil { - b.Fatal(err) - } - benchCrypt(b, bc) -} - func BenchmarkNone(b *testing.B) { bc, err := NewNoneBlockCrypt(pass[:32]) if err != nil { @@ -186,30 +146,6 @@ func BenchmarkCast5(b *testing.B) { benchCrypt(b, bc) } -func Benchmark3DES(b *testing.B) { - bc, err := NewTripleDESBlockCrypt(pass[:24]) - if err != nil { - b.Fatal(err) - } - benchCrypt(b, bc) -} - -func BenchmarkTwofish(b *testing.B) { - bc, err := NewTwofishBlockCrypt(pass[:32]) - if err != nil { - b.Fatal(err) - } - benchCrypt(b, bc) -} - -func BenchmarkXTEA(b *testing.B) { - bc, err := NewXTEABlockCrypt(pass[:16]) - if err != nil { - b.Fatal(err) - } - benchCrypt(b, bc) -} - func BenchmarkSalsa20(b *testing.B) { bc, err := NewSalsa20BlockCrypt(pass[:32]) if err != nil { @@ -219,6 +155,7 @@ func BenchmarkSalsa20(b *testing.B) { } func benchCrypt(b *testing.B, bc BlockCrypt) { + b.Helper() data := make([]byte, mtuLimit) io.ReadFull(rand.Reader, data) dec := make([]byte, mtuLimit) @@ -242,7 +179,7 @@ func BenchmarkCRC32(b *testing.B) { } func BenchmarkCsprngSystem(b *testing.B) { - data := make([]byte, md5.Size) + data := make([]byte, sha256.Size) b.SetBytes(int64(len(data))) for i := 0; i < b.N; i++ { @@ -250,28 +187,20 @@ func BenchmarkCsprngSystem(b *testing.B) { } } -func BenchmarkCsprngMD5(b *testing.B) { - var data [md5.Size]byte - b.SetBytes(md5.Size) - - for i := 0; i < b.N; i++ { - data = md5.Sum(data[:]) - } -} -func BenchmarkCsprngSHA1(b *testing.B) { - var data [sha1.Size]byte - b.SetBytes(sha1.Size) +func BenchmarkCsprngSHA256(b *testing.B) { + var data [sha256.Size]byte + b.SetBytes(sha256.Size) for i := 0; i < b.N; i++ { - data = sha1.Sum(data[:]) + data = sha256.Sum256(data[:]) } } func BenchmarkCsprngNonceMD5(b *testing.B) { - var ng nonceMD5 + var ng nonceSHA256 ng.Init() - b.SetBytes(md5.Size) - data := make([]byte, md5.Size) + b.SetBytes(sha256.Size) + data := make([]byte, sha256.Size) for i := 0; i < b.N; i++ { ng.Fill(data) } diff --git a/entropy.go b/entropy.go index 156c1cd2..a065427a 100644 --- a/entropy.go +++ b/entropy.go @@ -3,8 +3,8 @@ package kcp import ( "crypto/aes" "crypto/cipher" - "crypto/md5" "crypto/rand" + "crypto/sha256" "io" ) @@ -14,18 +14,18 @@ type Entropy interface { Fill(nonce []byte) } -// nonceMD5 nonce generator for packet header -type nonceMD5 struct { - seed [md5.Size]byte +// nonceSHA256 nonce generator for packet header +type nonceSHA256 struct { + seed [sha256.Size]byte } -func (n *nonceMD5) Init() { /*nothing required*/ } +func (*nonceSHA256) Init() { /* nothing required */ } -func (n *nonceMD5) Fill(nonce []byte) { +func (n *nonceSHA256) Fill(nonce []byte) { if n.seed[0] == 0 { // entropy update io.ReadFull(rand.Reader, n.seed[:]) } - n.seed = md5.Sum(n.seed[:]) + n.seed = sha256.Sum256(n.seed[:]) copy(nonce, n.seed[:]) } @@ -36,7 +36,7 @@ type nonceAES128 struct { } func (n *nonceAES128) Init() { - var key [16]byte //aes-128 + var key [16]byte // aes-128 io.ReadFull(rand.Reader, key[:]) io.ReadFull(rand.Reader, n.seed[:]) block, _ := aes.NewCipher(key[:]) diff --git a/fec.go b/fec.go index e2a4ab6f..a6854842 100644 --- a/fec.go +++ b/fec.go @@ -110,7 +110,7 @@ func (dec *fecDecoder) decode(in fecPacket) (recovered [][]byte) { dec.decodeCache = make([][]byte, dec.shardSize) dec.flagCache = make([]bool, dec.shardSize) dec.shouldTune = false - //log.Println("autotune to :", dec.dataShards, dec.parityShards) + } } } @@ -240,11 +240,11 @@ func (dec *fecDecoder) decode(in fecPacket) (recovered [][]byte) { if numExpired > 0 { dec.rx = dec.freeRange(0, numExpired, dec.rx) } - return + return recovered } // free a range of fecPacket -func (dec *fecDecoder) freeRange(first, n int, q []fecElement) []fecElement { +func (*fecDecoder) freeRange(first, n int, q []fecElement) []fecElement { for i := first; i < first+n; i++ { // recycle buffer xmitBuf.Put([]byte(q[i].fecPacket)) } @@ -370,7 +370,7 @@ func (enc *fecEncoder) encode(b []byte, rto uint32) (ps [][]byte) { enc.tsLatestPacket = now - return + return ps } func (enc *fecEncoder) markData(data []byte) { diff --git a/go.mod b/go.mod index 7709d078..0cfc04a2 100644 --- a/go.mod +++ b/go.mod @@ -1,23 +1,23 @@ module github.com/xtaci/kcp-go/v5 +go 1.21 + require ( github.com/klauspost/reedsolomon v1.12.0 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.6.1 + github.com/stretchr/testify v1.8.4 github.com/templexxx/xorsimd v0.4.2 github.com/tjfoc/gmsm v1.4.1 - github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae - golang.org/x/crypto v0.17.0 - golang.org/x/net v0.19.0 + github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 + golang.org/x/crypto v0.18.0 + golang.org/x/net v0.20.0 ) require ( - github.com/davecgh/go-spew v1.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/templexxx/cpu v0.1.0 // indirect - golang.org/x/sys v0.15.0 // indirect - gopkg.in/yaml.v3 v3.0.0 // indirect + golang.org/x/sys v0.16.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) - -go 1.21 diff --git a/go.sum b/go.sum index 8bba494c..ae6f3a15 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -32,22 +32,21 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/templexxx/cpu v0.1.0 h1:wVM+WIJP2nYaxVxqgHPD4wGA2aJ9rvrQRV8CvFzNb40= github.com/templexxx/cpu v0.1.0/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk= github.com/templexxx/xorsimd v0.4.2 h1:ocZZ+Nvu65LGHmCLZ7OoCtg8Fx8jnHKK37SjvngUoVI= github.com/templexxx/xorsimd v0.4.2/go.mod h1:HgwaPoDREdi6OnULpSfxhzaiiSUY4Fi3JPn1wpt28NI= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= -github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM= -github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= +github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E= +github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -58,8 +57,8 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -69,8 +68,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -95,8 +94,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/kcp.go b/kcp.go index 0c6c304f..d15b12bf 100644 --- a/kcp.go +++ b/kcp.go @@ -7,7 +7,7 @@ import ( ) const ( - IKCP_RTO_NDL = 30 // no delay min rto + IkcpRtoNdl = 30 // no delay min rto IKCP_RTO_MIN = 100 // normal min rto IKCP_RTO_DEF = 200 IKCP_RTO_MAX = 60000 @@ -37,41 +37,41 @@ var refTime time.Time = time.Now() // currentMs returns current elapsed monotonic milliseconds since program startup func currentMs() uint32 { return uint32(time.Since(refTime) / time.Millisecond) } -// output_callback is a prototype which ought capture conn and call conn.Write -type output_callback func(buf []byte, size int) +// outputCallback is a prototype which ought capture conn and call conn.Write +type outputCallback func(buf []byte, size int) /* encode 8 bits unsigned int */ -func ikcp_encode8u(p []byte, c byte) []byte { +func ikcpEncode8u(p []byte, c byte) []byte { p[0] = c return p[1:] } /* decode 8 bits unsigned int */ -func ikcp_decode8u(p []byte, c *byte) []byte { +func ikcpDecode8u(p []byte, c *byte) []byte { *c = p[0] return p[1:] } /* encode 16 bits unsigned int (lsb) */ -func ikcp_encode16u(p []byte, w uint16) []byte { +func ikcpEncode16u(p []byte, w uint16) []byte { binary.LittleEndian.PutUint16(p, w) return p[2:] } /* decode 16 bits unsigned int (lsb) */ -func ikcp_decode16u(p []byte, w *uint16) []byte { +func ikcpDecode16u(p []byte, w *uint16) []byte { *w = binary.LittleEndian.Uint16(p) return p[2:] } /* encode 32 bits unsigned int (lsb) */ -func ikcp_encode32u(p []byte, l uint32) []byte { +func ikcpEncode32u(p []byte, l uint32) []byte { binary.LittleEndian.PutUint32(p, l) return p[4:] } /* decode 32 bits unsigned int (lsb) */ -func ikcp_decode32u(p []byte, l *uint32) []byte { +func ikcpDecode32u(p []byte, l *uint32) []byte { *l = binary.LittleEndian.Uint32(p) return p[4:] } @@ -117,14 +117,14 @@ type segment struct { // encode a segment into buffer func (seg *segment) encode(ptr []byte) []byte { - ptr = ikcp_encode32u(ptr, seg.conv) - ptr = ikcp_encode8u(ptr, seg.cmd) - ptr = ikcp_encode8u(ptr, seg.frg) - ptr = ikcp_encode16u(ptr, seg.wnd) - ptr = ikcp_encode32u(ptr, seg.ts) - ptr = ikcp_encode32u(ptr, seg.sn) - ptr = ikcp_encode32u(ptr, seg.una) - ptr = ikcp_encode32u(ptr, uint32(len(seg.data))) + ptr = ikcpEncode32u(ptr, seg.conv) + ptr = ikcpEncode8u(ptr, seg.cmd) + ptr = ikcpEncode8u(ptr, seg.frg) + ptr = ikcpEncode16u(ptr, seg.wnd) + ptr = ikcpEncode32u(ptr, seg.ts) + ptr = ikcpEncode32u(ptr, seg.sn) + ptr = ikcpEncode32u(ptr, seg.una) + ptr = ikcpEncode32u(ptr, uint32(len(seg.data))) atomic.AddUint64(&DefaultSnmp.OutSegs, 1) return ptr } @@ -137,7 +137,7 @@ type KCP struct { rx_rttvar, rx_srtt int32 rx_rto, rx_minrto uint32 snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe uint32 - interval, ts_flush uint32 + interval, tsFlush uint32 nodelay, updated uint32 ts_probe, probe_wait uint32 dead_link, incr uint32 @@ -147,14 +147,14 @@ type KCP struct { snd_queue []segment rcv_queue []segment - snd_buf []segment - rcv_buf []segment + sndBuf []segment + rcvBuf []segment acklist []ackItem buffer []byte reserved int - output output_callback + output outputCallback } type ackItem struct { @@ -167,7 +167,7 @@ type ackItem struct { // 'conv' must be equal in the connection peers, or else data will be silently rejected. // // 'output' function will be called whenever these is data to be sent on wire. -func NewKCP(conv uint32, output output_callback) *KCP { +func NewKCP(conv uint32, output outputCallback) *KCP { kcp := new(KCP) kcp.conv = conv kcp.snd_wnd = IKCP_WND_SND @@ -179,7 +179,7 @@ func NewKCP(conv uint32, output output_callback) *KCP { kcp.rx_rto = IKCP_RTO_DEF kcp.rx_minrto = IKCP_RTO_MIN kcp.interval = IKCP_INTERVAL - kcp.ts_flush = IKCP_INTERVAL + kcp.tsFlush = IKCP_INTERVAL kcp.ssthresh = IKCP_THRESH_INIT kcp.dead_link = IKCP_DEADLINK kcp.output = output @@ -187,13 +187,13 @@ func NewKCP(conv uint32, output output_callback) *KCP { } // newSegment creates a KCP segment -func (kcp *KCP) newSegment(size int) (seg segment) { +func (*KCP) newSegment(size int) (seg segment) { seg.data = xmitBuf.Get().([]byte)[:size] - return + return seg } // delSegment recycles a KCP segment -func (kcp *KCP) delSegment(seg *segment) { +func (*KCP) delSegment(seg *segment) { if seg.data != nil { xmitBuf.Put(seg.data) seg.data = nil @@ -201,7 +201,7 @@ func (kcp *KCP) delSegment(seg *segment) { } // ReserveBytes keeps n bytes untouched from the beginning of the buffer, -// the output_callback function should be aware of this. +// the outputCallback function should be aware of this. // // Return false if n >= mss func (kcp *KCP) ReserveBytes(n int) bool { @@ -235,7 +235,7 @@ func (kcp *KCP) PeekSize() (length int) { break } } - return + return length } // Receive data from kcp state machine @@ -277,10 +277,10 @@ func (kcp *KCP) Recv(buffer []byte) (n int) { kcp.rcv_queue = kcp.remove_front(kcp.rcv_queue, count) } - // move available data from rcv_buf -> rcv_queue + // move available data from rcvBuf -> rcv_queue count = 0 - for k := range kcp.rcv_buf { - seg := &kcp.rcv_buf[k] + for k := range kcp.rcvBuf { + seg := &kcp.rcvBuf[k] if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue)+count < int(kcp.rcv_wnd) { kcp.rcv_nxt++ count++ @@ -290,8 +290,8 @@ func (kcp *KCP) Recv(buffer []byte) (n int) { } if count > 0 { - kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[:count]...) - kcp.rcv_buf = kcp.remove_front(kcp.rcv_buf, count) + kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcvBuf[:count]...) + kcp.rcvBuf = kcp.remove_front(kcp.rcvBuf, count) } // fast recover @@ -300,7 +300,7 @@ func (kcp *KCP) Recv(buffer []byte) (n int) { // tell remote my window size kcp.probe |= IKCP_ASK_TELL } - return + return n } // Send is user/upper level send, returns below zero for error @@ -396,8 +396,8 @@ func (kcp *KCP) update_ack(rtt int32) { } func (kcp *KCP) shrink_buf() { - if len(kcp.snd_buf) > 0 { - seg := &kcp.snd_buf[0] + if len(kcp.sndBuf) > 0 { + seg := &kcp.sndBuf[0] kcp.snd_una = seg.sn } else { kcp.snd_una = kcp.snd_nxt @@ -409,8 +409,8 @@ func (kcp *KCP) parse_ack(sn uint32) { return } - for k := range kcp.snd_buf { - seg := &kcp.snd_buf[k] + for k := range kcp.sndBuf { + seg := &kcp.sndBuf[k] if sn == seg.sn { // mark and free space, but leave the segment here, // and wait until `una` to delete this, then we don't @@ -431,8 +431,8 @@ func (kcp *KCP) parse_fastack(sn, ts uint32) { return } - for k := range kcp.snd_buf { - seg := &kcp.snd_buf[k] + for k := range kcp.sndBuf { + seg := &kcp.sndBuf[k] if _itimediff(sn, seg.sn) < 0 { break } else if sn != seg.sn && _itimediff(seg.ts, ts) <= 0 { @@ -443,8 +443,8 @@ func (kcp *KCP) parse_fastack(sn, ts uint32) { func (kcp *KCP) parse_una(una uint32) int { count := 0 - for k := range kcp.snd_buf { - seg := &kcp.snd_buf[k] + for k := range kcp.sndBuf { + seg := &kcp.sndBuf[k] if _itimediff(una, seg.sn) > 0 { kcp.delSegment(seg) count++ @@ -453,7 +453,7 @@ func (kcp *KCP) parse_una(una uint32) int { } } if count > 0 { - kcp.snd_buf = kcp.remove_front(kcp.snd_buf, count) + kcp.sndBuf = kcp.remove_front(kcp.sndBuf, count) } return count } @@ -471,11 +471,11 @@ func (kcp *KCP) parse_data(newseg segment) bool { return true } - n := len(kcp.rcv_buf) - 1 + n := len(kcp.rcvBuf) - 1 insert_idx := 0 repeat := false for i := n; i >= 0; i-- { - seg := &kcp.rcv_buf[i] + seg := &kcp.rcvBuf[i] if seg.sn == sn { repeat = true break @@ -493,18 +493,18 @@ func (kcp *KCP) parse_data(newseg segment) bool { newseg.data = dataCopy if insert_idx == n+1 { - kcp.rcv_buf = append(kcp.rcv_buf, newseg) + kcp.rcvBuf = append(kcp.rcvBuf, newseg) } else { - kcp.rcv_buf = append(kcp.rcv_buf, segment{}) - copy(kcp.rcv_buf[insert_idx+1:], kcp.rcv_buf[insert_idx:]) - kcp.rcv_buf[insert_idx] = newseg + kcp.rcvBuf = append(kcp.rcvBuf, segment{}) + copy(kcp.rcvBuf[insert_idx+1:], kcp.rcvBuf[insert_idx:]) + kcp.rcvBuf[insert_idx] = newseg } } - // move available data from rcv_buf -> rcv_queue + // move available data from rcvBuf -> rcv_queue count := 0 - for k := range kcp.rcv_buf { - seg := &kcp.rcv_buf[k] + for k := range kcp.rcvBuf { + seg := &kcp.rcvBuf[k] if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue)+count < int(kcp.rcv_wnd) { kcp.rcv_nxt++ count++ @@ -513,8 +513,8 @@ func (kcp *KCP) parse_data(newseg segment) bool { } } if count > 0 { - kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[:count]...) - kcp.rcv_buf = kcp.remove_front(kcp.rcv_buf, count) + kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcvBuf[:count]...) + kcp.rcvBuf = kcp.remove_front(kcp.rcvBuf, count) } return repeat @@ -546,18 +546,18 @@ func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int { break } - data = ikcp_decode32u(data, &conv) + data = ikcpDecode32u(data, &conv) if conv != kcp.conv { return -1 } - data = ikcp_decode8u(data, &cmd) - data = ikcp_decode8u(data, &frg) - data = ikcp_decode16u(data, &wnd) - data = ikcp_decode32u(data, &ts) - data = ikcp_decode32u(data, &sn) - data = ikcp_decode32u(data, &una) - data = ikcp_decode32u(data, &length) + data = ikcpDecode8u(data, &cmd) + data = ikcpDecode8u(data, &frg) + data = ikcpDecode16u(data, &wnd) + data = ikcpDecode32u(data, &ts) + data = ikcpDecode32u(data, &sn) + data = ikcpDecode32u(data, &una) + data = ikcpDecode32u(data, &length) if len(data) < int(length) { return -2 } @@ -576,12 +576,13 @@ func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int { } kcp.shrink_buf() - if cmd == IKCP_CMD_ACK { + switch cmd { + case IKCP_CMD_ACK: kcp.parse_ack(sn) kcp.parse_fastack(sn, ts) flag |= 1 latest = ts - } else if cmd == IKCP_CMD_PUSH { + case IKCP_CMD_PUSH: repeat := true if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) < 0 { kcp.ack_push(sn, ts) @@ -601,13 +602,13 @@ func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int { if regular && repeat { atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1) } - } else if cmd == IKCP_CMD_WASK { + case IKCP_CMD_WASK: // ready to send back IKCP_CMD_WINS in Ikcp_flush // tell remote my window size kcp.probe |= IKCP_ASK_TELL - } else if cmd == IKCP_CMD_WINS { + case IKCP_CMD_WINS: // do nothing - } else { + default: return -3 } @@ -662,7 +663,7 @@ func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int { return 0 } -func (kcp *KCP) wnd_unused() uint16 { +func (kcp *KCP) wndUnused() uint16 { if len(kcp.rcv_queue) < int(kcp.rcv_wnd) { return uint16(int(kcp.rcv_wnd) - len(kcp.rcv_queue)) } @@ -674,7 +675,7 @@ func (kcp *KCP) flush(ackOnly bool) uint32 { var seg segment seg.conv = kcp.conv seg.cmd = IKCP_CMD_ACK - seg.wnd = kcp.wnd_unused() + seg.wnd = kcp.wndUnused() seg.una = kcp.rcv_nxt buffer := kcp.buffer @@ -719,19 +720,18 @@ func (kcp *KCP) flush(ackOnly bool) uint32 { if kcp.probe_wait == 0 { kcp.probe_wait = IKCP_PROBE_INIT kcp.ts_probe = current + kcp.probe_wait - } else { - if _itimediff(current, kcp.ts_probe) >= 0 { - if kcp.probe_wait < IKCP_PROBE_INIT { - kcp.probe_wait = IKCP_PROBE_INIT - } - kcp.probe_wait += kcp.probe_wait / 2 - if kcp.probe_wait > IKCP_PROBE_LIMIT { - kcp.probe_wait = IKCP_PROBE_LIMIT - } - kcp.ts_probe = current + kcp.probe_wait - kcp.probe |= IKCP_ASK_SEND + } else if _itimediff(current, kcp.ts_probe) >= 0 { + if kcp.probe_wait < IKCP_PROBE_INIT { + kcp.probe_wait = IKCP_PROBE_INIT + } + kcp.probe_wait += kcp.probe_wait / 2 + if kcp.probe_wait > IKCP_PROBE_LIMIT { + kcp.probe_wait = IKCP_PROBE_LIMIT } + kcp.ts_probe = current + kcp.probe_wait + kcp.probe |= IKCP_ASK_SEND } + } else { kcp.ts_probe = 0 kcp.probe_wait = 0 @@ -769,7 +769,7 @@ func (kcp *KCP) flush(ackOnly bool) uint32 { newseg.conv = kcp.conv newseg.cmd = IKCP_CMD_PUSH newseg.sn = kcp.snd_nxt - kcp.snd_buf = append(kcp.snd_buf, newseg) + kcp.sndBuf = append(kcp.sndBuf, newseg) kcp.snd_nxt++ newSegsCount++ } @@ -788,7 +788,7 @@ func (kcp *KCP) flush(ackOnly bool) uint32 { var change, lostSegs, fastRetransSegs, earlyRetransSegs uint64 minrto := int32(kcp.interval) - ref := kcp.snd_buf[:len(kcp.snd_buf)] // for bounds check elimination + ref := kcp.sndBuf[:len(kcp.sndBuf)] // for bounds check elimination for k := range ref { segment := &ref[k] needsend := false @@ -913,20 +913,20 @@ func (kcp *KCP) Update() { current := currentMs() if kcp.updated == 0 { kcp.updated = 1 - kcp.ts_flush = current + kcp.tsFlush = current } - slap = _itimediff(current, kcp.ts_flush) + slap = _itimediff(current, kcp.tsFlush) if slap >= 10000 || slap < -10000 { - kcp.ts_flush = current + kcp.tsFlush = current slap = 0 } if slap >= 0 { - kcp.ts_flush += kcp.interval - if _itimediff(current, kcp.ts_flush) >= 0 { - kcp.ts_flush = current + kcp.interval + kcp.tsFlush += kcp.interval + if _itimediff(current, kcp.tsFlush) >= 0 { + kcp.tsFlush = current + kcp.interval } kcp.flush(false) } @@ -943,39 +943,39 @@ func (kcp *KCP) Update() { // or optimize ikcp_update when handling massive kcp connections) func (kcp *KCP) Check() uint32 { current := currentMs() - ts_flush := kcp.ts_flush - tm_flush := int32(0x7fffffff) - tm_packet := int32(0x7fffffff) + tsFlush := kcp.tsFlush + tmFlush := int32(0x7fffffff) //nolint:ineffassign // we want this here + tmPacket := int32(0x7fffffff) //nolint:ineffassign // we want this here minimal := uint32(0) if kcp.updated == 0 { return current } - if _itimediff(current, ts_flush) >= 10000 || - _itimediff(current, ts_flush) < -10000 { - ts_flush = current + if _itimediff(current, tsFlush) >= 10000 || + _itimediff(current, tsFlush) < -10000 { + tsFlush = current } - if _itimediff(current, ts_flush) >= 0 { + if _itimediff(current, tsFlush) >= 0 { return current } - tm_flush = _itimediff(ts_flush, current) + tmFlush = _itimediff(tsFlush, current) - for k := range kcp.snd_buf { - seg := &kcp.snd_buf[k] + for k := range kcp.sndBuf { + seg := &kcp.sndBuf[k] diff := _itimediff(seg.resendts, current) if diff <= 0 { return current } - if diff < tm_packet { - tm_packet = diff + if diff < tmPacket { + tmPacket = diff } } - minimal = uint32(tm_packet) - if tm_packet >= tm_flush { - minimal = uint32(tm_flush) + minimal = uint32(tmPacket) + if tmPacket >= tmFlush { + minimal = uint32(tmFlush) } if minimal >= kcp.interval { minimal = kcp.interval @@ -994,9 +994,6 @@ func (kcp *KCP) SetMtu(mtu int) int { } buffer := make([]byte, mtu) - if buffer == nil { - return -2 - } kcp.mtu = uint32(mtu) kcp.mss = kcp.mtu - IKCP_OVERHEAD - uint32(kcp.reserved) kcp.buffer = buffer @@ -1013,7 +1010,7 @@ func (kcp *KCP) NoDelay(nodelay, interval, resend, nc int) int { if nodelay >= 0 { kcp.nodelay = uint32(nodelay) if nodelay != 0 { - kcp.rx_minrto = IKCP_RTO_NDL + kcp.rx_minrto = IkcpRtoNdl } else { kcp.rx_minrto = IKCP_RTO_MIN } @@ -1048,14 +1045,14 @@ func (kcp *KCP) WndSize(sndwnd, rcvwnd int) int { // WaitSnd gets how many packet is waiting to be sent func (kcp *KCP) WaitSnd() int { - return len(kcp.snd_buf) + len(kcp.snd_queue) + return len(kcp.sndBuf) + len(kcp.snd_queue) } // remove front n elements from queue // if the number of elements to remove is more than half of the size. // just shift the rear elements to front, otherwise just reslice q to q[n:] // then the cost of runtime.growslice can always be less than n/2 -func (kcp *KCP) remove_front(q []segment, n int) []segment { +func (*KCP) remove_front(q []segment, n int) []segment { if n > cap(q)/2 { newn := copy(q, q[n:]) return q[:newn] @@ -1070,11 +1067,11 @@ func (kcp *KCP) ReleaseTX() { xmitBuf.Put(kcp.snd_queue[k].data) } } - for k := range kcp.snd_buf { - if kcp.snd_buf[k].data != nil { - xmitBuf.Put(kcp.snd_buf[k].data) + for k := range kcp.sndBuf { + if kcp.sndBuf[k].data != nil { + xmitBuf.Put(kcp.sndBuf[k].data) } } kcp.snd_queue = nil - kcp.snd_buf = nil + kcp.sndBuf = nil } diff --git a/kcp_test.go b/kcp_test.go index 49d55d5a..1f98a161 100644 --- a/kcp_test.go +++ b/kcp_test.go @@ -96,7 +96,7 @@ func testlink(t *testing.T, client *lossyconn.LossyConn, server *lossyconn.Lossy } } - echoTester := func(s *UDPSession, raddr net.Addr) { + echoTester := func(s *UDPSession, _ net.Addr) { s.SetNoDelay(nodelay, interval, resend, nc) buf := make([]byte, 64) var rtt time.Duration @@ -119,10 +119,10 @@ func testlink(t *testing.T, client *lossyconn.LossyConn, server *lossyconn.Lossy func BenchmarkFlush(b *testing.B) { kcp := NewKCP(1, func(buf []byte, size int) {}) - kcp.snd_buf = make([]segment, 1024) - for k := range kcp.snd_buf { - kcp.snd_buf[k].xmit = 1 - kcp.snd_buf[k].resendts = currentMs() + 10000 + kcp.sndBuf = make([]segment, 1024) + for k := range kcp.sndBuf { + kcp.sndBuf[k].xmit = 1 + kcp.sndBuf[k].resendts = currentMs() + 10000 } b.ResetTimer() b.ReportAllocs() diff --git a/readloop_generic.go b/readloop_generic.go index 5dbe4f44..08e72cb8 100644 --- a/readloop_generic.go +++ b/readloop_generic.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package kcp diff --git a/sess.go b/sess.go index 227d99b2..8f4606c5 100644 --- a/sess.go +++ b/sess.go @@ -44,12 +44,10 @@ var ( errTimeout = errors.New("timeout") ) -var ( - // a system-wide packet buffer shared among sending, receiving and FEC - // to mitigate high-frequency memory allocation for packets, bytes from xmitBuf - // is aligned to 64bit - xmitBuf sync.Pool -) +// a system-wide packet buffer shared among sending, receiving and FEC +// to mitigate high-frequency memory allocation for packets, bytes from xmitBuf +// is aligned to 64bit +var xmitBuf sync.Pool func init() { xmitBuf.New = func() interface{} { @@ -102,9 +100,8 @@ type ( nonce Entropy // packets waiting to be sent on wire - txqueue []ipv4.Message - xconn batchConn // for x/net - xconnWriteError error + txqueue []ipv4.Message + xconn batchConn // for x/net mu sync.Mutex } @@ -287,10 +284,9 @@ func (s *UDPSession) WriteBuffers(v [][]byte) (n int, err error) { if len(b) <= int(s.kcp.mss) { s.kcp.Send(b) break - } else { - s.kcp.Send(b[:s.kcp.mss]) - b = b[s.kcp.mss:] } + s.kcp.Send(b[:s.kcp.mss]) + b = b[s.kcp.mss:] } } @@ -358,12 +354,11 @@ func (s *UDPSession) Close() error { return nil } else if s.ownConn { // client socket close return s.conn.Close() - } else { - return nil } - } else { - return errors.WithStack(io.ErrClosedPipe) + return nil + } + return errors.WithStack(io.ErrClosedPipe) } // LocalAddr returns the local network address. The Addr returned is shared by all invocations of LocalAddr, so do not modify it. @@ -748,7 +743,6 @@ func (s *UDPSession) kcpInput(data []byte) { if fecRecovered > 0 { atomic.AddUint64(&DefaultSnmp.FECRecovered, fecRecovered) } - } type ( @@ -932,7 +926,7 @@ func (l *Listener) SetReadDeadline(t time.Time) error { } // SetWriteDeadline implements the Conn SetWriteDeadline method. -func (l *Listener) SetWriteDeadline(t time.Time) error { return errInvalidOperation } +func (*Listener) SetWriteDeadline(t time.Time) error { return errInvalidOperation } // Close stops listening on the UDP address, and closes the socket func (l *Listener) Close() error { diff --git a/sess_test.go b/sess_test.go index f4cc62c0..b8f8ed50 100644 --- a/sess_test.go +++ b/sess_test.go @@ -1,38 +1,40 @@ package kcp import ( - "crypto/sha1" + "crypto/sha256" "fmt" "io" "log" "net" "net/http" - _ "net/http/pprof" "sync" "sync/atomic" "testing" "time" "golang.org/x/crypto/pbkdf2" + + _ "net/http/pprof" //nolint:gosec,revive // for profiling ) -var baseport = uint32(10000) -var key = []byte("testkey") -var pass = pbkdf2.Key(key, []byte("testsalt"), 4096, 32, sha1.New) +var ( + baseport = uint32(10000) + key = []byte("testkey") + pass = pbkdf2.Key(key, []byte("testsalt"), 4096, 32, sha256.New) +) func init() { go func() { - log.Println(http.ListenAndServe("0.0.0.0:6060", nil)) + log.Println(http.ListenAndServe("0.0.0.0:6060", nil)) //nolint:gosec // for profiling }() log.Println("beginning tests, encryption:salsa20, fec:10/3") } func dialEcho(port int) (*UDPSession, error) { - //block, _ := NewNoneBlockCrypt(pass) - //block, _ := NewSimpleXORBlockCrypt(pass) - //block, _ := NewTEABlockCrypt(pass[:16]) - //block, _ := NewAESBlockCrypt(pass) + // block, _ := NewSimpleXORBlockCrypt(pass) + // block, _ := NewTEABlockCrypt(pass[:16]) + // block, _ := NewAESBlockCrypt(pass) block, _ := NewSalsa20BlockCrypt(pass) sess, err := DialWithOptions(fmt.Sprintf("127.0.0.1:%v", port), block, 10, 3) if err != nil { @@ -75,10 +77,9 @@ func dialSink(port int) (*UDPSession, error) { } func dialTinyBufferEcho(port int) (*UDPSession, error) { - //block, _ := NewNoneBlockCrypt(pass) - //block, _ := NewSimpleXORBlockCrypt(pass) - //block, _ := NewTEABlockCrypt(pass[:16]) - //block, _ := NewAESBlockCrypt(pass) + // block, _ := NewSimpleXORBlockCrypt(pass) + // block, _ := NewTEABlockCrypt(pass[:16]) + // block, _ := NewAESBlockCrypt(pass) block, _ := NewSalsa20BlockCrypt(pass) sess, err := DialWithOptions(fmt.Sprintf("127.0.0.1:%v", port), block, 10, 3) if err != nil { @@ -89,18 +90,17 @@ func dialTinyBufferEcho(port int) (*UDPSession, error) { // //////////////////////// func listenEcho(port int) (net.Listener, error) { - //block, _ := NewNoneBlockCrypt(pass) - //block, _ := NewSimpleXORBlockCrypt(pass) - //block, _ := NewTEABlockCrypt(pass[:16]) - //block, _ := NewAESBlockCrypt(pass) + // block, _ := NewSimpleXORBlockCrypt(pass) + // block, _ := NewTEABlockCrypt(pass[:16]) + // block, _ := NewAESBlockCrypt(pass) block, _ := NewSalsa20BlockCrypt(pass) return ListenWithOptions(fmt.Sprintf("127.0.0.1:%v", port), block, 10, 0) } + func listenTinyBufferEcho(port int) (net.Listener, error) { - //block, _ := NewNoneBlockCrypt(pass) - //block, _ := NewSimpleXORBlockCrypt(pass) - //block, _ := NewTEABlockCrypt(pass[:16]) - //block, _ := NewAESBlockCrypt(pass) + // block, _ := NewSimpleXORBlockCrypt(pass) + // block, _ := NewTEABlockCrypt(pass[:16]) + // block, _ := NewAESBlockCrypt(pass) block, _ := NewSalsa20BlockCrypt(pass) return ListenWithOptions(fmt.Sprintf("127.0.0.1:%v", port), block, 10, 3) } @@ -178,7 +178,7 @@ func tinyBufferEchoServer(port int) net.Listener { return l } -/////////////////////////// +// HANDLE ECHO //////////////////////////// func handleEcho(conn *UDPSession) { conn.SetStreamMode(true) @@ -229,7 +229,7 @@ func handleTinyBufferEcho(conn *UDPSession) { } } -/////////////////////////// +// TIMEOUT TEST //////////////////////////// func TestTimeout(t *testing.T) { port := int(atomic.AddUint32(&baseport, 1)) @@ -242,7 +242,6 @@ func TestTimeout(t *testing.T) { } buf := make([]byte, 10) - //timeout cli.SetDeadline(time.Now().Add(time.Second)) <-time.After(2 * time.Second) n, err := cli.Read(buf) @@ -263,9 +262,9 @@ func TestSendRecv(t *testing.T) { } cli.SetWriteDelay(true) cli.SetDUP(1) - const N = 100 + const n = 100 buf := make([]byte, 10) - for i := 0; i < N; i++ { + for i := 0; i < n; i++ { msg := fmt.Sprintf("hello%v", i) cli.Write([]byte(msg)) if n, err := cli.Read(buf); err == nil { @@ -289,10 +288,10 @@ func TestSendVector(t *testing.T) { panic(err) } cli.SetWriteDelay(false) - const N = 100 + const n = 100 buf := make([]byte, 20) v := make([][]byte, 2) - for i := 0; i < N; i++ { + for i := 0; i < n; i++ { v[0] = []byte(fmt.Sprintf("hello%v", i)) v[1] = []byte(fmt.Sprintf("world%v", i)) msg := fmt.Sprintf("hello%vworld%v", i, i) @@ -317,7 +316,7 @@ func TestTinyBufferReceiver(t *testing.T) { if err != nil { panic(err) } - const N = 100 + const n = 100 snd := byte(0) fillBuffer := func(buf []byte) { for i := 0; i < len(buf); i++ { @@ -338,7 +337,7 @@ func TestTinyBufferReceiver(t *testing.T) { } sndbuf := make([]byte, 7) rcvbuf := make([]byte, 7) - for i := 0; i < N; i++ { + for i := 0; i < n; i++ { fillBuffer(sndbuf) cli.Write(sndbuf) if n, err := io.ReadFull(cli, rcvbuf); err == nil { @@ -383,7 +382,7 @@ func TestClose(t *testing.T) { if err != nil { panic(err) } - if n, err = cli.Write(buf); err != nil { + if _, err = cli.Write(buf); err != nil { t.Fatal("write misbehavior") } @@ -412,21 +411,21 @@ func TestParallel1024CLIENT_64BMSG_64CNT(t *testing.T) { var wg sync.WaitGroup wg.Add(1024) for i := 0; i < 1024; i++ { - go parallel_client(&wg, port) + go parallelClient(&wg, port) } wg.Wait() } -func parallel_client(wg *sync.WaitGroup, port int) (err error) { +func parallelClient(wg *sync.WaitGroup, port int) (err error) { cli, err := dialEcho(port) if err != nil { panic(err) } - err = echo_tester(cli, 64, 64) + err = echoTester(cli, 64, 64) cli.Close() wg.Done() - return + return err } func BenchmarkEchoSpeed4K(b *testing.B) { @@ -446,6 +445,7 @@ func BenchmarkEchoSpeed1M(b *testing.B) { } func speedclient(b *testing.B, nbytes int) { + b.Helper() port := int(atomic.AddUint32(&baseport, 1)) l := echoServer(port) defer l.Close() @@ -456,7 +456,7 @@ func speedclient(b *testing.B, nbytes int) { panic(err) } - if err := echo_tester(cli, nbytes, b.N); err != nil { + if err := echoTester(cli, nbytes, b.N); err != nil { b.Fail() } b.SetBytes(int64(nbytes)) @@ -480,6 +480,7 @@ func BenchmarkSinkSpeed1M(b *testing.B) { } func sinkclient(b *testing.B, nbytes int) { + b.Helper() port := int(atomic.AddUint32(&baseport, 1)) l := sinkServer(port) defer l.Close() @@ -490,12 +491,12 @@ func sinkclient(b *testing.B, nbytes int) { panic(err) } - sink_tester(cli, nbytes, b.N) + sinkTester(cli, nbytes, b.N) b.SetBytes(int64(nbytes)) cli.Close() } -func echo_tester(cli net.Conn, msglen, msgcount int) error { +func echoTester(cli net.Conn, msglen, msgcount int) error { buf := make([]byte, msglen) for i := 0; i < msgcount; i++ { // send packet @@ -509,18 +510,18 @@ func echo_tester(cli net.Conn, msglen, msgcount int) error { n, err := cli.Read(buf) if err != nil { return err - } else { - nrecv += n - if nrecv == msglen { - break - } } + nrecv += n + if nrecv == msglen { + break + } + } } return nil } -func sink_tester(cli *UDPSession, msglen, msgcount int) error { +func sinkTester(cli *UDPSession, msglen, msgcount int) error { // sender buf := make([]byte, msglen) for i := 0; i < msgcount; i++ { diff --git a/snmp.go b/snmp.go index f9618107..10926ce0 100644 --- a/snmp.go +++ b/snmp.go @@ -38,7 +38,7 @@ func newSnmp() *Snmp { } // Header returns all field names -func (s *Snmp) Header() []string { +func (*Snmp) Header() []string { return []string{ "BytesSent", "BytesReceived", diff --git a/timedsched.go b/timedsched.go index 2db7c206..ae3ff178 100644 --- a/timedsched.go +++ b/timedsched.go @@ -8,7 +8,7 @@ import ( ) // SystemTimedSched is the library level timed-scheduler -var SystemTimedSched *TimedSched = NewTimedSched(runtime.NumCPU()) +var SystemTimedSched = NewTimedSched(runtime.NumCPU()) type timedFunc struct { execute func() diff --git a/tx_generic.go b/tx_generic.go index 0b4f3494..df33e5b5 100644 --- a/tx_generic.go +++ b/tx_generic.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package kcp