// NewReader creates a new BufferedReader based on an io.Reader. func NewReader(rawReader io.Reader) *BufferedReader { return &BufferedReader{ reader: rawReader, buffer: buf.New(), cached: true, } }
func TestSwitchAccount(t *testing.T) { assert := assert.On(t) sa := &protocol.CommandSwitchAccount{ Port: 1234, ID: uuid.New(), AlterIds: 1024, Level: 128, ValidMin: 16, } buffer := buf.New() err := MarshalCommand(sa, buffer) assert.Error(err).IsNil() cmd, err := UnmarshalCommand(1, buffer.BytesFrom(2)) assert.Error(err).IsNil() sa2, ok := cmd.(*protocol.CommandSwitchAccount) assert.Bool(ok).IsTrue() assert.Pointer(sa.Host).IsNil() assert.Pointer(sa2.Host).IsNil() assert.Port(sa.Port).Equals(sa2.Port) assert.String(sa.ID.String()).Equals(sa2.ID.String()) assert.Uint16(sa.AlterIds).Equals(sa2.AlterIds) assert.Byte(byte(sa.Level)).Equals(byte(sa2.Level)) assert.Byte(sa.ValidMin).Equals(sa2.ValidMin) }
func TestBufferedReader(t *testing.T) { assert := assert.On(t) content := buf.New() content.AppendSupplier(buf.ReadFrom(rand.Reader)) len := content.Len() reader := NewReader(content) assert.Bool(reader.Cached()).IsTrue() payload := make([]byte, 16) nBytes, err := reader.Read(payload) assert.Int(nBytes).Equals(16) assert.Error(err).IsNil() len2 := content.Len() assert.Int(len - len2).GreaterThan(16) nBytes, err = reader.Read(payload) assert.Int(nBytes).Equals(16) assert.Error(err).IsNil() assert.Int(content.Len()).Equals(len2) }
func (v *ChunkReader) Read() (*buf.Buffer, error) { buffer := buf.New() if err := buffer.AppendSupplier(buf.ReadFullFrom(v.reader, 2)); err != nil { buffer.Release() return nil, err } // There is a potential buffer overflow here. Large buffer is 64K bytes, // while uin16 + 10 will be more than that length := serial.BytesToUint16(buffer.BytesTo(2)) + AuthSize if length > buf.Size { // Theoretically the size of a chunk is 64K, but most Shadowsocks implementations used <4K buffer. buffer.Release() buffer = buf.NewLocal(int(length) + 128) } buffer.Clear() if err := buffer.AppendSupplier(buf.ReadFullFrom(v.reader, int(length))); err != nil { buffer.Release() return nil, err } authBytes := buffer.BytesTo(AuthSize) payload := buffer.BytesFrom(AuthSize) actualAuthBytes := make([]byte, AuthSize) v.auth.Authenticate(payload)(actualAuthBytes) if !bytes.Equal(authBytes, actualAuthBytes) { buffer.Release() return nil, errors.New("Shadowsocks|AuthenticationReader: Invalid auth.") } buffer.SliceFrom(AuthSize) return buffer, nil }
func TestWrongProtocolVersion(t *testing.T) { assert := assert.On(t) buffer := buf.New() buffer.AppendBytes(6, 1, 0) _, _, err := ReadAuthentication(buffer) assert.Error(err).Equals(proxy.ErrInvalidProtocolVersion) }
func TestZeroAuthenticationMethod(t *testing.T) { assert := assert.On(t) buffer := buf.New() buffer.AppendBytes(5, 0) _, _, err := ReadAuthentication(buffer) assert.Error(err).Equals(crypto.ErrAuthenticationFailed) }
func TestShadowsocksTCP(t *testing.T) { assert := assert.On(t) tcpServer := &tcp.Server{ Port: v2net.Port(50052), MsgProcessor: func(data []byte) []byte { buffer := make([]byte, 0, 2048) buffer = append(buffer, []byte("Processed: ")...) buffer = append(buffer, data...) return buffer }, } _, err := tcpServer.Start() assert.Error(err).IsNil() defer tcpServer.Close() assert.Error(InitializeServerSetOnce("test_6")).IsNil() for i := 0; i < 1; i++ { conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ IP: []byte{127, 0, 0, 1}, Port: 50050, }) assert.Error(err).IsNil() payload := "dokodemo request." nBytes, err := conn.Write([]byte(payload)) assert.Error(err).IsNil() assert.Int(nBytes).Equals(len(payload)) //conn.CloseWrite() response := buf.New() finished := false expectedResponse := "Processed: " + payload for { err := response.AppendSupplier(buf.ReadFrom(conn)) assert.Error(err).IsNil() if err != nil { break } if response.String() == expectedResponse { finished = true break } if response.Len() > len(expectedResponse) { fmt.Printf("Unexpected response: %v\n", response.Bytes()) break } } assert.Bool(finished).IsTrue() conn.Close() } CloseAllServers() }
func TestUDPReaderWriter(t *testing.T) { assert := assert.On(t) user := &protocol.User{ Account: serial.ToTypedMessage(&Account{ Password: "******", CipherType: CipherType_CHACHA20_IEFT, }), } cache := buf.New() writer := &UDPWriter{ Writer: cache, Request: &protocol.RequestHeader{ Version: Version, Address: v2net.DomainAddress("v2ray.com"), Port: 123, User: user, Option: RequestOptionOneTimeAuth, }, } reader := &UDPReader{ Reader: cache, User: user, } b := buf.New() b.AppendSupplier(serial.WriteString("test payload")) err := writer.Write(b) assert.Error(err).IsNil() payload, err := reader.Read() assert.Error(err).IsNil() assert.String(payload.String()).Equals("test payload") b = buf.New() b.AppendSupplier(serial.WriteString("test payload 2")) err = writer.Write(b) assert.Error(err).IsNil() payload, err = reader.Read() assert.Error(err).IsNil() assert.String(payload.String()).Equals("test payload 2") }
func TestIPv6Request(t *testing.T) { assert := assert.On(t) b := buf.New() b.AppendBytes(5, 1, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 0, 8) request, err := ReadRequest(b) assert.Error(err).IsNil() assert.Byte(request.Command).Equals(1) assert.Bytes(request.IPv6[:]).Equals([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}) assert.Port(request.Port).Equals(8) }
func TestStreamIO(t *testing.T) { assert := assert.On(t) stream := NewStream(context.Background()) b1 := buf.New() b1.AppendBytes('a') assert.Error(stream.Write(b1)).IsNil() _, err := stream.Read() assert.Error(err).IsNil() stream.Close() _, err = stream.Read() assert.Error(err).Equals(io.EOF) b2 := buf.New() b2.AppendBytes('b') err = stream.Write(b2) assert.Error(err).Equals(io.ErrClosedPipe) }
func TestNormalChunkReading(t *testing.T) { assert := assert.On(t) buffer := buf.New() buffer.AppendBytes( 0, 8, 39, 228, 69, 96, 133, 39, 254, 26, 201, 70, 11, 12, 13, 14, 15, 16, 17, 18) reader := NewChunkReader(buffer, NewAuthenticator(ChunkKeyGenerator( []byte{21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}))) payload, err := reader.Read() assert.Error(err).IsNil() assert.Bytes(payload.Bytes()).Equals([]byte{11, 12, 13, 14, 15, 16, 17, 18}) }
func TestUDPEncoding(t *testing.T) { assert := assert.On(t) b := buf.New() request := &protocol.RequestHeader{ Address: net.IPAddress([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6}), Port: 1024, } writer := NewUDPWriter(request, b) content := []byte{'a'} payload := buf.New() payload.Append(content) assert.Error(writer.Write(payload)).IsNil() reader := NewUDPReader(b) decodedPayload, err := reader.Read() assert.Error(err).IsNil() assert.Bytes(decodedPayload.Bytes()).Equals(content) }
func TestAuthenticationRequestRead(t *testing.T) { assert := assert.On(t) buffer := buf.New() buffer.AppendBytes( 0x05, // version 0x01, // nMethods 0x02, // methods ) request, _, err := ReadAuthentication(buffer) assert.Error(err).IsNil() assert.Byte(request.version).Equals(0x05) assert.Byte(request.nMethods).Equals(0x01) assert.Byte(request.authMethods[0]).Equals(0x02) }
func TestReaderWriter(t *testing.T) { assert := assert.On(t) cache := buf.New() b := buf.NewLocal(256) b.AppendSupplier(serial.WriteString("abcd" + ENDING)) writer := NewHeaderWriter(b) err := writer.Write(cache) assert.Error(err).IsNil() assert.Int(cache.Len()).Equals(8) _, err = cache.Write([]byte{'e', 'f', 'g'}) assert.Error(err).IsNil() reader := &HeaderReader{} buffer, err := reader.Read(cache) assert.Error(err).IsNil() assert.Bytes(buffer.Bytes()).Equals([]byte{'e', 'f', 'g'}) }
func TestBufferedWriter(t *testing.T) { assert := assert.On(t) content := buf.New() writer := NewWriter(content) assert.Bool(writer.IsBuffered()).IsTrue() payload := make([]byte, 16) nBytes, err := writer.Write(payload) assert.Int(nBytes).Equals(16) assert.Error(err).IsNil() assert.Bool(content.IsEmpty()).IsTrue() writer.SetBuffered(false) assert.Int(content.Len()).Equals(16) }
func (v *UDPNameServer) BuildQueryA(domain string, id uint16) *buf.Buffer { msg := new(dns.Msg) msg.Id = id msg.RecursionDesired = true msg.Question = []dns.Question{ { Name: dns.Fqdn(domain), Qtype: dns.TypeA, Qclass: dns.ClassINET, }} buffer := buf.New() buffer.AppendSupplier(func(b []byte) (int, error) { writtenBuffer, err := msg.PackBuffer(b) return len(writtenBuffer), err }) return buffer }
func TestRequestSerialization(t *testing.T) { assert := assert.On(t) user := &protocol.User{ Level: 0, Email: "*****@*****.**", } account := &vmess.Account{ Id: uuid.New().String(), AlterId: 0, } user.Account = serial.ToTypedMessage(account) expectedRequest := &protocol.RequestHeader{ Version: 1, User: user, Command: protocol.RequestCommandTCP, Option: protocol.RequestOptionConnectionReuse, Address: v2net.DomainAddress("www.v2ray.com"), Port: v2net.Port(443), Security: protocol.Security(protocol.SecurityType_AES128_GCM), } buffer := buf.New() client := NewClientSession(protocol.DefaultIDHash) client.EncodeRequestHeader(expectedRequest, buffer) userValidator := vmess.NewTimedUserValidator(protocol.DefaultIDHash) userValidator.Add(user) server := NewServerSession(userValidator) actualRequest, err := server.DecodeRequestHeader(buffer) assert.Error(err).IsNil() assert.Byte(expectedRequest.Version).Equals(actualRequest.Version) assert.Byte(byte(expectedRequest.Command)).Equals(byte(actualRequest.Command)) assert.Byte(byte(expectedRequest.Option)).Equals(byte(actualRequest.Option)) assert.Address(expectedRequest.Address).Equals(actualRequest.Address) assert.Port(expectedRequest.Port).Equals(actualRequest.Port) assert.Byte(byte(expectedRequest.Security)).Equals(byte(actualRequest.Security)) }
func TestRequestHeader(t *testing.T) { assert := assert.On(t) factory := HttpAuthenticatorFactory{} auth := factory.Create(&Config{ Request: &RequestConfig{ Uri: []string{"/"}, Header: []*Header{ { Name: "Test", Value: []string{"Value"}, }, }, }, }).(HttpAuthenticator) cache := buf.New() err := auth.GetClientWriter().Write(cache) assert.Error(err).IsNil() assert.String(cache.String()).Equals("GET / HTTP/1.1\r\nTest: Value\r\n\r\n") }
func TestRequestHeader(t *testing.T) { assert := assert.On(t) auth, err := NewHttpAuthenticator(context.Background(), &Config{ Request: &RequestConfig{ Uri: []string{"/"}, Header: []*Header{ { Name: "Test", Value: []string{"Value"}, }, }, }, }) assert.Error(err).IsNil() cache := buf.New() err = auth.GetClientWriter().Write(cache) assert.Error(err).IsNil() assert.String(cache.String()).Equals("GET / HTTP/1.1\r\nTest: Value\r\n\r\n") }
func NewTestPacketDispatcher(handler func(destination v2net.Destination, traffic ray.OutboundRay)) *TestPacketDispatcher { if handler == nil { handler = func(destination v2net.Destination, traffic ray.OutboundRay) { for { payload, err := traffic.OutboundInput().Read() if err != nil { break } output := buf.New() output.Append([]byte("Processed: ")) output.Append(payload.Bytes()) payload.Release() traffic.OutboundOutput().Write(output) } traffic.OutboundOutput().Close() } } return &TestPacketDispatcher{ Destination: make(chan v2net.Destination), Handler: handler, } }
func TestTCPRequest(t *testing.T) { assert := assert.On(t) request := &protocol.RequestHeader{ Version: Version, Command: protocol.RequestCommandTCP, Address: v2net.LocalHostIP, Option: RequestOptionOneTimeAuth, Port: 1234, User: &protocol.User{ Email: "*****@*****.**", Account: serial.ToTypedMessage(&Account{ Password: "******", CipherType: CipherType_CHACHA20, }), }, } data := buf.NewLocal(256) data.AppendSupplier(serial.WriteString("test string")) cache := buf.New() writer, err := WriteTCPRequest(request, cache) assert.Error(err).IsNil() writer.Write(data) decodedRequest, reader, err := ReadTCPSession(request.User, cache) assert.Error(err).IsNil() assert.Address(decodedRequest.Address).Equals(request.Address) assert.Port(decodedRequest.Port).Equals(request.Port) decodedData, err := reader.Read() assert.Error(err).IsNil() assert.String(decodedData.String()).Equals("test string") }
func TestEmptyRequest(t *testing.T) { assert := assert.On(t) _, err := ReadRequest(buf.New()) assert.Error(err).Equals(io.EOF) }
func TestEmptyAuthRequest(t *testing.T) { assert := assert.On(t) _, _, err := ReadAuthentication(buf.New()) assert.Error(err).Equals(io.EOF) }