| 1 |  | -From 0b9d0759f979a5d828b747ea51771f307c53d221 Mon Sep 17 00:00:00 2001
 | 
| 2 |  | -From: David Fifield <david@xxxxxxxxxxxxxxx>
 | 
| 3 |  | -Date: Thu, 9 Apr 2020 11:27:44 -0600
 | 
| 4 |  | -Subject: [PATCH] Remove crypt and FEC dependencies.
 | 
| 5 |  | -
 | 
| 6 |  | ----
 | 
| 7 |  | - crypt.go   | 618 -----------------------------------------------------
 | 
| 8 |  | - fec.go     | 337 -----------------------------
 | 
| 9 |  | - removed.go |  29 +++
 | 
| 10 |  | - 3 files changed, 29 insertions(+), 955 deletions(-)
 | 
| 11 |  | - delete mode 100644 crypt.go
 | 
| 12 |  | - delete mode 100644 fec.go
 | 
| 13 |  | - create mode 100644 removed.go
 | 
| 14 |  | -
 | 
| 15 |  | -diff --git a/crypt.go b/crypt.go
 | 
| 16 |  | -deleted file mode 100644
 | 
| 17 |  | -index d882852..0000000
 | 
| 18 |  | ---- a/crypt.go
 | 
| 19 |  | -+++ /dev/null
 | 
| 20 |  | -@@ -1,618 +0,0 @@
 | 
| 21 |  | --package kcp
 | 
| 22 |  | --
 | 
| 23 |  | --import (
 | 
| 24 |  | --	"crypto/aes"
 | 
| 25 |  | --	"crypto/cipher"
 | 
| 26 |  | --	"crypto/des"
 | 
| 27 |  | --	"crypto/sha1"
 | 
| 28 |  | --	"unsafe"
 | 
| 29 |  | --
 | 
| 30 |  | --	xor "github.com/templexxx/xorsimd"
 | 
| 31 |  | --	"github.com/tjfoc/gmsm/sm4"
 | 
| 32 |  | --
 | 
| 33 |  | --	"golang.org/x/crypto/blowfish"
 | 
| 34 |  | --	"golang.org/x/crypto/cast5"
 | 
| 35 |  | --	"golang.org/x/crypto/pbkdf2"
 | 
| 36 |  | --	"golang.org/x/crypto/salsa20"
 | 
| 37 |  | --	"golang.org/x/crypto/tea"
 | 
| 38 |  | --	"golang.org/x/crypto/twofish"
 | 
| 39 |  | --	"golang.org/x/crypto/xtea"
 | 
| 40 |  | --)
 | 
| 41 |  | --
 | 
| 42 |  | --var (
 | 
| 43 |  | --	initialVector = []byte{167, 115, 79, 156, 18, 172, 27, 1, 164, 21, 242, 193, 252, 120, 230, 107}
 | 
| 44 |  | --	saltxor       = `sH3CIVoF#rWLtJo6`
 | 
| 45 |  | --)
 | 
| 46 |  | --
 | 
| 47 |  | --// BlockCrypt defines encryption/decryption methods for a given byte slice.
 | 
| 48 |  | --// Notes on implementing: the data to be encrypted contains a builtin
 | 
| 49 |  | --// nonce at the first 16 bytes
 | 
| 50 |  | --type BlockCrypt interface {
 | 
| 51 |  | --	// Encrypt encrypts the whole block in src into dst.
 | 
| 52 |  | --	// Dst and src may point at the same memory.
 | 
| 53 |  | --	Encrypt(dst, src []byte)
 | 
| 54 |  | --
 | 
| 55 |  | --	// Decrypt decrypts the whole block in src into dst.
 | 
| 56 |  | --	// Dst and src may point at the same memory.
 | 
| 57 |  | --	Decrypt(dst, src []byte)
 | 
| 58 |  | --}
 | 
| 59 |  | --
 | 
| 60 |  | --type salsa20BlockCrypt struct {
 | 
| 61 |  | --	key [32]byte
 | 
| 62 |  | --}
 | 
| 63 |  | --
 | 
| 64 |  | --// NewSalsa20BlockCrypt https://en.wikipedia.org/wiki/Salsa20
 | 
| 65 |  | --func NewSalsa20BlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 66 |  | --	c := new(salsa20BlockCrypt)
 | 
| 67 |  | --	copy(c.key[:], key)
 | 
| 68 |  | --	return c, nil
 | 
| 69 |  | --}
 | 
| 70 |  | --
 | 
| 71 |  | --func (c *salsa20BlockCrypt) Encrypt(dst, src []byte) {
 | 
| 72 |  | --	salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key)
 | 
| 73 |  | --	copy(dst[:8], src[:8])
 | 
| 74 |  | --}
 | 
| 75 |  | --func (c *salsa20BlockCrypt) Decrypt(dst, src []byte) {
 | 
| 76 |  | --	salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key)
 | 
| 77 |  | --	copy(dst[:8], src[:8])
 | 
| 78 |  | --}
 | 
| 79 |  | --
 | 
| 80 |  | --type sm4BlockCrypt struct {
 | 
| 81 |  | --	encbuf [sm4.BlockSize]byte // 64bit alignment enc/dec buffer
 | 
| 82 |  | --	decbuf [2 * sm4.BlockSize]byte
 | 
| 83 |  | --	block  cipher.Block
 | 
| 84 |  | --}
 | 
| 85 |  | --
 | 
| 86 |  | --// NewSM4BlockCrypt https://github.com/tjfoc/gmsm/tree/master/sm4
 | 
| 87 |  | --func NewSM4BlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 88 |  | --	c := new(sm4BlockCrypt)
 | 
| 89 |  | --	block, err := sm4.NewCipher(key)
 | 
| 90 |  | --	if err != nil {
 | 
| 91 |  | --		return nil, err
 | 
| 92 |  | --	}
 | 
| 93 |  | --	c.block = block
 | 
| 94 |  | --	return c, nil
 | 
| 95 |  | --}
 | 
| 96 |  | --
 | 
| 97 |  | --func (c *sm4BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
 | 
| 98 |  | --func (c *sm4BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
 | 
| 99 |  | --
 | 
| 100 |  | --type twofishBlockCrypt struct {
 | 
| 101 |  | --	encbuf [twofish.BlockSize]byte
 | 
| 102 |  | --	decbuf [2 * twofish.BlockSize]byte
 | 
| 103 |  | --	block  cipher.Block
 | 
| 104 |  | --}
 | 
| 105 |  | --
 | 
| 106 |  | --// NewTwofishBlockCrypt https://en.wikipedia.org/wiki/Twofish
 | 
| 107 |  | --func NewTwofishBlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 108 |  | --	c := new(twofishBlockCrypt)
 | 
| 109 |  | --	block, err := twofish.NewCipher(key)
 | 
| 110 |  | --	if err != nil {
 | 
| 111 |  | --		return nil, err
 | 
| 112 |  | --	}
 | 
| 113 |  | --	c.block = block
 | 
| 114 |  | --	return c, nil
 | 
| 115 |  | --}
 | 
| 116 |  | --
 | 
| 117 |  | --func (c *twofishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
 | 
| 118 |  | --func (c *twofishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
 | 
| 119 |  | --
 | 
| 120 |  | --type tripleDESBlockCrypt struct {
 | 
| 121 |  | --	encbuf [des.BlockSize]byte
 | 
| 122 |  | --	decbuf [2 * des.BlockSize]byte
 | 
| 123 |  | --	block  cipher.Block
 | 
| 124 |  | --}
 | 
| 125 |  | --
 | 
| 126 |  | --// NewTripleDESBlockCrypt https://en.wikipedia.org/wiki/Triple_DES
 | 
| 127 |  | --func NewTripleDESBlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 128 |  | --	c := new(tripleDESBlockCrypt)
 | 
| 129 |  | --	block, err := des.NewTripleDESCipher(key)
 | 
| 130 |  | --	if err != nil {
 | 
| 131 |  | --		return nil, err
 | 
| 132 |  | --	}
 | 
| 133 |  | --	c.block = block
 | 
| 134 |  | --	return c, nil
 | 
| 135 |  | --}
 | 
| 136 |  | --
 | 
| 137 |  | --func (c *tripleDESBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
 | 
| 138 |  | --func (c *tripleDESBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
 | 
| 139 |  | --
 | 
| 140 |  | --type cast5BlockCrypt struct {
 | 
| 141 |  | --	encbuf [cast5.BlockSize]byte
 | 
| 142 |  | --	decbuf [2 * cast5.BlockSize]byte
 | 
| 143 |  | --	block  cipher.Block
 | 
| 144 |  | --}
 | 
| 145 |  | --
 | 
| 146 |  | --// NewCast5BlockCrypt https://en.wikipedia.org/wiki/CAST-128
 | 
| 147 |  | --func NewCast5BlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 148 |  | --	c := new(cast5BlockCrypt)
 | 
| 149 |  | --	block, err := cast5.NewCipher(key)
 | 
| 150 |  | --	if err != nil {
 | 
| 151 |  | --		return nil, err
 | 
| 152 |  | --	}
 | 
| 153 |  | --	c.block = block
 | 
| 154 |  | --	return c, nil
 | 
| 155 |  | --}
 | 
| 156 |  | --
 | 
| 157 |  | --func (c *cast5BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
 | 
| 158 |  | --func (c *cast5BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
 | 
| 159 |  | --
 | 
| 160 |  | --type blowfishBlockCrypt struct {
 | 
| 161 |  | --	encbuf [blowfish.BlockSize]byte
 | 
| 162 |  | --	decbuf [2 * blowfish.BlockSize]byte
 | 
| 163 |  | --	block  cipher.Block
 | 
| 164 |  | --}
 | 
| 165 |  | --
 | 
| 166 |  | --// NewBlowfishBlockCrypt https://en.wikipedia.org/wiki/Blowfish_(cipher)
 | 
| 167 |  | --func NewBlowfishBlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 168 |  | --	c := new(blowfishBlockCrypt)
 | 
| 169 |  | --	block, err := blowfish.NewCipher(key)
 | 
| 170 |  | --	if err != nil {
 | 
| 171 |  | --		return nil, err
 | 
| 172 |  | --	}
 | 
| 173 |  | --	c.block = block
 | 
| 174 |  | --	return c, nil
 | 
| 175 |  | --}
 | 
| 176 |  | --
 | 
| 177 |  | --func (c *blowfishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
 | 
| 178 |  | --func (c *blowfishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
 | 
| 179 |  | --
 | 
| 180 |  | --type aesBlockCrypt struct {
 | 
| 181 |  | --	encbuf [aes.BlockSize]byte
 | 
| 182 |  | --	decbuf [2 * aes.BlockSize]byte
 | 
| 183 |  | --	block  cipher.Block
 | 
| 184 |  | --}
 | 
| 185 |  | --
 | 
| 186 |  | --// NewAESBlockCrypt https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
 | 
| 187 |  | --func NewAESBlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 188 |  | --	c := new(aesBlockCrypt)
 | 
| 189 |  | --	block, err := aes.NewCipher(key)
 | 
| 190 |  | --	if err != nil {
 | 
| 191 |  | --		return nil, err
 | 
| 192 |  | --	}
 | 
| 193 |  | --	c.block = block
 | 
| 194 |  | --	return c, nil
 | 
| 195 |  | --}
 | 
| 196 |  | --
 | 
| 197 |  | --func (c *aesBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
 | 
| 198 |  | --func (c *aesBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
 | 
| 199 |  | --
 | 
| 200 |  | --type teaBlockCrypt struct {
 | 
| 201 |  | --	encbuf [tea.BlockSize]byte
 | 
| 202 |  | --	decbuf [2 * tea.BlockSize]byte
 | 
| 203 |  | --	block  cipher.Block
 | 
| 204 |  | --}
 | 
| 205 |  | --
 | 
| 206 |  | --// NewTEABlockCrypt https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
 | 
| 207 |  | --func NewTEABlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 208 |  | --	c := new(teaBlockCrypt)
 | 
| 209 |  | --	block, err := tea.NewCipherWithRounds(key, 16)
 | 
| 210 |  | --	if err != nil {
 | 
| 211 |  | --		return nil, err
 | 
| 212 |  | --	}
 | 
| 213 |  | --	c.block = block
 | 
| 214 |  | --	return c, nil
 | 
| 215 |  | --}
 | 
| 216 |  | --
 | 
| 217 |  | --func (c *teaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
 | 
| 218 |  | --func (c *teaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
 | 
| 219 |  | --
 | 
| 220 |  | --type xteaBlockCrypt struct {
 | 
| 221 |  | --	encbuf [xtea.BlockSize]byte
 | 
| 222 |  | --	decbuf [2 * xtea.BlockSize]byte
 | 
| 223 |  | --	block  cipher.Block
 | 
| 224 |  | --}
 | 
| 225 |  | --
 | 
| 226 |  | --// NewXTEABlockCrypt https://en.wikipedia.org/wiki/XTEA
 | 
| 227 |  | --func NewXTEABlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 228 |  | --	c := new(xteaBlockCrypt)
 | 
| 229 |  | --	block, err := xtea.NewCipher(key)
 | 
| 230 |  | --	if err != nil {
 | 
| 231 |  | --		return nil, err
 | 
| 232 |  | --	}
 | 
| 233 |  | --	c.block = block
 | 
| 234 |  | --	return c, nil
 | 
| 235 |  | --}
 | 
| 236 |  | --
 | 
| 237 |  | --func (c *xteaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) }
 | 
| 238 |  | --func (c *xteaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) }
 | 
| 239 |  | --
 | 
| 240 |  | --type simpleXORBlockCrypt struct {
 | 
| 241 |  | --	xortbl []byte
 | 
| 242 |  | --}
 | 
| 243 |  | --
 | 
| 244 |  | --// NewSimpleXORBlockCrypt simple xor with key expanding
 | 
| 245 |  | --func NewSimpleXORBlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 246 |  | --	c := new(simpleXORBlockCrypt)
 | 
| 247 |  | --	c.xortbl = pbkdf2.Key(key, []byte(saltxor), 32, mtuLimit, sha1.New)
 | 
| 248 |  | --	return c, nil
 | 
| 249 |  | --}
 | 
| 250 |  | --
 | 
| 251 |  | --func (c *simpleXORBlockCrypt) Encrypt(dst, src []byte) { xor.Bytes(dst, src, c.xortbl) }
 | 
| 252 |  | --func (c *simpleXORBlockCrypt) Decrypt(dst, src []byte) { xor.Bytes(dst, src, c.xortbl) }
 | 
| 253 |  | --
 | 
| 254 |  | --type noneBlockCrypt struct{}
 | 
| 255 |  | --
 | 
| 256 |  | --// NewNoneBlockCrypt does nothing but copying
 | 
| 257 |  | --func NewNoneBlockCrypt(key []byte) (BlockCrypt, error) {
 | 
| 258 |  | --	return new(noneBlockCrypt), nil
 | 
| 259 |  | --}
 | 
| 260 |  | --
 | 
| 261 |  | --func (c *noneBlockCrypt) Encrypt(dst, src []byte) { copy(dst, src) }
 | 
| 262 |  | --func (c *noneBlockCrypt) Decrypt(dst, src []byte) { copy(dst, src) }
 | 
| 263 |  | --
 | 
| 264 |  | --// packet encryption with local CFB mode
 | 
| 265 |  | --func encrypt(block cipher.Block, dst, src, buf []byte) {
 | 
| 266 |  | --	switch block.BlockSize() {
 | 
| 267 |  | --	case 8:
 | 
| 268 |  | --		encrypt8(block, dst, src, buf)
 | 
| 269 |  | --	case 16:
 | 
| 270 |  | --		encrypt16(block, dst, src, buf)
 | 
| 271 |  | --	default:
 | 
| 272 |  | --		panic("unsupported cipher block size")
 | 
| 273 |  | --	}
 | 
| 274 |  | --}
 | 
| 275 |  | --
 | 
| 276 |  | --// optimized encryption for the ciphers which works in 8-bytes
 | 
| 277 |  | --func encrypt8(block cipher.Block, dst, src, buf []byte) {
 | 
| 278 |  | --	tbl := buf[:8]
 | 
| 279 |  | --	block.Encrypt(tbl, initialVector)
 | 
| 280 |  | --	n := len(src) / 8
 | 
| 281 |  | --	base := 0
 | 
| 282 |  | --	repeat := n / 8
 | 
| 283 |  | --	left := n % 8
 | 
| 284 |  | --	ptr_tbl := (*uint64)(unsafe.Pointer(&tbl[0]))
 | 
| 285 |  | --
 | 
| 286 |  | --	for i := 0; i < repeat; i++ {
 | 
| 287 |  | --		s := src[base:][0:64]
 | 
| 288 |  | --		d := dst[base:][0:64]
 | 
| 289 |  | --		// 1
 | 
| 290 |  | --		*(*uint64)(unsafe.Pointer(&d[0])) = *(*uint64)(unsafe.Pointer(&s[0])) ^ *ptr_tbl
 | 
| 291 |  | --		block.Encrypt(tbl, d[0:8])
 | 
| 292 |  | --		// 2
 | 
| 293 |  | --		*(*uint64)(unsafe.Pointer(&d[8])) = *(*uint64)(unsafe.Pointer(&s[8])) ^ *ptr_tbl
 | 
| 294 |  | --		block.Encrypt(tbl, d[8:16])
 | 
| 295 |  | --		// 3
 | 
| 296 |  | --		*(*uint64)(unsafe.Pointer(&d[16])) = *(*uint64)(unsafe.Pointer(&s[16])) ^ *ptr_tbl
 | 
| 297 |  | --		block.Encrypt(tbl, d[16:24])
 | 
| 298 |  | --		// 4
 | 
| 299 |  | --		*(*uint64)(unsafe.Pointer(&d[24])) = *(*uint64)(unsafe.Pointer(&s[24])) ^ *ptr_tbl
 | 
| 300 |  | --		block.Encrypt(tbl, d[24:32])
 | 
| 301 |  | --		// 5
 | 
| 302 |  | --		*(*uint64)(unsafe.Pointer(&d[32])) = *(*uint64)(unsafe.Pointer(&s[32])) ^ *ptr_tbl
 | 
| 303 |  | --		block.Encrypt(tbl, d[32:40])
 | 
| 304 |  | --		// 6
 | 
| 305 |  | --		*(*uint64)(unsafe.Pointer(&d[40])) = *(*uint64)(unsafe.Pointer(&s[40])) ^ *ptr_tbl
 | 
| 306 |  | --		block.Encrypt(tbl, d[40:48])
 | 
| 307 |  | --		// 7
 | 
| 308 |  | --		*(*uint64)(unsafe.Pointer(&d[48])) = *(*uint64)(unsafe.Pointer(&s[48])) ^ *ptr_tbl
 | 
| 309 |  | --		block.Encrypt(tbl, d[48:56])
 | 
| 310 |  | --		// 8
 | 
| 311 |  | --		*(*uint64)(unsafe.Pointer(&d[56])) = *(*uint64)(unsafe.Pointer(&s[56])) ^ *ptr_tbl
 | 
| 312 |  | --		block.Encrypt(tbl, d[56:64])
 | 
| 313 |  | --		base += 64
 | 
| 314 |  | --	}
 | 
| 315 |  | --
 | 
| 316 |  | --	switch left {
 | 
| 317 |  | --	case 7:
 | 
| 318 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl
 | 
| 319 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 320 |  | --		base += 8
 | 
| 321 |  | --		fallthrough
 | 
| 322 |  | --	case 6:
 | 
| 323 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl
 | 
| 324 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 325 |  | --		base += 8
 | 
| 326 |  | --		fallthrough
 | 
| 327 |  | --	case 5:
 | 
| 328 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl
 | 
| 329 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 330 |  | --		base += 8
 | 
| 331 |  | --		fallthrough
 | 
| 332 |  | --	case 4:
 | 
| 333 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl
 | 
| 334 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 335 |  | --		base += 8
 | 
| 336 |  | --		fallthrough
 | 
| 337 |  | --	case 3:
 | 
| 338 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl
 | 
| 339 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 340 |  | --		base += 8
 | 
| 341 |  | --		fallthrough
 | 
| 342 |  | --	case 2:
 | 
| 343 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl
 | 
| 344 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 345 |  | --		base += 8
 | 
| 346 |  | --		fallthrough
 | 
| 347 |  | --	case 1:
 | 
| 348 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *ptr_tbl
 | 
| 349 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 350 |  | --		base += 8
 | 
| 351 |  | --		fallthrough
 | 
| 352 |  | --	case 0:
 | 
| 353 |  | --		xorBytes(dst[base:], src[base:], tbl)
 | 
| 354 |  | --	}
 | 
| 355 |  | --}
 | 
| 356 |  | --
 | 
| 357 |  | --// optimized encryption for the ciphers which works in 16-bytes
 | 
| 358 |  | --func encrypt16(block cipher.Block, dst, src, buf []byte) {
 | 
| 359 |  | --	tbl := buf[:16]
 | 
| 360 |  | --	block.Encrypt(tbl, initialVector)
 | 
| 361 |  | --	n := len(src) / 16
 | 
| 362 |  | --	base := 0
 | 
| 363 |  | --	repeat := n / 8
 | 
| 364 |  | --	left := n % 8
 | 
| 365 |  | --	for i := 0; i < repeat; i++ {
 | 
| 366 |  | --		s := src[base:][0:128]
 | 
| 367 |  | --		d := dst[base:][0:128]
 | 
| 368 |  | --		// 1
 | 
| 369 |  | --		xor.Bytes16Align(d[0:16], s[0:16], tbl)
 | 
| 370 |  | --		block.Encrypt(tbl, d[0:16])
 | 
| 371 |  | --		// 2
 | 
| 372 |  | --		xor.Bytes16Align(d[16:32], s[16:32], tbl)
 | 
| 373 |  | --		block.Encrypt(tbl, d[16:32])
 | 
| 374 |  | --		// 3
 | 
| 375 |  | --		xor.Bytes16Align(d[32:48], s[32:48], tbl)
 | 
| 376 |  | --		block.Encrypt(tbl, d[32:48])
 | 
| 377 |  | --		// 4
 | 
| 378 |  | --		xor.Bytes16Align(d[48:64], s[48:64], tbl)
 | 
| 379 |  | --		block.Encrypt(tbl, d[48:64])
 | 
| 380 |  | --		// 5
 | 
| 381 |  | --		xor.Bytes16Align(d[64:80], s[64:80], tbl)
 | 
| 382 |  | --		block.Encrypt(tbl, d[64:80])
 | 
| 383 |  | --		// 6
 | 
| 384 |  | --		xor.Bytes16Align(d[80:96], s[80:96], tbl)
 | 
| 385 |  | --		block.Encrypt(tbl, d[80:96])
 | 
| 386 |  | --		// 7
 | 
| 387 |  | --		xor.Bytes16Align(d[96:112], s[96:112], tbl)
 | 
| 388 |  | --		block.Encrypt(tbl, d[96:112])
 | 
| 389 |  | --		// 8
 | 
| 390 |  | --		xor.Bytes16Align(d[112:128], s[112:128], tbl)
 | 
| 391 |  | --		block.Encrypt(tbl, d[112:128])
 | 
| 392 |  | --		base += 128
 | 
| 393 |  | --	}
 | 
| 394 |  | --
 | 
| 395 |  | --	switch left {
 | 
| 396 |  | --	case 7:
 | 
| 397 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 398 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 399 |  | --		base += 16
 | 
| 400 |  | --		fallthrough
 | 
| 401 |  | --	case 6:
 | 
| 402 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 403 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 404 |  | --		base += 16
 | 
| 405 |  | --		fallthrough
 | 
| 406 |  | --	case 5:
 | 
| 407 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 408 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 409 |  | --		base += 16
 | 
| 410 |  | --		fallthrough
 | 
| 411 |  | --	case 4:
 | 
| 412 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 413 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 414 |  | --		base += 16
 | 
| 415 |  | --		fallthrough
 | 
| 416 |  | --	case 3:
 | 
| 417 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 418 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 419 |  | --		base += 16
 | 
| 420 |  | --		fallthrough
 | 
| 421 |  | --	case 2:
 | 
| 422 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 423 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 424 |  | --		base += 16
 | 
| 425 |  | --		fallthrough
 | 
| 426 |  | --	case 1:
 | 
| 427 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 428 |  | --		block.Encrypt(tbl, dst[base:])
 | 
| 429 |  | --		base += 16
 | 
| 430 |  | --		fallthrough
 | 
| 431 |  | --	case 0:
 | 
| 432 |  | --		xorBytes(dst[base:], src[base:], tbl)
 | 
| 433 |  | --	}
 | 
| 434 |  | --}
 | 
| 435 |  | --
 | 
| 436 |  | --// decryption
 | 
| 437 |  | --func decrypt(block cipher.Block, dst, src, buf []byte) {
 | 
| 438 |  | --	switch block.BlockSize() {
 | 
| 439 |  | --	case 8:
 | 
| 440 |  | --		decrypt8(block, dst, src, buf)
 | 
| 441 |  | --	case 16:
 | 
| 442 |  | --		decrypt16(block, dst, src, buf)
 | 
| 443 |  | --	default:
 | 
| 444 |  | --		panic("unsupported cipher block size")
 | 
| 445 |  | --	}
 | 
| 446 |  | --}
 | 
| 447 |  | --
 | 
| 448 |  | --// decrypt 8 bytes block, all byte slices are supposed to be 64bit aligned
 | 
| 449 |  | --func decrypt8(block cipher.Block, dst, src, buf []byte) {
 | 
| 450 |  | --	tbl := buf[0:8]
 | 
| 451 |  | --	next := buf[8:16]
 | 
| 452 |  | --	block.Encrypt(tbl, initialVector)
 | 
| 453 |  | --	n := len(src) / 8
 | 
| 454 |  | --	base := 0
 | 
| 455 |  | --	repeat := n / 8
 | 
| 456 |  | --	left := n % 8
 | 
| 457 |  | --	ptr_tbl := (*uint64)(unsafe.Pointer(&tbl[0]))
 | 
| 458 |  | --	ptr_next := (*uint64)(unsafe.Pointer(&next[0]))
 | 
| 459 |  | --
 | 
| 460 |  | --	for i := 0; i < repeat; i++ {
 | 
| 461 |  | --		s := src[base:][0:64]
 | 
| 462 |  | --		d := dst[base:][0:64]
 | 
| 463 |  | --		// 1
 | 
| 464 |  | --		block.Encrypt(next, s[0:8])
 | 
| 465 |  | --		*(*uint64)(unsafe.Pointer(&d[0])) = *(*uint64)(unsafe.Pointer(&s[0])) ^ *ptr_tbl
 | 
| 466 |  | --		// 2
 | 
| 467 |  | --		block.Encrypt(tbl, s[8:16])
 | 
| 468 |  | --		*(*uint64)(unsafe.Pointer(&d[8])) = *(*uint64)(unsafe.Pointer(&s[8])) ^ *ptr_next
 | 
| 469 |  | --		// 3
 | 
| 470 |  | --		block.Encrypt(next, s[16:24])
 | 
| 471 |  | --		*(*uint64)(unsafe.Pointer(&d[16])) = *(*uint64)(unsafe.Pointer(&s[16])) ^ *ptr_tbl
 | 
| 472 |  | --		// 4
 | 
| 473 |  | --		block.Encrypt(tbl, s[24:32])
 | 
| 474 |  | --		*(*uint64)(unsafe.Pointer(&d[24])) = *(*uint64)(unsafe.Pointer(&s[24])) ^ *ptr_next
 | 
| 475 |  | --		// 5
 | 
| 476 |  | --		block.Encrypt(next, s[32:40])
 | 
| 477 |  | --		*(*uint64)(unsafe.Pointer(&d[32])) = *(*uint64)(unsafe.Pointer(&s[32])) ^ *ptr_tbl
 | 
| 478 |  | --		// 6
 | 
| 479 |  | --		block.Encrypt(tbl, s[40:48])
 | 
| 480 |  | --		*(*uint64)(unsafe.Pointer(&d[40])) = *(*uint64)(unsafe.Pointer(&s[40])) ^ *ptr_next
 | 
| 481 |  | --		// 7
 | 
| 482 |  | --		block.Encrypt(next, s[48:56])
 | 
| 483 |  | --		*(*uint64)(unsafe.Pointer(&d[48])) = *(*uint64)(unsafe.Pointer(&s[48])) ^ *ptr_tbl
 | 
| 484 |  | --		// 8
 | 
| 485 |  | --		block.Encrypt(tbl, s[56:64])
 | 
| 486 |  | --		*(*uint64)(unsafe.Pointer(&d[56])) = *(*uint64)(unsafe.Pointer(&s[56])) ^ *ptr_next
 | 
| 487 |  | --		base += 64
 | 
| 488 |  | --	}
 | 
| 489 |  | --
 | 
| 490 |  | --	switch left {
 | 
| 491 |  | --	case 7:
 | 
| 492 |  | --		block.Encrypt(next, src[base:])
 | 
| 493 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *(*uint64)(unsafe.Pointer(&tbl[0]))
 | 
| 494 |  | --		tbl, next = next, tbl
 | 
| 495 |  | --		base += 8
 | 
| 496 |  | --		fallthrough
 | 
| 497 |  | --	case 6:
 | 
| 498 |  | --		block.Encrypt(next, src[base:])
 | 
| 499 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *(*uint64)(unsafe.Pointer(&tbl[0]))
 | 
| 500 |  | --		tbl, next = next, tbl
 | 
| 501 |  | --		base += 8
 | 
| 502 |  | --		fallthrough
 | 
| 503 |  | --	case 5:
 | 
| 504 |  | --		block.Encrypt(next, src[base:])
 | 
| 505 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *(*uint64)(unsafe.Pointer(&tbl[0]))
 | 
| 506 |  | --		tbl, next = next, tbl
 | 
| 507 |  | --		base += 8
 | 
| 508 |  | --		fallthrough
 | 
| 509 |  | --	case 4:
 | 
| 510 |  | --		block.Encrypt(next, src[base:])
 | 
| 511 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *(*uint64)(unsafe.Pointer(&tbl[0]))
 | 
| 512 |  | --		tbl, next = next, tbl
 | 
| 513 |  | --		base += 8
 | 
| 514 |  | --		fallthrough
 | 
| 515 |  | --	case 3:
 | 
| 516 |  | --		block.Encrypt(next, src[base:])
 | 
| 517 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *(*uint64)(unsafe.Pointer(&tbl[0]))
 | 
| 518 |  | --		tbl, next = next, tbl
 | 
| 519 |  | --		base += 8
 | 
| 520 |  | --		fallthrough
 | 
| 521 |  | --	case 2:
 | 
| 522 |  | --		block.Encrypt(next, src[base:])
 | 
| 523 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *(*uint64)(unsafe.Pointer(&tbl[0]))
 | 
| 524 |  | --		tbl, next = next, tbl
 | 
| 525 |  | --		base += 8
 | 
| 526 |  | --		fallthrough
 | 
| 527 |  | --	case 1:
 | 
| 528 |  | --		block.Encrypt(next, src[base:])
 | 
| 529 |  | --		*(*uint64)(unsafe.Pointer(&dst[base])) = *(*uint64)(unsafe.Pointer(&src[base])) ^ *(*uint64)(unsafe.Pointer(&tbl[0]))
 | 
| 530 |  | --		tbl, next = next, tbl
 | 
| 531 |  | --		base += 8
 | 
| 532 |  | --		fallthrough
 | 
| 533 |  | --	case 0:
 | 
| 534 |  | --		xorBytes(dst[base:], src[base:], tbl)
 | 
| 535 |  | --	}
 | 
| 536 |  | --}
 | 
| 537 |  | --
 | 
| 538 |  | --func decrypt16(block cipher.Block, dst, src, buf []byte) {
 | 
| 539 |  | --	tbl := buf[0:16]
 | 
| 540 |  | --	next := buf[16:32]
 | 
| 541 |  | --	block.Encrypt(tbl, initialVector)
 | 
| 542 |  | --	n := len(src) / 16
 | 
| 543 |  | --	base := 0
 | 
| 544 |  | --	repeat := n / 8
 | 
| 545 |  | --	left := n % 8
 | 
| 546 |  | --	for i := 0; i < repeat; i++ {
 | 
| 547 |  | --		s := src[base:][0:128]
 | 
| 548 |  | --		d := dst[base:][0:128]
 | 
| 549 |  | --		// 1
 | 
| 550 |  | --		block.Encrypt(next, s[0:16])
 | 
| 551 |  | --		xor.Bytes16Align(d[0:16], s[0:16], tbl)
 | 
| 552 |  | --		// 2
 | 
| 553 |  | --		block.Encrypt(tbl, s[16:32])
 | 
| 554 |  | --		xor.Bytes16Align(d[16:32], s[16:32], next)
 | 
| 555 |  | --		// 3
 | 
| 556 |  | --		block.Encrypt(next, s[32:48])
 | 
| 557 |  | --		xor.Bytes16Align(d[32:48], s[32:48], tbl)
 | 
| 558 |  | --		// 4
 | 
| 559 |  | --		block.Encrypt(tbl, s[48:64])
 | 
| 560 |  | --		xor.Bytes16Align(d[48:64], s[48:64], next)
 | 
| 561 |  | --		// 5
 | 
| 562 |  | --		block.Encrypt(next, s[64:80])
 | 
| 563 |  | --		xor.Bytes16Align(d[64:80], s[64:80], tbl)
 | 
| 564 |  | --		// 6
 | 
| 565 |  | --		block.Encrypt(tbl, s[80:96])
 | 
| 566 |  | --		xor.Bytes16Align(d[80:96], s[80:96], next)
 | 
| 567 |  | --		// 7
 | 
| 568 |  | --		block.Encrypt(next, s[96:112])
 | 
| 569 |  | --		xor.Bytes16Align(d[96:112], s[96:112], tbl)
 | 
| 570 |  | --		// 8
 | 
| 571 |  | --		block.Encrypt(tbl, s[112:128])
 | 
| 572 |  | --		xor.Bytes16Align(d[112:128], s[112:128], next)
 | 
| 573 |  | --		base += 128
 | 
| 574 |  | --	}
 | 
| 575 |  | --
 | 
| 576 |  | --	switch left {
 | 
| 577 |  | --	case 7:
 | 
| 578 |  | --		block.Encrypt(next, src[base:])
 | 
| 579 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 580 |  | --		tbl, next = next, tbl
 | 
| 581 |  | --		base += 16
 | 
| 582 |  | --		fallthrough
 | 
| 583 |  | --	case 6:
 | 
| 584 |  | --		block.Encrypt(next, src[base:])
 | 
| 585 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 586 |  | --		tbl, next = next, tbl
 | 
| 587 |  | --		base += 16
 | 
| 588 |  | --		fallthrough
 | 
| 589 |  | --	case 5:
 | 
| 590 |  | --		block.Encrypt(next, src[base:])
 | 
| 591 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 592 |  | --		tbl, next = next, tbl
 | 
| 593 |  | --		base += 16
 | 
| 594 |  | --		fallthrough
 | 
| 595 |  | --	case 4:
 | 
| 596 |  | --		block.Encrypt(next, src[base:])
 | 
| 597 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 598 |  | --		tbl, next = next, tbl
 | 
| 599 |  | --		base += 16
 | 
| 600 |  | --		fallthrough
 | 
| 601 |  | --	case 3:
 | 
| 602 |  | --		block.Encrypt(next, src[base:])
 | 
| 603 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 604 |  | --		tbl, next = next, tbl
 | 
| 605 |  | --		base += 16
 | 
| 606 |  | --		fallthrough
 | 
| 607 |  | --	case 2:
 | 
| 608 |  | --		block.Encrypt(next, src[base:])
 | 
| 609 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 610 |  | --		tbl, next = next, tbl
 | 
| 611 |  | --		base += 16
 | 
| 612 |  | --		fallthrough
 | 
| 613 |  | --	case 1:
 | 
| 614 |  | --		block.Encrypt(next, src[base:])
 | 
| 615 |  | --		xor.Bytes16Align(dst[base:], src[base:], tbl)
 | 
| 616 |  | --		tbl, next = next, tbl
 | 
| 617 |  | --		base += 16
 | 
| 618 |  | --		fallthrough
 | 
| 619 |  | --	case 0:
 | 
| 620 |  | --		xorBytes(dst[base:], src[base:], tbl)
 | 
| 621 |  | --	}
 | 
| 622 |  | --}
 | 
| 623 |  | --
 | 
| 624 |  | --// per bytes xors
 | 
| 625 |  | --func xorBytes(dst, a, b []byte) int {
 | 
| 626 |  | --	n := len(a)
 | 
| 627 |  | --	if len(b) < n {
 | 
| 628 |  | --		n = len(b)
 | 
| 629 |  | --	}
 | 
| 630 |  | --	if n == 0 {
 | 
| 631 |  | --		return 0
 | 
| 632 |  | --	}
 | 
| 633 |  | --
 | 
| 634 |  | --	for i := 0; i < n; i++ {
 | 
| 635 |  | --		dst[i] = a[i] ^ b[i]
 | 
| 636 |  | --	}
 | 
| 637 |  | --	return n
 | 
| 638 |  | --}
 | 
| 639 |  | -diff --git a/fec.go b/fec.go
 | 
| 640 |  | -deleted file mode 100644
 | 
| 641 |  | -index 97cd40b..0000000
 | 
| 642 |  | ---- a/fec.go
 | 
| 643 |  | -+++ /dev/null
 | 
| 644 |  | -@@ -1,337 +0,0 @@
 | 
| 645 |  | --package kcp
 | 
| 646 |  | --
 | 
| 647 |  | --import (
 | 
| 648 |  | --	"encoding/binary"
 | 
| 649 |  | --	"sync/atomic"
 | 
| 650 |  | --
 | 
| 651 |  | --	"github.com/klauspost/reedsolomon"
 | 
| 652 |  | --)
 | 
| 653 |  | --
 | 
| 654 |  | --const (
 | 
| 655 |  | --	fecHeaderSize      = 6
 | 
| 656 |  | --	fecHeaderSizePlus2 = fecHeaderSize + 2 // plus 2B data size
 | 
| 657 |  | --	typeData           = 0xf1
 | 
| 658 |  | --	typeParity         = 0xf2
 | 
| 659 |  | --	fecExpire          = 60000
 | 
| 660 |  | --)
 | 
| 661 |  | --
 | 
| 662 |  | --// fecPacket is a decoded FEC packet
 | 
| 663 |  | --type fecPacket []byte
 | 
| 664 |  | --
 | 
| 665 |  | --func (bts fecPacket) seqid() uint32 { return binary.LittleEndian.Uint32(bts) }
 | 
| 666 |  | --func (bts fecPacket) flag() uint16  { return binary.LittleEndian.Uint16(bts[4:]) }
 | 
| 667 |  | --func (bts fecPacket) data() []byte  { return bts[6:] }
 | 
| 668 |  | --
 | 
| 669 |  | --// fecElement has auxcilliary time field
 | 
| 670 |  | --type fecElement struct {
 | 
| 671 |  | --	fecPacket
 | 
| 672 |  | --	ts uint32
 | 
| 673 |  | --}
 | 
| 674 |  | --
 | 
| 675 |  | --// fecDecoder for decoding incoming packets
 | 
| 676 |  | --type fecDecoder struct {
 | 
| 677 |  | --	rxlimit      int // queue size limit
 | 
| 678 |  | --	dataShards   int
 | 
| 679 |  | --	parityShards int
 | 
| 680 |  | --	shardSize    int
 | 
| 681 |  | --	rx           []fecElement // ordered receive queue
 | 
| 682 |  | --
 | 
| 683 |  | --	// caches
 | 
| 684 |  | --	decodeCache [][]byte
 | 
| 685 |  | --	flagCache   []bool
 | 
| 686 |  | --
 | 
| 687 |  | --	// zeros
 | 
| 688 |  | --	zeros []byte
 | 
| 689 |  | --
 | 
| 690 |  | --	// RS decoder
 | 
| 691 |  | --	codec reedsolomon.Encoder
 | 
| 692 |  | --}
 | 
| 693 |  | --
 | 
| 694 |  | --func newFECDecoder(rxlimit, dataShards, parityShards int) *fecDecoder {
 | 
| 695 |  | --	if dataShards <= 0 || parityShards <= 0 {
 | 
| 696 |  | --		return nil
 | 
| 697 |  | --	}
 | 
| 698 |  | --	if rxlimit < dataShards+parityShards {
 | 
| 699 |  | --		return nil
 | 
| 700 |  | --	}
 | 
| 701 |  | --
 | 
| 702 |  | --	dec := new(fecDecoder)
 | 
| 703 |  | --	dec.rxlimit = rxlimit
 | 
| 704 |  | --	dec.dataShards = dataShards
 | 
| 705 |  | --	dec.parityShards = parityShards
 | 
| 706 |  | --	dec.shardSize = dataShards + parityShards
 | 
| 707 |  | --	codec, err := reedsolomon.New(dataShards, parityShards)
 | 
| 708 |  | --	if err != nil {
 | 
| 709 |  | --		return nil
 | 
| 710 |  | --	}
 | 
| 711 |  | --	dec.codec = codec
 | 
| 712 |  | --	dec.decodeCache = make([][]byte, dec.shardSize)
 | 
| 713 |  | --	dec.flagCache = make([]bool, dec.shardSize)
 | 
| 714 |  | --	dec.zeros = make([]byte, mtuLimit)
 | 
| 715 |  | --	return dec
 | 
| 716 |  | --}
 | 
| 717 |  | --
 | 
| 718 |  | --// decode a fec packet
 | 
| 719 |  | --func (dec *fecDecoder) decode(in fecPacket) (recovered [][]byte) {
 | 
| 720 |  | --	// insertion
 | 
| 721 |  | --	n := len(dec.rx) - 1
 | 
| 722 |  | --	insertIdx := 0
 | 
| 723 |  | --	for i := n; i >= 0; i-- {
 | 
| 724 |  | --		if in.seqid() == dec.rx[i].seqid() { // de-duplicate
 | 
| 725 |  | --			return nil
 | 
| 726 |  | --		} else if _itimediff(in.seqid(), dec.rx[i].seqid()) > 0 { // insertion
 | 
| 727 |  | --			insertIdx = i + 1
 | 
| 728 |  | --			break
 | 
| 729 |  | --		}
 | 
| 730 |  | --	}
 | 
| 731 |  | --
 | 
| 732 |  | --	// make a copy
 | 
| 733 |  | --	pkt := fecPacket(xmitBuf.Get().([]byte)[:len(in)])
 | 
| 734 |  | --	copy(pkt, in)
 | 
| 735 |  | --	elem := fecElement{pkt, currentMs()}
 | 
| 736 |  | --
 | 
| 737 |  | --	// insert into ordered rx queue
 | 
| 738 |  | --	if insertIdx == n+1 {
 | 
| 739 |  | --		dec.rx = append(dec.rx, elem)
 | 
| 740 |  | --	} else {
 | 
| 741 |  | --		dec.rx = append(dec.rx, fecElement{})
 | 
| 742 |  | --		copy(dec.rx[insertIdx+1:], dec.rx[insertIdx:]) // shift right
 | 
| 743 |  | --		dec.rx[insertIdx] = elem
 | 
| 744 |  | --	}
 | 
| 745 |  | --
 | 
| 746 |  | --	// shard range for current packet
 | 
| 747 |  | --	shardBegin := pkt.seqid() - pkt.seqid()%uint32(dec.shardSize)
 | 
| 748 |  | --	shardEnd := shardBegin + uint32(dec.shardSize) - 1
 | 
| 749 |  | --
 | 
| 750 |  | --	// max search range in ordered queue for current shard
 | 
| 751 |  | --	searchBegin := insertIdx - int(pkt.seqid()%uint32(dec.shardSize))
 | 
| 752 |  | --	if searchBegin < 0 {
 | 
| 753 |  | --		searchBegin = 0
 | 
| 754 |  | --	}
 | 
| 755 |  | --	searchEnd := searchBegin + dec.shardSize - 1
 | 
| 756 |  | --	if searchEnd >= len(dec.rx) {
 | 
| 757 |  | --		searchEnd = len(dec.rx) - 1
 | 
| 758 |  | --	}
 | 
| 759 |  | --
 | 
| 760 |  | --	// re-construct datashards
 | 
| 761 |  | --	if searchEnd-searchBegin+1 >= dec.dataShards {
 | 
| 762 |  | --		var numshard, numDataShard, first, maxlen int
 | 
| 763 |  | --
 | 
| 764 |  | --		// zero caches
 | 
| 765 |  | --		shards := dec.decodeCache
 | 
| 766 |  | --		shardsflag := dec.flagCache
 | 
| 767 |  | --		for k := range dec.decodeCache {
 | 
| 768 |  | --			shards[k] = nil
 | 
| 769 |  | --			shardsflag[k] = false
 | 
| 770 |  | --		}
 | 
| 771 |  | --
 | 
| 772 |  | --		// shard assembly
 | 
| 773 |  | --		for i := searchBegin; i <= searchEnd; i++ {
 | 
| 774 |  | --			seqid := dec.rx[i].seqid()
 | 
| 775 |  | --			if _itimediff(seqid, shardEnd) > 0 {
 | 
| 776 |  | --				break
 | 
| 777 |  | --			} else if _itimediff(seqid, shardBegin) >= 0 {
 | 
| 778 |  | --				shards[seqid%uint32(dec.shardSize)] = dec.rx[i].data()
 | 
| 779 |  | --				shardsflag[seqid%uint32(dec.shardSize)] = true
 | 
| 780 |  | --				numshard++
 | 
| 781 |  | --				if dec.rx[i].flag() == typeData {
 | 
| 782 |  | --					numDataShard++
 | 
| 783 |  | --				}
 | 
| 784 |  | --				if numshard == 1 {
 | 
| 785 |  | --					first = i
 | 
| 786 |  | --				}
 | 
| 787 |  | --				if len(dec.rx[i].data()) > maxlen {
 | 
| 788 |  | --					maxlen = len(dec.rx[i].data())
 | 
| 789 |  | --				}
 | 
| 790 |  | --			}
 | 
| 791 |  | --		}
 | 
| 792 |  | --
 | 
| 793 |  | --		if numDataShard == dec.dataShards {
 | 
| 794 |  | --			// case 1: no loss on data shards
 | 
| 795 |  | --			dec.rx = dec.freeRange(first, numshard, dec.rx)
 | 
| 796 |  | --		} else if numshard >= dec.dataShards {
 | 
| 797 |  | --			// case 2: loss on data shards, but it's recoverable from parity shards
 | 
| 798 |  | --			for k := range shards {
 | 
| 799 |  | --				if shards[k] != nil {
 | 
| 800 |  | --					dlen := len(shards[k])
 | 
| 801 |  | --					shards[k] = shards[k][:maxlen]
 | 
| 802 |  | --					copy(shards[k][dlen:], dec.zeros)
 | 
| 803 |  | --				} else if k < dec.dataShards {
 | 
| 804 |  | --					shards[k] = xmitBuf.Get().([]byte)[:0]
 | 
| 805 |  | --				}
 | 
| 806 |  | --			}
 | 
| 807 |  | --			if err := dec.codec.ReconstructData(shards); err == nil {
 | 
| 808 |  | --				for k := range shards[:dec.dataShards] {
 | 
| 809 |  | --					if !shardsflag[k] {
 | 
| 810 |  | --						// recovered data should be recycled
 | 
| 811 |  | --						recovered = append(recovered, shards[k])
 | 
| 812 |  | --					}
 | 
| 813 |  | --				}
 | 
| 814 |  | --			}
 | 
| 815 |  | --			dec.rx = dec.freeRange(first, numshard, dec.rx)
 | 
| 816 |  | --		}
 | 
| 817 |  | --	}
 | 
| 818 |  | --
 | 
| 819 |  | --	// keep rxlimit
 | 
| 820 |  | --	if len(dec.rx) > dec.rxlimit {
 | 
| 821 |  | --		if dec.rx[0].flag() == typeData { // track the unrecoverable data
 | 
| 822 |  | --			atomic.AddUint64(&DefaultSnmp.FECShortShards, 1)
 | 
| 823 |  | --		}
 | 
| 824 |  | --		dec.rx = dec.freeRange(0, 1, dec.rx)
 | 
| 825 |  | --	}
 | 
| 826 |  | --
 | 
| 827 |  | --	// timeout policy
 | 
| 828 |  | --	current := currentMs()
 | 
| 829 |  | --	numExpired := 0
 | 
| 830 |  | --	for k := range dec.rx {
 | 
| 831 |  | --		if _itimediff(current, dec.rx[k].ts) > fecExpire {
 | 
| 832 |  | --			numExpired++
 | 
| 833 |  | --			continue
 | 
| 834 |  | --		}
 | 
| 835 |  | --		break
 | 
| 836 |  | --	}
 | 
| 837 |  | --	if numExpired > 0 {
 | 
| 838 |  | --		dec.rx = dec.freeRange(0, numExpired, dec.rx)
 | 
| 839 |  | --	}
 | 
| 840 |  | --	return
 | 
| 841 |  | --}
 | 
| 842 |  | --
 | 
| 843 |  | --// free a range of fecPacket
 | 
| 844 |  | --func (dec *fecDecoder) freeRange(first, n int, q []fecElement) []fecElement {
 | 
| 845 |  | --	for i := first; i < first+n; i++ { // recycle buffer
 | 
| 846 |  | --		xmitBuf.Put([]byte(q[i].fecPacket))
 | 
| 847 |  | --	}
 | 
| 848 |  | --
 | 
| 849 |  | --	if first == 0 && n < cap(q)/2 {
 | 
| 850 |  | --		return q[n:]
 | 
| 851 |  | --	}
 | 
| 852 |  | --	copy(q[first:], q[first+n:])
 | 
| 853 |  | --	return q[:len(q)-n]
 | 
| 854 |  | --}
 | 
| 855 |  | --
 | 
| 856 |  | --// release all segments back to xmitBuf
 | 
| 857 |  | --func (dec *fecDecoder) release() {
 | 
| 858 |  | --	if n := len(dec.rx); n > 0 {
 | 
| 859 |  | --		dec.rx = dec.freeRange(0, n, dec.rx)
 | 
| 860 |  | --	}
 | 
| 861 |  | --}
 | 
| 862 |  | --
 | 
| 863 |  | --type (
 | 
| 864 |  | --	// fecEncoder for encoding outgoing packets
 | 
| 865 |  | --	fecEncoder struct {
 | 
| 866 |  | --		dataShards   int
 | 
| 867 |  | --		parityShards int
 | 
| 868 |  | --		shardSize    int
 | 
| 869 |  | --		paws         uint32 // Protect Against Wrapped Sequence numbers
 | 
| 870 |  | --		next         uint32 // next seqid
 | 
| 871 |  | --
 | 
| 872 |  | --		shardCount int // count the number of datashards collected
 | 
| 873 |  | --		maxSize    int // track maximum data length in datashard
 | 
| 874 |  | --
 | 
| 875 |  | --		headerOffset  int // FEC header offset
 | 
| 876 |  | --		payloadOffset int // FEC payload offset
 | 
| 877 |  | --
 | 
| 878 |  | --		// caches
 | 
| 879 |  | --		shardCache  [][]byte
 | 
| 880 |  | --		encodeCache [][]byte
 | 
| 881 |  | --
 | 
| 882 |  | --		// zeros
 | 
| 883 |  | --		zeros []byte
 | 
| 884 |  | --
 | 
| 885 |  | --		// RS encoder
 | 
| 886 |  | --		codec reedsolomon.Encoder
 | 
| 887 |  | --	}
 | 
| 888 |  | --)
 | 
| 889 |  | --
 | 
| 890 |  | --func newFECEncoder(dataShards, parityShards, offset int) *fecEncoder {
 | 
| 891 |  | --	if dataShards <= 0 || parityShards <= 0 {
 | 
| 892 |  | --		return nil
 | 
| 893 |  | --	}
 | 
| 894 |  | --	enc := new(fecEncoder)
 | 
| 895 |  | --	enc.dataShards = dataShards
 | 
| 896 |  | --	enc.parityShards = parityShards
 | 
| 897 |  | --	enc.shardSize = dataShards + parityShards
 | 
| 898 |  | --	enc.paws = 0xffffffff / uint32(enc.shardSize) * uint32(enc.shardSize)
 | 
| 899 |  | --	enc.headerOffset = offset
 | 
| 900 |  | --	enc.payloadOffset = enc.headerOffset + fecHeaderSize
 | 
| 901 |  | --
 | 
| 902 |  | --	codec, err := reedsolomon.New(dataShards, parityShards)
 | 
| 903 |  | --	if err != nil {
 | 
| 904 |  | --		return nil
 | 
| 905 |  | --	}
 | 
| 906 |  | --	enc.codec = codec
 | 
| 907 |  | --
 | 
| 908 |  | --	// caches
 | 
| 909 |  | --	enc.encodeCache = make([][]byte, enc.shardSize)
 | 
| 910 |  | --	enc.shardCache = make([][]byte, enc.shardSize)
 | 
| 911 |  | --	for k := range enc.shardCache {
 | 
| 912 |  | --		enc.shardCache[k] = make([]byte, mtuLimit)
 | 
| 913 |  | --	}
 | 
| 914 |  | --	enc.zeros = make([]byte, mtuLimit)
 | 
| 915 |  | --	return enc
 | 
| 916 |  | --}
 | 
| 917 |  | --
 | 
| 918 |  | --// encodes the packet, outputs parity shards if we have collected quorum datashards
 | 
| 919 |  | --// notice: the contents of 'ps' will be re-written in successive calling
 | 
| 920 |  | --func (enc *fecEncoder) encode(b []byte) (ps [][]byte) {
 | 
| 921 |  | --	// The header format:
 | 
| 922 |  | --	// | FEC SEQID(4B) | FEC TYPE(2B) | SIZE (2B) | PAYLOAD(SIZE-2) |
 | 
| 923 |  | --	// |<-headerOffset                |<-payloadOffset
 | 
| 924 |  | --	enc.markData(b[enc.headerOffset:])
 | 
| 925 |  | --	binary.LittleEndian.PutUint16(b[enc.payloadOffset:], uint16(len(b[enc.payloadOffset:])))
 | 
| 926 |  | --
 | 
| 927 |  | --	// copy data from payloadOffset to fec shard cache
 | 
| 928 |  | --	sz := len(b)
 | 
| 929 |  | --	enc.shardCache[enc.shardCount] = enc.shardCache[enc.shardCount][:sz]
 | 
| 930 |  | --	copy(enc.shardCache[enc.shardCount][enc.payloadOffset:], b[enc.payloadOffset:])
 | 
| 931 |  | --	enc.shardCount++
 | 
| 932 |  | --
 | 
| 933 |  | --	// track max datashard length
 | 
| 934 |  | --	if sz > enc.maxSize {
 | 
| 935 |  | --		enc.maxSize = sz
 | 
| 936 |  | --	}
 | 
| 937 |  | --
 | 
| 938 |  | --	//  Generation of Reed-Solomon Erasure Code
 | 
| 939 |  | --	if enc.shardCount == enc.dataShards {
 | 
| 940 |  | --		// fill '0' into the tail of each datashard
 | 
| 941 |  | --		for i := 0; i < enc.dataShards; i++ {
 | 
| 942 |  | --			shard := enc.shardCache[i]
 | 
| 943 |  | --			slen := len(shard)
 | 
| 944 |  | --			copy(shard[slen:enc.maxSize], enc.zeros)
 | 
| 945 |  | --		}
 | 
| 946 |  | --
 | 
| 947 |  | --		// construct equal-sized slice with stripped header
 | 
| 948 |  | --		cache := enc.encodeCache
 | 
| 949 |  | --		for k := range cache {
 | 
| 950 |  | --			cache[k] = enc.shardCache[k][enc.payloadOffset:enc.maxSize]
 | 
| 951 |  | --		}
 | 
| 952 |  | --
 | 
| 953 |  | --		// encoding
 | 
| 954 |  | --		if err := enc.codec.Encode(cache); err == nil {
 | 
| 955 |  | --			ps = enc.shardCache[enc.dataShards:]
 | 
| 956 |  | --			for k := range ps {
 | 
| 957 |  | --				enc.markParity(ps[k][enc.headerOffset:])
 | 
| 958 |  | --				ps[k] = ps[k][:enc.maxSize]
 | 
| 959 |  | --			}
 | 
| 960 |  | --		}
 | 
| 961 |  | --
 | 
| 962 |  | --		// counters resetting
 | 
| 963 |  | --		enc.shardCount = 0
 | 
| 964 |  | --		enc.maxSize = 0
 | 
| 965 |  | --	}
 | 
| 966 |  | --
 | 
| 967 |  | --	return
 | 
| 968 |  | --}
 | 
| 969 |  | --
 | 
| 970 |  | --func (enc *fecEncoder) markData(data []byte) {
 | 
| 971 |  | --	binary.LittleEndian.PutUint32(data, enc.next)
 | 
| 972 |  | --	binary.LittleEndian.PutUint16(data[4:], typeData)
 | 
| 973 |  | --	enc.next++
 | 
| 974 |  | --}
 | 
| 975 |  | --
 | 
| 976 |  | --func (enc *fecEncoder) markParity(data []byte) {
 | 
| 977 |  | --	binary.LittleEndian.PutUint32(data, enc.next)
 | 
| 978 |  | --	binary.LittleEndian.PutUint16(data[4:], typeParity)
 | 
| 979 |  | --	// sequence wrap will only happen at parity shard
 | 
| 980 |  | --	enc.next = (enc.next + 1) % enc.paws
 | 
| 981 |  | --}
 | 
| 982 |  | -diff --git a/removed.go b/removed.go
 | 
| 983 |  | -new file mode 100644
 | 
| 984 |  | -index 0000000..5ecf446
 | 
| 985 |  | ---- /dev/null
 | 
| 986 |  | -+++ b/removed.go
 | 
| 987 |  | -@@ -0,0 +1,29 @@
 | 
| 988 |  | -+package kcp
 | 
| 989 |  | -+
 | 
| 990 |  | -+// Dummy implementations for types from crypt.go and fec.go, removed to reduce
 | 
| 991 |  | -+// dependencies.
 | 
| 992 |  | -+
 | 
| 993 |  | -+const (
 | 
| 994 |  | -+	fecHeaderSize      = 6
 | 
| 995 |  | -+	fecHeaderSizePlus2 = fecHeaderSize + 2
 | 
| 996 |  | -+	typeData           = 0xf1
 | 
| 997 |  | -+	typeParity         = 0xf2
 | 
| 998 |  | -+)
 | 
| 999 |  | -+
 | 
| 1000 |  | -+type (
 | 
| 1001 |  | -+	BlockCrypt interface {
 | 
| 1002 |  | -+		Encrypt(_, _ []byte)
 | 
| 1003 |  | -+		Decrypt(_, _ []byte)
 | 
| 1004 |  | -+	}
 | 
| 1005 |  | -+	fecDecoder struct{}
 | 
| 1006 |  | -+	fecEncoder struct{}
 | 
| 1007 |  | -+	fecPacket  []byte
 | 
| 1008 |  | -+)
 | 
| 1009 |  | -+
 | 
| 1010 |  | -+func newFECDecoder(rxlimit, dataShards, parityShards int) *fecDecoder { return nil }
 | 
| 1011 |  | -+func newFECEncoder(dataShards, parityShards, offset int) *fecEncoder  { return nil }
 | 
| 1012 |  | -+
 | 
| 1013 |  | -+func (_ *fecDecoder) decode(in fecPacket) [][]byte { panic("disabled") }
 | 
| 1014 |  | -+func (_ *fecDecoder) release()                     { panic("disabled") }
 | 
| 1015 |  | -+func (_ *fecEncoder) encode(b []byte) [][]byte     { panic("disabled") }
 | 
| 1016 |  | -+func (_ fecPacket) flag() uint16                   { panic("disabled") }
 | 
| 1017 |  | --- 
 | 
| 1018 |  | -2.20.1
 | 
| 1019 |  | - |