diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go index 6ca797110..e2ecf1ee1 100644 --- a/app/dns/nameserver.go +++ b/app/dns/nameserver.go @@ -103,7 +103,7 @@ func (v *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 { // Private: Visible for testing. func (v *UDPNameServer) HandleResponse(dest v2net.Destination, payload *alloc.Buffer) { msg := new(dns.Msg) - err := msg.Unpack(payload.Value) + err := msg.Unpack(payload.Bytes()) if err != nil { log.Warning("DNS: Failed to parse DNS response: ", err) return @@ -156,7 +156,7 @@ func (v *UDPNameServer) BuildQueryA(domain string, id uint16) *alloc.Buffer { Qclass: dns.ClassINET, }} - writtenBuffer, _ := msg.PackBuffer(buffer.Value) + writtenBuffer, _ := msg.PackBuffer(buffer.Bytes()) buffer.Slice(0, len(writtenBuffer)) return buffer diff --git a/common/alloc/buffer.go b/common/alloc/buffer.go index ec04189d5..f0b46b2de 100644 --- a/common/alloc/buffer.go +++ b/common/alloc/buffer.go @@ -117,11 +117,39 @@ func (b *Buffer) PrependHash(h hash.Hash) *Buffer { return b } +func (b *Buffer) Byte(index int) byte { + return b.Value[index] +} + // Bytes returns the content bytes of this Buffer. func (b *Buffer) Bytes() []byte { return b.Value } +func (b *Buffer) BytesRange(from, to int) []byte { + if from < 0 { + from += len(b.Value) + } + if to < 0 { + to += len(b.Value) + } + return b.Value[from:to] +} + +func (b *Buffer) BytesFrom(from int) []byte { + if from < 0 { + from += len(b.Value) + } + return b.Value[from:] +} + +func (b *Buffer) BytesTo(to int) []byte { + if to < 0 { + to += len(b.Value) + } + return b.Value[:to] +} + // Slice cuts the buffer at the given position. func (b *Buffer) Slice(from, to int) *Buffer { b.offset += from diff --git a/common/alloc/buffer_test.go b/common/alloc/buffer_test.go index 4785c8174..4c598ec73 100644 --- a/common/alloc/buffer_test.go +++ b/common/alloc/buffer_test.go @@ -43,10 +43,10 @@ func TestBufferPrepend(t *testing.T) { buffer.Prepend([]byte{'x', 'y', 'z'}) assert.Int(buffer.Len()).Equals(6) - assert.Bytes(buffer.Value).Equals([]byte("xyzabc")) + assert.String(buffer.String()).Equals("xyzabc") buffer.Prepend([]byte{'u', 'v', 'w'}) - assert.Bytes(buffer.Value).Equals([]byte("uvwxyzabc")) + assert.String(buffer.String()).Equals("uvwxyzabc") } func TestBufferString(t *testing.T) { diff --git a/common/io/buffered_writer.go b/common/io/buffered_writer.go index 7899c4216..92bf84a16 100644 --- a/common/io/buffered_writer.go +++ b/common/io/buffered_writer.go @@ -87,7 +87,7 @@ func (v *BufferedWriter) Flush() error { func (v *BufferedWriter) FlushWithoutLock() error { defer v.buffer.Clear() for !v.buffer.IsEmpty() { - nBytes, err := v.writer.Write(v.buffer.Value) + nBytes, err := v.writer.Write(v.buffer.Bytes()) if err != nil { return err } diff --git a/common/io/buffered_writer_test.go b/common/io/buffered_writer_test.go index 8013de3ba..9907578c3 100644 --- a/common/io/buffered_writer_test.go +++ b/common/io/buffered_writer_test.go @@ -49,5 +49,5 @@ func TestBufferedWriterLargePayload(t *testing.T) { nBytes, err = writer.Write(payload[1024:]) assert.Error(err).IsNil() assert.Int(nBytes).Equals(63 * 1024) - assert.Bytes(content.Value).Equals(payload) + assert.Bytes(content.Bytes()).Equals(payload) } diff --git a/common/io/writer.go b/common/io/writer.go index fd469ae45..9d8a78e3d 100644 --- a/common/io/writer.go +++ b/common/io/writer.go @@ -30,7 +30,7 @@ func NewAdaptiveWriter(writer io.Writer) *AdaptiveWriter { func (v *AdaptiveWriter) Write(buffer *alloc.Buffer) error { defer buffer.Release() for !buffer.IsEmpty() { - nBytes, err := v.writer.Write(buffer.Value) + nBytes, err := v.writer.Write(buffer.Bytes()) if err != nil { return err } diff --git a/common/io/writer_test.go b/common/io/writer_test.go index cd1a44e7e..d4c117608 100644 --- a/common/io/writer_test.go +++ b/common/io/writer_test.go @@ -13,8 +13,8 @@ import ( func TestAdaptiveWriter(t *testing.T) { assert := assert.On(t) - lb := alloc.NewBuffer() - rand.Read(lb.Value) + lb := alloc.NewBuffer().Clear() + lb.FillFrom(rand.Reader) writeBuffer := make([]byte, 0, 1024*1024) diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index dad683225..e1635a780 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -126,7 +126,7 @@ func (v *DokodemoDoor) handleUDPResponse(dest v2net.Destination, payload *alloc. if !v.accepting { return } - v.udpHub.WriteTo(payload.Value, dest) + v.udpHub.WriteTo(payload.Bytes(), dest) } func (v *DokodemoDoor) ListenTCP() error { diff --git a/proxy/freedom/freedom.go b/proxy/freedom/freedom.go index 6fdbe7919..bc94966d3 100644 --- a/proxy/freedom/freedom.go +++ b/proxy/freedom/freedom.go @@ -96,7 +96,7 @@ func (v *FreedomConnection) Dispatch(destination v2net.Destination, payload *all output := ray.OutboundOutput() if !payload.IsEmpty() { - conn.Write(payload.Value) + conn.Write(payload.Bytes()) } go func() { diff --git a/proxy/freedom/freedom_test.go b/proxy/freedom/freedom_test.go index 3aa2217d8..c005fe5d5 100644 --- a/proxy/freedom/freedom_test.go +++ b/proxy/freedom/freedom_test.go @@ -54,7 +54,7 @@ func TestSinglePacket(t *testing.T) { respPayload, err := traffic.InboundOutput().Read() assert.Error(err).IsNil() - assert.Bytes(respPayload.Value).Equals([]byte("Processed: Data to be sent to remote")) + assert.String(respPayload.String()).Equals("Processed: Data to be sent to remote") tcpServer.Close() } diff --git a/proxy/shadowsocks/ota.go b/proxy/shadowsocks/ota.go index 6729800d9..15698a175 100644 --- a/proxy/shadowsocks/ota.go +++ b/proxy/shadowsocks/ota.go @@ -72,26 +72,26 @@ func (v *ChunkReader) Release() { func (v *ChunkReader) Read() (*alloc.Buffer, error) { buffer := alloc.NewBuffer() - if _, err := io.ReadFull(v.reader, buffer.Value[:2]); err != nil { + if _, err := io.ReadFull(v.reader, buffer.BytesTo(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 + length := serial.BytesToUint16(buffer.BytesTo(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(v.reader, buffer.Value[:length]); err != nil { + if _, err := io.ReadFull(v.reader, buffer.BytesTo(int(length))); err != nil { buffer.Release() return nil, err } buffer.Slice(0, int(length)) - authBytes := buffer.Value[:AuthSize] - payload := buffer.Value[AuthSize:] + authBytes := buffer.BytesTo(AuthSize) + payload := buffer.BytesFrom(AuthSize) actualAuthBytes := v.auth.Authenticate(nil, payload) if !bytes.Equal(authBytes, actualAuthBytes) { @@ -123,7 +123,7 @@ func (v *ChunkWriter) Release() { func (v *ChunkWriter) Write(payload *alloc.Buffer) error { totalLength := payload.Len() payload.SliceBack(AuthSize) - v.auth.Authenticate(payload.Value[:0], payload.Value[AuthSize:]) + v.auth.Authenticate(payload.BytesTo(0), payload.BytesFrom(AuthSize)) payload.PrependUint16(uint16(totalLength)) _, err := v.writer.Write(payload.Bytes()) return err diff --git a/proxy/shadowsocks/ota_test.go b/proxy/shadowsocks/ota_test.go index 2b8015011..957bcbac5 100644 --- a/proxy/shadowsocks/ota_test.go +++ b/proxy/shadowsocks/ota_test.go @@ -17,10 +17,10 @@ func TestNormalChunkReading(t *testing.T) { []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}) + assert.Bytes(payload.Bytes()).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}) + assert.Bytes(payload.Bytes()).Equals([]byte{3, 4, 11, 12, 13, 14, 15, 16, 17, 18}) } func TestNormalChunkWriting(t *testing.T) { @@ -32,5 +32,5 @@ func TestNormalChunkWriting(t *testing.T) { err := writer.Write(alloc.NewLocalBuffer(256).Clear().Append([]byte{11, 12, 13, 14, 15, 16, 17, 18})) assert.Error(err).IsNil() - assert.Bytes(buffer.Value).Equals([]byte{0, 8, 39, 228, 69, 96, 133, 39, 254, 26, 201, 70, 11, 12, 13, 14, 15, 16, 17, 18}) + assert.Bytes(buffer.Bytes()).Equals([]byte{0, 8, 39, 228, 69, 96, 133, 39, 254, 26, 201, 70, 11, 12, 13, 14, 15, 16, 17, 18}) } diff --git a/proxy/shadowsocks/protocol.go b/proxy/shadowsocks/protocol.go index 45fc1bdc9..733cca732 100644 --- a/proxy/shadowsocks/protocol.go +++ b/proxy/shadowsocks/protocol.go @@ -32,12 +32,12 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea defer buffer.Release() ivLen := account.Cipher.IVSize() - _, err = io.ReadFull(reader, buffer.Value[:ivLen]) + _, err = io.ReadFull(reader, buffer.Bytes()[:ivLen]) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IV.") } - iv := append([]byte(nil), buffer.Value[:ivLen]...) + iv := append([]byte(nil), buffer.Bytes()[:ivLen]...) stream, err := account.Cipher.NewDecodingStream(account.Key, iv) if err != nil { @@ -53,13 +53,13 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea } lenBuffer := 1 - _, err = io.ReadFull(reader, buffer.Value[:1]) + _, err = io.ReadFull(reader, buffer.Bytes()[:1]) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read address type.") } - addrType := (buffer.Value[0] & 0x0F) - if (buffer.Value[0] & 0x10) == 0x10 { + addrType := (buffer.Bytes()[0] & 0x0F) + if (buffer.Bytes()[0] & 0x10) == 0x10 { request.Option |= RequestOptionOneTimeAuth } @@ -73,52 +73,52 @@ func ReadTCPSession(user *protocol.User, reader io.Reader) (*protocol.RequestHea switch addrType { case AddrTypeIPv4: - _, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+4]) + _, err := io.ReadFull(reader, buffer.BytesRange(lenBuffer, lenBuffer+4)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IPv4 address.") } - request.Address = v2net.IPAddress(buffer.Value[lenBuffer : lenBuffer+4]) + request.Address = v2net.IPAddress(buffer.BytesRange(lenBuffer, lenBuffer+4)) lenBuffer += 4 case AddrTypeIPv6: - _, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+16]) + _, err := io.ReadFull(reader, buffer.BytesRange(lenBuffer, lenBuffer+16)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read IPv6 address.") } - request.Address = v2net.IPAddress(buffer.Value[lenBuffer : lenBuffer+16]) + request.Address = v2net.IPAddress(buffer.BytesRange(lenBuffer, lenBuffer+16)) lenBuffer += 16 case AddrTypeDomain: - _, err := io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+1]) + _, err := io.ReadFull(reader, buffer.BytesRange(lenBuffer, lenBuffer+1)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read domain lenth.") } - domainLength := int(buffer.Value[lenBuffer]) + domainLength := int(buffer.Bytes()[lenBuffer]) lenBuffer++ - _, err = io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+domainLength]) + _, err = io.ReadFull(reader, buffer.BytesRange(lenBuffer, lenBuffer+domainLength)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read domain.") } - request.Address = v2net.DomainAddress(string(buffer.Value[lenBuffer : lenBuffer+domainLength])) + request.Address = v2net.DomainAddress(string(buffer.BytesRange(lenBuffer, lenBuffer+domainLength))) lenBuffer += domainLength default: return nil, nil, errors.New("Shadowsocks|TCP: Unknown address type: ", addrType) } - _, err = io.ReadFull(reader, buffer.Value[lenBuffer:lenBuffer+2]) + _, err = io.ReadFull(reader, buffer.BytesRange(lenBuffer, lenBuffer+2)) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read port.") } - request.Port = v2net.PortFromBytes(buffer.Value[lenBuffer : lenBuffer+2]) + request.Port = v2net.PortFromBytes(buffer.BytesRange(lenBuffer, lenBuffer+2)) lenBuffer += 2 if request.Option.Has(RequestOptionOneTimeAuth) { - authBytes := buffer.Value[lenBuffer : lenBuffer+AuthSize] + authBytes := buffer.BytesRange(lenBuffer, lenBuffer+AuthSize) _, err = io.ReadFull(reader, authBytes) if err != nil { return nil, nil, errors.Base(err).Message("Shadowsocks|TCP: Failed to read OTA.") } - actualAuth := authenticator.Authenticate(nil, buffer.Value[0:lenBuffer]) + actualAuth := authenticator.Authenticate(nil, buffer.BytesTo(lenBuffer)) if !bytes.Equal(actualAuth, authBytes) { return nil, nil, errors.New("Shadowsocks|TCP: Invalid OTA") } @@ -175,7 +175,7 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (v2io.Wr header.AppendUint16(uint16(request.Port)) if request.Option.Has(RequestOptionOneTimeAuth) { - header.Value[0] |= 0x10 + header.Bytes()[0] |= 0x10 authenticator := NewAuthenticator(HeaderKeyGenerator(account.Key, iv)) header.Value = authenticator.Authenticate(header.Value, header.Value) diff --git a/proxy/shadowsocks/protocol_test.go b/proxy/shadowsocks/protocol_test.go index cb4614466..3a3f7c3d1 100644 --- a/proxy/shadowsocks/protocol_test.go +++ b/proxy/shadowsocks/protocol_test.go @@ -35,7 +35,7 @@ func TestUDPEncoding(t *testing.T) { decodedRequest, decodedData, err := DecodeUDPPacket(request.User, encodedData) assert.Error(err).IsNil() - assert.Bytes(decodedData.Value).Equals(data.Value) + assert.Bytes(decodedData.Bytes()).Equals(data.Bytes()) assert.Address(decodedRequest.Address).Equals(request.Address) assert.Port(decodedRequest.Port).Equals(request.Port) } @@ -73,7 +73,7 @@ func TestTCPRequest(t *testing.T) { decodedData, err := reader.Read() assert.Error(err).IsNil() - assert.Bytes(decodedData.Value).Equals([]byte("test string")) + assert.String(decodedData.String()).Equals("test string") } func TestUDPReaderWriter(t *testing.T) { diff --git a/proxy/shadowsocks/server.go b/proxy/shadowsocks/server.go index e2a208982..44d811f6e 100644 --- a/proxy/shadowsocks/server.go +++ b/proxy/shadowsocks/server.go @@ -139,7 +139,7 @@ func (v *Server) handlerUDPPayload(payload *alloc.Buffer, session *proxy.Session } defer data.Release() - v.udpHub.WriteTo(data.Value, source) + v.udpHub.WriteTo(data.Bytes(), source) }) } diff --git a/proxy/socks/protocol/socks_test.go b/proxy/socks/protocol/socks_test.go index c61983f07..5f800bd5d 100644 --- a/proxy/socks/protocol/socks_test.go +++ b/proxy/socks/protocol/socks_test.go @@ -95,7 +95,7 @@ func TestResponseWrite(t *testing.T) { 0x72, 0x72, 0x72, 0x72, byte(0x00), byte(0x035), } - assert.Bytes(buffer.Value).Equals(expectedBytes) + assert.Bytes(buffer.Bytes()).Equals(expectedBytes) } func TestSetIPv6(t *testing.T) { @@ -107,7 +107,7 @@ func TestSetIPv6(t *testing.T) { buffer := alloc.NewLocalBuffer(2048).Clear() defer buffer.Release() response.Write(buffer) - assert.Bytes(buffer.Value).Equals([]byte{ + assert.Bytes(buffer.Bytes()).Equals([]byte{ socksVersion, 0, 0, AddrTypeIPv6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 0}) } @@ -120,7 +120,7 @@ func TestSetDomain(t *testing.T) { buffer := alloc.NewLocalBuffer(2048).Clear() defer buffer.Release() response.Write(buffer) - assert.Bytes(buffer.Value).Equals([]byte{ + assert.Bytes(buffer.Bytes()).Equals([]byte{ socksVersion, 0, 0, AddrTypeDomain, 9, 118, 50, 114, 97, 121, 46, 99, 111, 109, 0, 0}) }