func TestSingleIO(t *testing.T) { assert := assert.On(t) content := bytes.NewBuffer(make([]byte, 0, 1024*1024)) writer := NewAuthChunkWriter(v2io.NewAdaptiveWriter(content)) writer.Write(alloc.NewBuffer().Clear().AppendString("abcd")) writer.Write(alloc.NewBuffer().Clear()) writer.Release() reader := NewAuthChunkReader(content) buffer, err := reader.Read() assert.Error(err).IsNil() assert.Bytes(buffer.Value).Equals([]byte("abcd")) }
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: loader.NewTypedSettings(&Account{ Password: "******", CipherType: CipherType_CHACHA20, }), }, } data := alloc.NewLocalBuffer(256).Clear().AppendString("test string") cache := alloc.NewBuffer().Clear() 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.Bytes(decodedData.Value).Equals([]byte("test string")) }
func NewBufferedWriter(rawWriter io.Writer) *BufferedWriter { return &BufferedWriter{ writer: rawWriter, buffer: alloc.NewBuffer().Clear(), cached: true, } }
func (this *ChainWriter) Write(payload []byte) (int, error) { this.Lock() defer this.Unlock() if this.writer == nil { return 0, io.ErrClosedPipe } bytesWritten := 0 size := len(payload) for size > 0 { buffer := alloc.NewBuffer().Clear() if size > alloc.BufferSize { buffer.Append(payload[:alloc.BufferSize]) size -= alloc.BufferSize payload = payload[alloc.BufferSize:] bytesWritten += alloc.BufferSize } else { buffer.Append(payload) bytesWritten += size size = 0 } err := this.writer.Write(buffer) if err != nil { return bytesWritten, err } } return bytesWritten, nil }
func TestZeroAuthenticationMethod(t *testing.T) { assert := assert.On(t) buffer := alloc.NewBuffer().Clear().AppendBytes(5, 0) _, _, err := ReadAuthentication(buffer) assert.Error(err).Equals(proxy.ErrInvalidAuthentication) }
func (this *ChunkReader) Read() (*alloc.Buffer, error) { buffer := alloc.NewBuffer() if _, err := io.ReadFull(this.reader, buffer.Value[: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.Value[:2]) + AuthSize if length > alloc.BufferSize { // Theoretically the size of a chunk is 64K, but most Shadowsocks implementations used <4K buffer. buffer.Release() buffer = alloc.NewLocalBuffer(int(length) + 128) } if _, err := io.ReadFull(this.reader, buffer.Value[:length]); err != nil { buffer.Release() return nil, err } buffer.Slice(0, int(length)) authBytes := buffer.Value[:AuthSize] payload := buffer.Value[AuthSize:] actualAuthBytes := this.auth.Authenticate(nil, payload) if !bytes.Equal(authBytes, actualAuthBytes) { buffer.Release() return nil, errors.New("Shadowsocks|AuthenticationReader: Invalid auth.") } buffer.SliceFrom(AuthSize) return buffer, nil }
func TestSwitchAccount(t *testing.T) { assert := assert.On(t) sa := &protocol.CommandSwitchAccount{ Port: 1234, ID: uuid.New(), AlterIds: 1024, Level: 128, ValidMin: 16, } buffer := alloc.NewBuffer().Clear() err := MarshalCommand(sa, buffer) assert.Error(err).IsNil() cmd, err := UnmarshalCommand(1, buffer.Value[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 TestWrongProtocolVersion(t *testing.T) { assert := assert.On(t) buffer := alloc.NewBuffer().Clear().AppendBytes(6, 1, 0) _, _, err := ReadAuthentication(buffer) assert.Error(err).Equals(proxy.ErrInvalidProtocolVersion) }
func TestBufferedReader(t *testing.T) { assert := assert.On(t) content := alloc.NewLargeBuffer() len := content.Len() reader := NewBufferedReader(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) reader.SetCached(false) payload2 := alloc.NewBuffer() reader.Read(payload2.Value) assert.Int(content.Len()).Equals(len2) reader.Read(payload2.Value) assert.Int(content.Len()).LessThan(len2) }
func NewBufferedReader(rawReader io.Reader) *BufferedReader { return &BufferedReader{ reader: rawReader, buffer: alloc.NewBuffer().Clear(), cached: true, } }
func TestIPv6Request(t *testing.T) { assert := assert.On(t) request, err := ReadRequest(alloc.NewBuffer().Clear().AppendBytes(5, 1, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 0, 8)) 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 TestAuthenticate(t *testing.T) { assert := assert.On(t) buffer := alloc.NewBuffer().Clear() buffer.AppendBytes(1, 2, 3, 4) Authenticate(buffer) assert.Bytes(buffer.Value).Equals([]byte{0, 8, 87, 52, 168, 125, 1, 2, 3, 4}) b2, err := NewAuthChunkReader(buffer).Read() assert.Error(err).IsNil() assert.Bytes(b2.Value).Equals([]byte{1, 2, 3, 4}) }
func TestUDPReaderWriter(t *testing.T) { assert := assert.On(t) user := &protocol.User{ Account: loader.NewTypedSettings(&Account{ Password: "******", CipherType: CipherType_CHACHA20_IEFT, }), } cache := alloc.NewBuffer().Clear() 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, } err := writer.Write(alloc.NewBuffer().Clear().AppendString("test payload")) assert.Error(err).IsNil() payload, err := reader.Read() assert.Error(err).IsNil() assert.String(payload.String()).Equals("test payload") err = writer.Write(alloc.NewBuffer().Clear().AppendString("test payload 2")) assert.Error(err).IsNil() payload, err = reader.Read() assert.Error(err).IsNil() assert.String(payload.String()).Equals("test payload 2") }
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 := alloc.NewBuffer().Clear() finished := false for { _, err := response.FillFrom(conn) assert.Error(err).IsNil() if err != nil { break } if response.String() == "Processed: "+payload { finished = true break } } assert.Bool(finished).IsTrue() conn.Close() } CloseAllServers() }
func NewBuffer() *Buffer { b := &Buffer{ next: 0, released: 0, hold: true, buffer: alloc.NewBuffer(), } for idx := range b.distro { content := b.buffer.Value[idx*DistroSize : (idx+1)*DistroSize] b.distro[idx] = alloc.CreateBuffer(content, b) } return b }
func TestAdaptiveWriter(t *testing.T) { assert := assert.On(t) lb := alloc.NewBuffer() rand.Read(lb.Value) writeBuffer := make([]byte, 0, 1024*1024) writer := NewAdaptiveWriter(NewBufferedWriter(bytes.NewBuffer(writeBuffer))) err := writer.Write(lb) assert.Error(err).IsNil() assert.Bytes(lb.Bytes()).Equals(writeBuffer) }
func TestHTTPResponse(t *testing.T) { assert := assert.On(t) buffer := alloc.NewBuffer().Clear() httpResponse := new(HTTPResponse) httpResponse.WriteTo(v2io.NewAdaptiveWriter(buffer)) reader := bufio.NewReader(buffer) response, err := http.ReadResponse(reader, nil) assert.Error(err).IsNil() assert.Int(response.StatusCode).Equals(403) }
func TestReaderWriter(t *testing.T) { assert := assert.On(t) cache := alloc.NewBuffer() writer := NewHeaderWriter(alloc.NewLocalBuffer(256).Clear().AppendString("abcd" + ENDING)) writer.Write(cache) cache.Write([]byte{'e', 'f', 'g'}) reader := &HeaderReader{} buffer, err := reader.Read(cache) assert.Error(err).IsNil() assert.Bytes(buffer.Value).Equals([]byte{'e', 'f', 'g'}) }
func TestNormalChunkReading(t *testing.T) { assert := assert.On(t) buffer := alloc.NewBuffer().Clear().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.Value).Equals([]byte{11, 12, 13, 14, 15, 16, 17, 18}) payload.PrependBytes(3, 4) assert.Bytes(payload.Value).Equals([]byte{3, 4, 11, 12, 13, 14, 15, 16, 17, 18}) }
func TestAuthenticationRequestRead(t *testing.T) { assert := assert.On(t) buffer := alloc.NewBuffer().Clear().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 TestLargeIO(t *testing.T) { assert := assert.On(t) content := make([]byte, 1024*1024) rand.Read(content) chunckContent := bytes.NewBuffer(make([]byte, 0, len(content)*2)) writer := NewAuthChunkWriter(v2io.NewAdaptiveWriter(chunckContent)) writeSize := 0 for { chunkSize := 7 * 1024 if chunkSize+writeSize > len(content) { chunkSize = len(content) - writeSize } writer.Write(alloc.NewBuffer().Clear().Append(content[writeSize : writeSize+chunkSize])) writeSize += chunkSize if writeSize == len(content) { break } } writer.Write(alloc.NewBuffer().Clear()) writer.Release() actualContent := make([]byte, 0, len(content)) reader := NewAuthChunkReader(chunckContent) for { buffer, err := reader.Read() if err == io.EOF { break } assert.Error(err).IsNil() actualContent = append(actualContent, buffer.Value...) } assert.Int(len(actualContent)).Equals(len(content)) assert.Bytes(actualContent).Equals(content) }
func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) { if len(packet) < 5 { return nil, transport.ErrCorruptedPacket } request := new(Socks5UDPRequest) // packet[0] and packet[1] are reserved request.Fragment = packet[2] addrType := packet[3] var dataBegin int switch addrType { case AddrTypeIPv4: if len(packet) < 10 { return nil, transport.ErrCorruptedPacket } ip := packet[4:8] request.Port = v2net.PortFromBytes(packet[8:10]) request.Address = v2net.IPAddress(ip) dataBegin = 10 case AddrTypeIPv6: if len(packet) < 22 { return nil, transport.ErrCorruptedPacket } ip := packet[4:20] request.Port = v2net.PortFromBytes(packet[20:22]) request.Address = v2net.IPAddress(ip) dataBegin = 22 case AddrTypeDomain: domainLength := int(packet[4]) if len(packet) < 5+domainLength+2 { return nil, transport.ErrCorruptedPacket } domain := string(packet[5 : 5+domainLength]) request.Port = v2net.PortFromBytes(packet[5+domainLength : 5+domainLength+2]) request.Address = v2net.ParseAddress(domain) dataBegin = 5 + domainLength + 2 default: log.Warning("Unknown address type ", addrType) return nil, ErrorUnknownAddressType } if len(packet) > dataBegin { request.Data = alloc.NewBuffer().Clear().Append(packet[dataBegin:]) } return request, nil }
func ReadUDPRequest(packet []byte) (*Socks5UDPRequest, error) { if len(packet) < 5 { return nil, errors.New("Socks|UDP: Insufficient length of packet.") } request := new(Socks5UDPRequest) // packet[0] and packet[1] are reserved request.Fragment = packet[2] addrType := packet[3] var dataBegin int switch addrType { case AddrTypeIPv4: if len(packet) < 10 { return nil, errors.New("Socks|UDP: Insufficient length of packet.") } ip := packet[4:8] request.Port = v2net.PortFromBytes(packet[8:10]) request.Address = v2net.IPAddress(ip) dataBegin = 10 case AddrTypeIPv6: if len(packet) < 22 { return nil, errors.New("Socks|UDP: Insufficient length of packet.") } ip := packet[4:20] request.Port = v2net.PortFromBytes(packet[20:22]) request.Address = v2net.IPAddress(ip) dataBegin = 22 case AddrTypeDomain: domainLength := int(packet[4]) if len(packet) < 5+domainLength+2 { return nil, errors.New("Socks|UDP: Insufficient length of packet.") } domain := string(packet[5 : 5+domainLength]) request.Port = v2net.PortFromBytes(packet[5+domainLength : 5+domainLength+2]) request.Address = v2net.ParseAddress(domain) dataBegin = 5 + domainLength + 2 default: return nil, fmt.Errorf("Socks|UDP: Unknown address type %d", addrType) } if len(packet) > dataBegin { request.Data = alloc.NewBuffer().Clear().Append(packet[dataBegin:]) } return request, nil }
func (this *UDPNameServer) BuildQueryA(domain string, id uint16) *alloc.Buffer { buffer := alloc.NewBuffer() msg := new(dns.Msg) msg.Id = id msg.RecursionDesired = true msg.Question = []dns.Question{ { Name: dns.Fqdn(domain), Qtype: dns.TypeA, Qclass: dns.ClassINET, }} writtenBuffer, _ := msg.PackBuffer(buffer.Value) buffer.Slice(0, len(writtenBuffer)) return buffer }
func TestBufferedWriter(t *testing.T) { assert := assert.On(t) content := alloc.NewBuffer().Clear() writer := NewBufferedWriter(content) assert.Bool(writer.Cached()).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.SetCached(false) assert.Int(content.Len()).Equals(16) }
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 = loader.NewTypedSettings(account) expectedRequest := &protocol.RequestHeader{ Version: 1, User: user, Command: protocol.RequestCommandTCP, Option: protocol.RequestOption(0), Address: v2net.DomainAddress("www.v2ray.com"), Port: v2net.Port(443), } buffer := alloc.NewBuffer().Clear() 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) }
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 := alloc.NewBuffer().Clear() 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 (this *UDPHub) start() { this.Lock() this.accepting = true this.Unlock() oobBytes := make([]byte, 256) for this.Running() { buffer := alloc.NewBuffer() nBytes, noob, _, addr, err := ReadUDPMsg(this.conn, buffer.Value, oobBytes) if err != nil { log.Info("UDP|Hub: Failed to read UDP msg: ", err) buffer.Release() continue } buffer.Slice(0, nBytes) session := new(proxy.SessionInfo) session.Source = v2net.UDPDestination(v2net.IPAddress(addr.IP), v2net.Port(addr.Port)) if this.option.ReceiveOriginalDest && noob > 0 { session.Destination = RetrieveOriginalDest(oobBytes[:noob]) } go this.option.Callback(buffer, session) } }
func TestEmptyRequest(t *testing.T) { assert := assert.On(t) _, err := ReadRequest(alloc.NewBuffer().Clear()) assert.Error(err).Equals(io.EOF) }
func TestEmptyAuthRequest(t *testing.T) { assert := assert.On(t) _, _, err := ReadAuthentication(alloc.NewBuffer().Clear()) assert.Error(err).Equals(io.EOF) }