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  }