├── .gitignore ├── README.md ├── buildp2p.sh ├── kcp-go ├── LICENSE ├── batchconn.go ├── crypt.go ├── entropy.go ├── fec.go ├── kcp.go ├── readloop_generic.go ├── readloop_linux.go ├── sess.go ├── snmp.go ├── tx_generic.go ├── tx_linux.go └── updater.go ├── p2pclient ├── config.go ├── main.go └── signal.go └── p2pserver ├── config.go ├── main.go └── signal.go /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Introduction 2 | >A p2p tunnel(based on kcptun) which establishs port forwarding channel for both clients. 3 | >Need one server with public ip and one udp port for hole digging. 4 | 5 | ### QuickStart 6 | Download a corresponding one from precompiled [Releases](https://github.com/hikaricai/p2p_tun/releases). 7 | 8 | ``` 9 | Server: ./p2pserver -l ":4000" 10 | Client_A: ./p2pclient -r "SERVER_IP:4000" -l ":10022" -t "TARGET_IP_A:22" -k 4321 11 | Client_B: ./p2pclient -r "SERVER_IP:4000" -l ":10022" -t "TARGET_IP_B:22" -k 4321 12 | ``` 13 | The above commands will establish port forwarding channel for both Client_A and Client_B as: 14 | 15 | > Application1 -> **Client_A(10022/tcp) -> Client_B** -> TARGET_IP_B:(22/tcp) 16 | > Application2 -> **Client_B(10022/tcp) -> Client_A** -> TARGET_IP_A:(22/tcp) 17 | 18 | which tunnels the original connection: 19 | 20 | > Application1 -> TARGET_IP_B:(22/tcp) 21 | > Application2 -> TARGET_IP_A:(22/tcp) 22 | 23 | ### Install from source 24 | 25 | ``` 26 | $go get -u github.com/hikaricai/p2p_tun/... 27 | ``` 28 | 29 | #### Usage 30 | 31 | ``` 32 | root@ubuntu:~/p2p_tun# ./p2pclient -h 33 | NAME: 34 | p2p_tun - client(based on kcptun) 35 | 36 | USAGE: 37 | p2pclient [global options] command [command options] [arguments...] 38 | 39 | VERSION: 40 | SELFBUILD 41 | 42 | COMMANDS: 43 | help, h Shows a list of commands or help for one command 44 | 45 | GLOBAL OPTIONS: 46 | --targettcp value, -t value target server address (default: "127.0.0.1:22") 47 | --listentcp value, -l value local listen address (default: ":12948") 48 | --remoteudp value, -r value kcp server address (default: "vps:29900") 49 | --bindudp value, -b value bind local udp (default: ":29900") 50 | --key value, -k value p2p pair key (default: "1234") 51 | --passwd value pre-shared secret between client and server (default: "1234") [$KCPTUN_KEY] 52 | --crypt value aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, sm4, none (default: "aes") 53 | --mode value profiles: fast3, fast2, fast, normal, manual (default: "fast2") 54 | --conn value set num of UDP connections to server (default: 1) 55 | --autoexpire value set auto expiration time(in seconds) for a single UDP connection, 0 to disable (default: 0) 56 | --mtu value set maximum transmission unit for UDP packets (default: 1350) 57 | --sndwnd value set send window size(num of packets) (default: 1024) 58 | --rcvwnd value set receive window size(num of packets) (default: 1024) 59 | --datashard value, --ds value set reed-solomon erasure coding - datashard (default: 10) 60 | --parityshard value, --ps value set reed-solomon erasure coding - parityshard (default: 3) 61 | --dscp value set DSCP(6bit) (default: 0) 62 | --nocomp disable compression 63 | --sockbuf value per-socket buffer in bytes (default: 4194304) 64 | --keepalive value seconds between heartbeats (default: 10) 65 | --snmplog value collect snmp to file, aware of timeformat in golang, like: ./snmp-20060102.log 66 | --snmpperiod value snmp collect period, in seconds (default: 60) 67 | --log value specify a log file to output, default goes to stderr 68 | --quiet to suppress the 'stream open/close' messages 69 | -c value config from json file, which will override the command from shell 70 | --help, -h show help 71 | --version, -v print the version 72 | 73 | ``` 74 | 75 | ### Todo 76 | 77 | Code refactoring with Rust Lang!!! 78 | 79 | ### References 80 | 81 | 1. https://github.com/xtaci/kcptun/ --- A Stable & Secure Tunnel Based On KCP with N:M Multiplexing 82 | 83 | 84 | -------------------------------------------------------------------------------- /buildp2p.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VERSION=`date -u +%Y%m%d` 4 | LDFLAGS="-X main.VERSION=$VERSION -s -w" 5 | GCFLAGS="" 6 | 7 | OSES=(linux windows) 8 | ARCHS=(amd64 386) 9 | for os in ${OSES[@]}; do 10 | for arch in ${ARCHS[@]}; do 11 | suffix="" 12 | if [ "$os" == "windows" ] 13 | then 14 | suffix=".exe" 15 | fi 16 | env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o p2pclient_${os}_${arch}${suffix} github.com/hikaricai/p2p_tun/p2pclient 17 | env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o p2pserver_${os}_${arch}${suffix} github.com/hikaricai/p2p_tun/p2pserver 18 | tar -zcf p2ptun-${os}-${arch}-$VERSION.tar.gz p2pclient_${os}_${arch}${suffix} p2pserver_${os}_${arch}${suffix} 19 | done 20 | done 21 | 22 | # ARM 23 | ARMS=(7) 24 | for v in ${ARMS[@]}; do 25 | env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o p2pclient_linux_arm$v github.com/hikaricai/p2p_tun/p2pclient 26 | env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o p2pserver_linux_arm$v github.com/hikaricai/p2p_tun/p2pserver 27 | done 28 | tar -zcf p2ptun-linux-arm-$VERSION.tar.gz p2pclient_linux_arm* p2pserver_linux_arm* 29 | -------------------------------------------------------------------------------- /kcp-go/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Daniel Fu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /kcp-go/batchconn.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import "golang.org/x/net/ipv4" 4 | 5 | const ( 6 | batchSize = 16 7 | ) 8 | 9 | type batchConn interface { 10 | WriteBatch(ms []ipv4.Message, flags int) (int, error) 11 | ReadBatch(ms []ipv4.Message, flags int) (int, error) 12 | } 13 | -------------------------------------------------------------------------------- /kcp-go/crypt.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/des" 7 | "crypto/sha1" 8 | 9 | "github.com/templexxx/xor" 10 | "github.com/tjfoc/gmsm/sm4" 11 | 12 | "golang.org/x/crypto/blowfish" 13 | "golang.org/x/crypto/cast5" 14 | "golang.org/x/crypto/pbkdf2" 15 | "golang.org/x/crypto/salsa20" 16 | "golang.org/x/crypto/tea" 17 | "golang.org/x/crypto/twofish" 18 | "golang.org/x/crypto/xtea" 19 | ) 20 | 21 | var ( 22 | initialVector = []byte{167, 115, 79, 156, 18, 172, 27, 1, 164, 21, 242, 193, 252, 120, 230, 107} 23 | saltxor = `sH3CIVoF#rWLtJo6` 24 | ) 25 | 26 | // BlockCrypt defines encryption/decryption methods for a given byte slice. 27 | // Notes on implementing: the data to be encrypted contains a builtin 28 | // nonce at the first 16 bytes 29 | type BlockCrypt interface { 30 | // Encrypt encrypts the whole block in src into dst. 31 | // Dst and src may point at the same memory. 32 | Encrypt(dst, src []byte) 33 | 34 | // Decrypt decrypts the whole block in src into dst. 35 | // Dst and src may point at the same memory. 36 | Decrypt(dst, src []byte) 37 | } 38 | 39 | type salsa20BlockCrypt struct { 40 | key [32]byte 41 | } 42 | 43 | // NewSalsa20BlockCrypt https://en.wikipedia.org/wiki/Salsa20 44 | func NewSalsa20BlockCrypt(key []byte) (BlockCrypt, error) { 45 | c := new(salsa20BlockCrypt) 46 | copy(c.key[:], key) 47 | return c, nil 48 | } 49 | 50 | func (c *salsa20BlockCrypt) Encrypt(dst, src []byte) { 51 | salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key) 52 | copy(dst[:8], src[:8]) 53 | } 54 | func (c *salsa20BlockCrypt) Decrypt(dst, src []byte) { 55 | salsa20.XORKeyStream(dst[8:], src[8:], src[:8], &c.key) 56 | copy(dst[:8], src[:8]) 57 | } 58 | 59 | type sm4BlockCrypt struct { 60 | encbuf [sm4.BlockSize]byte 61 | decbuf [2 * sm4.BlockSize]byte 62 | block cipher.Block 63 | } 64 | 65 | // NewSM4BlockCrypt https://github.com/tjfoc/gmsm/tree/master/sm4 66 | func NewSM4BlockCrypt(key []byte) (BlockCrypt, error) { 67 | c := new(sm4BlockCrypt) 68 | block, err := sm4.NewCipher(key) 69 | if err != nil { 70 | return nil, err 71 | } 72 | c.block = block 73 | return c, nil 74 | } 75 | 76 | func (c *sm4BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } 77 | func (c *sm4BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } 78 | 79 | type twofishBlockCrypt struct { 80 | encbuf [twofish.BlockSize]byte 81 | decbuf [2 * twofish.BlockSize]byte 82 | block cipher.Block 83 | } 84 | 85 | // NewTwofishBlockCrypt https://en.wikipedia.org/wiki/Twofish 86 | func NewTwofishBlockCrypt(key []byte) (BlockCrypt, error) { 87 | c := new(twofishBlockCrypt) 88 | block, err := twofish.NewCipher(key) 89 | if err != nil { 90 | return nil, err 91 | } 92 | c.block = block 93 | return c, nil 94 | } 95 | 96 | func (c *twofishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } 97 | func (c *twofishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } 98 | 99 | type tripleDESBlockCrypt struct { 100 | encbuf [des.BlockSize]byte 101 | decbuf [2 * des.BlockSize]byte 102 | block cipher.Block 103 | } 104 | 105 | // NewTripleDESBlockCrypt https://en.wikipedia.org/wiki/Triple_DES 106 | func NewTripleDESBlockCrypt(key []byte) (BlockCrypt, error) { 107 | c := new(tripleDESBlockCrypt) 108 | block, err := des.NewTripleDESCipher(key) 109 | if err != nil { 110 | return nil, err 111 | } 112 | c.block = block 113 | return c, nil 114 | } 115 | 116 | func (c *tripleDESBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } 117 | func (c *tripleDESBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } 118 | 119 | type cast5BlockCrypt struct { 120 | encbuf [cast5.BlockSize]byte 121 | decbuf [2 * cast5.BlockSize]byte 122 | block cipher.Block 123 | } 124 | 125 | // NewCast5BlockCrypt https://en.wikipedia.org/wiki/CAST-128 126 | func NewCast5BlockCrypt(key []byte) (BlockCrypt, error) { 127 | c := new(cast5BlockCrypt) 128 | block, err := cast5.NewCipher(key) 129 | if err != nil { 130 | return nil, err 131 | } 132 | c.block = block 133 | return c, nil 134 | } 135 | 136 | func (c *cast5BlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } 137 | func (c *cast5BlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } 138 | 139 | type blowfishBlockCrypt struct { 140 | encbuf [blowfish.BlockSize]byte 141 | decbuf [2 * blowfish.BlockSize]byte 142 | block cipher.Block 143 | } 144 | 145 | // NewBlowfishBlockCrypt https://en.wikipedia.org/wiki/Blowfish_(cipher) 146 | func NewBlowfishBlockCrypt(key []byte) (BlockCrypt, error) { 147 | c := new(blowfishBlockCrypt) 148 | block, err := blowfish.NewCipher(key) 149 | if err != nil { 150 | return nil, err 151 | } 152 | c.block = block 153 | return c, nil 154 | } 155 | 156 | func (c *blowfishBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } 157 | func (c *blowfishBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } 158 | 159 | type aesBlockCrypt struct { 160 | encbuf [aes.BlockSize]byte 161 | decbuf [2 * aes.BlockSize]byte 162 | block cipher.Block 163 | } 164 | 165 | // NewAESBlockCrypt https://en.wikipedia.org/wiki/Advanced_Encryption_Standard 166 | func NewAESBlockCrypt(key []byte) (BlockCrypt, error) { 167 | c := new(aesBlockCrypt) 168 | block, err := aes.NewCipher(key) 169 | if err != nil { 170 | return nil, err 171 | } 172 | c.block = block 173 | return c, nil 174 | } 175 | 176 | func (c *aesBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } 177 | func (c *aesBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } 178 | 179 | type teaBlockCrypt struct { 180 | encbuf [tea.BlockSize]byte 181 | decbuf [2 * tea.BlockSize]byte 182 | block cipher.Block 183 | } 184 | 185 | // NewTEABlockCrypt https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm 186 | func NewTEABlockCrypt(key []byte) (BlockCrypt, error) { 187 | c := new(teaBlockCrypt) 188 | block, err := tea.NewCipherWithRounds(key, 16) 189 | if err != nil { 190 | return nil, err 191 | } 192 | c.block = block 193 | return c, nil 194 | } 195 | 196 | func (c *teaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } 197 | func (c *teaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } 198 | 199 | type xteaBlockCrypt struct { 200 | encbuf [xtea.BlockSize]byte 201 | decbuf [2 * xtea.BlockSize]byte 202 | block cipher.Block 203 | } 204 | 205 | // NewXTEABlockCrypt https://en.wikipedia.org/wiki/XTEA 206 | func NewXTEABlockCrypt(key []byte) (BlockCrypt, error) { 207 | c := new(xteaBlockCrypt) 208 | block, err := xtea.NewCipher(key) 209 | if err != nil { 210 | return nil, err 211 | } 212 | c.block = block 213 | return c, nil 214 | } 215 | 216 | func (c *xteaBlockCrypt) Encrypt(dst, src []byte) { encrypt(c.block, dst, src, c.encbuf[:]) } 217 | func (c *xteaBlockCrypt) Decrypt(dst, src []byte) { decrypt(c.block, dst, src, c.decbuf[:]) } 218 | 219 | type simpleXORBlockCrypt struct { 220 | xortbl []byte 221 | } 222 | 223 | // NewSimpleXORBlockCrypt simple xor with key expanding 224 | func NewSimpleXORBlockCrypt(key []byte) (BlockCrypt, error) { 225 | c := new(simpleXORBlockCrypt) 226 | c.xortbl = pbkdf2.Key(key, []byte(saltxor), 32, mtuLimit, sha1.New) 227 | return c, nil 228 | } 229 | 230 | func (c *simpleXORBlockCrypt) Encrypt(dst, src []byte) { xor.Bytes(dst, src, c.xortbl) } 231 | func (c *simpleXORBlockCrypt) Decrypt(dst, src []byte) { xor.Bytes(dst, src, c.xortbl) } 232 | 233 | type noneBlockCrypt struct{} 234 | 235 | // NewNoneBlockCrypt does nothing but copying 236 | func NewNoneBlockCrypt(key []byte) (BlockCrypt, error) { 237 | return new(noneBlockCrypt), nil 238 | } 239 | 240 | func (c *noneBlockCrypt) Encrypt(dst, src []byte) { copy(dst, src) } 241 | func (c *noneBlockCrypt) Decrypt(dst, src []byte) { copy(dst, src) } 242 | 243 | // packet encryption with local CFB mode 244 | func encrypt(block cipher.Block, dst, src, buf []byte) { 245 | switch block.BlockSize() { 246 | case 8: 247 | encrypt8(block, dst, src, buf) 248 | case 16: 249 | encrypt16(block, dst, src, buf) 250 | default: 251 | encryptVariant(block, dst, src, buf) 252 | } 253 | } 254 | 255 | // optimized encryption for the ciphers which works in 8-bytes 256 | func encrypt8(block cipher.Block, dst, src, buf []byte) { 257 | tbl := buf[:8] 258 | block.Encrypt(tbl, initialVector) 259 | n := len(src) / 8 260 | base := 0 261 | repeat := n / 8 262 | left := n % 8 263 | for i := 0; i < repeat; i++ { 264 | s := src[base:][0:64] 265 | d := dst[base:][0:64] 266 | // 1 267 | xor.BytesSrc1(d[0:8], s[0:8], tbl) 268 | block.Encrypt(tbl, d[0:8]) 269 | // 2 270 | xor.BytesSrc1(d[8:16], s[8:16], tbl) 271 | block.Encrypt(tbl, d[8:16]) 272 | // 3 273 | xor.BytesSrc1(d[16:24], s[16:24], tbl) 274 | block.Encrypt(tbl, d[16:24]) 275 | // 4 276 | xor.BytesSrc1(d[24:32], s[24:32], tbl) 277 | block.Encrypt(tbl, d[24:32]) 278 | // 5 279 | xor.BytesSrc1(d[32:40], s[32:40], tbl) 280 | block.Encrypt(tbl, d[32:40]) 281 | // 6 282 | xor.BytesSrc1(d[40:48], s[40:48], tbl) 283 | block.Encrypt(tbl, d[40:48]) 284 | // 7 285 | xor.BytesSrc1(d[48:56], s[48:56], tbl) 286 | block.Encrypt(tbl, d[48:56]) 287 | // 8 288 | xor.BytesSrc1(d[56:64], s[56:64], tbl) 289 | block.Encrypt(tbl, d[56:64]) 290 | base += 64 291 | } 292 | 293 | switch left { 294 | case 7: 295 | xor.BytesSrc1(dst[base:], src[base:], tbl) 296 | block.Encrypt(tbl, dst[base:]) 297 | base += 8 298 | fallthrough 299 | case 6: 300 | xor.BytesSrc1(dst[base:], src[base:], tbl) 301 | block.Encrypt(tbl, dst[base:]) 302 | base += 8 303 | fallthrough 304 | case 5: 305 | xor.BytesSrc1(dst[base:], src[base:], tbl) 306 | block.Encrypt(tbl, dst[base:]) 307 | base += 8 308 | fallthrough 309 | case 4: 310 | xor.BytesSrc1(dst[base:], src[base:], tbl) 311 | block.Encrypt(tbl, dst[base:]) 312 | base += 8 313 | fallthrough 314 | case 3: 315 | xor.BytesSrc1(dst[base:], src[base:], tbl) 316 | block.Encrypt(tbl, dst[base:]) 317 | base += 8 318 | fallthrough 319 | case 2: 320 | xor.BytesSrc1(dst[base:], src[base:], tbl) 321 | block.Encrypt(tbl, dst[base:]) 322 | base += 8 323 | fallthrough 324 | case 1: 325 | xor.BytesSrc1(dst[base:], src[base:], tbl) 326 | block.Encrypt(tbl, dst[base:]) 327 | base += 8 328 | fallthrough 329 | case 0: 330 | xor.BytesSrc0(dst[base:], src[base:], tbl) 331 | } 332 | } 333 | 334 | // optimized encryption for the ciphers which works in 16-bytes 335 | func encrypt16(block cipher.Block, dst, src, buf []byte) { 336 | tbl := buf[:16] 337 | block.Encrypt(tbl, initialVector) 338 | n := len(src) / 16 339 | base := 0 340 | repeat := n / 8 341 | left := n % 8 342 | for i := 0; i < repeat; i++ { 343 | s := src[base:][0:128] 344 | d := dst[base:][0:128] 345 | // 1 346 | xor.BytesSrc1(d[0:16], s[0:16], tbl) 347 | block.Encrypt(tbl, d[0:16]) 348 | // 2 349 | xor.BytesSrc1(d[16:32], s[16:32], tbl) 350 | block.Encrypt(tbl, d[16:32]) 351 | // 3 352 | xor.BytesSrc1(d[32:48], s[32:48], tbl) 353 | block.Encrypt(tbl, d[32:48]) 354 | // 4 355 | xor.BytesSrc1(d[48:64], s[48:64], tbl) 356 | block.Encrypt(tbl, d[48:64]) 357 | // 5 358 | xor.BytesSrc1(d[64:80], s[64:80], tbl) 359 | block.Encrypt(tbl, d[64:80]) 360 | // 6 361 | xor.BytesSrc1(d[80:96], s[80:96], tbl) 362 | block.Encrypt(tbl, d[80:96]) 363 | // 7 364 | xor.BytesSrc1(d[96:112], s[96:112], tbl) 365 | block.Encrypt(tbl, d[96:112]) 366 | // 8 367 | xor.BytesSrc1(d[112:128], s[112:128], tbl) 368 | block.Encrypt(tbl, d[112:128]) 369 | base += 128 370 | } 371 | 372 | switch left { 373 | case 7: 374 | xor.BytesSrc1(dst[base:], src[base:], tbl) 375 | block.Encrypt(tbl, dst[base:]) 376 | base += 16 377 | fallthrough 378 | case 6: 379 | xor.BytesSrc1(dst[base:], src[base:], tbl) 380 | block.Encrypt(tbl, dst[base:]) 381 | base += 16 382 | fallthrough 383 | case 5: 384 | xor.BytesSrc1(dst[base:], src[base:], tbl) 385 | block.Encrypt(tbl, dst[base:]) 386 | base += 16 387 | fallthrough 388 | case 4: 389 | xor.BytesSrc1(dst[base:], src[base:], tbl) 390 | block.Encrypt(tbl, dst[base:]) 391 | base += 16 392 | fallthrough 393 | case 3: 394 | xor.BytesSrc1(dst[base:], src[base:], tbl) 395 | block.Encrypt(tbl, dst[base:]) 396 | base += 16 397 | fallthrough 398 | case 2: 399 | xor.BytesSrc1(dst[base:], src[base:], tbl) 400 | block.Encrypt(tbl, dst[base:]) 401 | base += 16 402 | fallthrough 403 | case 1: 404 | xor.BytesSrc1(dst[base:], src[base:], tbl) 405 | block.Encrypt(tbl, dst[base:]) 406 | base += 16 407 | fallthrough 408 | case 0: 409 | xor.BytesSrc0(dst[base:], src[base:], tbl) 410 | } 411 | } 412 | 413 | func encryptVariant(block cipher.Block, dst, src, buf []byte) { 414 | blocksize := block.BlockSize() 415 | tbl := buf[:blocksize] 416 | block.Encrypt(tbl, initialVector) 417 | n := len(src) / blocksize 418 | base := 0 419 | repeat := n / 8 420 | left := n % 8 421 | for i := 0; i < repeat; i++ { 422 | // 1 423 | xor.BytesSrc1(dst[base:], src[base:], tbl) 424 | block.Encrypt(tbl, dst[base:]) 425 | base += blocksize 426 | 427 | // 2 428 | xor.BytesSrc1(dst[base:], src[base:], tbl) 429 | block.Encrypt(tbl, dst[base:]) 430 | base += blocksize 431 | 432 | // 3 433 | xor.BytesSrc1(dst[base:], src[base:], tbl) 434 | block.Encrypt(tbl, dst[base:]) 435 | base += blocksize 436 | 437 | // 4 438 | xor.BytesSrc1(dst[base:], src[base:], tbl) 439 | block.Encrypt(tbl, dst[base:]) 440 | base += blocksize 441 | 442 | // 5 443 | xor.BytesSrc1(dst[base:], src[base:], tbl) 444 | block.Encrypt(tbl, dst[base:]) 445 | base += blocksize 446 | 447 | // 6 448 | xor.BytesSrc1(dst[base:], src[base:], tbl) 449 | block.Encrypt(tbl, dst[base:]) 450 | base += blocksize 451 | 452 | // 7 453 | xor.BytesSrc1(dst[base:], src[base:], tbl) 454 | block.Encrypt(tbl, dst[base:]) 455 | base += blocksize 456 | 457 | // 8 458 | xor.BytesSrc1(dst[base:], src[base:], tbl) 459 | block.Encrypt(tbl, dst[base:]) 460 | base += blocksize 461 | } 462 | 463 | switch left { 464 | case 7: 465 | xor.BytesSrc1(dst[base:], src[base:], tbl) 466 | block.Encrypt(tbl, dst[base:]) 467 | base += blocksize 468 | fallthrough 469 | case 6: 470 | xor.BytesSrc1(dst[base:], src[base:], tbl) 471 | block.Encrypt(tbl, dst[base:]) 472 | base += blocksize 473 | fallthrough 474 | case 5: 475 | xor.BytesSrc1(dst[base:], src[base:], tbl) 476 | block.Encrypt(tbl, dst[base:]) 477 | base += blocksize 478 | fallthrough 479 | case 4: 480 | xor.BytesSrc1(dst[base:], src[base:], tbl) 481 | block.Encrypt(tbl, dst[base:]) 482 | base += blocksize 483 | fallthrough 484 | case 3: 485 | xor.BytesSrc1(dst[base:], src[base:], tbl) 486 | block.Encrypt(tbl, dst[base:]) 487 | base += blocksize 488 | fallthrough 489 | case 2: 490 | xor.BytesSrc1(dst[base:], src[base:], tbl) 491 | block.Encrypt(tbl, dst[base:]) 492 | base += blocksize 493 | fallthrough 494 | case 1: 495 | xor.BytesSrc1(dst[base:], src[base:], tbl) 496 | block.Encrypt(tbl, dst[base:]) 497 | base += blocksize 498 | fallthrough 499 | case 0: 500 | xor.BytesSrc0(dst[base:], src[base:], tbl) 501 | } 502 | } 503 | 504 | // decryption 505 | func decrypt(block cipher.Block, dst, src, buf []byte) { 506 | switch block.BlockSize() { 507 | case 8: 508 | decrypt8(block, dst, src, buf) 509 | case 16: 510 | decrypt16(block, dst, src, buf) 511 | default: 512 | decryptVariant(block, dst, src, buf) 513 | } 514 | } 515 | 516 | func decrypt8(block cipher.Block, dst, src, buf []byte) { 517 | tbl := buf[0:8] 518 | next := buf[8:16] 519 | block.Encrypt(tbl, initialVector) 520 | n := len(src) / 8 521 | base := 0 522 | repeat := n / 8 523 | left := n % 8 524 | for i := 0; i < repeat; i++ { 525 | s := src[base:][0:64] 526 | d := dst[base:][0:64] 527 | // 1 528 | block.Encrypt(next, s[0:8]) 529 | xor.BytesSrc1(d[0:8], s[0:8], tbl) 530 | // 2 531 | block.Encrypt(tbl, s[8:16]) 532 | xor.BytesSrc1(d[8:16], s[8:16], next) 533 | // 3 534 | block.Encrypt(next, s[16:24]) 535 | xor.BytesSrc1(d[16:24], s[16:24], tbl) 536 | // 4 537 | block.Encrypt(tbl, s[24:32]) 538 | xor.BytesSrc1(d[24:32], s[24:32], next) 539 | // 5 540 | block.Encrypt(next, s[32:40]) 541 | xor.BytesSrc1(d[32:40], s[32:40], tbl) 542 | // 6 543 | block.Encrypt(tbl, s[40:48]) 544 | xor.BytesSrc1(d[40:48], s[40:48], next) 545 | // 7 546 | block.Encrypt(next, s[48:56]) 547 | xor.BytesSrc1(d[48:56], s[48:56], tbl) 548 | // 8 549 | block.Encrypt(tbl, s[56:64]) 550 | xor.BytesSrc1(d[56:64], s[56:64], next) 551 | base += 64 552 | } 553 | 554 | switch left { 555 | case 7: 556 | block.Encrypt(next, src[base:]) 557 | xor.BytesSrc1(dst[base:], src[base:], tbl) 558 | tbl, next = next, tbl 559 | base += 8 560 | fallthrough 561 | case 6: 562 | block.Encrypt(next, src[base:]) 563 | xor.BytesSrc1(dst[base:], src[base:], tbl) 564 | tbl, next = next, tbl 565 | base += 8 566 | fallthrough 567 | case 5: 568 | block.Encrypt(next, src[base:]) 569 | xor.BytesSrc1(dst[base:], src[base:], tbl) 570 | tbl, next = next, tbl 571 | base += 8 572 | fallthrough 573 | case 4: 574 | block.Encrypt(next, src[base:]) 575 | xor.BytesSrc1(dst[base:], src[base:], tbl) 576 | tbl, next = next, tbl 577 | base += 8 578 | fallthrough 579 | case 3: 580 | block.Encrypt(next, src[base:]) 581 | xor.BytesSrc1(dst[base:], src[base:], tbl) 582 | tbl, next = next, tbl 583 | base += 8 584 | fallthrough 585 | case 2: 586 | block.Encrypt(next, src[base:]) 587 | xor.BytesSrc1(dst[base:], src[base:], tbl) 588 | tbl, next = next, tbl 589 | base += 8 590 | fallthrough 591 | case 1: 592 | block.Encrypt(next, src[base:]) 593 | xor.BytesSrc1(dst[base:], src[base:], tbl) 594 | tbl, next = next, tbl 595 | base += 8 596 | fallthrough 597 | case 0: 598 | xor.BytesSrc0(dst[base:], src[base:], tbl) 599 | } 600 | } 601 | 602 | func decrypt16(block cipher.Block, dst, src, buf []byte) { 603 | tbl := buf[0:16] 604 | next := buf[16:32] 605 | block.Encrypt(tbl, initialVector) 606 | n := len(src) / 16 607 | base := 0 608 | repeat := n / 8 609 | left := n % 8 610 | for i := 0; i < repeat; i++ { 611 | s := src[base:][0:128] 612 | d := dst[base:][0:128] 613 | // 1 614 | block.Encrypt(next, s[0:16]) 615 | xor.BytesSrc1(d[0:16], s[0:16], tbl) 616 | // 2 617 | block.Encrypt(tbl, s[16:32]) 618 | xor.BytesSrc1(d[16:32], s[16:32], next) 619 | // 3 620 | block.Encrypt(next, s[32:48]) 621 | xor.BytesSrc1(d[32:48], s[32:48], tbl) 622 | // 4 623 | block.Encrypt(tbl, s[48:64]) 624 | xor.BytesSrc1(d[48:64], s[48:64], next) 625 | // 5 626 | block.Encrypt(next, s[64:80]) 627 | xor.BytesSrc1(d[64:80], s[64:80], tbl) 628 | // 6 629 | block.Encrypt(tbl, s[80:96]) 630 | xor.BytesSrc1(d[80:96], s[80:96], next) 631 | // 7 632 | block.Encrypt(next, s[96:112]) 633 | xor.BytesSrc1(d[96:112], s[96:112], tbl) 634 | // 8 635 | block.Encrypt(tbl, s[112:128]) 636 | xor.BytesSrc1(d[112:128], s[112:128], next) 637 | base += 128 638 | } 639 | 640 | switch left { 641 | case 7: 642 | block.Encrypt(next, src[base:]) 643 | xor.BytesSrc1(dst[base:], src[base:], tbl) 644 | tbl, next = next, tbl 645 | base += 16 646 | fallthrough 647 | case 6: 648 | block.Encrypt(next, src[base:]) 649 | xor.BytesSrc1(dst[base:], src[base:], tbl) 650 | tbl, next = next, tbl 651 | base += 16 652 | fallthrough 653 | case 5: 654 | block.Encrypt(next, src[base:]) 655 | xor.BytesSrc1(dst[base:], src[base:], tbl) 656 | tbl, next = next, tbl 657 | base += 16 658 | fallthrough 659 | case 4: 660 | block.Encrypt(next, src[base:]) 661 | xor.BytesSrc1(dst[base:], src[base:], tbl) 662 | tbl, next = next, tbl 663 | base += 16 664 | fallthrough 665 | case 3: 666 | block.Encrypt(next, src[base:]) 667 | xor.BytesSrc1(dst[base:], src[base:], tbl) 668 | tbl, next = next, tbl 669 | base += 16 670 | fallthrough 671 | case 2: 672 | block.Encrypt(next, src[base:]) 673 | xor.BytesSrc1(dst[base:], src[base:], tbl) 674 | tbl, next = next, tbl 675 | base += 16 676 | fallthrough 677 | case 1: 678 | block.Encrypt(next, src[base:]) 679 | xor.BytesSrc1(dst[base:], src[base:], tbl) 680 | tbl, next = next, tbl 681 | base += 16 682 | fallthrough 683 | case 0: 684 | xor.BytesSrc0(dst[base:], src[base:], tbl) 685 | } 686 | } 687 | 688 | func decryptVariant(block cipher.Block, dst, src, buf []byte) { 689 | blocksize := block.BlockSize() 690 | tbl := buf[:blocksize] 691 | next := buf[blocksize:] 692 | block.Encrypt(tbl, initialVector) 693 | n := len(src) / blocksize 694 | base := 0 695 | repeat := n / 8 696 | left := n % 8 697 | for i := 0; i < repeat; i++ { 698 | // 1 699 | block.Encrypt(next, src[base:]) 700 | xor.BytesSrc1(dst[base:], src[base:], tbl) 701 | base += blocksize 702 | 703 | // 2 704 | block.Encrypt(tbl, src[base:]) 705 | xor.BytesSrc1(dst[base:], src[base:], next) 706 | base += blocksize 707 | 708 | // 3 709 | block.Encrypt(next, src[base:]) 710 | xor.BytesSrc1(dst[base:], src[base:], tbl) 711 | base += blocksize 712 | 713 | // 4 714 | block.Encrypt(tbl, src[base:]) 715 | xor.BytesSrc1(dst[base:], src[base:], next) 716 | base += blocksize 717 | 718 | // 5 719 | block.Encrypt(next, src[base:]) 720 | xor.BytesSrc1(dst[base:], src[base:], tbl) 721 | base += blocksize 722 | 723 | // 6 724 | block.Encrypt(tbl, src[base:]) 725 | xor.BytesSrc1(dst[base:], src[base:], next) 726 | base += blocksize 727 | 728 | // 7 729 | block.Encrypt(next, src[base:]) 730 | xor.BytesSrc1(dst[base:], src[base:], tbl) 731 | base += blocksize 732 | 733 | // 8 734 | block.Encrypt(tbl, src[base:]) 735 | xor.BytesSrc1(dst[base:], src[base:], next) 736 | base += blocksize 737 | } 738 | 739 | switch left { 740 | case 7: 741 | block.Encrypt(next, src[base:]) 742 | xor.BytesSrc1(dst[base:], src[base:], tbl) 743 | tbl, next = next, tbl 744 | base += blocksize 745 | fallthrough 746 | case 6: 747 | block.Encrypt(next, src[base:]) 748 | xor.BytesSrc1(dst[base:], src[base:], tbl) 749 | tbl, next = next, tbl 750 | base += blocksize 751 | fallthrough 752 | case 5: 753 | block.Encrypt(next, src[base:]) 754 | xor.BytesSrc1(dst[base:], src[base:], tbl) 755 | tbl, next = next, tbl 756 | base += blocksize 757 | fallthrough 758 | case 4: 759 | block.Encrypt(next, src[base:]) 760 | xor.BytesSrc1(dst[base:], src[base:], tbl) 761 | tbl, next = next, tbl 762 | base += blocksize 763 | fallthrough 764 | case 3: 765 | block.Encrypt(next, src[base:]) 766 | xor.BytesSrc1(dst[base:], src[base:], tbl) 767 | tbl, next = next, tbl 768 | base += blocksize 769 | fallthrough 770 | case 2: 771 | block.Encrypt(next, src[base:]) 772 | xor.BytesSrc1(dst[base:], src[base:], tbl) 773 | tbl, next = next, tbl 774 | base += blocksize 775 | fallthrough 776 | case 1: 777 | block.Encrypt(next, src[base:]) 778 | xor.BytesSrc1(dst[base:], src[base:], tbl) 779 | tbl, next = next, tbl 780 | base += blocksize 781 | fallthrough 782 | case 0: 783 | xor.BytesSrc0(dst[base:], src[base:], tbl) 784 | } 785 | } 786 | -------------------------------------------------------------------------------- /kcp-go/entropy.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/md5" 7 | "crypto/rand" 8 | "io" 9 | ) 10 | 11 | // Entropy defines a entropy source 12 | type Entropy interface { 13 | Init() 14 | Fill(nonce []byte) 15 | } 16 | 17 | // nonceMD5 nonce generator for packet header 18 | type nonceMD5 struct { 19 | seed [md5.Size]byte 20 | } 21 | 22 | func (n *nonceMD5) Init() { /*nothing required*/ } 23 | 24 | func (n *nonceMD5) Fill(nonce []byte) { 25 | if n.seed[0] == 0 { // entropy update 26 | io.ReadFull(rand.Reader, n.seed[:]) 27 | } 28 | n.seed = md5.Sum(n.seed[:]) 29 | copy(nonce, n.seed[:]) 30 | } 31 | 32 | // nonceAES128 nonce generator for packet headers 33 | type nonceAES128 struct { 34 | seed [aes.BlockSize]byte 35 | block cipher.Block 36 | } 37 | 38 | func (n *nonceAES128) Init() { 39 | var key [16]byte //aes-128 40 | io.ReadFull(rand.Reader, key[:]) 41 | io.ReadFull(rand.Reader, n.seed[:]) 42 | block, _ := aes.NewCipher(key[:]) 43 | n.block = block 44 | } 45 | 46 | func (n *nonceAES128) Fill(nonce []byte) { 47 | if n.seed[0] == 0 { // entropy update 48 | io.ReadFull(rand.Reader, n.seed[:]) 49 | } 50 | n.block.Encrypt(n.seed[:], n.seed[:]) 51 | copy(nonce, n.seed[:]) 52 | } 53 | -------------------------------------------------------------------------------- /kcp-go/fec.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import ( 4 | "encoding/binary" 5 | "sync/atomic" 6 | 7 | "github.com/klauspost/reedsolomon" 8 | ) 9 | 10 | const ( 11 | fecHeaderSize = 6 12 | fecHeaderSizePlus2 = fecHeaderSize + 2 // plus 2B data size 13 | typeData = 0xf1 14 | typeParity = 0xf2 15 | ) 16 | 17 | // fecPacket is a decoded FEC packet 18 | type fecPacket []byte 19 | 20 | func (bts fecPacket) seqid() uint32 { return binary.LittleEndian.Uint32(bts) } 21 | func (bts fecPacket) flag() uint16 { return binary.LittleEndian.Uint16(bts[4:]) } 22 | func (bts fecPacket) data() []byte { return bts[6:] } 23 | 24 | // fecDecoder for decoding incoming packets 25 | type fecDecoder struct { 26 | rxlimit int // queue size limit 27 | dataShards int 28 | parityShards int 29 | shardSize int 30 | rx []fecPacket // ordered receive queue 31 | 32 | // caches 33 | decodeCache [][]byte 34 | flagCache []bool 35 | 36 | // zeros 37 | zeros []byte 38 | 39 | // RS decoder 40 | codec reedsolomon.Encoder 41 | } 42 | 43 | func newFECDecoder(rxlimit, dataShards, parityShards int) *fecDecoder { 44 | if dataShards <= 0 || parityShards <= 0 { 45 | return nil 46 | } 47 | if rxlimit < dataShards+parityShards { 48 | return nil 49 | } 50 | 51 | dec := new(fecDecoder) 52 | dec.rxlimit = rxlimit 53 | dec.dataShards = dataShards 54 | dec.parityShards = parityShards 55 | dec.shardSize = dataShards + parityShards 56 | codec, err := reedsolomon.New(dataShards, parityShards) 57 | if err != nil { 58 | return nil 59 | } 60 | dec.codec = codec 61 | dec.decodeCache = make([][]byte, dec.shardSize) 62 | dec.flagCache = make([]bool, dec.shardSize) 63 | dec.zeros = make([]byte, mtuLimit) 64 | return dec 65 | } 66 | 67 | // decode a fec packet 68 | func (dec *fecDecoder) decode(in fecPacket) (recovered [][]byte) { 69 | // insertion 70 | n := len(dec.rx) - 1 71 | insertIdx := 0 72 | for i := n; i >= 0; i-- { 73 | if in.seqid() == dec.rx[i].seqid() { // de-duplicate 74 | return nil 75 | } else if _itimediff(in.seqid(), dec.rx[i].seqid()) > 0 { // insertion 76 | insertIdx = i + 1 77 | break 78 | } 79 | } 80 | 81 | // make a copy 82 | pkt := fecPacket(xmitBuf.Get().([]byte)[:len(in)]) 83 | copy(pkt, in) 84 | 85 | // insert into ordered rx queue 86 | if insertIdx == n+1 { 87 | dec.rx = append(dec.rx, pkt) 88 | } else { 89 | dec.rx = append(dec.rx, fecPacket{}) 90 | copy(dec.rx[insertIdx+1:], dec.rx[insertIdx:]) // shift right 91 | dec.rx[insertIdx] = pkt 92 | } 93 | 94 | // shard range for current packet 95 | shardBegin := pkt.seqid() - pkt.seqid()%uint32(dec.shardSize) 96 | shardEnd := shardBegin + uint32(dec.shardSize) - 1 97 | 98 | // max search range in ordered queue for current shard 99 | searchBegin := insertIdx - int(pkt.seqid()%uint32(dec.shardSize)) 100 | if searchBegin < 0 { 101 | searchBegin = 0 102 | } 103 | searchEnd := searchBegin + dec.shardSize - 1 104 | if searchEnd >= len(dec.rx) { 105 | searchEnd = len(dec.rx) - 1 106 | } 107 | 108 | // re-construct datashards 109 | if searchEnd-searchBegin+1 >= dec.dataShards { 110 | var numshard, numDataShard, first, maxlen int 111 | 112 | // zero caches 113 | shards := dec.decodeCache 114 | shardsflag := dec.flagCache 115 | for k := range dec.decodeCache { 116 | shards[k] = nil 117 | shardsflag[k] = false 118 | } 119 | 120 | // shard assembly 121 | for i := searchBegin; i <= searchEnd; i++ { 122 | seqid := dec.rx[i].seqid() 123 | if _itimediff(seqid, shardEnd) > 0 { 124 | break 125 | } else if _itimediff(seqid, shardBegin) >= 0 { 126 | shards[seqid%uint32(dec.shardSize)] = dec.rx[i].data() 127 | shardsflag[seqid%uint32(dec.shardSize)] = true 128 | numshard++ 129 | if dec.rx[i].flag() == typeData { 130 | numDataShard++ 131 | } 132 | if numshard == 1 { 133 | first = i 134 | } 135 | if len(dec.rx[i].data()) > maxlen { 136 | maxlen = len(dec.rx[i].data()) 137 | } 138 | } 139 | } 140 | 141 | if numDataShard == dec.dataShards { 142 | // case 1: no loss on data shards 143 | dec.rx = dec.freeRange(first, numshard, dec.rx) 144 | } else if numshard >= dec.dataShards { 145 | // case 2: loss on data shards, but it's recoverable from parity shards 146 | for k := range shards { 147 | if shards[k] != nil { 148 | dlen := len(shards[k]) 149 | shards[k] = shards[k][:maxlen] 150 | copy(shards[k][dlen:], dec.zeros) 151 | } else { 152 | shards[k] = xmitBuf.Get().([]byte)[:0] 153 | } 154 | } 155 | if err := dec.codec.ReconstructData(shards); err == nil { 156 | for k := range shards[:dec.dataShards] { 157 | if !shardsflag[k] { 158 | // recovered data should be recycled 159 | recovered = append(recovered, shards[k]) 160 | } 161 | } 162 | } 163 | dec.rx = dec.freeRange(first, numshard, dec.rx) 164 | } 165 | } 166 | 167 | // keep rxlimit 168 | if len(dec.rx) > dec.rxlimit { 169 | if dec.rx[0].flag() == typeData { // track the unrecoverable data 170 | atomic.AddUint64(&DefaultSnmp.FECShortShards, 1) 171 | } 172 | dec.rx = dec.freeRange(0, 1, dec.rx) 173 | } 174 | return 175 | } 176 | 177 | // free a range of fecPacket 178 | func (dec *fecDecoder) freeRange(first, n int, q []fecPacket) []fecPacket { 179 | for i := first; i < first+n; i++ { // recycle buffer 180 | xmitBuf.Put([]byte(q[i])) 181 | } 182 | 183 | if first == 0 && n < cap(q)/2 { 184 | return q[n:] 185 | } 186 | copy(q[first:], q[first+n:]) 187 | return q[:len(q)-n] 188 | } 189 | 190 | type ( 191 | // fecEncoder for encoding outgoing packets 192 | fecEncoder struct { 193 | dataShards int 194 | parityShards int 195 | shardSize int 196 | paws uint32 // Protect Against Wrapped Sequence numbers 197 | next uint32 // next seqid 198 | 199 | shardCount int // count the number of datashards collected 200 | maxSize int // track maximum data length in datashard 201 | 202 | headerOffset int // FEC header offset 203 | payloadOffset int // FEC payload offset 204 | 205 | // caches 206 | shardCache [][]byte 207 | encodeCache [][]byte 208 | 209 | // zeros 210 | zeros []byte 211 | 212 | // RS encoder 213 | codec reedsolomon.Encoder 214 | } 215 | ) 216 | 217 | func newFECEncoder(dataShards, parityShards, offset int) *fecEncoder { 218 | if dataShards <= 0 || parityShards <= 0 { 219 | return nil 220 | } 221 | enc := new(fecEncoder) 222 | enc.dataShards = dataShards 223 | enc.parityShards = parityShards 224 | enc.shardSize = dataShards + parityShards 225 | enc.paws = (0xffffffff/uint32(enc.shardSize) - 1) * uint32(enc.shardSize) 226 | enc.headerOffset = offset 227 | enc.payloadOffset = enc.headerOffset + fecHeaderSize 228 | 229 | codec, err := reedsolomon.New(dataShards, parityShards) 230 | if err != nil { 231 | return nil 232 | } 233 | enc.codec = codec 234 | 235 | // caches 236 | enc.encodeCache = make([][]byte, enc.shardSize) 237 | enc.shardCache = make([][]byte, enc.shardSize) 238 | for k := range enc.shardCache { 239 | enc.shardCache[k] = make([]byte, mtuLimit) 240 | } 241 | enc.zeros = make([]byte, mtuLimit) 242 | return enc 243 | } 244 | 245 | // encodes the packet, outputs parity shards if we have collected quorum datashards 246 | // notice: the contents of 'ps' will be re-written in successive calling 247 | func (enc *fecEncoder) encode(b []byte) (ps [][]byte) { 248 | // The header format: 249 | // | FEC SEQID(4B) | FEC TYPE(2B) | SIZE (2B) | PAYLOAD(SIZE-2) | 250 | // |<-headerOffset |<-payloadOffset 251 | enc.markData(b[enc.headerOffset:]) 252 | binary.LittleEndian.PutUint16(b[enc.payloadOffset:], uint16(len(b[enc.payloadOffset:]))) 253 | 254 | // copy data from payloadOffset to fec shard cache 255 | sz := len(b) 256 | enc.shardCache[enc.shardCount] = enc.shardCache[enc.shardCount][:sz] 257 | copy(enc.shardCache[enc.shardCount][enc.payloadOffset:], b[enc.payloadOffset:]) 258 | enc.shardCount++ 259 | 260 | // track max datashard length 261 | if sz > enc.maxSize { 262 | enc.maxSize = sz 263 | } 264 | 265 | // Generation of Reed-Solomon Erasure Code 266 | if enc.shardCount == enc.dataShards { 267 | // fill '0' into the tail of each datashard 268 | for i := 0; i < enc.dataShards; i++ { 269 | shard := enc.shardCache[i] 270 | slen := len(shard) 271 | copy(shard[slen:enc.maxSize], enc.zeros) 272 | } 273 | 274 | // construct equal-sized slice with stripped header 275 | cache := enc.encodeCache 276 | for k := range cache { 277 | cache[k] = enc.shardCache[k][enc.payloadOffset:enc.maxSize] 278 | } 279 | 280 | // encoding 281 | if err := enc.codec.Encode(cache); err == nil { 282 | ps = enc.shardCache[enc.dataShards:] 283 | for k := range ps { 284 | enc.markParity(ps[k][enc.headerOffset:]) 285 | ps[k] = ps[k][:enc.maxSize] 286 | } 287 | } 288 | 289 | // counters resetting 290 | enc.shardCount = 0 291 | enc.maxSize = 0 292 | } 293 | 294 | return 295 | } 296 | 297 | func (enc *fecEncoder) markData(data []byte) { 298 | binary.LittleEndian.PutUint32(data, enc.next) 299 | binary.LittleEndian.PutUint16(data[4:], typeData) 300 | enc.next++ 301 | } 302 | 303 | func (enc *fecEncoder) markParity(data []byte) { 304 | binary.LittleEndian.PutUint32(data, enc.next) 305 | binary.LittleEndian.PutUint16(data[4:], typeParity) 306 | // sequence wrap will only happen at parity shard 307 | enc.next = (enc.next + 1) % enc.paws 308 | } 309 | -------------------------------------------------------------------------------- /kcp-go/kcp.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import ( 4 | "encoding/binary" 5 | "sync/atomic" 6 | ) 7 | 8 | const ( 9 | IKCP_RTO_NDL = 30 // no delay min rto 10 | IKCP_RTO_MIN = 100 // normal min rto 11 | IKCP_RTO_DEF = 200 12 | IKCP_RTO_MAX = 60000 13 | IKCP_CMD_PUSH = 81 // cmd: push data 14 | IKCP_CMD_ACK = 82 // cmd: ack 15 | IKCP_CMD_WASK = 83 // cmd: window probe (ask) 16 | IKCP_CMD_WINS = 84 // cmd: window size (tell) 17 | IKCP_ASK_SEND = 1 // need to send IKCP_CMD_WASK 18 | IKCP_ASK_TELL = 2 // need to send IKCP_CMD_WINS 19 | IKCP_WND_SND = 32 20 | IKCP_WND_RCV = 32 21 | IKCP_MTU_DEF = 1400 22 | IKCP_ACK_FAST = 3 23 | IKCP_INTERVAL = 100 24 | IKCP_OVERHEAD = 24 25 | IKCP_DEADLINK = 20 26 | IKCP_THRESH_INIT = 2 27 | IKCP_THRESH_MIN = 2 28 | IKCP_PROBE_INIT = 7000 // 7 secs to probe window size 29 | IKCP_PROBE_LIMIT = 120000 // up to 120 secs to probe window 30 | ) 31 | 32 | // output_callback is a prototype which ought capture conn and call conn.Write 33 | type output_callback func(buf []byte, size int) 34 | 35 | /* encode 8 bits unsigned int */ 36 | func ikcp_encode8u(p []byte, c byte) []byte { 37 | p[0] = c 38 | return p[1:] 39 | } 40 | 41 | /* decode 8 bits unsigned int */ 42 | func ikcp_decode8u(p []byte, c *byte) []byte { 43 | *c = p[0] 44 | return p[1:] 45 | } 46 | 47 | /* encode 16 bits unsigned int (lsb) */ 48 | func ikcp_encode16u(p []byte, w uint16) []byte { 49 | binary.LittleEndian.PutUint16(p, w) 50 | return p[2:] 51 | } 52 | 53 | /* decode 16 bits unsigned int (lsb) */ 54 | func ikcp_decode16u(p []byte, w *uint16) []byte { 55 | *w = binary.LittleEndian.Uint16(p) 56 | return p[2:] 57 | } 58 | 59 | /* encode 32 bits unsigned int (lsb) */ 60 | func ikcp_encode32u(p []byte, l uint32) []byte { 61 | binary.LittleEndian.PutUint32(p, l) 62 | return p[4:] 63 | } 64 | 65 | /* decode 32 bits unsigned int (lsb) */ 66 | func ikcp_decode32u(p []byte, l *uint32) []byte { 67 | *l = binary.LittleEndian.Uint32(p) 68 | return p[4:] 69 | } 70 | 71 | func _imin_(a, b uint32) uint32 { 72 | if a <= b { 73 | return a 74 | } 75 | return b 76 | } 77 | 78 | func _imax_(a, b uint32) uint32 { 79 | if a >= b { 80 | return a 81 | } 82 | return b 83 | } 84 | 85 | func _ibound_(lower, middle, upper uint32) uint32 { 86 | return _imin_(_imax_(lower, middle), upper) 87 | } 88 | 89 | func _itimediff(later, earlier uint32) int32 { 90 | return (int32)(later - earlier) 91 | } 92 | 93 | // segment defines a KCP segment 94 | type segment struct { 95 | conv uint32 96 | cmd uint8 97 | frg uint8 98 | wnd uint16 99 | ts uint32 100 | sn uint32 101 | una uint32 102 | rto uint32 103 | xmit uint32 104 | resendts uint32 105 | fastack uint32 106 | acked uint32 // mark if the seg has acked 107 | data []byte 108 | } 109 | 110 | // encode a segment into buffer 111 | func (seg *segment) encode(ptr []byte) []byte { 112 | ptr = ikcp_encode32u(ptr, seg.conv) 113 | ptr = ikcp_encode8u(ptr, seg.cmd) 114 | ptr = ikcp_encode8u(ptr, seg.frg) 115 | ptr = ikcp_encode16u(ptr, seg.wnd) 116 | ptr = ikcp_encode32u(ptr, seg.ts) 117 | ptr = ikcp_encode32u(ptr, seg.sn) 118 | ptr = ikcp_encode32u(ptr, seg.una) 119 | ptr = ikcp_encode32u(ptr, uint32(len(seg.data))) 120 | atomic.AddUint64(&DefaultSnmp.OutSegs, 1) 121 | return ptr 122 | } 123 | 124 | // KCP defines a single KCP connection 125 | type KCP struct { 126 | conv, mtu, mss, state uint32 127 | snd_una, snd_nxt, rcv_nxt uint32 128 | ssthresh uint32 129 | rx_rttvar, rx_srtt int32 130 | rx_rto, rx_minrto uint32 131 | snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe uint32 132 | interval, ts_flush uint32 133 | nodelay, updated uint32 134 | ts_probe, probe_wait uint32 135 | dead_link, incr uint32 136 | 137 | fastresend int32 138 | nocwnd, stream int32 139 | 140 | snd_queue []segment 141 | rcv_queue []segment 142 | snd_buf []segment 143 | rcv_buf []segment 144 | 145 | acklist []ackItem 146 | 147 | buffer []byte 148 | reserved int 149 | output output_callback 150 | } 151 | 152 | type ackItem struct { 153 | sn uint32 154 | ts uint32 155 | } 156 | 157 | // NewKCP create a new kcp state machine 158 | // 159 | // 'conv' must be equal in the connection peers, or else data will be silently rejected. 160 | // 161 | // 'output' function will be called whenever these is data to be sent on wire. 162 | func NewKCP(conv uint32, output output_callback) *KCP { 163 | kcp := new(KCP) 164 | kcp.conv = conv 165 | kcp.snd_wnd = IKCP_WND_SND 166 | kcp.rcv_wnd = IKCP_WND_RCV 167 | kcp.rmt_wnd = IKCP_WND_RCV 168 | kcp.mtu = IKCP_MTU_DEF 169 | kcp.mss = kcp.mtu - IKCP_OVERHEAD 170 | kcp.buffer = make([]byte, kcp.mtu) 171 | kcp.rx_rto = IKCP_RTO_DEF 172 | kcp.rx_minrto = IKCP_RTO_MIN 173 | kcp.interval = IKCP_INTERVAL 174 | kcp.ts_flush = IKCP_INTERVAL 175 | kcp.ssthresh = IKCP_THRESH_INIT 176 | kcp.dead_link = IKCP_DEADLINK 177 | kcp.output = output 178 | return kcp 179 | } 180 | 181 | // newSegment creates a KCP segment 182 | func (kcp *KCP) newSegment(size int) (seg segment) { 183 | seg.data = xmitBuf.Get().([]byte)[:size] 184 | return 185 | } 186 | 187 | // delSegment recycles a KCP segment 188 | func (kcp *KCP) delSegment(seg *segment) { 189 | if seg.data != nil { 190 | xmitBuf.Put(seg.data) 191 | seg.data = nil 192 | } 193 | } 194 | 195 | // ReserveBytes keeps n bytes untouched from the beginning of the buffer, 196 | // the output_callback function should be aware of this. 197 | // 198 | // Return false if n >= mss 199 | func (kcp *KCP) ReserveBytes(n int) bool { 200 | if n >= int(kcp.mtu-IKCP_OVERHEAD) || n < 0 { 201 | return false 202 | } 203 | kcp.reserved = n 204 | kcp.mss = kcp.mtu - IKCP_OVERHEAD - uint32(n) 205 | return true 206 | } 207 | 208 | // PeekSize checks the size of next message in the recv queue 209 | func (kcp *KCP) PeekSize() (length int) { 210 | if len(kcp.rcv_queue) == 0 { 211 | return -1 212 | } 213 | 214 | seg := &kcp.rcv_queue[0] 215 | if seg.frg == 0 { 216 | return len(seg.data) 217 | } 218 | 219 | if len(kcp.rcv_queue) < int(seg.frg+1) { 220 | return -1 221 | } 222 | 223 | for k := range kcp.rcv_queue { 224 | seg := &kcp.rcv_queue[k] 225 | length += len(seg.data) 226 | if seg.frg == 0 { 227 | break 228 | } 229 | } 230 | return 231 | } 232 | 233 | // Receive data from kcp state machine 234 | // 235 | // Return number of bytes read. 236 | // 237 | // Return -1 when there is no readable data. 238 | // 239 | // Return -2 if len(buffer) is smaller than kcp.PeekSize(). 240 | func (kcp *KCP) Recv(buffer []byte) (n int) { 241 | peeksize := kcp.PeekSize() 242 | if peeksize < 0 { 243 | return -1 244 | } 245 | 246 | if peeksize > len(buffer) { 247 | return -2 248 | } 249 | 250 | var fast_recover bool 251 | if len(kcp.rcv_queue) >= int(kcp.rcv_wnd) { 252 | fast_recover = true 253 | } 254 | 255 | // merge fragment 256 | count := 0 257 | for k := range kcp.rcv_queue { 258 | seg := &kcp.rcv_queue[k] 259 | copy(buffer, seg.data) 260 | buffer = buffer[len(seg.data):] 261 | n += len(seg.data) 262 | count++ 263 | kcp.delSegment(seg) 264 | if seg.frg == 0 { 265 | break 266 | } 267 | } 268 | if count > 0 { 269 | kcp.rcv_queue = kcp.remove_front(kcp.rcv_queue, count) 270 | } 271 | 272 | // move available data from rcv_buf -> rcv_queue 273 | count = 0 274 | for k := range kcp.rcv_buf { 275 | seg := &kcp.rcv_buf[k] 276 | if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) { 277 | kcp.rcv_nxt++ 278 | count++ 279 | } else { 280 | break 281 | } 282 | } 283 | 284 | if count > 0 { 285 | kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[:count]...) 286 | kcp.rcv_buf = kcp.remove_front(kcp.rcv_buf, count) 287 | } 288 | 289 | // fast recover 290 | if len(kcp.rcv_queue) < int(kcp.rcv_wnd) && fast_recover { 291 | // ready to send back IKCP_CMD_WINS in ikcp_flush 292 | // tell remote my window size 293 | kcp.probe |= IKCP_ASK_TELL 294 | } 295 | return 296 | } 297 | 298 | // Send is user/upper level send, returns below zero for error 299 | func (kcp *KCP) Send(buffer []byte) int { 300 | var count int 301 | if len(buffer) == 0 { 302 | return -1 303 | } 304 | 305 | // append to previous segment in streaming mode (if possible) 306 | if kcp.stream != 0 { 307 | n := len(kcp.snd_queue) 308 | if n > 0 { 309 | seg := &kcp.snd_queue[n-1] 310 | if len(seg.data) < int(kcp.mss) { 311 | capacity := int(kcp.mss) - len(seg.data) 312 | extend := capacity 313 | if len(buffer) < capacity { 314 | extend = len(buffer) 315 | } 316 | 317 | // grow slice, the underlying cap is guaranteed to 318 | // be larger than kcp.mss 319 | oldlen := len(seg.data) 320 | seg.data = seg.data[:oldlen+extend] 321 | copy(seg.data[oldlen:], buffer) 322 | buffer = buffer[extend:] 323 | } 324 | } 325 | 326 | if len(buffer) == 0 { 327 | return 0 328 | } 329 | } 330 | 331 | if len(buffer) <= int(kcp.mss) { 332 | count = 1 333 | } else { 334 | count = (len(buffer) + int(kcp.mss) - 1) / int(kcp.mss) 335 | } 336 | 337 | if count > 255 { 338 | return -2 339 | } 340 | 341 | if count == 0 { 342 | count = 1 343 | } 344 | 345 | for i := 0; i < count; i++ { 346 | var size int 347 | if len(buffer) > int(kcp.mss) { 348 | size = int(kcp.mss) 349 | } else { 350 | size = len(buffer) 351 | } 352 | seg := kcp.newSegment(size) 353 | copy(seg.data, buffer[:size]) 354 | if kcp.stream == 0 { // message mode 355 | seg.frg = uint8(count - i - 1) 356 | } else { // stream mode 357 | seg.frg = 0 358 | } 359 | kcp.snd_queue = append(kcp.snd_queue, seg) 360 | buffer = buffer[size:] 361 | } 362 | return 0 363 | } 364 | 365 | func (kcp *KCP) update_ack(rtt int32) { 366 | // https://tools.ietf.org/html/rfc6298 367 | var rto uint32 368 | if kcp.rx_srtt == 0 { 369 | kcp.rx_srtt = rtt 370 | kcp.rx_rttvar = rtt >> 1 371 | } else { 372 | delta := rtt - kcp.rx_srtt 373 | kcp.rx_srtt += delta >> 3 374 | if delta < 0 { 375 | delta = -delta 376 | } 377 | if rtt < kcp.rx_srtt-kcp.rx_rttvar { 378 | // if the new RTT sample is below the bottom of the range of 379 | // what an RTT measurement is expected to be. 380 | // give an 8x reduced weight versus its normal weighting 381 | kcp.rx_rttvar += (delta - kcp.rx_rttvar) >> 5 382 | } else { 383 | kcp.rx_rttvar += (delta - kcp.rx_rttvar) >> 2 384 | } 385 | } 386 | rto = uint32(kcp.rx_srtt) + _imax_(kcp.interval, uint32(kcp.rx_rttvar)<<2) 387 | kcp.rx_rto = _ibound_(kcp.rx_minrto, rto, IKCP_RTO_MAX) 388 | } 389 | 390 | func (kcp *KCP) shrink_buf() { 391 | if len(kcp.snd_buf) > 0 { 392 | seg := &kcp.snd_buf[0] 393 | kcp.snd_una = seg.sn 394 | } else { 395 | kcp.snd_una = kcp.snd_nxt 396 | } 397 | } 398 | 399 | func (kcp *KCP) parse_ack(sn uint32) { 400 | if _itimediff(sn, kcp.snd_una) < 0 || _itimediff(sn, kcp.snd_nxt) >= 0 { 401 | return 402 | } 403 | 404 | for k := range kcp.snd_buf { 405 | seg := &kcp.snd_buf[k] 406 | if sn == seg.sn { 407 | // mark and free space, but leave the segment here, 408 | // and wait until `una` to delete this, then we don't 409 | // have to shift the segments behind forward, 410 | // which is an expensive operation for large window 411 | seg.acked = 1 412 | kcp.delSegment(seg) 413 | break 414 | } 415 | if _itimediff(sn, seg.sn) < 0 { 416 | break 417 | } 418 | } 419 | } 420 | 421 | func (kcp *KCP) parse_fastack(sn, ts uint32) { 422 | if _itimediff(sn, kcp.snd_una) < 0 || _itimediff(sn, kcp.snd_nxt) >= 0 { 423 | return 424 | } 425 | 426 | for k := range kcp.snd_buf { 427 | seg := &kcp.snd_buf[k] 428 | if _itimediff(sn, seg.sn) < 0 { 429 | break 430 | } else if sn != seg.sn && _itimediff(seg.ts, ts) <= 0 { 431 | seg.fastack++ 432 | } 433 | } 434 | } 435 | 436 | func (kcp *KCP) parse_una(una uint32) { 437 | count := 0 438 | for k := range kcp.snd_buf { 439 | seg := &kcp.snd_buf[k] 440 | if _itimediff(una, seg.sn) > 0 { 441 | kcp.delSegment(seg) 442 | count++ 443 | } else { 444 | break 445 | } 446 | } 447 | if count > 0 { 448 | kcp.snd_buf = kcp.remove_front(kcp.snd_buf, count) 449 | } 450 | } 451 | 452 | // ack append 453 | func (kcp *KCP) ack_push(sn, ts uint32) { 454 | kcp.acklist = append(kcp.acklist, ackItem{sn, ts}) 455 | } 456 | 457 | // returns true if data has repeated 458 | func (kcp *KCP) parse_data(newseg segment) bool { 459 | sn := newseg.sn 460 | if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) >= 0 || 461 | _itimediff(sn, kcp.rcv_nxt) < 0 { 462 | return true 463 | } 464 | 465 | n := len(kcp.rcv_buf) - 1 466 | insert_idx := 0 467 | repeat := false 468 | for i := n; i >= 0; i-- { 469 | seg := &kcp.rcv_buf[i] 470 | if seg.sn == sn { 471 | repeat = true 472 | break 473 | } 474 | if _itimediff(sn, seg.sn) > 0 { 475 | insert_idx = i + 1 476 | break 477 | } 478 | } 479 | 480 | if !repeat { 481 | // replicate the content if it's new 482 | dataCopy := xmitBuf.Get().([]byte)[:len(newseg.data)] 483 | copy(dataCopy, newseg.data) 484 | newseg.data = dataCopy 485 | 486 | if insert_idx == n+1 { 487 | kcp.rcv_buf = append(kcp.rcv_buf, newseg) 488 | } else { 489 | kcp.rcv_buf = append(kcp.rcv_buf, segment{}) 490 | copy(kcp.rcv_buf[insert_idx+1:], kcp.rcv_buf[insert_idx:]) 491 | kcp.rcv_buf[insert_idx] = newseg 492 | } 493 | } 494 | 495 | // move available data from rcv_buf -> rcv_queue 496 | count := 0 497 | for k := range kcp.rcv_buf { 498 | seg := &kcp.rcv_buf[k] 499 | if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) { 500 | kcp.rcv_nxt++ 501 | count++ 502 | } else { 503 | break 504 | } 505 | } 506 | if count > 0 { 507 | kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[:count]...) 508 | kcp.rcv_buf = kcp.remove_front(kcp.rcv_buf, count) 509 | } 510 | 511 | return repeat 512 | } 513 | 514 | // Input a packet into kcp state machine. 515 | // 516 | // 'regular' indicates it's a real data packet from remote, and it means it's not generated from ReedSolomon 517 | // codecs. 518 | // 519 | // 'ackNoDelay' will trigger immediate ACK, but surely it will not be efficient in bandwidth 520 | func (kcp *KCP) Input(data []byte, regular, ackNoDelay bool) int { 521 | snd_una := kcp.snd_una 522 | if len(data) < IKCP_OVERHEAD { 523 | return -1 524 | } 525 | 526 | var latest uint32 // the latest ack packet 527 | var flag int 528 | var inSegs uint64 529 | 530 | for { 531 | var ts, sn, length, una, conv uint32 532 | var wnd uint16 533 | var cmd, frg uint8 534 | 535 | if len(data) < int(IKCP_OVERHEAD) { 536 | break 537 | } 538 | 539 | data = ikcp_decode32u(data, &conv) 540 | if conv != kcp.conv { 541 | return -1 542 | } 543 | 544 | data = ikcp_decode8u(data, &cmd) 545 | data = ikcp_decode8u(data, &frg) 546 | data = ikcp_decode16u(data, &wnd) 547 | data = ikcp_decode32u(data, &ts) 548 | data = ikcp_decode32u(data, &sn) 549 | data = ikcp_decode32u(data, &una) 550 | data = ikcp_decode32u(data, &length) 551 | if len(data) < int(length) { 552 | return -2 553 | } 554 | 555 | if cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK && 556 | cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS { 557 | return -3 558 | } 559 | 560 | // only trust window updates from regular packets. i.e: latest update 561 | if regular { 562 | kcp.rmt_wnd = uint32(wnd) 563 | } 564 | kcp.parse_una(una) 565 | kcp.shrink_buf() 566 | 567 | if cmd == IKCP_CMD_ACK { 568 | kcp.parse_ack(sn) 569 | kcp.parse_fastack(sn, ts) 570 | flag |= 1 571 | latest = ts 572 | } else if cmd == IKCP_CMD_PUSH { 573 | repeat := true 574 | if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) < 0 { 575 | kcp.ack_push(sn, ts) 576 | if _itimediff(sn, kcp.rcv_nxt) >= 0 { 577 | var seg segment 578 | seg.conv = conv 579 | seg.cmd = cmd 580 | seg.frg = frg 581 | seg.wnd = wnd 582 | seg.ts = ts 583 | seg.sn = sn 584 | seg.una = una 585 | seg.data = data[:length] // delayed data copying 586 | repeat = kcp.parse_data(seg) 587 | } 588 | } 589 | if regular && repeat { 590 | atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1) 591 | } 592 | } else if cmd == IKCP_CMD_WASK { 593 | // ready to send back IKCP_CMD_WINS in Ikcp_flush 594 | // tell remote my window size 595 | kcp.probe |= IKCP_ASK_TELL 596 | } else if cmd == IKCP_CMD_WINS { 597 | // do nothing 598 | } else { 599 | return -3 600 | } 601 | 602 | inSegs++ 603 | data = data[length:] 604 | } 605 | atomic.AddUint64(&DefaultSnmp.InSegs, inSegs) 606 | 607 | // update rtt with the latest ts 608 | // ignore the FEC packet 609 | if flag != 0 && regular { 610 | current := currentMs() 611 | if _itimediff(current, latest) >= 0 { 612 | kcp.update_ack(_itimediff(current, latest)) 613 | } 614 | } 615 | 616 | // cwnd update when packet arrived 617 | if kcp.nocwnd == 0 { 618 | if _itimediff(kcp.snd_una, snd_una) > 0 { 619 | if kcp.cwnd < kcp.rmt_wnd { 620 | mss := kcp.mss 621 | if kcp.cwnd < kcp.ssthresh { 622 | kcp.cwnd++ 623 | kcp.incr += mss 624 | } else { 625 | if kcp.incr < mss { 626 | kcp.incr = mss 627 | } 628 | kcp.incr += (mss*mss)/kcp.incr + (mss / 16) 629 | if (kcp.cwnd+1)*mss <= kcp.incr { 630 | kcp.cwnd++ 631 | } 632 | } 633 | if kcp.cwnd > kcp.rmt_wnd { 634 | kcp.cwnd = kcp.rmt_wnd 635 | kcp.incr = kcp.rmt_wnd * mss 636 | } 637 | } 638 | } 639 | } 640 | 641 | if ackNoDelay && len(kcp.acklist) > 0 { // ack immediately 642 | kcp.flush(true) 643 | } 644 | return 0 645 | } 646 | 647 | func (kcp *KCP) wnd_unused() uint16 { 648 | if len(kcp.rcv_queue) < int(kcp.rcv_wnd) { 649 | return uint16(int(kcp.rcv_wnd) - len(kcp.rcv_queue)) 650 | } 651 | return 0 652 | } 653 | 654 | // flush pending data 655 | func (kcp *KCP) flush(ackOnly bool) uint32 { 656 | var seg segment 657 | seg.conv = kcp.conv 658 | seg.cmd = IKCP_CMD_ACK 659 | seg.wnd = kcp.wnd_unused() 660 | seg.una = kcp.rcv_nxt 661 | 662 | buffer := kcp.buffer 663 | ptr := buffer[kcp.reserved:] // keep n bytes untouched 664 | 665 | // makeSpace makes room for writing 666 | makeSpace := func(space int) { 667 | size := len(buffer) - len(ptr) 668 | if size+space > int(kcp.mtu) { 669 | kcp.output(buffer, size) 670 | ptr = buffer[kcp.reserved:] 671 | } 672 | } 673 | 674 | // flush bytes in buffer if there is any 675 | flushBuffer := func() { 676 | size := len(buffer) - len(ptr) 677 | if size > kcp.reserved { 678 | kcp.output(buffer, size) 679 | } 680 | } 681 | 682 | // flush acknowledges 683 | for i, ack := range kcp.acklist { 684 | makeSpace(IKCP_OVERHEAD) 685 | // filter jitters caused by bufferbloat 686 | if ack.sn >= kcp.rcv_nxt || len(kcp.acklist)-1 == i { 687 | seg.sn, seg.ts = ack.sn, ack.ts 688 | ptr = seg.encode(ptr) 689 | } 690 | } 691 | kcp.acklist = kcp.acklist[0:0] 692 | 693 | if ackOnly { // flash remain ack segments 694 | flushBuffer() 695 | return kcp.interval 696 | } 697 | 698 | // probe window size (if remote window size equals zero) 699 | if kcp.rmt_wnd == 0 { 700 | current := currentMs() 701 | if kcp.probe_wait == 0 { 702 | kcp.probe_wait = IKCP_PROBE_INIT 703 | kcp.ts_probe = current + kcp.probe_wait 704 | } else { 705 | if _itimediff(current, kcp.ts_probe) >= 0 { 706 | if kcp.probe_wait < IKCP_PROBE_INIT { 707 | kcp.probe_wait = IKCP_PROBE_INIT 708 | } 709 | kcp.probe_wait += kcp.probe_wait / 2 710 | if kcp.probe_wait > IKCP_PROBE_LIMIT { 711 | kcp.probe_wait = IKCP_PROBE_LIMIT 712 | } 713 | kcp.ts_probe = current + kcp.probe_wait 714 | kcp.probe |= IKCP_ASK_SEND 715 | } 716 | } 717 | } else { 718 | kcp.ts_probe = 0 719 | kcp.probe_wait = 0 720 | } 721 | 722 | // flush window probing commands 723 | if (kcp.probe & IKCP_ASK_SEND) != 0 { 724 | seg.cmd = IKCP_CMD_WASK 725 | makeSpace(IKCP_OVERHEAD) 726 | ptr = seg.encode(ptr) 727 | } 728 | 729 | // flush window probing commands 730 | if (kcp.probe & IKCP_ASK_TELL) != 0 { 731 | seg.cmd = IKCP_CMD_WINS 732 | makeSpace(IKCP_OVERHEAD) 733 | ptr = seg.encode(ptr) 734 | } 735 | 736 | kcp.probe = 0 737 | 738 | // calculate window size 739 | cwnd := _imin_(kcp.snd_wnd, kcp.rmt_wnd) 740 | if kcp.nocwnd == 0 { 741 | cwnd = _imin_(kcp.cwnd, cwnd) 742 | } 743 | 744 | // sliding window, controlled by snd_nxt && sna_una+cwnd 745 | newSegsCount := 0 746 | for k := range kcp.snd_queue { 747 | if _itimediff(kcp.snd_nxt, kcp.snd_una+cwnd) >= 0 { 748 | break 749 | } 750 | newseg := kcp.snd_queue[k] 751 | newseg.conv = kcp.conv 752 | newseg.cmd = IKCP_CMD_PUSH 753 | newseg.sn = kcp.snd_nxt 754 | kcp.snd_buf = append(kcp.snd_buf, newseg) 755 | kcp.snd_nxt++ 756 | newSegsCount++ 757 | } 758 | if newSegsCount > 0 { 759 | kcp.snd_queue = kcp.remove_front(kcp.snd_queue, newSegsCount) 760 | } 761 | 762 | // calculate resent 763 | resent := uint32(kcp.fastresend) 764 | if kcp.fastresend <= 0 { 765 | resent = 0xffffffff 766 | } 767 | 768 | // check for retransmissions 769 | current := currentMs() 770 | var change, lost, lostSegs, fastRetransSegs, earlyRetransSegs uint64 771 | minrto := int32(kcp.interval) 772 | 773 | ref := kcp.snd_buf[:len(kcp.snd_buf)] // for bounds check elimination 774 | for k := range ref { 775 | segment := &ref[k] 776 | needsend := false 777 | if segment.acked == 1 { 778 | continue 779 | } 780 | if segment.xmit == 0 { // initial transmit 781 | needsend = true 782 | segment.rto = kcp.rx_rto 783 | segment.resendts = current + segment.rto 784 | } else if _itimediff(current, segment.resendts) >= 0 { // RTO 785 | needsend = true 786 | if kcp.nodelay == 0 { 787 | segment.rto += kcp.rx_rto 788 | } else { 789 | segment.rto += kcp.rx_rto / 2 790 | } 791 | segment.resendts = current + segment.rto 792 | lost++ 793 | lostSegs++ 794 | } else if segment.fastack >= resent { // fast retransmit 795 | needsend = true 796 | segment.fastack = 0 797 | segment.rto = kcp.rx_rto 798 | segment.resendts = current + segment.rto 799 | change++ 800 | fastRetransSegs++ 801 | } else if segment.fastack > 0 && newSegsCount == 0 { // early retransmit 802 | needsend = true 803 | segment.fastack = 0 804 | segment.rto = kcp.rx_rto 805 | segment.resendts = current + segment.rto 806 | change++ 807 | earlyRetransSegs++ 808 | } 809 | 810 | if needsend { 811 | current = currentMs() 812 | segment.xmit++ 813 | segment.ts = current 814 | segment.wnd = seg.wnd 815 | segment.una = seg.una 816 | 817 | need := IKCP_OVERHEAD + len(segment.data) 818 | makeSpace(need) 819 | ptr = segment.encode(ptr) 820 | copy(ptr, segment.data) 821 | ptr = ptr[len(segment.data):] 822 | 823 | if segment.xmit >= kcp.dead_link { 824 | kcp.state = 0xFFFFFFFF 825 | } 826 | } 827 | 828 | // get the nearest rto 829 | if rto := _itimediff(segment.resendts, current); rto > 0 && rto < minrto { 830 | minrto = rto 831 | } 832 | } 833 | 834 | // flash remain segments 835 | flushBuffer() 836 | 837 | // counter updates 838 | sum := lostSegs 839 | if lostSegs > 0 { 840 | atomic.AddUint64(&DefaultSnmp.LostSegs, lostSegs) 841 | } 842 | if fastRetransSegs > 0 { 843 | atomic.AddUint64(&DefaultSnmp.FastRetransSegs, fastRetransSegs) 844 | sum += fastRetransSegs 845 | } 846 | if earlyRetransSegs > 0 { 847 | atomic.AddUint64(&DefaultSnmp.EarlyRetransSegs, earlyRetransSegs) 848 | sum += earlyRetransSegs 849 | } 850 | if sum > 0 { 851 | atomic.AddUint64(&DefaultSnmp.RetransSegs, sum) 852 | } 853 | 854 | // cwnd update 855 | if kcp.nocwnd == 0 { 856 | // update ssthresh 857 | // rate halving, https://tools.ietf.org/html/rfc6937 858 | if change > 0 { 859 | inflight := kcp.snd_nxt - kcp.snd_una 860 | kcp.ssthresh = inflight / 2 861 | if kcp.ssthresh < IKCP_THRESH_MIN { 862 | kcp.ssthresh = IKCP_THRESH_MIN 863 | } 864 | kcp.cwnd = kcp.ssthresh + resent 865 | kcp.incr = kcp.cwnd * kcp.mss 866 | } 867 | 868 | // congestion control, https://tools.ietf.org/html/rfc5681 869 | if lost > 0 { 870 | kcp.ssthresh = cwnd / 2 871 | if kcp.ssthresh < IKCP_THRESH_MIN { 872 | kcp.ssthresh = IKCP_THRESH_MIN 873 | } 874 | kcp.cwnd = 1 875 | kcp.incr = kcp.mss 876 | } 877 | 878 | if kcp.cwnd < 1 { 879 | kcp.cwnd = 1 880 | kcp.incr = kcp.mss 881 | } 882 | } 883 | 884 | return uint32(minrto) 885 | } 886 | 887 | // (deprecated) 888 | // 889 | // Update updates state (call it repeatedly, every 10ms-100ms), or you can ask 890 | // ikcp_check when to call it again (without ikcp_input/_send calling). 891 | // 'current' - current timestamp in millisec. 892 | func (kcp *KCP) Update() { 893 | var slap int32 894 | 895 | current := currentMs() 896 | if kcp.updated == 0 { 897 | kcp.updated = 1 898 | kcp.ts_flush = current 899 | } 900 | 901 | slap = _itimediff(current, kcp.ts_flush) 902 | 903 | if slap >= 10000 || slap < -10000 { 904 | kcp.ts_flush = current 905 | slap = 0 906 | } 907 | 908 | if slap >= 0 { 909 | kcp.ts_flush += kcp.interval 910 | if _itimediff(current, kcp.ts_flush) >= 0 { 911 | kcp.ts_flush = current + kcp.interval 912 | } 913 | kcp.flush(false) 914 | } 915 | } 916 | 917 | // (deprecated) 918 | // 919 | // Check determines when should you invoke ikcp_update: 920 | // returns when you should invoke ikcp_update in millisec, if there 921 | // is no ikcp_input/_send calling. you can call ikcp_update in that 922 | // time, instead of call update repeatly. 923 | // Important to reduce unnacessary ikcp_update invoking. use it to 924 | // schedule ikcp_update (eg. implementing an epoll-like mechanism, 925 | // or optimize ikcp_update when handling massive kcp connections) 926 | func (kcp *KCP) Check() uint32 { 927 | current := currentMs() 928 | ts_flush := kcp.ts_flush 929 | tm_flush := int32(0x7fffffff) 930 | tm_packet := int32(0x7fffffff) 931 | minimal := uint32(0) 932 | if kcp.updated == 0 { 933 | return current 934 | } 935 | 936 | if _itimediff(current, ts_flush) >= 10000 || 937 | _itimediff(current, ts_flush) < -10000 { 938 | ts_flush = current 939 | } 940 | 941 | if _itimediff(current, ts_flush) >= 0 { 942 | return current 943 | } 944 | 945 | tm_flush = _itimediff(ts_flush, current) 946 | 947 | for k := range kcp.snd_buf { 948 | seg := &kcp.snd_buf[k] 949 | diff := _itimediff(seg.resendts, current) 950 | if diff <= 0 { 951 | return current 952 | } 953 | if diff < tm_packet { 954 | tm_packet = diff 955 | } 956 | } 957 | 958 | minimal = uint32(tm_packet) 959 | if tm_packet >= tm_flush { 960 | minimal = uint32(tm_flush) 961 | } 962 | if minimal >= kcp.interval { 963 | minimal = kcp.interval 964 | } 965 | 966 | return current + minimal 967 | } 968 | 969 | // SetMtu changes MTU size, default is 1400 970 | func (kcp *KCP) SetMtu(mtu int) int { 971 | if mtu < 50 || mtu < IKCP_OVERHEAD { 972 | return -1 973 | } 974 | if kcp.reserved >= int(kcp.mtu-IKCP_OVERHEAD) || kcp.reserved < 0 { 975 | return -1 976 | } 977 | 978 | buffer := make([]byte, mtu) 979 | if buffer == nil { 980 | return -2 981 | } 982 | kcp.mtu = uint32(mtu) 983 | kcp.mss = kcp.mtu - IKCP_OVERHEAD - uint32(kcp.reserved) 984 | kcp.buffer = buffer 985 | return 0 986 | } 987 | 988 | // NoDelay options 989 | // fastest: ikcp_nodelay(kcp, 1, 20, 2, 1) 990 | // nodelay: 0:disable(default), 1:enable 991 | // interval: internal update timer interval in millisec, default is 100ms 992 | // resend: 0:disable fast resend(default), 1:enable fast resend 993 | // nc: 0:normal congestion control(default), 1:disable congestion control 994 | func (kcp *KCP) NoDelay(nodelay, interval, resend, nc int) int { 995 | if nodelay >= 0 { 996 | kcp.nodelay = uint32(nodelay) 997 | if nodelay != 0 { 998 | kcp.rx_minrto = IKCP_RTO_NDL 999 | } else { 1000 | kcp.rx_minrto = IKCP_RTO_MIN 1001 | } 1002 | } 1003 | if interval >= 0 { 1004 | if interval > 5000 { 1005 | interval = 5000 1006 | } else if interval < 10 { 1007 | interval = 10 1008 | } 1009 | kcp.interval = uint32(interval) 1010 | } 1011 | if resend >= 0 { 1012 | kcp.fastresend = int32(resend) 1013 | } 1014 | if nc >= 0 { 1015 | kcp.nocwnd = int32(nc) 1016 | } 1017 | return 0 1018 | } 1019 | 1020 | // WndSize sets maximum window size: sndwnd=32, rcvwnd=32 by default 1021 | func (kcp *KCP) WndSize(sndwnd, rcvwnd int) int { 1022 | if sndwnd > 0 { 1023 | kcp.snd_wnd = uint32(sndwnd) 1024 | } 1025 | if rcvwnd > 0 { 1026 | kcp.rcv_wnd = uint32(rcvwnd) 1027 | } 1028 | return 0 1029 | } 1030 | 1031 | // WaitSnd gets how many packet is waiting to be sent 1032 | func (kcp *KCP) WaitSnd() int { 1033 | return len(kcp.snd_buf) + len(kcp.snd_queue) 1034 | } 1035 | 1036 | // remove front n elements from queue 1037 | // if the number of elements to remove is more than half of the size. 1038 | // just shift the rear elements to front, otherwise just reslice q to q[n:] 1039 | // then the cost of runtime.growslice can always be less than n/2 1040 | func (kcp *KCP) remove_front(q []segment, n int) []segment { 1041 | if n > cap(q)/2 { 1042 | newn := copy(q, q[n:]) 1043 | return q[:newn] 1044 | } 1045 | return q[n:] 1046 | } 1047 | -------------------------------------------------------------------------------- /kcp-go/readloop_generic.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package kcp 4 | 5 | import ( 6 | "sync/atomic" 7 | 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | func (s *UDPSession) readLoop() { 12 | buf := make([]byte, mtuLimit) 13 | var src string 14 | for { 15 | if n, addr, err := s.conn.ReadFrom(buf); err == nil { 16 | // make sure the packet is from the same source 17 | if src == "" { // set source address 18 | src = addr.String() 19 | } else if addr.String() != src { 20 | atomic.AddUint64(&DefaultSnmp.InErrs, 1) 21 | continue 22 | } 23 | 24 | if n >= s.headerSize+IKCP_OVERHEAD { 25 | s.packetInput(buf[:n]) 26 | } else { 27 | atomic.AddUint64(&DefaultSnmp.InErrs, 1) 28 | } 29 | } else { 30 | s.notifyReadError(errors.WithStack(err)) 31 | return 32 | } 33 | } 34 | } 35 | 36 | func (l *Listener) monitor() { 37 | buf := make([]byte, mtuLimit) 38 | for { 39 | if n, from, err := l.conn.ReadFrom(buf); err == nil { 40 | if n >= l.headerSize+IKCP_OVERHEAD { 41 | l.packetInput(buf[:n], from) 42 | } else { 43 | atomic.AddUint64(&DefaultSnmp.InErrs, 1) 44 | } 45 | } else { 46 | l.notifyReadError(errors.WithStack(err)) 47 | return 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /kcp-go/readloop_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package kcp 4 | 5 | import ( 6 | "net" 7 | "sync/atomic" 8 | 9 | "github.com/pkg/errors" 10 | "golang.org/x/net/ipv4" 11 | "golang.org/x/net/ipv6" 12 | ) 13 | 14 | // the read loop for a client session 15 | func (s *UDPSession) readLoop() { 16 | var src string 17 | msgs := make([]ipv4.Message, batchSize) 18 | for k := range msgs { 19 | msgs[k].Buffers = [][]byte{make([]byte, mtuLimit)} 20 | } 21 | 22 | for { 23 | if count, err := s.xconn.ReadBatch(msgs, 0); err == nil { 24 | for i := 0; i < count; i++ { 25 | msg := &msgs[i] 26 | // make sure the packet is from the same source 27 | if src == "" { // set source address if nil 28 | src = msg.Addr.String() 29 | s.remote = msg.Addr// added by hikari 30 | } else if msg.Addr.String() != src { 31 | atomic.AddUint64(&DefaultSnmp.InErrs, 1) 32 | continue 33 | } 34 | 35 | if msg.N < s.headerSize+IKCP_OVERHEAD { 36 | atomic.AddUint64(&DefaultSnmp.InErrs, 1) 37 | continue 38 | } 39 | 40 | // source and size has validated 41 | s.packetInput(msg.Buffers[0][:msg.N]) 42 | } 43 | } else { 44 | s.notifyReadError(errors.WithStack(err)) 45 | return 46 | } 47 | } 48 | } 49 | 50 | // monitor incoming data for all connections of server 51 | func (l *Listener) monitor() { 52 | addr, _ := net.ResolveUDPAddr("udp", l.conn.LocalAddr().String()) 53 | var xconn batchConn 54 | if addr.IP.To4() != nil { 55 | xconn = ipv4.NewPacketConn(l.conn) 56 | } else { 57 | xconn = ipv6.NewPacketConn(l.conn) 58 | } 59 | 60 | msgs := make([]ipv4.Message, batchSize) 61 | for k := range msgs { 62 | msgs[k].Buffers = [][]byte{make([]byte, mtuLimit)} 63 | } 64 | 65 | for { 66 | if count, err := xconn.ReadBatch(msgs, 0); err == nil { 67 | for i := 0; i < count; i++ { 68 | msg := &msgs[i] 69 | if msg.N >= l.headerSize+IKCP_OVERHEAD { 70 | l.packetInput(msg.Buffers[0][:msg.N], msg.Addr) 71 | } else { 72 | atomic.AddUint64(&DefaultSnmp.InErrs, 1) 73 | } 74 | } 75 | } else { 76 | l.notifyReadError(errors.WithStack(err)) 77 | return 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /kcp-go/sess.go: -------------------------------------------------------------------------------- 1 | // Package kcp-go is a Reliable-UDP library for golang. 2 | // 3 | // This library intents to provide a smooth, resilient, ordered, 4 | // error-checked and anonymous delivery of streams over UDP packets. 5 | // 6 | // The interfaces of this package aims to be compatible with 7 | // net.Conn in standard library, but offers powerful features for advanced users. 8 | package kcp 9 | 10 | import ( 11 | "crypto/rand" 12 | "encoding/binary" 13 | "hash/crc32" 14 | "io" 15 | "net" 16 | "sync" 17 | "sync/atomic" 18 | "time" 19 | 20 | "github.com/pkg/errors" 21 | "golang.org/x/net/ipv4" 22 | "golang.org/x/net/ipv6" 23 | ) 24 | 25 | const ( 26 | // 16-bytes nonce for each packet 27 | nonceSize = 16 28 | 29 | // 4-bytes packet checksum 30 | crcSize = 4 31 | 32 | // overall crypto header size 33 | cryptHeaderSize = nonceSize + crcSize 34 | 35 | // maximum packet size 36 | mtuLimit = 1500 37 | 38 | // FEC keeps rxFECMulti* (dataShard+parityShard) ordered packets in memory 39 | rxFECMulti = 3 40 | 41 | // accept backlog 42 | acceptBacklog = 128 43 | ) 44 | 45 | var ( 46 | errInvalidOperation = errors.New("invalid operation") 47 | errTimeout = errors.New("timeout") 48 | firstPacket = true 49 | ) 50 | 51 | var ( 52 | // a system-wide packet buffer shared among sending, receiving and FEC 53 | // to mitigate high-frequency memory allocation for packets 54 | xmitBuf sync.Pool 55 | ) 56 | 57 | func init() { 58 | xmitBuf.New = func() interface{} { 59 | return make([]byte, mtuLimit) 60 | } 61 | } 62 | 63 | type ( 64 | // UDPSession defines a KCP session implemented by UDP 65 | UDPSession struct { 66 | updaterIdx int // record slice index in updater 67 | conn net.PacketConn // the underlying packet connection 68 | kcp *KCP // KCP ARQ protocol 69 | l *Listener // pointing to the Listener object if it's been accepted by a Listener 70 | block BlockCrypt // block encryption object 71 | 72 | // kcp receiving is based on packets 73 | // recvbuf turns packets into stream 74 | recvbuf []byte 75 | bufptr []byte 76 | 77 | // FEC codec 78 | fecDecoder *fecDecoder 79 | fecEncoder *fecEncoder 80 | 81 | // settings 82 | remote net.Addr // remote peer address 83 | rd time.Time // read deadline 84 | wd time.Time // write deadline 85 | headerSize int // the header size additional to a KCP frame 86 | ackNoDelay bool // send ack immediately for each incoming packet(testing purpose) 87 | writeDelay bool // delay kcp.flush() for Write() for bulk transfer 88 | dup int // duplicate udp packets(testing purpose) 89 | 90 | // notifications 91 | die chan struct{} // notify current session has Closed 92 | dieOnce sync.Once 93 | chReadEvent chan struct{} // notify Read() can be called without blocking 94 | chWriteEvent chan struct{} // notify Write() can be called without blocking 95 | 96 | // socket error handling 97 | socketReadError atomic.Value 98 | socketWriteError atomic.Value 99 | chSocketReadError chan struct{} 100 | chSocketWriteError chan struct{} 101 | socketReadErrorOnce sync.Once 102 | socketWriteErrorOnce sync.Once 103 | 104 | // nonce generator 105 | nonce Entropy 106 | 107 | // packets waiting to be sent on wire 108 | txqueue []ipv4.Message 109 | xconn batchConn // for x/net 110 | 111 | mu sync.Mutex 112 | } 113 | 114 | setReadBuffer interface { 115 | SetReadBuffer(bytes int) error 116 | } 117 | 118 | setWriteBuffer interface { 119 | SetWriteBuffer(bytes int) error 120 | } 121 | ) 122 | 123 | // newUDPSession create a new udp session for client or server 124 | func newUDPSession(conv uint32, dataShards, parityShards int, l *Listener, conn net.PacketConn, remote net.Addr, block BlockCrypt) *UDPSession { 125 | sess := new(UDPSession) 126 | sess.die = make(chan struct{}) 127 | sess.nonce = new(nonceAES128) 128 | sess.nonce.Init() 129 | sess.chReadEvent = make(chan struct{}, 1) 130 | sess.chWriteEvent = make(chan struct{}, 1) 131 | sess.chSocketReadError = make(chan struct{}) 132 | sess.chSocketWriteError = make(chan struct{}) 133 | sess.remote = remote 134 | sess.conn = conn 135 | sess.l = l 136 | sess.block = block 137 | sess.recvbuf = make([]byte, mtuLimit) 138 | 139 | // cast to writebatch conn 140 | addr, _ := net.ResolveUDPAddr("udp", conn.LocalAddr().String()) 141 | if addr.IP.To4() != nil { 142 | sess.xconn = ipv4.NewPacketConn(conn) 143 | } else { 144 | sess.xconn = ipv6.NewPacketConn(conn) 145 | } 146 | 147 | // FEC codec initialization 148 | sess.fecDecoder = newFECDecoder(rxFECMulti*(dataShards+parityShards), dataShards, parityShards) 149 | if sess.block != nil { 150 | sess.fecEncoder = newFECEncoder(dataShards, parityShards, cryptHeaderSize) 151 | } else { 152 | sess.fecEncoder = newFECEncoder(dataShards, parityShards, 0) 153 | } 154 | 155 | // calculate additional header size introduced by FEC and encryption 156 | if sess.block != nil { 157 | sess.headerSize += cryptHeaderSize 158 | } 159 | if sess.fecEncoder != nil { 160 | sess.headerSize += fecHeaderSizePlus2 161 | } 162 | 163 | sess.kcp = NewKCP(conv, func(buf []byte, size int) { 164 | if size >= IKCP_OVERHEAD+sess.headerSize { 165 | sess.output(buf[:size]) 166 | } 167 | }) 168 | sess.kcp.ReserveBytes(sess.headerSize) 169 | 170 | // register current session to the global updater, 171 | // which call sess.update() periodically. 172 | updater.addSession(sess) 173 | 174 | if sess.l == nil { // it's a client connection 175 | go sess.readLoop() 176 | atomic.AddUint64(&DefaultSnmp.ActiveOpens, 1) 177 | } else { 178 | atomic.AddUint64(&DefaultSnmp.PassiveOpens, 1) 179 | } 180 | 181 | currestab := atomic.AddUint64(&DefaultSnmp.CurrEstab, 1) 182 | maxconn := atomic.LoadUint64(&DefaultSnmp.MaxConn) 183 | if currestab > maxconn { 184 | atomic.CompareAndSwapUint64(&DefaultSnmp.MaxConn, maxconn, currestab) 185 | } 186 | 187 | return sess 188 | } 189 | 190 | // Read implements net.Conn 191 | func (s *UDPSession) Read(b []byte) (n int, err error) { 192 | for { 193 | s.mu.Lock() 194 | if len(s.bufptr) > 0 { // copy from buffer into b 195 | n = copy(b, s.bufptr) 196 | s.bufptr = s.bufptr[n:] 197 | s.mu.Unlock() 198 | atomic.AddUint64(&DefaultSnmp.BytesReceived, uint64(n)) 199 | return n, nil 200 | } 201 | 202 | if size := s.kcp.PeekSize(); size > 0 { // peek data size from kcp 203 | if len(b) >= size { // receive data into 'b' directly 204 | s.kcp.Recv(b) 205 | s.mu.Unlock() 206 | atomic.AddUint64(&DefaultSnmp.BytesReceived, uint64(size)) 207 | return size, nil 208 | } 209 | 210 | // if necessary resize the stream buffer to guarantee a sufficent buffer space 211 | if cap(s.recvbuf) < size { 212 | s.recvbuf = make([]byte, size) 213 | } 214 | 215 | // resize the length of recvbuf to correspond to data size 216 | s.recvbuf = s.recvbuf[:size] 217 | s.kcp.Recv(s.recvbuf) 218 | n = copy(b, s.recvbuf) // copy to 'b' 219 | s.bufptr = s.recvbuf[n:] // pointer update 220 | s.mu.Unlock() 221 | atomic.AddUint64(&DefaultSnmp.BytesReceived, uint64(n)) 222 | return n, nil 223 | } 224 | 225 | // deadline for current reading operation 226 | var timeout *time.Timer 227 | var c <-chan time.Time 228 | if !s.rd.IsZero() { 229 | if time.Now().After(s.rd) { 230 | s.mu.Unlock() 231 | return 0, errors.WithStack(errTimeout) 232 | } 233 | 234 | delay := s.rd.Sub(time.Now()) 235 | timeout = time.NewTimer(delay) 236 | c = timeout.C 237 | } 238 | s.mu.Unlock() 239 | 240 | // wait for read event or timeout or error 241 | select { 242 | case <-s.chReadEvent: 243 | if timeout != nil { 244 | timeout.Stop() 245 | } 246 | case <-c: 247 | return 0, errors.WithStack(errTimeout) 248 | case <-s.chSocketReadError: 249 | return 0, s.socketReadError.Load().(error) 250 | case <-s.die: 251 | return 0, errors.WithStack(io.ErrClosedPipe) 252 | } 253 | } 254 | } 255 | 256 | // Write implements net.Conn 257 | func (s *UDPSession) Write(b []byte) (n int, err error) { return s.WriteBuffers([][]byte{b}) } 258 | 259 | // WriteBuffers write a vector of byte slices to the underlying connection 260 | func (s *UDPSession) WriteBuffers(v [][]byte) (n int, err error) { 261 | for { 262 | select { 263 | case <-s.chSocketWriteError: 264 | return 0, s.socketWriteError.Load().(error) 265 | case <-s.die: 266 | return 0, errors.WithStack(io.ErrClosedPipe) 267 | default: 268 | } 269 | 270 | s.mu.Lock() 271 | if s.kcp.WaitSnd() < int(s.kcp.snd_wnd) { 272 | for _, b := range v { 273 | n += len(b) 274 | for { 275 | if len(b) <= int(s.kcp.mss) { 276 | s.kcp.Send(b) 277 | break 278 | } else { 279 | s.kcp.Send(b[:s.kcp.mss]) 280 | b = b[s.kcp.mss:] 281 | } 282 | } 283 | } 284 | 285 | if s.kcp.WaitSnd() >= int(s.kcp.snd_wnd) || !s.writeDelay { 286 | s.kcp.flush(false) 287 | s.uncork() 288 | } 289 | s.mu.Unlock() 290 | atomic.AddUint64(&DefaultSnmp.BytesSent, uint64(n)) 291 | return n, nil 292 | } 293 | 294 | var timeout *time.Timer 295 | var c <-chan time.Time 296 | if !s.wd.IsZero() { 297 | if time.Now().After(s.wd) { 298 | s.mu.Unlock() 299 | return 0, errors.WithStack(errTimeout) 300 | } 301 | delay := s.wd.Sub(time.Now()) 302 | timeout = time.NewTimer(delay) 303 | c = timeout.C 304 | } 305 | s.mu.Unlock() 306 | 307 | select { 308 | case <-s.chWriteEvent: 309 | if timeout != nil { 310 | timeout.Stop() 311 | } 312 | case <-c: 313 | return 0, errors.WithStack(errTimeout) 314 | case <-s.chSocketWriteError: 315 | return 0, s.socketWriteError.Load().(error) 316 | case <-s.die: 317 | return 0, errors.WithStack(io.ErrClosedPipe) 318 | } 319 | } 320 | } 321 | 322 | // uncork sends data in txqueue if there is any 323 | func (s *UDPSession) uncork() { 324 | if len(s.txqueue) > 0 { 325 | s.tx(s.txqueue) 326 | s.txqueue = s.txqueue[:0] 327 | } 328 | return 329 | } 330 | 331 | // Close closes the connection. 332 | func (s *UDPSession) Close() error { 333 | var once bool 334 | s.dieOnce.Do(func() { 335 | close(s.die) 336 | once = true 337 | }) 338 | 339 | if once { 340 | // remove from updater 341 | updater.removeSession(s) 342 | atomic.AddUint64(&DefaultSnmp.CurrEstab, ^uint64(0)) 343 | 344 | if s.l != nil { // belongs to listener 345 | s.l.closeSession(s.remote) 346 | return nil 347 | } else { // client socket close 348 | return s.conn.Close() 349 | } 350 | } else { 351 | return errors.WithStack(io.ErrClosedPipe) 352 | } 353 | } 354 | 355 | // LocalAddr returns the local network address. The Addr returned is shared by all invocations of LocalAddr, so do not modify it. 356 | func (s *UDPSession) LocalAddr() net.Addr { return s.conn.LocalAddr() } 357 | 358 | // RemoteAddr returns the remote network address. The Addr returned is shared by all invocations of RemoteAddr, so do not modify it. 359 | func (s *UDPSession) RemoteAddr() net.Addr { return s.remote } 360 | 361 | // SetDeadline sets the deadline associated with the listener. A zero time value disables the deadline. 362 | func (s *UDPSession) SetDeadline(t time.Time) error { 363 | s.mu.Lock() 364 | defer s.mu.Unlock() 365 | s.rd = t 366 | s.wd = t 367 | s.notifyReadEvent() 368 | s.notifyWriteEvent() 369 | return nil 370 | } 371 | 372 | // SetReadDeadline implements the Conn SetReadDeadline method. 373 | func (s *UDPSession) SetReadDeadline(t time.Time) error { 374 | s.mu.Lock() 375 | defer s.mu.Unlock() 376 | s.rd = t 377 | s.notifyReadEvent() 378 | return nil 379 | } 380 | 381 | // SetWriteDeadline implements the Conn SetWriteDeadline method. 382 | func (s *UDPSession) SetWriteDeadline(t time.Time) error { 383 | s.mu.Lock() 384 | defer s.mu.Unlock() 385 | s.wd = t 386 | s.notifyWriteEvent() 387 | return nil 388 | } 389 | 390 | // SetWriteDelay delays write for bulk transfer until the next update interval 391 | func (s *UDPSession) SetWriteDelay(delay bool) { 392 | s.mu.Lock() 393 | defer s.mu.Unlock() 394 | s.writeDelay = delay 395 | } 396 | 397 | // SetWindowSize set maximum window size 398 | func (s *UDPSession) SetWindowSize(sndwnd, rcvwnd int) { 399 | s.mu.Lock() 400 | defer s.mu.Unlock() 401 | s.kcp.WndSize(sndwnd, rcvwnd) 402 | } 403 | 404 | // SetMtu sets the maximum transmission unit(not including UDP header) 405 | func (s *UDPSession) SetMtu(mtu int) bool { 406 | if mtu > mtuLimit { 407 | return false 408 | } 409 | 410 | s.mu.Lock() 411 | defer s.mu.Unlock() 412 | s.kcp.SetMtu(mtu) 413 | return true 414 | } 415 | 416 | // SetStreamMode toggles the stream mode on/off 417 | func (s *UDPSession) SetStreamMode(enable bool) { 418 | s.mu.Lock() 419 | defer s.mu.Unlock() 420 | if enable { 421 | s.kcp.stream = 1 422 | } else { 423 | s.kcp.stream = 0 424 | } 425 | } 426 | 427 | // SetACKNoDelay changes ack flush option, set true to flush ack immediately, 428 | func (s *UDPSession) SetACKNoDelay(nodelay bool) { 429 | s.mu.Lock() 430 | defer s.mu.Unlock() 431 | s.ackNoDelay = nodelay 432 | } 433 | 434 | // (deprecated) 435 | // 436 | // SetDUP duplicates udp packets for kcp output. 437 | func (s *UDPSession) SetDUP(dup int) { 438 | s.mu.Lock() 439 | defer s.mu.Unlock() 440 | s.dup = dup 441 | } 442 | 443 | // SetNoDelay calls nodelay() of kcp 444 | // https://github.com/skywind3000/kcp/blob/master/README.en.md#protocol-configuration 445 | func (s *UDPSession) SetNoDelay(nodelay, interval, resend, nc int) { 446 | s.mu.Lock() 447 | defer s.mu.Unlock() 448 | s.kcp.NoDelay(nodelay, interval, resend, nc) 449 | } 450 | 451 | // SetDSCP sets the 6bit DSCP field in IPv4 header, or 8bit Traffic Class in IPv6 header. 452 | // 453 | // It has no effect if it's accepted from Listener. 454 | func (s *UDPSession) SetDSCP(dscp int) error { 455 | s.mu.Lock() 456 | defer s.mu.Unlock() 457 | if s.l == nil { 458 | if nc, ok := s.conn.(net.Conn); ok { 459 | addr, _ := net.ResolveUDPAddr("udp", nc.LocalAddr().String()) 460 | if addr.IP.To4() != nil { 461 | return ipv4.NewConn(nc).SetTOS(dscp << 2) 462 | } else { 463 | return ipv6.NewConn(nc).SetTrafficClass(dscp) 464 | } 465 | } 466 | } 467 | return errInvalidOperation 468 | } 469 | 470 | // SetReadBuffer sets the socket read buffer, no effect if it's accepted from Listener 471 | func (s *UDPSession) SetReadBuffer(bytes int) error { 472 | s.mu.Lock() 473 | defer s.mu.Unlock() 474 | if s.l == nil { 475 | if nc, ok := s.conn.(setReadBuffer); ok { 476 | return nc.SetReadBuffer(bytes) 477 | } 478 | } 479 | return errInvalidOperation 480 | } 481 | 482 | // SetWriteBuffer sets the socket write buffer, no effect if it's accepted from Listener 483 | func (s *UDPSession) SetWriteBuffer(bytes int) error { 484 | s.mu.Lock() 485 | defer s.mu.Unlock() 486 | if s.l == nil { 487 | if nc, ok := s.conn.(setWriteBuffer); ok { 488 | return nc.SetWriteBuffer(bytes) 489 | } 490 | } 491 | return errInvalidOperation 492 | } 493 | 494 | // post-processing for sending a packet from kcp core 495 | // steps: 496 | // 1. FEC packet generation 497 | // 2. CRC32 integrity 498 | // 3. Encryption 499 | // 4. TxQueue 500 | func (s *UDPSession) output(buf []byte) { 501 | var ecc [][]byte 502 | 503 | // 1. FEC encoding 504 | if s.fecEncoder != nil { 505 | ecc = s.fecEncoder.encode(buf) 506 | } 507 | 508 | // 2&3. crc32 & encryption 509 | if s.block != nil { 510 | s.nonce.Fill(buf[:nonceSize]) 511 | checksum := crc32.ChecksumIEEE(buf[cryptHeaderSize:]) 512 | binary.LittleEndian.PutUint32(buf[nonceSize:], checksum) 513 | s.block.Encrypt(buf, buf) 514 | 515 | for k := range ecc { 516 | s.nonce.Fill(ecc[k][:nonceSize]) 517 | checksum := crc32.ChecksumIEEE(ecc[k][cryptHeaderSize:]) 518 | binary.LittleEndian.PutUint32(ecc[k][nonceSize:], checksum) 519 | s.block.Encrypt(ecc[k], ecc[k]) 520 | } 521 | } 522 | 523 | // 4. TxQueue 524 | var msg ipv4.Message 525 | for i := 0; i < s.dup+1; i++ { 526 | bts := xmitBuf.Get().([]byte)[:len(buf)] 527 | copy(bts, buf) 528 | msg.Buffers = [][]byte{bts} 529 | msg.Addr = s.remote 530 | s.txqueue = append(s.txqueue, msg) 531 | } 532 | 533 | for k := range ecc { 534 | bts := xmitBuf.Get().([]byte)[:len(ecc[k])] 535 | copy(bts, ecc[k]) 536 | msg.Buffers = [][]byte{bts} 537 | msg.Addr = s.remote 538 | s.txqueue = append(s.txqueue, msg) 539 | } 540 | } 541 | 542 | // kcp update, returns interval for next calling 543 | func (s *UDPSession) update() (interval time.Duration) { 544 | s.mu.Lock() 545 | waitsnd := s.kcp.WaitSnd() 546 | interval = time.Duration(s.kcp.flush(false)) * time.Millisecond 547 | if s.kcp.WaitSnd() < waitsnd { 548 | s.notifyWriteEvent() 549 | } 550 | s.uncork() 551 | s.mu.Unlock() 552 | return 553 | } 554 | 555 | // GetConv gets conversation id of a session 556 | func (s *UDPSession) GetConv() uint32 { return s.kcp.conv } 557 | 558 | func (s *UDPSession) notifyReadEvent() { 559 | select { 560 | case s.chReadEvent <- struct{}{}: 561 | default: 562 | } 563 | } 564 | 565 | func (s *UDPSession) notifyWriteEvent() { 566 | select { 567 | case s.chWriteEvent <- struct{}{}: 568 | default: 569 | } 570 | } 571 | 572 | func (s *UDPSession) notifyReadError(err error) { 573 | s.socketReadErrorOnce.Do(func() { 574 | s.socketReadError.Store(err) 575 | close(s.chSocketReadError) 576 | }) 577 | } 578 | 579 | func (s *UDPSession) notifyWriteError(err error) { 580 | s.socketWriteErrorOnce.Do(func() { 581 | s.socketWriteError.Store(err) 582 | close(s.chSocketWriteError) 583 | }) 584 | } 585 | 586 | // packet input stage 587 | func (s *UDPSession) packetInput(data []byte) { 588 | dataValid := false 589 | if s.block != nil { 590 | s.block.Decrypt(data, data) 591 | data = data[nonceSize:] 592 | checksum := crc32.ChecksumIEEE(data[crcSize:]) 593 | if checksum == binary.LittleEndian.Uint32(data) { 594 | data = data[crcSize:] 595 | dataValid = true 596 | } else { 597 | atomic.AddUint64(&DefaultSnmp.InCsumErrors, 1) 598 | } 599 | } else if s.block == nil { 600 | dataValid = true 601 | } 602 | 603 | if dataValid { 604 | s.kcpInput(data) 605 | } 606 | } 607 | 608 | func (s *UDPSession) kcpInput(data []byte) { 609 | var kcpInErrors, fecErrs, fecRecovered, fecParityShards uint64 610 | 611 | if s.fecDecoder != nil { 612 | if len(data) > fecHeaderSize { // must be larger than fec header size 613 | f := fecPacket(data) 614 | if f.flag() == typeData || f.flag() == typeParity { // header check 615 | if f.flag() == typeParity { 616 | fecParityShards++ 617 | } 618 | recovers := s.fecDecoder.decode(f) 619 | 620 | s.mu.Lock() 621 | waitsnd := s.kcp.WaitSnd() 622 | if f.flag() == typeData { 623 | if ret := s.kcp.Input(data[fecHeaderSizePlus2:], true, s.ackNoDelay); ret != 0 { 624 | kcpInErrors++ 625 | } 626 | } 627 | 628 | for _, r := range recovers { 629 | if len(r) >= 2 { // must be larger than 2bytes 630 | sz := binary.LittleEndian.Uint16(r) 631 | if int(sz) <= len(r) && sz >= 2 { 632 | if ret := s.kcp.Input(r[2:sz], false, s.ackNoDelay); ret == 0 { 633 | fecRecovered++ 634 | } else { 635 | kcpInErrors++ 636 | } 637 | } else { 638 | fecErrs++ 639 | } 640 | } else { 641 | fecErrs++ 642 | } 643 | // recycle the recovers 644 | xmitBuf.Put(r) 645 | } 646 | 647 | // to notify the readers to receive the data 648 | if n := s.kcp.PeekSize(); n > 0 { 649 | s.notifyReadEvent() 650 | } 651 | // to notify the writers when queue is shorter(e.g. ACKed) 652 | if s.kcp.WaitSnd() < waitsnd { 653 | s.notifyWriteEvent() 654 | } 655 | s.uncork() 656 | s.mu.Unlock() 657 | } else { 658 | atomic.AddUint64(&DefaultSnmp.InErrs, 1) 659 | } 660 | } else { 661 | atomic.AddUint64(&DefaultSnmp.InErrs, 1) 662 | } 663 | } else { 664 | s.mu.Lock() 665 | waitsnd := s.kcp.WaitSnd() 666 | if ret := s.kcp.Input(data, true, s.ackNoDelay); ret != 0 { 667 | kcpInErrors++ 668 | } 669 | if n := s.kcp.PeekSize(); n > 0 { 670 | s.notifyReadEvent() 671 | } 672 | if s.kcp.WaitSnd() < waitsnd { 673 | s.notifyWriteEvent() 674 | } 675 | s.uncork() 676 | s.mu.Unlock() 677 | } 678 | 679 | atomic.AddUint64(&DefaultSnmp.InPkts, 1) 680 | atomic.AddUint64(&DefaultSnmp.InBytes, uint64(len(data))) 681 | if fecParityShards > 0 { 682 | atomic.AddUint64(&DefaultSnmp.FECParityShards, fecParityShards) 683 | } 684 | if kcpInErrors > 0 { 685 | atomic.AddUint64(&DefaultSnmp.KCPInErrors, kcpInErrors) 686 | } 687 | if fecErrs > 0 { 688 | atomic.AddUint64(&DefaultSnmp.FECErrs, fecErrs) 689 | } 690 | if fecRecovered > 0 { 691 | atomic.AddUint64(&DefaultSnmp.FECRecovered, fecRecovered) 692 | } 693 | 694 | } 695 | 696 | type ( 697 | // Listener defines a server which will be waiting to accept incoming connections 698 | Listener struct { 699 | block BlockCrypt // block encryption 700 | dataShards int // FEC data shard 701 | parityShards int // FEC parity shard 702 | fecDecoder *fecDecoder // FEC mock initialization 703 | conn net.PacketConn // the underlying packet connection 704 | 705 | sessions map[string]*UDPSession // all sessions accepted by this Listener 706 | sessionLock sync.Mutex 707 | chAccepts chan *UDPSession // Listen() backlog 708 | chSessionClosed chan net.Addr // session close queue 709 | headerSize int // the additional header to a KCP frame 710 | 711 | die chan struct{} // notify the listener has closed 712 | dieOnce sync.Once 713 | 714 | // socket error handling 715 | socketReadError atomic.Value 716 | chSocketReadError chan struct{} 717 | socketReadErrorOnce sync.Once 718 | 719 | rd atomic.Value // read deadline for Accept() 720 | } 721 | ) 722 | 723 | // packet input stage 724 | func (l *Listener) packetInput(data []byte, addr net.Addr) { 725 | dataValid := false 726 | if l.block != nil { 727 | l.block.Decrypt(data, data) 728 | data = data[nonceSize:] 729 | checksum := crc32.ChecksumIEEE(data[crcSize:]) 730 | if checksum == binary.LittleEndian.Uint32(data) { 731 | data = data[crcSize:] 732 | dataValid = true 733 | } else { 734 | atomic.AddUint64(&DefaultSnmp.InCsumErrors, 1) 735 | } 736 | } else if l.block == nil { 737 | dataValid = true 738 | } 739 | 740 | if dataValid { 741 | l.sessionLock.Lock() 742 | s, ok := l.sessions[addr.String()] 743 | l.sessionLock.Unlock() 744 | 745 | if !ok { // new address:port 746 | if len(l.chAccepts) < cap(l.chAccepts) { // do not let the new sessions overwhelm accept queue 747 | var conv uint32 748 | convValid := false 749 | if l.fecDecoder != nil { 750 | isfec := binary.LittleEndian.Uint16(data[4:]) 751 | if isfec == typeData { 752 | conv = binary.LittleEndian.Uint32(data[fecHeaderSizePlus2:]) 753 | convValid = true 754 | } 755 | } else { 756 | conv = binary.LittleEndian.Uint32(data) 757 | convValid = true 758 | } 759 | 760 | if convValid { // creates a new session only if the 'conv' field in kcp is accessible 761 | s := newUDPSession(conv, l.dataShards, l.parityShards, l, l.conn, addr, l.block) 762 | s.kcpInput(data) 763 | l.sessionLock.Lock() 764 | l.sessions[addr.String()] = s 765 | l.sessionLock.Unlock() 766 | l.chAccepts <- s 767 | } 768 | } 769 | } else { 770 | s.kcpInput(data) 771 | } 772 | } 773 | } 774 | 775 | func (l *Listener) notifyReadError(err error) { 776 | l.socketReadErrorOnce.Do(func() { 777 | l.socketReadError.Store(err) 778 | close(l.chSocketReadError) 779 | 780 | // propagate read error to all sessions 781 | l.sessionLock.Lock() 782 | for _, s := range l.sessions { 783 | s.notifyReadError(err) 784 | } 785 | l.sessionLock.Unlock() 786 | }) 787 | } 788 | 789 | // SetReadBuffer sets the socket read buffer for the Listener 790 | func (l *Listener) SetReadBuffer(bytes int) error { 791 | if nc, ok := l.conn.(setReadBuffer); ok { 792 | return nc.SetReadBuffer(bytes) 793 | } 794 | return errInvalidOperation 795 | } 796 | 797 | // SetWriteBuffer sets the socket write buffer for the Listener 798 | func (l *Listener) SetWriteBuffer(bytes int) error { 799 | if nc, ok := l.conn.(setWriteBuffer); ok { 800 | return nc.SetWriteBuffer(bytes) 801 | } 802 | return errInvalidOperation 803 | } 804 | 805 | // SetDSCP sets the 6bit DSCP field in IPv4 header, or 8bit Traffic Class in IPv6 header. 806 | func (l *Listener) SetDSCP(dscp int) error { 807 | if nc, ok := l.conn.(net.Conn); ok { 808 | addr, _ := net.ResolveUDPAddr("udp", nc.LocalAddr().String()) 809 | if addr.IP.To4() != nil { 810 | return ipv4.NewConn(nc).SetTOS(dscp << 2) 811 | } else { 812 | return ipv6.NewConn(nc).SetTrafficClass(dscp) 813 | } 814 | } 815 | return errInvalidOperation 816 | } 817 | 818 | // Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn. 819 | func (l *Listener) Accept() (net.Conn, error) { 820 | return l.AcceptKCP() 821 | } 822 | 823 | // AcceptKCP accepts a KCP connection 824 | func (l *Listener) AcceptKCP() (*UDPSession, error) { 825 | var timeout <-chan time.Time 826 | if tdeadline, ok := l.rd.Load().(time.Time); ok && !tdeadline.IsZero() { 827 | timeout = time.After(tdeadline.Sub(time.Now())) 828 | } 829 | 830 | select { 831 | case <-timeout: 832 | return nil, errors.WithStack(errTimeout) 833 | case c := <-l.chAccepts: 834 | return c, nil 835 | case <-l.chSocketReadError: 836 | return nil, l.socketReadError.Load().(error) 837 | case <-l.die: 838 | return nil, errors.WithStack(io.ErrClosedPipe) 839 | } 840 | } 841 | 842 | // SetDeadline sets the deadline associated with the listener. A zero time value disables the deadline. 843 | func (l *Listener) SetDeadline(t time.Time) error { 844 | l.SetReadDeadline(t) 845 | l.SetWriteDeadline(t) 846 | return nil 847 | } 848 | 849 | // SetReadDeadline implements the Conn SetReadDeadline method. 850 | func (l *Listener) SetReadDeadline(t time.Time) error { 851 | l.rd.Store(t) 852 | return nil 853 | } 854 | 855 | // SetWriteDeadline implements the Conn SetWriteDeadline method. 856 | func (l *Listener) SetWriteDeadline(t time.Time) error { return errInvalidOperation } 857 | 858 | // Close stops listening on the UDP address, and closes the socket 859 | func (l *Listener) Close() error { 860 | var once bool 861 | l.dieOnce.Do(func() { 862 | close(l.die) 863 | once = true 864 | }) 865 | 866 | if once { 867 | return l.conn.Close() 868 | } else { 869 | return errors.WithStack(io.ErrClosedPipe) 870 | } 871 | } 872 | 873 | // closeSession notify the listener that a session has closed 874 | func (l *Listener) closeSession(remote net.Addr) (ret bool) { 875 | l.sessionLock.Lock() 876 | defer l.sessionLock.Unlock() 877 | if _, ok := l.sessions[remote.String()]; ok { 878 | delete(l.sessions, remote.String()) 879 | return true 880 | } 881 | return false 882 | } 883 | 884 | // Addr returns the listener's network address, The Addr returned is shared by all invocations of Addr, so do not modify it. 885 | func (l *Listener) Addr() net.Addr { return l.conn.LocalAddr() } 886 | 887 | // Listen listens for incoming KCP packets addressed to the local address laddr on the network "udp", 888 | func Listen(laddr string) (net.Listener, error) { return ListenWithOptions(laddr, nil, 0, 0) } 889 | 890 | // ListenWithOptions listens for incoming KCP packets addressed to the local address laddr on the network "udp" with packet encryption. 891 | // 892 | // 'block' is the block encryption algorithm to encrypt packets. 893 | // 894 | // 'dataShards', 'parityShards' specifiy how many parity packets will be generated following the data packets. 895 | // 896 | // Check https://github.com/klauspost/reedsolomon for details 897 | func ListenWithOptions(laddr string, block BlockCrypt, dataShards, parityShards int) (*Listener, error) { 898 | udpaddr, err := net.ResolveUDPAddr("udp", laddr) 899 | if err != nil { 900 | return nil, errors.WithStack(err) 901 | } 902 | conn, err := net.ListenUDP("udp", udpaddr) 903 | if err != nil { 904 | return nil, errors.WithStack(err) 905 | } 906 | 907 | return ServeConn(block, dataShards, parityShards, conn) 908 | } 909 | 910 | // ServeConn serves KCP protocol for a single packet connection. 911 | func ServeConn(block BlockCrypt, dataShards, parityShards int, conn net.PacketConn) (*Listener, error) { 912 | l := new(Listener) 913 | l.conn = conn 914 | l.sessions = make(map[string]*UDPSession) 915 | l.chAccepts = make(chan *UDPSession, acceptBacklog) 916 | l.chSessionClosed = make(chan net.Addr) 917 | l.die = make(chan struct{}) 918 | l.dataShards = dataShards 919 | l.parityShards = parityShards 920 | l.block = block 921 | l.fecDecoder = newFECDecoder(rxFECMulti*(dataShards+parityShards), dataShards, parityShards) 922 | l.chSocketReadError = make(chan struct{}) 923 | 924 | // calculate header size 925 | if l.block != nil { 926 | l.headerSize += cryptHeaderSize 927 | } 928 | if l.fecDecoder != nil { 929 | l.headerSize += fecHeaderSizePlus2 930 | } 931 | 932 | go l.monitor() 933 | return l, nil 934 | } 935 | 936 | // Dial connects to the remote address "raddr" on the network "udp" without encryption and FEC 937 | func Dial(raddr string) (net.Conn, error) { return DialWithOptions(raddr, nil, 0, 0) } 938 | 939 | // DialWithOptions connects to the remote address "raddr" on the network "udp" with packet encryption 940 | // 941 | // 'block' is the block encryption algorithm to encrypt packets. 942 | // 943 | // 'dataShards', 'parityShards' specifiy how many parity packets will be generated following the data packets. 944 | // 945 | // Check https://github.com/klauspost/reedsolomon for details 946 | func DialWithOptions(raddr string, block BlockCrypt, dataShards, parityShards int) (*UDPSession, error) { 947 | // network type detection 948 | udpaddr, err := net.ResolveUDPAddr("udp", raddr) 949 | if err != nil { 950 | return nil, errors.WithStack(err) 951 | } 952 | network := "udp4" 953 | if udpaddr.IP.To4() == nil { 954 | network = "udp" 955 | } 956 | 957 | conn, err := net.ListenUDP(network, nil) 958 | if err != nil { 959 | return nil, errors.WithStack(err) 960 | } 961 | 962 | return NewConn(raddr, block, dataShards, parityShards, conn) 963 | } 964 | 965 | // NewConn establishes a session and talks KCP protocol over a packet connection. 966 | func NewConn(raddr string, block BlockCrypt, dataShards, parityShards int, conn net.PacketConn) (*UDPSession, error) { 967 | udpaddr, err := net.ResolveUDPAddr("udp", raddr) 968 | if err != nil { 969 | return nil, errors.WithStack(err) 970 | } 971 | 972 | var convid uint32 973 | binary.Read(rand.Reader, binary.LittleEndian, &convid) 974 | return newUDPSession(convid, dataShards, parityShards, nil, conn, udpaddr, block), nil 975 | } 976 | 977 | // monotonic reference time point 978 | var refTime time.Time = time.Now() 979 | 980 | // currentMs returns current elasped monotonic milliseconds since program startup 981 | func currentMs() uint32 { return uint32(time.Now().Sub(refTime) / time.Millisecond) } 982 | 983 | func NewP2pConn(udpConn net.PacketConn, raddr string, block BlockCrypt, dataShards, parityShards int) (*UDPSession, error){ 984 | udpaddr, err := net.ResolveUDPAddr("udp", raddr) 985 | if err != nil { 986 | return nil, errors.Wrap(err, "net.ResolveUDPAddr") 987 | } 988 | 989 | return newUDPSession(0x1, dataShards, parityShards, nil, udpConn, udpaddr, block), nil 990 | } -------------------------------------------------------------------------------- /kcp-go/snmp.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import ( 4 | "fmt" 5 | "sync/atomic" 6 | ) 7 | 8 | // Snmp defines network statistics indicator 9 | type Snmp struct { 10 | BytesSent uint64 // bytes sent from upper level 11 | BytesReceived uint64 // bytes received to upper level 12 | MaxConn uint64 // max number of connections ever reached 13 | ActiveOpens uint64 // accumulated active open connections 14 | PassiveOpens uint64 // accumulated passive open connections 15 | CurrEstab uint64 // current number of established connections 16 | InErrs uint64 // UDP read errors reported from net.PacketConn 17 | InCsumErrors uint64 // checksum errors from CRC32 18 | KCPInErrors uint64 // packet iput errors reported from KCP 19 | InPkts uint64 // incoming packets count 20 | OutPkts uint64 // outgoing packets count 21 | InSegs uint64 // incoming KCP segments 22 | OutSegs uint64 // outgoing KCP segments 23 | InBytes uint64 // UDP bytes received 24 | OutBytes uint64 // UDP bytes sent 25 | RetransSegs uint64 // accmulated retransmited segments 26 | FastRetransSegs uint64 // accmulated fast retransmitted segments 27 | EarlyRetransSegs uint64 // accmulated early retransmitted segments 28 | LostSegs uint64 // number of segs infered as lost 29 | RepeatSegs uint64 // number of segs duplicated 30 | FECRecovered uint64 // correct packets recovered from FEC 31 | FECErrs uint64 // incorrect packets recovered from FEC 32 | FECParityShards uint64 // FEC segments received 33 | FECShortShards uint64 // number of data shards that's not enough for recovery 34 | } 35 | 36 | func newSnmp() *Snmp { 37 | return new(Snmp) 38 | } 39 | 40 | // Header returns all field names 41 | func (s *Snmp) Header() []string { 42 | return []string{ 43 | "BytesSent", 44 | "BytesReceived", 45 | "MaxConn", 46 | "ActiveOpens", 47 | "PassiveOpens", 48 | "CurrEstab", 49 | "InErrs", 50 | "InCsumErrors", 51 | "KCPInErrors", 52 | "InPkts", 53 | "OutPkts", 54 | "InSegs", 55 | "OutSegs", 56 | "InBytes", 57 | "OutBytes", 58 | "RetransSegs", 59 | "FastRetransSegs", 60 | "EarlyRetransSegs", 61 | "LostSegs", 62 | "RepeatSegs", 63 | "FECParityShards", 64 | "FECErrs", 65 | "FECRecovered", 66 | "FECShortShards", 67 | } 68 | } 69 | 70 | // ToSlice returns current snmp info as slice 71 | func (s *Snmp) ToSlice() []string { 72 | snmp := s.Copy() 73 | return []string{ 74 | fmt.Sprint(snmp.BytesSent), 75 | fmt.Sprint(snmp.BytesReceived), 76 | fmt.Sprint(snmp.MaxConn), 77 | fmt.Sprint(snmp.ActiveOpens), 78 | fmt.Sprint(snmp.PassiveOpens), 79 | fmt.Sprint(snmp.CurrEstab), 80 | fmt.Sprint(snmp.InErrs), 81 | fmt.Sprint(snmp.InCsumErrors), 82 | fmt.Sprint(snmp.KCPInErrors), 83 | fmt.Sprint(snmp.InPkts), 84 | fmt.Sprint(snmp.OutPkts), 85 | fmt.Sprint(snmp.InSegs), 86 | fmt.Sprint(snmp.OutSegs), 87 | fmt.Sprint(snmp.InBytes), 88 | fmt.Sprint(snmp.OutBytes), 89 | fmt.Sprint(snmp.RetransSegs), 90 | fmt.Sprint(snmp.FastRetransSegs), 91 | fmt.Sprint(snmp.EarlyRetransSegs), 92 | fmt.Sprint(snmp.LostSegs), 93 | fmt.Sprint(snmp.RepeatSegs), 94 | fmt.Sprint(snmp.FECParityShards), 95 | fmt.Sprint(snmp.FECErrs), 96 | fmt.Sprint(snmp.FECRecovered), 97 | fmt.Sprint(snmp.FECShortShards), 98 | } 99 | } 100 | 101 | // Copy make a copy of current snmp snapshot 102 | func (s *Snmp) Copy() *Snmp { 103 | d := newSnmp() 104 | d.BytesSent = atomic.LoadUint64(&s.BytesSent) 105 | d.BytesReceived = atomic.LoadUint64(&s.BytesReceived) 106 | d.MaxConn = atomic.LoadUint64(&s.MaxConn) 107 | d.ActiveOpens = atomic.LoadUint64(&s.ActiveOpens) 108 | d.PassiveOpens = atomic.LoadUint64(&s.PassiveOpens) 109 | d.CurrEstab = atomic.LoadUint64(&s.CurrEstab) 110 | d.InErrs = atomic.LoadUint64(&s.InErrs) 111 | d.InCsumErrors = atomic.LoadUint64(&s.InCsumErrors) 112 | d.KCPInErrors = atomic.LoadUint64(&s.KCPInErrors) 113 | d.InPkts = atomic.LoadUint64(&s.InPkts) 114 | d.OutPkts = atomic.LoadUint64(&s.OutPkts) 115 | d.InSegs = atomic.LoadUint64(&s.InSegs) 116 | d.OutSegs = atomic.LoadUint64(&s.OutSegs) 117 | d.InBytes = atomic.LoadUint64(&s.InBytes) 118 | d.OutBytes = atomic.LoadUint64(&s.OutBytes) 119 | d.RetransSegs = atomic.LoadUint64(&s.RetransSegs) 120 | d.FastRetransSegs = atomic.LoadUint64(&s.FastRetransSegs) 121 | d.EarlyRetransSegs = atomic.LoadUint64(&s.EarlyRetransSegs) 122 | d.LostSegs = atomic.LoadUint64(&s.LostSegs) 123 | d.RepeatSegs = atomic.LoadUint64(&s.RepeatSegs) 124 | d.FECParityShards = atomic.LoadUint64(&s.FECParityShards) 125 | d.FECErrs = atomic.LoadUint64(&s.FECErrs) 126 | d.FECRecovered = atomic.LoadUint64(&s.FECRecovered) 127 | d.FECShortShards = atomic.LoadUint64(&s.FECShortShards) 128 | return d 129 | } 130 | 131 | // Reset values to zero 132 | func (s *Snmp) Reset() { 133 | atomic.StoreUint64(&s.BytesSent, 0) 134 | atomic.StoreUint64(&s.BytesReceived, 0) 135 | atomic.StoreUint64(&s.MaxConn, 0) 136 | atomic.StoreUint64(&s.ActiveOpens, 0) 137 | atomic.StoreUint64(&s.PassiveOpens, 0) 138 | atomic.StoreUint64(&s.CurrEstab, 0) 139 | atomic.StoreUint64(&s.InErrs, 0) 140 | atomic.StoreUint64(&s.InCsumErrors, 0) 141 | atomic.StoreUint64(&s.KCPInErrors, 0) 142 | atomic.StoreUint64(&s.InPkts, 0) 143 | atomic.StoreUint64(&s.OutPkts, 0) 144 | atomic.StoreUint64(&s.InSegs, 0) 145 | atomic.StoreUint64(&s.OutSegs, 0) 146 | atomic.StoreUint64(&s.InBytes, 0) 147 | atomic.StoreUint64(&s.OutBytes, 0) 148 | atomic.StoreUint64(&s.RetransSegs, 0) 149 | atomic.StoreUint64(&s.FastRetransSegs, 0) 150 | atomic.StoreUint64(&s.EarlyRetransSegs, 0) 151 | atomic.StoreUint64(&s.LostSegs, 0) 152 | atomic.StoreUint64(&s.RepeatSegs, 0) 153 | atomic.StoreUint64(&s.FECParityShards, 0) 154 | atomic.StoreUint64(&s.FECErrs, 0) 155 | atomic.StoreUint64(&s.FECRecovered, 0) 156 | atomic.StoreUint64(&s.FECShortShards, 0) 157 | } 158 | 159 | // DefaultSnmp is the global KCP connection statistics collector 160 | var DefaultSnmp *Snmp 161 | 162 | func init() { 163 | DefaultSnmp = newSnmp() 164 | } 165 | -------------------------------------------------------------------------------- /kcp-go/tx_generic.go: -------------------------------------------------------------------------------- 1 | // +build !linux 2 | 3 | package kcp 4 | 5 | import ( 6 | "sync/atomic" 7 | 8 | "github.com/pkg/errors" 9 | "golang.org/x/net/ipv4" 10 | ) 11 | 12 | func (s *UDPSession) tx(txqueue []ipv4.Message) { 13 | nbytes := 0 14 | npkts := 0 15 | for k := range txqueue { 16 | if n, err := s.conn.WriteTo(txqueue[k].Buffers[0], txqueue[k].Addr); err == nil { 17 | nbytes += n 18 | npkts++ 19 | xmitBuf.Put(txqueue[k].Buffers[0]) 20 | } else { 21 | s.notifyWriteError(errors.WithStack(err)) 22 | break 23 | } 24 | } 25 | atomic.AddUint64(&DefaultSnmp.OutPkts, uint64(npkts)) 26 | atomic.AddUint64(&DefaultSnmp.OutBytes, uint64(nbytes)) 27 | } 28 | -------------------------------------------------------------------------------- /kcp-go/tx_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package kcp 4 | 5 | import ( 6 | "sync/atomic" 7 | 8 | "github.com/pkg/errors" 9 | "golang.org/x/net/ipv4" 10 | ) 11 | 12 | func (s *UDPSession) tx(txqueue []ipv4.Message) { 13 | nbytes := 0 14 | npkts := 0 15 | for len(txqueue) > 0 { 16 | if n, err := s.xconn.WriteBatch(txqueue, 0); err == nil { 17 | for k := range txqueue[:n] { 18 | nbytes += len(txqueue[k].Buffers[0]) 19 | xmitBuf.Put(txqueue[k].Buffers[0]) 20 | } 21 | npkts += n 22 | txqueue = txqueue[n:] 23 | } else { 24 | s.notifyWriteError(errors.WithStack(err)) 25 | break 26 | } 27 | } 28 | 29 | atomic.AddUint64(&DefaultSnmp.OutPkts, uint64(npkts)) 30 | atomic.AddUint64(&DefaultSnmp.OutBytes, uint64(nbytes)) 31 | } 32 | -------------------------------------------------------------------------------- /kcp-go/updater.go: -------------------------------------------------------------------------------- 1 | package kcp 2 | 3 | import ( 4 | "container/heap" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | var updater updateHeap 10 | 11 | func init() { 12 | updater.init() 13 | go updater.updateTask() 14 | } 15 | 16 | // entry contains a session update info 17 | type entry struct { 18 | ts time.Time 19 | s *UDPSession 20 | } 21 | 22 | // a global heap managed kcp.flush() caller 23 | type updateHeap struct { 24 | entries []entry 25 | mu sync.Mutex 26 | chWakeUp chan struct{} 27 | } 28 | 29 | func (h *updateHeap) Len() int { return len(h.entries) } 30 | func (h *updateHeap) Less(i, j int) bool { return h.entries[i].ts.Before(h.entries[j].ts) } 31 | func (h *updateHeap) Swap(i, j int) { 32 | h.entries[i], h.entries[j] = h.entries[j], h.entries[i] 33 | h.entries[i].s.updaterIdx = i 34 | h.entries[j].s.updaterIdx = j 35 | } 36 | 37 | func (h *updateHeap) Push(x interface{}) { 38 | h.entries = append(h.entries, x.(entry)) 39 | n := len(h.entries) 40 | h.entries[n-1].s.updaterIdx = n - 1 41 | } 42 | 43 | func (h *updateHeap) Pop() interface{} { 44 | n := len(h.entries) 45 | x := h.entries[n-1] 46 | h.entries[n-1].s.updaterIdx = -1 47 | h.entries[n-1] = entry{} // manual set nil for GC 48 | h.entries = h.entries[0 : n-1] 49 | return x 50 | } 51 | 52 | func (h *updateHeap) init() { 53 | h.chWakeUp = make(chan struct{}, 1) 54 | } 55 | 56 | func (h *updateHeap) addSession(s *UDPSession) { 57 | h.mu.Lock() 58 | heap.Push(h, entry{time.Now(), s}) 59 | h.mu.Unlock() 60 | h.wakeup() 61 | } 62 | 63 | func (h *updateHeap) removeSession(s *UDPSession) { 64 | h.mu.Lock() 65 | if s.updaterIdx != -1 { 66 | heap.Remove(h, s.updaterIdx) 67 | } 68 | h.mu.Unlock() 69 | } 70 | 71 | func (h *updateHeap) wakeup() { 72 | select { 73 | case h.chWakeUp <- struct{}{}: 74 | default: 75 | } 76 | } 77 | 78 | func (h *updateHeap) updateTask() { 79 | timer := time.NewTimer(0) 80 | for { 81 | select { 82 | case <-timer.C: 83 | case <-h.chWakeUp: 84 | } 85 | 86 | h.mu.Lock() 87 | hlen := h.Len() 88 | for i := 0; i < hlen; i++ { 89 | entry := &h.entries[0] 90 | if !time.Now().Before(entry.ts) { 91 | interval := entry.s.update() 92 | entry.ts = time.Now().Add(interval) 93 | heap.Fix(h, 0) 94 | } else { 95 | break 96 | } 97 | } 98 | 99 | if hlen > 0 { 100 | timer.Reset(h.entries[0].ts.Sub(time.Now())) 101 | } 102 | h.mu.Unlock() 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /p2pclient/config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "os" 6 | ) 7 | 8 | // Config for client 9 | type Config struct { 10 | ListenTcp string `json:"listentcp"` 11 | TargetTcp string `json:"targettcp"` 12 | BindUdp string `json:"bindudp"` 13 | RemoteUdp string `json:"remoteudp"` 14 | Key string `json:"key"` 15 | Passwd string `json:"passwd"` 16 | Crypt string `json:"crypt"` 17 | Mode string `json:"mode"` 18 | AutoExpire int `json:"autoexpire"` 19 | MTU int `json:"mtu"` 20 | SndWnd int `json:"sndwnd"` 21 | RcvWnd int `json:"rcvwnd"` 22 | DataShard int `json:"datashard"` 23 | ParityShard int `json:"parityshard"` 24 | DSCP int `json:"dscp"` 25 | NoComp bool `json:"nocomp"` 26 | AckNodelay bool `json:"acknodelay"` 27 | NoDelay int `json:"nodelay"` 28 | Interval int `json:"interval"` 29 | Resend int `json:"resend"` 30 | NoCongestion int `json:"nc"` 31 | SockBuf int `json:"sockbuf"` 32 | KeepAlive int `json:"keepalive"` 33 | Log string `json:"log"` 34 | SnmpLog string `json:"snmplog"` 35 | SnmpPeriod int `json:"snmpperiod"` 36 | Quiet bool `json:"quiet"` 37 | } 38 | 39 | func parseJSONConfig(config *Config, path string) error { 40 | file, err := os.Open(path) // For read access. 41 | if err != nil { 42 | return err 43 | } 44 | defer file.Close() 45 | 46 | return json.NewDecoder(file).Decode(config) 47 | } 48 | 49 | -------------------------------------------------------------------------------- /p2pclient/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "crypto/sha1" 6 | "encoding/json" 7 | "github.com/hikaricai/p2p_tun/kcp-go" 8 | "github.com/xtaci/kcptun/generic" 9 | "io" 10 | "log" 11 | "math/rand" 12 | "net" 13 | "os" 14 | "sync" 15 | "sync/atomic" 16 | "time" 17 | "golang.org/x/crypto/pbkdf2" 18 | "github.com/urfave/cli" 19 | "github.com/xtaci/smux" 20 | ) 21 | 22 | var ( 23 | // VERSION is injected by buildflags 24 | VERSION = "SELFBUILD" 25 | // SALT is use for pbkdf2 key expansion 26 | SALT = "kcp-go" 27 | isServer = false 28 | pingInterval = 10 29 | xmitBuf sync.Pool 30 | ) 31 | 32 | func handleLocalTcp(sess *smux.Session, p1 io.ReadWriteCloser, quiet bool) { 33 | if !quiet { 34 | log.Println("stream opened") 35 | defer log.Println("stream closed") 36 | } 37 | defer p1.Close() 38 | p2, err := sess.OpenStream() 39 | if err != nil { 40 | return 41 | } 42 | defer p2.Close() 43 | 44 | streamCopy := func(dst io.Writer, src io.ReadCloser) chan struct{} { 45 | die := make(chan struct{}) 46 | go func() { 47 | buf := xmitBuf.Get().([]byte) 48 | generic.CopyBuffer(dst, src, buf) 49 | xmitBuf.Put(buf) 50 | close(die) 51 | }() 52 | return die 53 | } 54 | 55 | select { 56 | case <-streamCopy(p1, p2): 57 | case <-streamCopy(p2, p1): 58 | } 59 | } 60 | 61 | func checkError(err error) { 62 | if err != nil { 63 | log.Printf("%+v\n", err) 64 | os.Exit(-1) 65 | } 66 | } 67 | 68 | func main() { 69 | rand.Seed(int64(time.Now().Nanosecond())) 70 | if VERSION == "SELFBUILD" { 71 | // add more log flags for debugging 72 | log.SetFlags(log.LstdFlags | log.Lshortfile) 73 | } 74 | xmitBuf.New = func() interface{} { 75 | return make([]byte, 32768) 76 | } 77 | myApp := cli.NewApp() 78 | myApp.Name = "p2pclient" 79 | myApp.Usage = "client(with kcptun)" 80 | myApp.Version = VERSION 81 | myApp.Flags = []cli.Flag{ 82 | cli.StringFlag{ 83 | Name: "targettcp, t", 84 | Value: "127.0.0.1:22", 85 | Usage: "target server address", 86 | }, 87 | cli.StringFlag{ 88 | Name: "listentcp,l", 89 | Value: ":2022", 90 | Usage: "local listen address", 91 | }, 92 | cli.StringFlag{ 93 | Name: "remoteudp, r", 94 | Value: "127.0.0.1:4000", 95 | Usage: "kcp server address", 96 | }, 97 | cli.StringFlag{ 98 | Name: "key, k", 99 | Value: "1234", 100 | Usage: "p2p pair key", 101 | }, 102 | cli.StringFlag{ 103 | Name: "passwd", 104 | Value: "1234", 105 | Usage: "pre-shared secret between client and server", 106 | EnvVar: "KCPTUN_KEY", 107 | }, 108 | cli.StringFlag{ 109 | Name: "crypt", 110 | Value: "none", 111 | Usage: "aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, sm4, none", 112 | }, 113 | cli.StringFlag{ 114 | Name: "mode", 115 | Value: "fast", 116 | Usage: "profiles: fast3, fast2, fast, normal, manual", 117 | }, 118 | cli.IntFlag{ 119 | Name: "conn", 120 | Value: 1, 121 | Usage: "set num of UDP connections to server", 122 | }, 123 | cli.IntFlag{ 124 | Name: "autoexpire", 125 | Value: 0, 126 | Usage: "set auto expiration time(in seconds) for a single UDP connection, 0 to disable", 127 | }, 128 | cli.IntFlag{ 129 | Name: "mtu", 130 | Value: 1350, 131 | Usage: "set maximum transmission unit for UDP packets", 132 | }, 133 | cli.IntFlag{ 134 | Name: "sndwnd", 135 | Value: 1024, 136 | Usage: "set send window size(num of packets)", 137 | }, 138 | cli.IntFlag{ 139 | Name: "rcvwnd", 140 | Value: 1024, 141 | Usage: "set receive window size(num of packets)", 142 | }, 143 | cli.IntFlag{ 144 | Name: "datashard,ds", 145 | Value: 0, 146 | Usage: "set reed-solomon erasure coding - datashard", 147 | }, 148 | cli.IntFlag{ 149 | Name: "parityshard,ps", 150 | Value: 0, 151 | Usage: "set reed-solomon erasure coding - parityshard", 152 | }, 153 | cli.IntFlag{ 154 | Name: "dscp", 155 | Value: 0, 156 | Usage: "set DSCP(6bit)", 157 | }, 158 | cli.BoolFlag{ 159 | Name: "nocomp", 160 | Usage: "disable compression", 161 | }, 162 | cli.BoolFlag{ 163 | Name: "acknodelay", 164 | Usage: "flush ack immediately when a packet is received", 165 | Hidden: true, 166 | }, 167 | cli.IntFlag{ 168 | Name: "nodelay", 169 | Value: 0, 170 | Hidden: true, 171 | }, 172 | cli.IntFlag{ 173 | Name: "interval", 174 | Value: 50, 175 | Hidden: true, 176 | }, 177 | cli.IntFlag{ 178 | Name: "resend", 179 | Value: 0, 180 | Hidden: true, 181 | }, 182 | cli.IntFlag{ 183 | Name: "nc", 184 | Value: 0, 185 | Hidden: true, 186 | }, 187 | cli.IntFlag{ 188 | Name: "sockbuf", 189 | Value: 4194304, // socket buffer size in bytes 190 | Usage: "per-socket buffer in bytes", 191 | }, 192 | cli.IntFlag{ 193 | Name: "keepalive", 194 | Value: 10, // nat keepalive interval in seconds 195 | Usage: "seconds between heartbeats", 196 | }, 197 | cli.StringFlag{ 198 | Name: "snmplog", 199 | Value: "", 200 | Usage: "collect snmp to file, aware of timeformat in golang, like: ./snmp-20060102.log", 201 | }, 202 | cli.IntFlag{ 203 | Name: "snmpperiod", 204 | Value: 60, 205 | Usage: "snmp collect period, in seconds", 206 | }, 207 | cli.StringFlag{ 208 | Name: "log", 209 | Value: "", 210 | Usage: "specify a log file to output, default goes to stderr", 211 | }, 212 | cli.BoolFlag{ 213 | Name: "quiet", 214 | Usage: "to suppress the 'stream open/close' messages", 215 | }, 216 | cli.StringFlag{ 217 | Name: "c", 218 | Value: "", // when the value is not empty, the config path must exists 219 | Usage: "config from json file, which will override the command from shell", 220 | }, 221 | } 222 | myApp.Action = func(c *cli.Context) error { 223 | config := Config{} 224 | config.ListenTcp = c.String("listentcp") 225 | config.RemoteUdp = c.String("remoteudp") 226 | config.TargetTcp = c.String("targettcp") 227 | config.Key = c.String("key") 228 | config.Passwd = c.String("passwd") 229 | config.Crypt = c.String("crypt") 230 | config.Mode = c.String("mode") 231 | config.MTU = c.Int("mtu") 232 | config.SndWnd = c.Int("sndwnd") 233 | config.RcvWnd = c.Int("rcvwnd") 234 | config.DataShard = c.Int("datashard") 235 | config.ParityShard = c.Int("parityshard") 236 | config.DSCP = c.Int("dscp") 237 | config.NoComp = c.Bool("nocomp") 238 | config.AckNodelay = c.Bool("acknodelay") 239 | config.NoDelay = c.Int("nodelay") 240 | config.Interval = c.Int("interval") 241 | config.Resend = c.Int("resend") 242 | config.NoCongestion = c.Int("nc") 243 | config.SockBuf = c.Int("sockbuf") 244 | config.KeepAlive = c.Int("keepalive") 245 | config.Quiet = c.Bool("quiet") 246 | 247 | if c.String("c") != "" { 248 | err := parseJSONConfig(&config, c.String("c")) 249 | checkError(err) 250 | } 251 | 252 | switch config.Mode { 253 | case "normal": 254 | config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 40, 2, 1 255 | case "fast": 256 | config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 30, 2, 1 257 | case "fast2": 258 | config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 20, 2, 1 259 | case "fast3": 260 | config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 10, 2, 1 261 | } 262 | 263 | log.Println("version:", VERSION) 264 | 265 | chTCPConn := make(chan *net.TCPConn, 16) 266 | 267 | go tcpListener(chTCPConn, &config) 268 | for{ 269 | peerAddr, err := getPeerAddr(&config) 270 | time.Sleep(2*time.Second) 271 | if err == nil{ 272 | p2pHandle(&config, peerAddr, chTCPConn) 273 | }else{ 274 | time.Sleep(time.Duration(pingInterval)*time.Second) 275 | } 276 | } 277 | } 278 | myApp.Run(os.Args) 279 | } 280 | 281 | func p2pHandle(config *Config, peerAddr string, chTCPConn chan *net.TCPConn){ 282 | udpAddr, err := net.ResolveUDPAddr("udp4", config.BindUdp) 283 | checkError(err) 284 | udpconn, err := net.ListenUDP("udp4", udpAddr) 285 | checkError(err) 286 | defer udpconn.Close() 287 | 288 | smuxSession, err := newSmuxSession(udpconn, config, peerAddr) 289 | checkError(err) 290 | 291 | go handleTargetTcp(config.TargetTcp, smuxSession, config.Quiet) 292 | tickerCheck := time.NewTicker(10*time.Second) 293 | defer tickerCheck.Stop() 294 | for { 295 | select { 296 | case p1 := <-chTCPConn: 297 | go handleLocalTcp(smuxSession, p1, config.Quiet) 298 | case <-tickerCheck.C: 299 | if smuxSession.IsClosed(){ 300 | log.Println("p2p session closed") 301 | return 302 | } 303 | } 304 | } 305 | } 306 | 307 | func tcpListener(chTCPConn chan *net.TCPConn, config *Config){ 308 | listenTcpAddr, err := net.ResolveTCPAddr("tcp4", config.ListenTcp) 309 | checkError(err) 310 | listener, err := net.ListenTCP("tcp4", listenTcpAddr) 311 | checkError(err) 312 | log.Println("listening on:", listener.Addr()) 313 | for{ 314 | p1, err := listener.AcceptTCP() 315 | if err != nil { 316 | log.Fatalln(err) 317 | checkError(err) 318 | } 319 | chTCPConn <- p1 320 | } 321 | } 322 | 323 | func getPeerAddr(config *Config)(string, error){ 324 | udpAddr, err := net.ResolveUDPAddr("udp4", "0.0.0.0:0") 325 | checkError(err) 326 | udpconn, err := net.ListenUDP("udp4", udpAddr) 327 | checkError(err) 328 | config.BindUdp = udpconn.LocalAddr().String() 329 | log.Println("config.BindUdp is ", config.BindUdp) 330 | defer udpconn.Close() 331 | 332 | kcpConn, err := newKcpConn(udpconn, config, config.RemoteUdp) 333 | defer kcpConn.Close() 334 | 335 | var dataReady int32 336 | var chPing = make(chan struct{}) 337 | defer close(chPing) 338 | 339 | go pingCheck(kcpConn, &dataReady, chPing) 340 | reader := bufio.NewReader(kcpConn) 341 | pairMess := phaseJsonMess("login", config.Key) 342 | finMess := phaseJsonMess("fin", "good bye") 343 | var peerAddr string 344 | log.Println("writing mess") 345 | _, err = kcpConn.Write(pairMess) 346 | if err != nil { 347 | log.Println("kcpConn.Write", err) 348 | return "", err 349 | } 350 | for { 351 | log.Println("waiting for server") 352 | line, err := reader.ReadString('\n') 353 | if err != nil { 354 | log.Println("reader.ReadString", err) 355 | return "", err 356 | } 357 | var mess DigHoleMess 358 | json.Unmarshal([]byte(line), &mess) 359 | log.Println("rcv Cmd", mess.Cmd) 360 | switch mess.Cmd { 361 | case "ping": 362 | atomic.StoreInt32(&dataReady, 1) 363 | log.Println("rcv ping") 364 | case "pair_s": 365 | isServer = true 366 | peerAddr = mess.Data 367 | log.Println("peer addr is ", peerAddr) 368 | kcpConn.Write(finMess) 369 | case "pair_c": 370 | isServer = false 371 | peerAddr = mess.Data 372 | log.Println("peer addr is ", peerAddr) 373 | kcpConn.Write(finMess) 374 | case "fin": 375 | return peerAddr, nil 376 | } 377 | } 378 | } 379 | 380 | func pingCheck(conn *kcp.UDPSession, dataReady *int32, chPing chan struct {}){ 381 | jsonPingMess := phaseJsonMess("ping", "hello") 382 | tickerPing := time.NewTicker(time.Duration(pingInterval)*time.Second) 383 | defer tickerPing.Stop() 384 | defer log.Println("pingCheck return") 385 | for { 386 | select { 387 | case <-tickerPing.C: 388 | if !atomic.CompareAndSwapInt32(dataReady, 1, 0) { 389 | log.Println("ping timeout") 390 | conn.Close() 391 | return 392 | } 393 | conn.Write(jsonPingMess) 394 | case <- chPing: 395 | return 396 | } 397 | } 398 | } 399 | 400 | type DigHoleMess struct { 401 | Cmd string 402 | Data string 403 | } 404 | 405 | func phaseJsonMess(cmd string, data string) []byte { 406 | mess := DigHoleMess{cmd, data} 407 | jsonMess, err := json.Marshal(mess) 408 | if err != nil { 409 | log.Println(err) 410 | } 411 | return append(jsonMess, '\n') 412 | } 413 | 414 | func newSmuxSession(udpconn net.PacketConn, config *Config, remoteAddr string) (*smux.Session, error) { 415 | kcpconn, err := newKcpConn(udpconn, config, remoteAddr) 416 | if err != nil { 417 | return nil, err 418 | } 419 | smuxConfig := smux.DefaultConfig() 420 | smuxConfig.MaxReceiveBuffer = config.SockBuf 421 | smuxConfig.KeepAliveInterval = time.Duration(config.KeepAlive) * time.Second 422 | smuxConfig.KeepAliveTimeout = time.Duration(config.KeepAlive) * time.Second*3 423 | // stream multiplex 424 | var smuxSession *smux.Session 425 | if isServer { 426 | smuxSession, err = smux.Server(kcpconn, smuxConfig) 427 | } else { 428 | smuxSession, err = smux.Client(kcpconn, smuxConfig) 429 | } 430 | if err == nil { 431 | log.Println("connection:", kcpconn.LocalAddr(), "->", kcpconn.RemoteAddr()) 432 | } 433 | return smuxSession, err 434 | } 435 | 436 | func newKcpConn(udpconn net.PacketConn, config *Config, remoteAddr string) (*kcp.UDPSession, error) { 437 | log.Println("initiating key derivation") 438 | pass := pbkdf2.Key([]byte(config.Passwd), []byte(SALT), 4096, 32, sha1.New) 439 | var block kcp.BlockCrypt 440 | switch config.Crypt { 441 | case "sm4": 442 | block, _ = kcp.NewSM4BlockCrypt(pass[:16]) 443 | case "tea": 444 | block, _ = kcp.NewTEABlockCrypt(pass[:16]) 445 | case "xor": 446 | block, _ = kcp.NewSimpleXORBlockCrypt(pass) 447 | case "none": 448 | block, _ = kcp.NewNoneBlockCrypt(pass) 449 | case "aes-128": 450 | block, _ = kcp.NewAESBlockCrypt(pass[:16]) 451 | case "aes-192": 452 | block, _ = kcp.NewAESBlockCrypt(pass[:24]) 453 | case "blowfish": 454 | block, _ = kcp.NewBlowfishBlockCrypt(pass) 455 | case "twofish": 456 | block, _ = kcp.NewTwofishBlockCrypt(pass) 457 | case "cast5": 458 | block, _ = kcp.NewCast5BlockCrypt(pass[:16]) 459 | case "3des": 460 | block, _ = kcp.NewTripleDESBlockCrypt(pass[:24]) 461 | case "xtea": 462 | block, _ = kcp.NewXTEABlockCrypt(pass[:16]) 463 | case "salsa20": 464 | block, _ = kcp.NewSalsa20BlockCrypt(pass) 465 | default: 466 | config.Crypt = "aes" 467 | block, _ = kcp.NewAESBlockCrypt(pass) 468 | } 469 | 470 | kcpconn, err := kcp.NewP2pConn(udpconn, remoteAddr, block, config.DataShard, config.ParityShard) 471 | if err != nil { 472 | return nil, err 473 | } 474 | 475 | kcpconn.SetStreamMode(true) 476 | kcpconn.SetWriteDelay(false) 477 | kcpconn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion) 478 | kcpconn.SetWindowSize(config.SndWnd, config.RcvWnd) 479 | kcpconn.SetMtu(config.MTU) 480 | kcpconn.SetACKNoDelay(config.AckNodelay) 481 | 482 | if err := kcpconn.SetDSCP(config.DSCP); err != nil { 483 | log.Println("SetDSCP:", err) 484 | } 485 | if err := kcpconn.SetReadBuffer(config.SockBuf); err != nil { 486 | log.Println("SetReadBuffer:", err) 487 | } 488 | if err := kcpconn.SetWriteBuffer(config.SockBuf); err != nil { 489 | log.Println("SetWriteBuffer:", err) 490 | } 491 | return kcpconn, err 492 | } 493 | 494 | func handleTargetTcp(addr string, session *smux.Session, quiet bool) { 495 | for { 496 | p1, err := session.AcceptStream() 497 | if err != nil { 498 | log.Println(err) 499 | return 500 | } 501 | p2, err := net.DialTimeout("tcp", addr, 5*time.Second) 502 | if err != nil { 503 | p1.Close() 504 | log.Println(err) 505 | continue 506 | } 507 | go func() { 508 | if !quiet { 509 | log.Println("tcp client opened") 510 | defer log.Println("tcp client closed") 511 | } 512 | defer p1.Close() 513 | defer p2.Close() 514 | 515 | streamCopy := func(dst io.Writer, src io.ReadCloser) chan struct{} { 516 | die := make(chan struct{}) 517 | go func() { 518 | buf := xmitBuf.Get().([]byte) 519 | generic.CopyBuffer(dst, src, buf) 520 | xmitBuf.Put(buf) 521 | close(die) 522 | }() 523 | return die 524 | } 525 | 526 | select { 527 | case <-streamCopy(p1, p2): 528 | case <-streamCopy(p2, p1): 529 | } 530 | }() 531 | } 532 | } 533 | 534 | -------------------------------------------------------------------------------- /p2pclient/signal.go: -------------------------------------------------------------------------------- 1 | // +build linux darwin freebsd 2 | 3 | package main 4 | 5 | import ( 6 | "log" 7 | "os" 8 | "os/signal" 9 | "syscall" 10 | 11 | kcp "github.com/hikaricai/p2p_tun/kcp-go" 12 | ) 13 | 14 | func init() { 15 | go sigHandler() 16 | } 17 | 18 | func sigHandler() { 19 | ch := make(chan os.Signal, 1) 20 | signal.Notify(ch, syscall.SIGUSR1) 21 | signal.Ignore(syscall.SIGPIPE) 22 | 23 | for { 24 | switch <-ch { 25 | case syscall.SIGUSR1: 26 | log.Printf("KCP SNMP:%+v", kcp.DefaultSnmp.Copy()) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /p2pserver/config.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "os" 6 | ) 7 | 8 | // Config for server 9 | type Config struct { 10 | Listen string `json:"listen"` 11 | Passwd string `json:"passwd"` 12 | Crypt string `json:"crypt"` 13 | Mode string `json:"mode"` 14 | MTU int `json:"mtu"` 15 | SndWnd int `json:"sndwnd"` 16 | RcvWnd int `json:"rcvwnd"` 17 | DataShard int `json:"datashard"` 18 | ParityShard int `json:"parityshard"` 19 | DSCP int `json:"dscp"` 20 | NoComp bool `json:"nocomp"` 21 | AckNodelay bool `json:"acknodelay"` 22 | NoDelay int `json:"nodelay"` 23 | Interval int `json:"interval"` 24 | Resend int `json:"resend"` 25 | NoCongestion int `json:"nc"` 26 | SockBuf int `json:"sockbuf"` 27 | KeepAlive int `json:"keepalive"` 28 | Log string `json:"log"` 29 | SnmpLog string `json:"snmplog"` 30 | SnmpPeriod int `json:"snmpperiod"` 31 | Pprof bool `json:"pprof"` 32 | Quiet bool `json:"quiet"` 33 | } 34 | 35 | func parseJSONConfig(config *Config, path string) error { 36 | file, err := os.Open(path) // For read access. 37 | if err != nil { 38 | return err 39 | } 40 | defer file.Close() 41 | 42 | return json.NewDecoder(file).Decode(config) 43 | } 44 | -------------------------------------------------------------------------------- /p2pserver/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "crypto/sha1" 6 | "encoding/json" 7 | "github.com/hikaricai/p2p_tun/kcp-go" 8 | "log" 9 | "math/rand" 10 | "os" 11 | "sync" 12 | "sync/atomic" 13 | "time" 14 | 15 | "golang.org/x/crypto/pbkdf2" 16 | 17 | "github.com/urfave/cli" 18 | ) 19 | 20 | var ( 21 | // VERSION is injected by buildflags 22 | VERSION = "SELFBUILD" 23 | // SALT is use for pbkdf2 key expansion 24 | SALT = "kcp-go" 25 | pingInterval = 10 26 | ) 27 | 28 | func checkError(err error) { 29 | if err != nil { 30 | log.Printf("%+v\n", err) 31 | os.Exit(-1) 32 | } 33 | } 34 | 35 | func main() { 36 | rand.Seed(int64(time.Now().Nanosecond())) 37 | if VERSION == "SELFBUILD" { 38 | // add more log flags for debugging 39 | log.SetFlags(log.LstdFlags | log.Lshortfile) 40 | } 41 | myApp := cli.NewApp() 42 | myApp.Name = "p2pserver" 43 | myApp.Usage = "server(with kcptun)" 44 | myApp.Version = VERSION 45 | myApp.Flags = []cli.Flag{ 46 | cli.StringFlag{ 47 | Name: "listen,l", 48 | Value: "0.0.0.0:4000", 49 | Usage: "kcp server listen address", 50 | }, 51 | cli.StringFlag{ 52 | Name: "passwd", 53 | Value: "1234", 54 | Usage: "pre-shared secret between client and server", 55 | EnvVar: "KCPTUN_KEY", 56 | }, 57 | cli.StringFlag{ 58 | Name: "crypt", 59 | Value: "none", 60 | Usage: "aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, sm4, none", 61 | }, 62 | cli.StringFlag{ 63 | Name: "mode", 64 | Value: "fast", 65 | Usage: "profiles: fast3, fast2, fast, normal, manual", 66 | }, 67 | cli.IntFlag{ 68 | Name: "mtu", 69 | Value: 1350, 70 | Usage: "set maximum transmission unit for UDP packets", 71 | }, 72 | cli.IntFlag{ 73 | Name: "sndwnd", 74 | Value: 1024, 75 | Usage: "set send window size(num of packets)", 76 | }, 77 | cli.IntFlag{ 78 | Name: "rcvwnd", 79 | Value: 1024, 80 | Usage: "set receive window size(num of packets)", 81 | }, 82 | cli.IntFlag{ 83 | Name: "datashard,ds", 84 | Value: 0, 85 | Usage: "set reed-solomon erasure coding - datashard", 86 | }, 87 | cli.IntFlag{ 88 | Name: "parityshard,ps", 89 | Value: 0, 90 | Usage: "set reed-solomon erasure coding - parityshard", 91 | }, 92 | cli.IntFlag{ 93 | Name: "dscp", 94 | Value: 0, 95 | Usage: "set DSCP(6bit)", 96 | }, 97 | cli.BoolFlag{ 98 | Name: "nocomp", 99 | Usage: "disable compression", 100 | }, 101 | cli.BoolFlag{ 102 | Name: "acknodelay", 103 | Usage: "flush ack immediately when a packet is received", 104 | Hidden: true, 105 | }, 106 | cli.IntFlag{ 107 | Name: "nodelay", 108 | Value: 0, 109 | Hidden: true, 110 | }, 111 | cli.IntFlag{ 112 | Name: "interval", 113 | Value: 50, 114 | Hidden: true, 115 | }, 116 | cli.IntFlag{ 117 | Name: "resend", 118 | Value: 0, 119 | Hidden: true, 120 | }, 121 | cli.IntFlag{ 122 | Name: "nc", 123 | Value: 0, 124 | Hidden: true, 125 | }, 126 | cli.IntFlag{ 127 | Name: "sockbuf", 128 | Value: 4194304, // socket buffer size in bytes 129 | Usage: "per-socket buffer in bytes", 130 | }, 131 | cli.IntFlag{ 132 | Name: "keepalive", 133 | Value: 10, // nat keepalive interval in seconds 134 | Usage: "seconds between heartbeats", 135 | }, 136 | cli.StringFlag{ 137 | Name: "snmplog", 138 | Value: "", 139 | Usage: "collect snmp to file, aware of timeformat in golang, like: ./snmp-20060102.log", 140 | }, 141 | cli.IntFlag{ 142 | Name: "snmpperiod", 143 | Value: 60, 144 | Usage: "snmp collect period, in seconds", 145 | }, 146 | cli.BoolFlag{ 147 | Name: "pprof", 148 | Usage: "start profiling server on :6060", 149 | }, 150 | cli.StringFlag{ 151 | Name: "log", 152 | Value: "", 153 | Usage: "specify a log file to output, default goes to stderr", 154 | }, 155 | cli.BoolFlag{ 156 | Name: "quiet", 157 | Usage: "to suppress the 'stream open/close' messages", 158 | }, 159 | cli.StringFlag{ 160 | Name: "c", 161 | Value: "", // when the value is not empty, the config path must exists 162 | Usage: "config from json file, which will override the command from shell", 163 | }, 164 | } 165 | myApp.Action = func(c *cli.Context) error { 166 | config := Config{} 167 | config.Listen = c.String("listen") 168 | config.Passwd = c.String("passwd") 169 | config.Crypt = c.String("crypt") 170 | config.Mode = c.String("mode") 171 | config.MTU = c.Int("mtu") 172 | config.SndWnd = c.Int("sndwnd") 173 | config.RcvWnd = c.Int("rcvwnd") 174 | config.DataShard = c.Int("datashard") 175 | config.ParityShard = c.Int("parityshard") 176 | config.DSCP = c.Int("dscp") 177 | config.NoComp = c.Bool("nocomp") 178 | config.AckNodelay = c.Bool("acknodelay") 179 | config.NoDelay = c.Int("nodelay") 180 | config.Interval = c.Int("interval") 181 | config.Resend = c.Int("resend") 182 | config.NoCongestion = c.Int("nc") 183 | config.SockBuf = c.Int("sockbuf") 184 | config.KeepAlive = c.Int("keepalive") 185 | config.SnmpLog = c.String("snmplog") 186 | config.SnmpPeriod = c.Int("snmpperiod") 187 | config.Pprof = c.Bool("pprof") 188 | config.Quiet = c.Bool("quiet") 189 | 190 | if c.String("c") != "" { 191 | //Now only support json config file 192 | err := parseJSONConfig(&config, c.String("c")) 193 | checkError(err) 194 | } 195 | switch config.Mode { 196 | case "normal": 197 | config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 40, 2, 1 198 | case "fast": 199 | config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 30, 2, 1 200 | case "fast2": 201 | config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 20, 2, 1 202 | case "fast3": 203 | config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 10, 2, 1 204 | } 205 | 206 | log.Println("version:", VERSION) 207 | log.Println("initiating key derivation") 208 | pass := pbkdf2.Key([]byte(config.Passwd), []byte(SALT), 4096, 32, sha1.New) 209 | var block kcp.BlockCrypt 210 | switch config.Crypt { 211 | case "sm4": 212 | block, _ = kcp.NewSM4BlockCrypt(pass[:16]) 213 | case "tea": 214 | block, _ = kcp.NewTEABlockCrypt(pass[:16]) 215 | case "xor": 216 | block, _ = kcp.NewSimpleXORBlockCrypt(pass) 217 | case "none": 218 | block, _ = kcp.NewNoneBlockCrypt(pass) 219 | case "aes-128": 220 | block, _ = kcp.NewAESBlockCrypt(pass[:16]) 221 | case "aes-192": 222 | block, _ = kcp.NewAESBlockCrypt(pass[:24]) 223 | case "blowfish": 224 | block, _ = kcp.NewBlowfishBlockCrypt(pass) 225 | case "twofish": 226 | block, _ = kcp.NewTwofishBlockCrypt(pass) 227 | case "cast5": 228 | block, _ = kcp.NewCast5BlockCrypt(pass[:16]) 229 | case "3des": 230 | block, _ = kcp.NewTripleDESBlockCrypt(pass[:24]) 231 | case "xtea": 232 | block, _ = kcp.NewXTEABlockCrypt(pass[:16]) 233 | case "salsa20": 234 | block, _ = kcp.NewSalsa20BlockCrypt(pass) 235 | default: 236 | config.Crypt = "aes" 237 | block, _ = kcp.NewAESBlockCrypt(pass) 238 | } 239 | 240 | lis, err := kcp.ListenWithOptions(config.Listen, block, config.DataShard, config.ParityShard) 241 | checkError(err) 242 | log.Println("listening on:", lis.Addr()) 243 | 244 | if err := lis.SetDSCP(config.DSCP); err != nil { 245 | log.Println("SetDSCP:", err) 246 | } 247 | if err := lis.SetReadBuffer(config.SockBuf); err != nil { 248 | log.Println("SetReadBuffer:", err) 249 | } 250 | if err := lis.SetWriteBuffer(config.SockBuf); err != nil { 251 | log.Println("SetWriteBuffer:", err) 252 | } 253 | 254 | for { 255 | log.Println("listening new kcp") 256 | if conn, err := lis.AcceptKCP(); err == nil { 257 | log.Println("remote address:", conn.RemoteAddr()) 258 | conn.SetStreamMode(true) 259 | conn.SetWriteDelay(false) 260 | conn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion) 261 | conn.SetMtu(config.MTU) 262 | conn.SetWindowSize(config.SndWnd, config.RcvWnd) 263 | conn.SetACKNoDelay(config.AckNodelay) 264 | 265 | go handleClient(conn) 266 | } else { 267 | log.Printf("%+v", err) 268 | } 269 | } 270 | } 271 | myApp.Run(os.Args) 272 | } 273 | 274 | type DigHoleMess struct { 275 | Cmd string 276 | Data string 277 | } 278 | 279 | type UdpSess struct { 280 | conn *kcp.UDPSession 281 | pingFlag int32 282 | isFin bool 283 | } 284 | type P2PSession struct { 285 | key string 286 | sess1 *UdpSess 287 | sess2 *UdpSess 288 | chFin chan struct{} 289 | mu sync.Mutex 290 | } 291 | 292 | var keymap = make(map[string]*P2PSession) 293 | 294 | var keymu sync.Mutex 295 | func registSession(session *P2PSession, sess *UdpSess) (ret bool){ 296 | ret = true 297 | session.mu.Lock() 298 | if session.sess1 == nil{ 299 | session.sess1 = sess 300 | }else if session.sess2 == nil{ 301 | session.sess2 = sess 302 | }else{ 303 | ret = false 304 | } 305 | if ret == true && session.sess1 != nil && session.sess2 != nil{ 306 | conn1 := session.sess1.conn 307 | conn2 := session.sess2.conn 308 | addr1 := conn1.RemoteAddr().String() 309 | addr2 := conn2.RemoteAddr().String() 310 | jsonPair1Mess := phaseJsonMess("pair_s", addr2) 311 | jsonPair2Mess := phaseJsonMess("pair_c", addr1) 312 | log.Println("pairing ", addr1,addr2) 313 | conn1.Write(jsonPair1Mess) 314 | conn2.Write(jsonPair2Mess) 315 | } 316 | session.mu.Unlock() 317 | return ret 318 | } 319 | func handleClient(conn *kcp.UDPSession) { 320 | var session *P2PSession; 321 | key := "" 322 | reader := bufio.NewReader(conn) 323 | defer conn.Close() 324 | var ok bool 325 | var registed = false 326 | sess := &UdpSess{conn,1,false} 327 | for { 328 | line, err := reader.ReadString('\n') 329 | if err != nil { 330 | log.Println("reader.ReadString", err) 331 | return 332 | } 333 | var mess DigHoleMess 334 | err = json.Unmarshal([]byte(line), &mess) 335 | if err != nil{ 336 | continue 337 | } 338 | switch mess.Cmd { 339 | case "login": 340 | remoteAddr := conn.RemoteAddr().String() 341 | log.Println("login from ", remoteAddr) 342 | key = mess.Data 343 | log.Println("key is ", key) 344 | keymu.Lock() 345 | session, ok = keymap[key] 346 | if ok { 347 | registed = registSession(session,sess) 348 | } else { 349 | log.Println("make new P2PSession") 350 | session = new(P2PSession) 351 | session.key = key 352 | session.sess1 = sess 353 | session.chFin = make(chan struct{}) 354 | keymap[key] = session 355 | registed = true 356 | go p2pSessionHandler(session) 357 | } 358 | keymu.Unlock() 359 | jsonPingMess := phaseJsonMess("ping", "hello") 360 | conn.Write(jsonPingMess) 361 | case "ping": 362 | log.Println("rcv ping from ", conn.RemoteAddr().String()) 363 | if registed == false{ 364 | keymu.Lock() 365 | session, ok = keymap[key] 366 | if ok { 367 | registed = registSession(session,sess) 368 | } else { 369 | log.Println("make new P2PSession") 370 | session = new(P2PSession) 371 | session.key = key 372 | session.sess1 = sess 373 | session.chFin = make(chan struct{}) 374 | keymap[key] = session 375 | registed = true 376 | go p2pSessionHandler(session) 377 | } 378 | keymu.Unlock() 379 | } 380 | atomic.StoreInt32(&sess.pingFlag, 1) 381 | jsonPingMess := phaseJsonMess("ping", "hello") 382 | conn.Write(jsonPingMess) 383 | case "fin": 384 | log.Println("fin from", conn.RemoteAddr().String()) 385 | sess.isFin = true 386 | session.chFin <- struct{}{} 387 | } 388 | } 389 | } 390 | 391 | 392 | func p2pSessionHandler(session *P2PSession){ 393 | tickerPing := time.NewTicker(time.Duration(pingInterval)*time.Second) 394 | defer tickerPing.Stop() 395 | for { 396 | select { 397 | case <-tickerPing.C: 398 | if session.sess1 != nil && !atomic.CompareAndSwapInt32(&session.sess1.pingFlag, 1, 0) { 399 | session.mu.Lock() 400 | session.sess1.conn.Close() 401 | session.sess1 = nil 402 | log.Println("sess1 ping timeout") 403 | session.mu.Unlock() 404 | } 405 | if session.sess2 != nil && !atomic.CompareAndSwapInt32(&session.sess2.pingFlag, 1, 0) { 406 | session.mu.Lock() 407 | session.sess2.conn.Close() 408 | session.sess2 = nil 409 | log.Println("sess2 ping timeout") 410 | session.mu.Unlock() 411 | } 412 | case <-session.chFin: 413 | if session.sess1 == nil || session.sess2 == nil{ 414 | continue 415 | } 416 | if session.sess1.isFin == true && session.sess2.isFin == true{ 417 | jsonFinMess := phaseJsonMess("fin", "bye") 418 | session.sess1.conn.Write(jsonFinMess) 419 | session.sess2.conn.Write(jsonFinMess) 420 | time.Sleep(time.Second) 421 | session.sess1.conn.Close() 422 | session.sess2.conn.Close() 423 | keymu.Lock() 424 | delete(keymap,session.key) 425 | keymu.Unlock() 426 | return 427 | } 428 | } 429 | } 430 | } 431 | 432 | func phaseJsonMess(cmd string, data string) []byte { 433 | mess := DigHoleMess{cmd, data} 434 | jsonMess, err := json.Marshal(mess) 435 | if err != nil { 436 | log.Println(err) 437 | } 438 | return append(jsonMess, '\n') 439 | } 440 | -------------------------------------------------------------------------------- /p2pserver/signal.go: -------------------------------------------------------------------------------- 1 | // +build linux darwin freebsd 2 | 3 | package main 4 | 5 | import ( 6 | "log" 7 | "os" 8 | "os/signal" 9 | "syscall" 10 | 11 | kcp "github.com/hikaricai/p2p_tun/kcp-go" 12 | ) 13 | 14 | func init() { 15 | go sigHandler() 16 | } 17 | 18 | func sigHandler() { 19 | ch := make(chan os.Signal, 1) 20 | signal.Notify(ch, syscall.SIGUSR1) 21 | signal.Ignore(syscall.SIGPIPE) 22 | 23 | for { 24 | switch <-ch { 25 | case syscall.SIGUSR1: 26 | log.Printf("KCP SNMP:%+v", kcp.DefaultSnmp.Copy()) 27 | } 28 | } 29 | } 30 | --------------------------------------------------------------------------------