|
9 | 9 | "crypto/tls"
|
10 | 10 | "crypto/x509"
|
11 | 11 | "fmt"
|
| 12 | + "io" |
| 13 | + "io/ioutil" |
12 | 14 | "net"
|
13 | 15 | "testing"
|
14 | 16 | )
|
@@ -741,6 +743,186 @@ func Test_MisconfiguredTLSServerRespondsWithUnderlyingError(t *testing.T) {
|
741 | 743 | }
|
742 | 744 | }
|
743 | 745 |
|
| 746 | +type testConn struct { |
| 747 | + readFromCalledWith io.Reader |
| 748 | + reads int |
| 749 | + net.Conn // nil; crash on any unexpected use |
| 750 | +} |
| 751 | + |
| 752 | +func (c *testConn) ReadFrom(r io.Reader) (int64, error) { |
| 753 | + c.readFromCalledWith = r |
| 754 | + b, err := ioutil.ReadAll(r) |
| 755 | + return int64(len(b)), err |
| 756 | +} |
| 757 | +func (c *testConn) Write(p []byte) (int, error) { |
| 758 | + return len(p), nil |
| 759 | +} |
| 760 | +func (c *testConn) Read(p []byte) (int, error) { |
| 761 | + if c.reads == 0 { |
| 762 | + return 0, io.EOF |
| 763 | + } |
| 764 | + c.reads-- |
| 765 | + return 1, nil |
| 766 | +} |
| 767 | + |
| 768 | +func TestCopyToWrappedConnection(t *testing.T) { |
| 769 | + innerConn := &testConn{} |
| 770 | + wrappedConn := NewConn(innerConn) |
| 771 | + dummySrc := &testConn{reads: 1} |
| 772 | + |
| 773 | + io.Copy(wrappedConn, dummySrc) |
| 774 | + if innerConn.readFromCalledWith != dummySrc { |
| 775 | + t.Error("Expected io.Copy to delegate to ReadFrom function of inner destination connection") |
| 776 | + } |
| 777 | +} |
| 778 | + |
| 779 | +func TestCopyFromWrappedConnection(t *testing.T) { |
| 780 | + wrappedConn := NewConn(&testConn{reads: 1}) |
| 781 | + dummyDst := &testConn{} |
| 782 | + |
| 783 | + io.Copy(dummyDst, wrappedConn) |
| 784 | + if dummyDst.readFromCalledWith != wrappedConn.conn { |
| 785 | + t.Errorf("Expected io.Copy to pass inner source connection to ReadFrom method of destination") |
| 786 | + } |
| 787 | +} |
| 788 | + |
| 789 | +func TestCopyFromWrappedConnectionToWrappedConnection(t *testing.T) { |
| 790 | + innerConn1 := &testConn{reads: 1} |
| 791 | + wrappedConn1 := NewConn(innerConn1) |
| 792 | + innerConn2 := &testConn{} |
| 793 | + wrappedConn2 := NewConn(innerConn2) |
| 794 | + |
| 795 | + io.Copy(wrappedConn1, wrappedConn2) |
| 796 | + if innerConn1.readFromCalledWith != innerConn2 { |
| 797 | + t.Errorf("Expected io.Copy to pass inner source connection to ReadFrom of inner destination connection") |
| 798 | + } |
| 799 | +} |
| 800 | + |
| 801 | +func benchmarkTCPProxy(size int, b *testing.B) { |
| 802 | + //create and start the echo backend |
| 803 | + backend, err := net.Listen("tcp", "127.0.0.1:0") |
| 804 | + if err != nil { |
| 805 | + b.Fatalf("err: %v", err) |
| 806 | + } |
| 807 | + defer backend.Close() |
| 808 | + go func() { |
| 809 | + for { |
| 810 | + conn, err := backend.Accept() |
| 811 | + if err != nil { |
| 812 | + break |
| 813 | + } |
| 814 | + _, err = io.Copy(conn, conn) |
| 815 | + conn.Close() |
| 816 | + if err != nil { |
| 817 | + b.Fatalf("Failed to read entire payload: %v", err) |
| 818 | + } |
| 819 | + } |
| 820 | + }() |
| 821 | + |
| 822 | + //start the proxyprotocol enabled tcp proxy |
| 823 | + l, err := net.Listen("tcp", "127.0.0.1:0") |
| 824 | + if err != nil { |
| 825 | + b.Fatalf("err: %v", err) |
| 826 | + } |
| 827 | + defer l.Close() |
| 828 | + pl := &Listener{Listener: l} |
| 829 | + go func() { |
| 830 | + for { |
| 831 | + conn, err := pl.Accept() |
| 832 | + if err != nil { |
| 833 | + break |
| 834 | + } |
| 835 | + bConn, err := net.Dial("tcp", backend.Addr().String()) |
| 836 | + if err != nil { |
| 837 | + b.Fatalf("failed to dial backend: %v", err) |
| 838 | + } |
| 839 | + go func() { |
| 840 | + _, err = io.Copy(bConn, conn) |
| 841 | + if err != nil { |
| 842 | + b.Fatalf("Failed to proxy incoming data to backend: %v", err) |
| 843 | + } |
| 844 | + bConn.(*net.TCPConn).CloseWrite() |
| 845 | + }() |
| 846 | + _, err = io.Copy(conn, bConn) |
| 847 | + if err != nil { |
| 848 | + b.Fatalf("Failed to proxy data from backend: %v", err) |
| 849 | + } |
| 850 | + conn.Close() |
| 851 | + bConn.Close() |
| 852 | + } |
| 853 | + }() |
| 854 | + |
| 855 | + data := make([]byte, size) |
| 856 | + |
| 857 | + header := &Header{ |
| 858 | + Version: 2, |
| 859 | + Command: PROXY, |
| 860 | + TransportProtocol: TCPv4, |
| 861 | + SourceAddr: &net.TCPAddr{ |
| 862 | + IP: net.ParseIP("10.1.1.1"), |
| 863 | + Port: 1000, |
| 864 | + }, |
| 865 | + DestinationAddr: &net.TCPAddr{ |
| 866 | + IP: net.ParseIP("20.2.2.2"), |
| 867 | + Port: 2000, |
| 868 | + }, |
| 869 | + } |
| 870 | + |
| 871 | + //now for the actual benchmark |
| 872 | + b.ResetTimer() |
| 873 | + for n := 0; n < b.N; n++ { |
| 874 | + conn, err := net.Dial("tcp", pl.Addr().String()) |
| 875 | + if err != nil { |
| 876 | + b.Fatalf("err: %v", err) |
| 877 | + } |
| 878 | + // Write out the header! |
| 879 | + header.WriteTo(conn) |
| 880 | + //send data |
| 881 | + go func() { |
| 882 | + _, err = conn.Write(data) |
| 883 | + if err != nil { |
| 884 | + b.Fatalf("Failed to write data: %v", err) |
| 885 | + } |
| 886 | + conn.(*net.TCPConn).CloseWrite() |
| 887 | + |
| 888 | + }() |
| 889 | + //receive data |
| 890 | + n, err := io.Copy(ioutil.Discard, conn) |
| 891 | + if n != int64(len(data)) { |
| 892 | + b.Fatalf("Expected to receive %d bytes, got %d", len(data), n) |
| 893 | + } |
| 894 | + if err != nil { |
| 895 | + b.Fatalf("Failed to read data: %v", err) |
| 896 | + } |
| 897 | + conn.Close() |
| 898 | + } |
| 899 | +} |
| 900 | + |
| 901 | +func BenchmarkTCPProxy16KB(b *testing.B) { |
| 902 | + benchmarkTCPProxy(16*1024, b) |
| 903 | +} |
| 904 | +func BenchmarkTCPProxy32KB(b *testing.B) { |
| 905 | + benchmarkTCPProxy(32*1024, b) |
| 906 | +} |
| 907 | +func BenchmarkTCPProxy64KB(b *testing.B) { |
| 908 | + benchmarkTCPProxy(64*1024, b) |
| 909 | +} |
| 910 | +func BenchmarkTCPProxy128KB(b *testing.B) { |
| 911 | + benchmarkTCPProxy(128*1024, b) |
| 912 | +} |
| 913 | +func BenchmarkTCPProxy256KB(b *testing.B) { |
| 914 | + benchmarkTCPProxy(256*1024, b) |
| 915 | +} |
| 916 | +func BenchmarkTCPProxy512KB(b *testing.B) { |
| 917 | + benchmarkTCPProxy(512*1024, b) |
| 918 | +} |
| 919 | +func BenchmarkTCPProxy1024KB(b *testing.B) { |
| 920 | + benchmarkTCPProxy(1024*1024, b) |
| 921 | +} |
| 922 | +func BenchmarkTCPProxy2048KB(b *testing.B) { |
| 923 | + benchmarkTCPProxy(2048*1024, b) |
| 924 | +} |
| 925 | + |
744 | 926 | // copied from src/net/http/internal/testcert.go
|
745 | 927 |
|
746 | 928 | // Copyright 2015 The Go Authors. All rights reserved.
|
|
0 commit comments