github.com/geph-official/geph2@v0.22.6-0.20210211030601-f527cb59b0df/libs/kcp-go/sess_test.go (about) 1 package kcp 2 3 import ( 4 "crypto/sha1" 5 "fmt" 6 "io" 7 "log" 8 "net" 9 "net/http" 10 _ "net/http/pprof" 11 "sync" 12 "sync/atomic" 13 "testing" 14 "time" 15 16 "golang.org/x/crypto/pbkdf2" 17 ) 18 19 var baseport = uint32(10000) 20 var key = []byte("testkey") 21 var pass = pbkdf2.Key(key, []byte("testsalt"), 4096, 32, sha1.New) 22 23 func init() { 24 go func() { 25 log.Println(http.ListenAndServe("0.0.0.0:6060", nil)) 26 }() 27 28 log.Println("beginning tests, encryption:salsa20, fec:10/3") 29 } 30 31 func dialEcho(port int) (*UDPSession, error) { 32 //block, _ := NewNoneBlockCrypt(pass) 33 //block, _ := NewSimpleXORBlockCrypt(pass) 34 //block, _ := NewTEABlockCrypt(pass[:16]) 35 //block, _ := NewAESBlockCrypt(pass) 36 block, _ := NewSalsa20BlockCrypt(pass) 37 sess, err := DialWithOptions(fmt.Sprintf("127.0.0.1:%v", port), block, 10, 3) 38 if err != nil { 39 panic(err) 40 } 41 42 sess.SetStreamMode(true) 43 sess.SetStreamMode(false) 44 sess.SetStreamMode(true) 45 sess.SetWindowSize(1024, 1024) 46 sess.SetReadBuffer(16 * 1024 * 1024) 47 sess.SetWriteBuffer(16 * 1024 * 1024) 48 sess.SetStreamMode(true) 49 sess.SetNoDelay(1, 10, 2, 1) 50 sess.SetMtu(1400) 51 sess.SetMtu(1600) 52 sess.SetMtu(1400) 53 sess.SetACKNoDelay(true) 54 sess.SetACKNoDelay(false) 55 sess.SetDeadline(time.Now().Add(time.Minute)) 56 return sess, err 57 } 58 59 func dialSink(port int) (*UDPSession, error) { 60 sess, err := DialWithOptions(fmt.Sprintf("127.0.0.1:%v", port), nil, 0, 0) 61 if err != nil { 62 panic(err) 63 } 64 65 sess.SetStreamMode(true) 66 sess.SetWindowSize(1024, 1024) 67 sess.SetReadBuffer(16 * 1024 * 1024) 68 sess.SetWriteBuffer(16 * 1024 * 1024) 69 sess.SetStreamMode(true) 70 sess.SetNoDelay(1, 10, 2, 1) 71 sess.SetMtu(1400) 72 sess.SetACKNoDelay(false) 73 sess.SetDeadline(time.Now().Add(time.Minute)) 74 return sess, err 75 } 76 77 func dialTinyBufferEcho(port int) (*UDPSession, error) { 78 //block, _ := NewNoneBlockCrypt(pass) 79 //block, _ := NewSimpleXORBlockCrypt(pass) 80 //block, _ := NewTEABlockCrypt(pass[:16]) 81 //block, _ := NewAESBlockCrypt(pass) 82 block, _ := NewSalsa20BlockCrypt(pass) 83 sess, err := DialWithOptions(fmt.Sprintf("127.0.0.1:%v", port), block, 10, 3) 84 if err != nil { 85 panic(err) 86 } 87 return sess, err 88 } 89 90 ////////////////////////// 91 func listenEcho(port int) (net.Listener, error) { 92 //block, _ := NewNoneBlockCrypt(pass) 93 //block, _ := NewSimpleXORBlockCrypt(pass) 94 //block, _ := NewTEABlockCrypt(pass[:16]) 95 //block, _ := NewAESBlockCrypt(pass) 96 block, _ := NewSalsa20BlockCrypt(pass) 97 return ListenWithOptions(fmt.Sprintf("127.0.0.1:%v", port), block, 10, 3) 98 } 99 func listenTinyBufferEcho(port int) (net.Listener, error) { 100 //block, _ := NewNoneBlockCrypt(pass) 101 //block, _ := NewSimpleXORBlockCrypt(pass) 102 //block, _ := NewTEABlockCrypt(pass[:16]) 103 //block, _ := NewAESBlockCrypt(pass) 104 block, _ := NewSalsa20BlockCrypt(pass) 105 return ListenWithOptions(fmt.Sprintf("127.0.0.1:%v", port), block, 10, 3) 106 } 107 108 func listenSink(port int) (net.Listener, error) { 109 return ListenWithOptions(fmt.Sprintf("127.0.0.1:%v", port), nil, 0, 0) 110 } 111 112 func echoServer(port int) net.Listener { 113 l, err := listenEcho(port) 114 if err != nil { 115 panic(err) 116 } 117 118 go func() { 119 kcplistener := l.(*Listener) 120 kcplistener.SetReadBuffer(4 * 1024 * 1024) 121 kcplistener.SetWriteBuffer(4 * 1024 * 1024) 122 kcplistener.SetDSCP(46) 123 for { 124 s, err := l.Accept() 125 if err != nil { 126 return 127 } 128 129 // coverage test 130 s.(*UDPSession).SetReadBuffer(4 * 1024 * 1024) 131 s.(*UDPSession).SetWriteBuffer(4 * 1024 * 1024) 132 go handleEcho(s.(*UDPSession)) 133 } 134 }() 135 136 return l 137 } 138 139 func sinkServer(port int) net.Listener { 140 l, err := listenSink(port) 141 if err != nil { 142 panic(err) 143 } 144 145 go func() { 146 kcplistener := l.(*Listener) 147 kcplistener.SetReadBuffer(4 * 1024 * 1024) 148 kcplistener.SetWriteBuffer(4 * 1024 * 1024) 149 kcplistener.SetDSCP(46) 150 for { 151 s, err := l.Accept() 152 if err != nil { 153 return 154 } 155 156 go handleSink(s.(*UDPSession)) 157 } 158 }() 159 160 return l 161 } 162 163 func tinyBufferEchoServer(port int) net.Listener { 164 l, err := listenTinyBufferEcho(port) 165 if err != nil { 166 panic(err) 167 } 168 169 go func() { 170 for { 171 s, err := l.Accept() 172 if err != nil { 173 return 174 } 175 go handleTinyBufferEcho(s.(*UDPSession)) 176 } 177 }() 178 return l 179 } 180 181 /////////////////////////// 182 183 func handleEcho(conn *UDPSession) { 184 conn.SetStreamMode(true) 185 conn.SetWindowSize(4096, 4096) 186 conn.SetNoDelay(1, 10, 2, 1) 187 conn.SetDSCP(46) 188 conn.SetMtu(1400) 189 conn.SetACKNoDelay(false) 190 conn.SetReadDeadline(time.Now().Add(time.Hour)) 191 conn.SetWriteDeadline(time.Now().Add(time.Hour)) 192 buf := make([]byte, 65536) 193 for { 194 n, err := conn.Read(buf) 195 if err != nil { 196 return 197 } 198 conn.Write(buf[:n]) 199 } 200 } 201 202 func handleSink(conn *UDPSession) { 203 conn.SetStreamMode(true) 204 conn.SetWindowSize(4096, 4096) 205 conn.SetNoDelay(1, 10, 2, 1) 206 conn.SetDSCP(46) 207 conn.SetMtu(1400) 208 conn.SetACKNoDelay(false) 209 conn.SetReadDeadline(time.Now().Add(time.Hour)) 210 conn.SetWriteDeadline(time.Now().Add(time.Hour)) 211 buf := make([]byte, 65536) 212 for { 213 _, err := conn.Read(buf) 214 if err != nil { 215 return 216 } 217 } 218 } 219 220 func handleTinyBufferEcho(conn *UDPSession) { 221 conn.SetStreamMode(true) 222 buf := make([]byte, 2) 223 for { 224 n, err := conn.Read(buf) 225 if err != nil { 226 return 227 } 228 conn.Write(buf[:n]) 229 } 230 } 231 232 /////////////////////////// 233 234 func TestTimeout(t *testing.T) { 235 port := int(atomic.AddUint32(&baseport, 1)) 236 l := echoServer(port) 237 defer l.Close() 238 239 cli, err := dialEcho(port) 240 if err != nil { 241 panic(err) 242 } 243 buf := make([]byte, 10) 244 245 //timeout 246 cli.SetDeadline(time.Now().Add(time.Second)) 247 <-time.After(2 * time.Second) 248 n, err := cli.Read(buf) 249 if n != 0 || err == nil { 250 t.Fail() 251 } 252 cli.Close() 253 } 254 255 func TestSendRecv(t *testing.T) { 256 port := int(atomic.AddUint32(&baseport, 1)) 257 l := echoServer(port) 258 defer l.Close() 259 260 cli, err := dialEcho(port) 261 if err != nil { 262 panic(err) 263 } 264 cli.SetWriteDelay(true) 265 cli.SetDUP(1) 266 const N = 100 267 buf := make([]byte, 10) 268 for i := 0; i < N; i++ { 269 msg := fmt.Sprintf("hello%v", i) 270 cli.Write([]byte(msg)) 271 if n, err := cli.Read(buf); err == nil { 272 if string(buf[:n]) != msg { 273 t.Fail() 274 } 275 } else { 276 panic(err) 277 } 278 } 279 cli.Close() 280 } 281 282 func TestSendVector(t *testing.T) { 283 port := int(atomic.AddUint32(&baseport, 1)) 284 l := echoServer(port) 285 defer l.Close() 286 287 cli, err := dialEcho(port) 288 if err != nil { 289 panic(err) 290 } 291 cli.SetWriteDelay(false) 292 const N = 100 293 buf := make([]byte, 20) 294 v := make([][]byte, 2) 295 for i := 0; i < N; i++ { 296 v[0] = []byte(fmt.Sprintf("hello%v", i)) 297 v[1] = []byte(fmt.Sprintf("world%v", i)) 298 msg := fmt.Sprintf("hello%vworld%v", i, i) 299 cli.WriteBuffers(v) 300 if n, err := cli.Read(buf); err == nil { 301 if string(buf[:n]) != msg { 302 t.Error(string(buf[:n]), msg) 303 } 304 } else { 305 panic(err) 306 } 307 } 308 cli.Close() 309 } 310 311 func TestTinyBufferReceiver(t *testing.T) { 312 port := int(atomic.AddUint32(&baseport, 1)) 313 l := tinyBufferEchoServer(port) 314 defer l.Close() 315 316 cli, err := dialTinyBufferEcho(port) 317 if err != nil { 318 panic(err) 319 } 320 const N = 100 321 snd := byte(0) 322 fillBuffer := func(buf []byte) { 323 for i := 0; i < len(buf); i++ { 324 buf[i] = snd 325 snd++ 326 } 327 } 328 329 rcv := byte(0) 330 check := func(buf []byte) bool { 331 for i := 0; i < len(buf); i++ { 332 if buf[i] != rcv { 333 return false 334 } 335 rcv++ 336 } 337 return true 338 } 339 sndbuf := make([]byte, 7) 340 rcvbuf := make([]byte, 7) 341 for i := 0; i < N; i++ { 342 fillBuffer(sndbuf) 343 cli.Write(sndbuf) 344 if n, err := io.ReadFull(cli, rcvbuf); err == nil { 345 if !check(rcvbuf[:n]) { 346 t.Fail() 347 } 348 } else { 349 panic(err) 350 } 351 } 352 cli.Close() 353 } 354 355 func TestClose(t *testing.T) { 356 var n int 357 var err error 358 359 port := int(atomic.AddUint32(&baseport, 1)) 360 l := echoServer(port) 361 defer l.Close() 362 363 cli, err := dialEcho(port) 364 if err != nil { 365 panic(err) 366 } 367 368 // double close 369 cli.Close() 370 if cli.Close() == nil { 371 t.Fatal("double close misbehavior") 372 } 373 374 // write after close 375 buf := make([]byte, 10) 376 n, err = cli.Write(buf) 377 if n != 0 || err == nil { 378 t.Fatal("write after close misbehavior") 379 } 380 381 // write, close, read, read 382 cli, err = dialEcho(port) 383 if err != nil { 384 panic(err) 385 } 386 if n, err = cli.Write(buf); err != nil { 387 t.Fatal("write misbehavior") 388 } 389 390 // wait until data arrival 391 time.Sleep(2 * time.Second) 392 // drain 393 cli.Close() 394 n, err = io.ReadFull(cli, buf) 395 if err != nil { 396 t.Fatal("closed conn drain bytes failed", err, n) 397 } 398 399 // after drain, read should return error 400 n, err = cli.Read(buf) 401 if n != 0 || err == nil { 402 t.Fatal("write->close->drain->read misbehavior", err, n) 403 } 404 cli.Close() 405 } 406 407 func TestParallel1024CLIENT_64BMSG_64CNT(t *testing.T) { 408 port := int(atomic.AddUint32(&baseport, 1)) 409 l := echoServer(port) 410 defer l.Close() 411 412 var wg sync.WaitGroup 413 wg.Add(1024) 414 for i := 0; i < 1024; i++ { 415 go parallel_client(&wg, port) 416 } 417 wg.Wait() 418 } 419 420 func parallel_client(wg *sync.WaitGroup, port int) (err error) { 421 cli, err := dialEcho(port) 422 if err != nil { 423 panic(err) 424 } 425 426 err = echo_tester(cli, 64, 64) 427 cli.Close() 428 wg.Done() 429 return 430 } 431 432 func BenchmarkEchoSpeed4K(b *testing.B) { 433 speedclient(b, 4096) 434 } 435 436 func BenchmarkEchoSpeed64K(b *testing.B) { 437 speedclient(b, 65536) 438 } 439 440 func BenchmarkEchoSpeed512K(b *testing.B) { 441 speedclient(b, 524288) 442 } 443 444 func BenchmarkEchoSpeed1M(b *testing.B) { 445 speedclient(b, 1048576) 446 } 447 448 func speedclient(b *testing.B, nbytes int) { 449 port := int(atomic.AddUint32(&baseport, 1)) 450 l := echoServer(port) 451 defer l.Close() 452 453 b.ReportAllocs() 454 cli, err := dialEcho(port) 455 if err != nil { 456 panic(err) 457 } 458 459 if err := echo_tester(cli, nbytes, b.N); err != nil { 460 b.Fail() 461 } 462 b.SetBytes(int64(nbytes)) 463 cli.Close() 464 } 465 466 func BenchmarkSinkSpeed4K(b *testing.B) { 467 sinkclient(b, 4096) 468 } 469 470 func BenchmarkSinkSpeed64K(b *testing.B) { 471 sinkclient(b, 65536) 472 } 473 474 func BenchmarkSinkSpeed256K(b *testing.B) { 475 sinkclient(b, 524288) 476 } 477 478 func BenchmarkSinkSpeed1M(b *testing.B) { 479 sinkclient(b, 1048576) 480 } 481 482 func sinkclient(b *testing.B, nbytes int) { 483 port := int(atomic.AddUint32(&baseport, 1)) 484 l := sinkServer(port) 485 defer l.Close() 486 487 b.ReportAllocs() 488 cli, err := dialSink(port) 489 if err != nil { 490 panic(err) 491 } 492 493 sink_tester(cli, nbytes, b.N) 494 b.SetBytes(int64(nbytes)) 495 cli.Close() 496 } 497 498 func echo_tester(cli net.Conn, msglen, msgcount int) error { 499 buf := make([]byte, msglen) 500 for i := 0; i < msgcount; i++ { 501 // send packet 502 if _, err := cli.Write(buf); err != nil { 503 return err 504 } 505 506 // receive packet 507 nrecv := 0 508 for { 509 n, err := cli.Read(buf) 510 if err != nil { 511 return err 512 } else { 513 nrecv += n 514 if nrecv == msglen { 515 break 516 } 517 } 518 } 519 } 520 return nil 521 } 522 523 func sink_tester(cli *UDPSession, msglen, msgcount int) error { 524 // sender 525 buf := make([]byte, msglen) 526 for i := 0; i < msgcount; i++ { 527 if _, err := cli.Write(buf); err != nil { 528 return err 529 } 530 } 531 return nil 532 } 533 534 func TestSNMP(t *testing.T) { 535 t.Log(DefaultSnmp.Copy()) 536 t.Log(DefaultSnmp.Header()) 537 t.Log(DefaultSnmp.ToSlice()) 538 DefaultSnmp.Reset() 539 t.Log(DefaultSnmp.ToSlice()) 540 } 541 542 func TestListenerClose(t *testing.T) { 543 port := int(atomic.AddUint32(&baseport, 1)) 544 l, err := ListenWithOptions(fmt.Sprintf("127.0.0.1:%v", port), nil, 10, 3) 545 if err != nil { 546 t.Fail() 547 } 548 l.SetReadDeadline(time.Now().Add(time.Second)) 549 l.SetWriteDeadline(time.Now().Add(time.Second)) 550 l.SetDeadline(time.Now().Add(time.Second)) 551 time.Sleep(2 * time.Second) 552 if _, err := l.Accept(); err == nil { 553 t.Fail() 554 } 555 556 l.Close() 557 fakeaddr, _ := net.ResolveUDPAddr("udp6", "127.0.0.1:1111") 558 if l.closeSession(fakeaddr) { 559 t.Fail() 560 } 561 }