diff --git a/app/router/condition_geoip.go b/app/router/condition_geoip.go index 3627190e9..0d508dfd4 100644 --- a/app/router/condition_geoip.go +++ b/app/router/condition_geoip.go @@ -1,10 +1,10 @@ package router import ( + "encoding/binary" "sort" "v2ray.com/core/common/net" - "v2ray.com/core/common/serial" ) type ipv6 struct { @@ -63,12 +63,12 @@ func (m *GeoIPMatcher) Init(cidrs []*CIDR) error { prefix := uint8(cidr.Prefix) switch len(ip) { case 4: - m.ip4 = append(m.ip4, normalize4(serial.BytesToUint32(ip), prefix)) + m.ip4 = append(m.ip4, normalize4(binary.BigEndian.Uint32(ip), prefix)) m.prefix4 = append(m.prefix4, prefix) case 16: ip6 := ipv6{ - a: serial.BytesToUint64(ip[0:8]), - b: serial.BytesToUint64(ip[8:16]), + a: binary.BigEndian.Uint64(ip[0:8]), + b: binary.BigEndian.Uint64(ip[8:16]), } ip6 = normalize6(ip6, prefix) @@ -147,11 +147,11 @@ func (m *GeoIPMatcher) match6(ip ipv6) bool { func (m *GeoIPMatcher) Match(ip net.IP) bool { switch len(ip) { case 4: - return m.match4(serial.BytesToUint32(ip)) + return m.match4(binary.BigEndian.Uint32(ip)) case 16: return m.match6(ipv6{ - a: serial.BytesToUint64(ip[0:8]), - b: serial.BytesToUint64(ip[8:16]), + a: binary.BigEndian.Uint64(ip[0:8]), + b: binary.BigEndian.Uint64(ip[8:16]), }) default: return false diff --git a/common/crypto/chunk.go b/common/crypto/chunk.go index 322548025..6fb037a85 100755 --- a/common/crypto/chunk.go +++ b/common/crypto/chunk.go @@ -1,6 +1,7 @@ package crypto import ( + "encoding/binary" "io" "v2ray.com/core/common" @@ -36,7 +37,7 @@ func (PlainChunkSizeParser) Encode(size uint16, b []byte) []byte { } func (PlainChunkSizeParser) Decode(b []byte) (uint16, error) { - return serial.BytesToUint16(b), nil + return binary.BigEndian.Uint16(b), nil } type AEADChunkSizeParser struct { @@ -59,7 +60,7 @@ func (p *AEADChunkSizeParser) Decode(b []byte) (uint16, error) { if err != nil { return 0, err } - return serial.BytesToUint16(b) + uint16(p.Auth.Overhead()), nil + return binary.BigEndian.Uint16(b) + uint16(p.Auth.Overhead()), nil } type ChunkStreamReader struct { diff --git a/common/mux/frame.go b/common/mux/frame.go index 5bfed2f43..495e39b79 100644 --- a/common/mux/frame.go +++ b/common/mux/frame.go @@ -9,7 +9,6 @@ import ( "v2ray.com/core/common/buf" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" - "v2ray.com/core/common/serial" "v2ray.com/core/common/vio" ) @@ -92,7 +91,7 @@ func (f FrameMetadata) WriteTo(b *buf.Buffer) error { // Unmarshal reads FrameMetadata from the given reader. func (f *FrameMetadata) Unmarshal(reader io.Reader) error { - metaLen, err := serial.ReadUint16(reader) + metaLen, err := vio.ReadUint16(reader) if err != nil { return err } @@ -116,7 +115,7 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error { return newError("insufficient buffer: ", b.Len()) } - f.SessionID = serial.BytesToUint16(b.BytesTo(2)) + f.SessionID = binary.BigEndian.Uint16(b.BytesTo(2)) f.SessionStatus = SessionStatus(b.Byte(2)) f.Option = bitmask.Byte(b.Byte(3)) f.Target.Network = net.Network_Unknown diff --git a/common/mux/reader.go b/common/mux/reader.go index d9ace3dbf..b6def6892 100644 --- a/common/mux/reader.go +++ b/common/mux/reader.go @@ -5,7 +5,7 @@ import ( "v2ray.com/core/common/buf" "v2ray.com/core/common/crypto" - "v2ray.com/core/common/serial" + "v2ray.com/core/common/vio" ) // PacketReader is an io.Reader that reads whole chunk of Mux frames every time. @@ -28,7 +28,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) { return nil, io.EOF } - size, err := serial.ReadUint16(r.reader) + size, err := vio.ReadUint16(r.reader) if err != nil { return nil, err } diff --git a/common/net/port.go b/common/net/port.go index 5882da05a..3594ca0d2 100644 --- a/common/net/port.go +++ b/common/net/port.go @@ -1,6 +1,7 @@ package net import ( + "encoding/binary" "strconv" "v2ray.com/core/common/serial" @@ -12,7 +13,7 @@ type Port uint16 // PortFromBytes converts a byte array to a Port, assuming bytes are in big endian order. // @unsafe Caller must ensure that the byte array has at least 2 elements. func PortFromBytes(port []byte) Port { - return Port(serial.BytesToUint16(port)) + return Port(binary.BigEndian.Uint16(port)) } // PortFromInt converts an integer to a Port. diff --git a/common/protocol/tls/sniff.go b/common/protocol/tls/sniff.go index 784f2a519..85ca4820f 100644 --- a/common/protocol/tls/sniff.go +++ b/common/protocol/tls/sniff.go @@ -1,11 +1,11 @@ package tls import ( + "encoding/binary" "errors" "strings" "v2ray.com/core/common" - "v2ray.com/core/common/serial" ) type SniffHeader struct { @@ -133,7 +133,7 @@ func SniffTLS(b []byte) (*SniffHeader, error) { if !IsValidTLSVersion(b[1], b[2]) { return nil, errNotTLS } - headerLen := int(serial.BytesToUint16(b[3:5])) + headerLen := int(binary.BigEndian.Uint16(b[3:5])) if 5+headerLen > len(b) { return nil, common.ErrNoClue } diff --git a/common/serial/bytes.go b/common/serial/bytes.go deleted file mode 100755 index 3ed65ee50..000000000 --- a/common/serial/bytes.go +++ /dev/null @@ -1,77 +0,0 @@ -package serial - -import "encoding/hex" - -// ByteToHexString converts a byte into hex string. -func ByteToHexString(value byte) string { - return hex.EncodeToString([]byte{value}) -} - -// BytesToUint16 deserializes a byte array to a uint16 in big endian order. The byte array must have at least 2 elements. -func BytesToUint16(value []byte) uint16 { - _ = value[1] // bounds check hint to compiler; see golang.org/issue/14808 - return uint16(value[0])<<8 | uint16(value[1]) -} - -// BytesToUint32 deserializes a byte array to a uint32 in big endian order. The byte array must have at least 4 elements. -func BytesToUint32(value []byte) uint32 { - _ = value[3] - return uint32(value[0])<<24 | - uint32(value[1])<<16 | - uint32(value[2])<<8 | - uint32(value[3]) -} - -// BytesToInt deserializes a bytes array (of at leat 4 bytes) to an int in big endian order. -func BytesToInt(value []byte) int { - _ = value[3] - return int(value[0])<<24 | - int(value[1])<<16 | - int(value[2])<<8 | - int(value[3]) -} - -// BytesToInt64 deserializes a byte array to an int64 in big endian order. The byte array must have at least 8 elements. -func BytesToInt64(value []byte) int64 { - _ = value[7] - return int64(value[0])<<56 | - int64(value[1])<<48 | - int64(value[2])<<40 | - int64(value[3])<<32 | - int64(value[4])<<24 | - int64(value[5])<<16 | - int64(value[6])<<8 | - int64(value[7]) -} - -func BytesToUint64(value []byte) uint64 { - _ = value[7] - return uint64(value[0])<<56 | - uint64(value[1])<<48 | - uint64(value[2])<<40 | - uint64(value[3])<<32 | - uint64(value[4])<<24 | - uint64(value[5])<<16 | - uint64(value[6])<<8 | - uint64(value[7]) -} - -// BytesToHexString converts a byte array into hex string. -func BytesToHexString(value []byte) string { - m := hex.EncodedLen(len(value)) - if m == 0 { - return "[]" - } - n := 1 + m + m/2 - b := make([]byte, n) - hex.Encode(b[1:], value) - b[0] = '[' - for i, j := n-3, m-2+1; i > 0; i -= 3 { - b[i+2] = ',' - b[i+1] = b[j+1] - b[i] = b[j] - j -= 2 - } - b[n-1] = ']' - return string(b) -} diff --git a/common/serial/bytes_test.go b/common/serial/bytes_test.go deleted file mode 100644 index 65245f9e0..000000000 --- a/common/serial/bytes_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package serial_test - -import ( - "testing" - - . "v2ray.com/core/common/serial" - . "v2ray.com/ext/assert" -) - -func TestBytesToHex(t *testing.T) { - assert := With(t) - - cases := []struct { - input []byte - output string - }{ - {input: []byte{}, output: "[]"}, - {input: []byte("a"), output: "[61]"}, - {input: []byte("abcd"), output: "[61,62,63,64]"}, - {input: []byte(";kdfpa;dfkaepr3ira;dlkvn;vopaehra;dkhf"), output: "[3b,6b,64,66,70,61,3b,64,66,6b,61,65,70,72,33,69,72,61,3b,64,6c,6b,76,6e,3b,76,6f,70,61,65,68,72,61,3b,64,6b,68,66]"}, - } - - for _, test := range cases { - assert(test.output, Equals, BytesToHexString(test.input)) - } -} - -func TestInt64(t *testing.T) { - assert := With(t) - - x := int64(375134875348) - b := Int64ToBytes(x, []byte{}) - v := BytesToInt64(b) - assert(x, Equals, v) -} diff --git a/common/serial/numbers.go b/common/serial/numbers.go index a4473ddeb..a255c71be 100755 --- a/common/serial/numbers.go +++ b/common/serial/numbers.go @@ -1,7 +1,6 @@ package serial import "strconv" -import "io" // Uint16ToBytes serializes a uint16 into bytes in big endian order. func Uint16ToBytes(value uint16, b []byte) []byte { @@ -12,14 +11,6 @@ func Uint16ToString(value uint16) string { return strconv.Itoa(int(value)) } -func ReadUint16(reader io.Reader) (uint16, error) { - var b [2]byte - if _, err := io.ReadFull(reader, b[:]); err != nil { - return 0, err - } - return BytesToUint16(b[:]), nil -} - func Uint32ToBytes(value uint32, b []byte) []byte { return append(b, byte(value>>24), byte(value>>16), byte(value>>8), byte(value)) } @@ -35,14 +26,6 @@ func WriteUint32(value uint32) func([]byte) (int, error) { } } -func IntToBytes(value int, b []byte) []byte { - return append(b, byte(value>>24), byte(value>>16), byte(value>>8), byte(value)) -} - -func IntToString(value int) string { - return Int64ToString(int64(value)) -} - func Int64ToBytes(value int64, b []byte) []byte { return append(b, byte(value>>56), diff --git a/common/serial/string.go b/common/serial/string.go index 509c324ad..c8e0144ce 100644 --- a/common/serial/string.go +++ b/common/serial/string.go @@ -20,8 +20,6 @@ func ToString(v interface{}) string { return value.String() case error: return value.Error() - case []byte: - return BytesToHexString(value) default: return fmt.Sprintf("%+v", value) } diff --git a/common/vio/serial.go b/common/vio/serial.go index 7dcfa36a5..f3180ee70 100644 --- a/common/vio/serial.go +++ b/common/vio/serial.go @@ -11,6 +11,14 @@ func WriteUint32(writer io.Writer, value uint32) (int, error) { return writer.Write(b[:]) } +func ReadUint16(reader io.Reader) (uint16, error) { + var b [2]byte + if _, err := io.ReadFull(reader, b[:]); err != nil { + return 0, err + } + return binary.BigEndian.Uint16(b[:]), nil +} + func WriteUint16(writer io.Writer, value uint16) (int, error) { var b [2]byte binary.BigEndian.PutUint16(b[:], value) diff --git a/proxy/shadowsocks/ota.go b/proxy/shadowsocks/ota.go index c0d101873..4e4b1a0f9 100644 --- a/proxy/shadowsocks/ota.go +++ b/proxy/shadowsocks/ota.go @@ -4,12 +4,14 @@ import ( "bytes" "crypto/hmac" "crypto/sha1" + "encoding/binary" "io" "v2ray.com/core/common" "v2ray.com/core/common/buf" "v2ray.com/core/common/bytespool" "v2ray.com/core/common/serial" + "v2ray.com/core/common/vio" ) const ( @@ -48,11 +50,11 @@ func HeaderKeyGenerator(key []byte, iv []byte) func() []byte { } func ChunkKeyGenerator(iv []byte) func() []byte { - chunkID := 0 + chunkID := uint32(0) return func() []byte { - newKey := make([]byte, 0, len(iv)+4) - newKey = append(newKey, iv...) - newKey = serial.IntToBytes(chunkID, newKey) + newKey := make([]byte, len(iv)+4) + copy(newKey, iv) + binary.BigEndian.PutUint32(newKey[len(iv):], newKey) chunkID++ return newKey } @@ -71,7 +73,7 @@ func NewChunkReader(reader io.Reader, auth *Authenticator) *ChunkReader { } func (v *ChunkReader) ReadMultiBuffer() (buf.MultiBuffer, error) { - size, err := serial.ReadUint16(v.reader) + size, err := vio.ReadUint16(v.reader) if err != nil { return nil, newError("failed to read size") } diff --git a/proxy/vmess/encoding/auth.go b/proxy/vmess/encoding/auth.go index dc668d879..49df46b33 100644 --- a/proxy/vmess/encoding/auth.go +++ b/proxy/vmess/encoding/auth.go @@ -2,6 +2,7 @@ package encoding import ( "crypto/md5" + "encoding/binary" "hash/fnv" "v2ray.com/core/common" @@ -59,7 +60,7 @@ func (*FnvAuthenticator) Seal(dst, nonce, plaintext, additionalData []byte) []by // Open implements AEAD.Open(). func (*FnvAuthenticator) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { - if serial.BytesToUint32(ciphertext[:4]) != Authenticate(ciphertext[4:]) { + if binary.BigEndian.Uint32(ciphertext[:4]) != Authenticate(ciphertext[4:]) { return dst, newError("invalid authentication") } return append(dst, ciphertext[4:]...), nil @@ -94,12 +95,12 @@ func (*ShakeSizeParser) SizeBytes() int32 { func (s *ShakeSizeParser) next() uint16 { common.Must2(s.shake.Read(s.buffer[:])) - return serial.BytesToUint16(s.buffer[:]) + return binary.BigEndian.Uint16(s.buffer[:]) } func (s *ShakeSizeParser) Decode(b []byte) (uint16, error) { mask := s.next() - size := serial.BytesToUint16(b) + size := binary.BigEndian.Uint16(b) return mask ^ size, nil } diff --git a/proxy/vmess/encoding/commands.go b/proxy/vmess/encoding/commands.go index f3e7ef659..261e47167 100644 --- a/proxy/vmess/encoding/commands.go +++ b/proxy/vmess/encoding/commands.go @@ -1,6 +1,7 @@ package encoding import ( + "encoding/binary" "io" "v2ray.com/core/common" @@ -57,7 +58,7 @@ func UnmarshalCommand(cmdID byte, data []byte) (protocol.ResponseCommand, error) return nil, newError("insufficient length") } expectedAuth := Authenticate(data[4:]) - actualAuth := serial.BytesToUint32(data[:4]) + actualAuth := binary.BigEndian.Uint32(data[:4]) if expectedAuth != actualAuth { return nil, newError("invalid auth") } @@ -134,7 +135,7 @@ func (f *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error if len(data) < alterIDStart+2 { return nil, newError("insufficient length.") } - cmd.AlterIds = serial.BytesToUint16(data[alterIDStart : alterIDStart+2]) + cmd.AlterIds = binary.BigEndian.Uint16(data[alterIDStart : alterIDStart+2]) levelStart := alterIDStart + 2 if len(data) < levelStart+1 { return nil, newError("insufficient length.") diff --git a/proxy/vmess/encoding/server.go b/proxy/vmess/encoding/server.go index c95673e0e..f185fb47d 100644 --- a/proxy/vmess/encoding/server.go +++ b/proxy/vmess/encoding/server.go @@ -2,6 +2,7 @@ package encoding import ( "crypto/md5" + "encoding/binary" "hash/fnv" "io" "sync" @@ -15,7 +16,6 @@ import ( "v2ray.com/core/common/crypto" "v2ray.com/core/common/net" "v2ray.com/core/common/protocol" - "v2ray.com/core/common/serial" "v2ray.com/core/common/task" "v2ray.com/core/proxy/vmess" ) @@ -191,7 +191,7 @@ func (s *ServerSession) DecodeRequestHeader(reader io.Reader) (*protocol.Request fnv1a := fnv.New32a() common.Must2(fnv1a.Write(buffer.BytesTo(-4))) actualHash := fnv1a.Sum32() - expectedHash := serial.BytesToUint32(buffer.BytesFrom(-4)) + expectedHash := binary.BigEndian.Uint32(buffer.BytesFrom(-4)) if actualHash != expectedHash { return nil, newError("invalid auth") diff --git a/transport/internet/headers/wechat/wechat.go b/transport/internet/headers/wechat/wechat.go index 5baa3e853..86106b561 100644 --- a/transport/internet/headers/wechat/wechat.go +++ b/transport/internet/headers/wechat/wechat.go @@ -2,14 +2,14 @@ package wechat import ( "context" + "encoding/binary" "v2ray.com/core/common" "v2ray.com/core/common/dice" - "v2ray.com/core/common/serial" ) type VideoChat struct { - sn int + sn uint32 } func (vc *VideoChat) Size() int32 { @@ -19,16 +19,23 @@ func (vc *VideoChat) Size() int32 { // Write implements io.Writer. func (vc *VideoChat) Write(b []byte) (int, error) { vc.sn++ - b = append(b[:0], 0xa1, 0x08) - b = serial.IntToBytes(vc.sn, b) - b = append(b, 0x10, 0x11, 0x18, 0x30, 0x22, 0x30) + b[0] = 0xa1 + b[1] = 0x08 + binary.BigEndian.PutUint32(b[2:], vc.sn) // b[2:6] + b[6] = 0x00 + b[7] = 0x10 + b[8] = 0x11 + b[9] = 0x18 + b[10] = 0x30 + b[11] = 0x22 + b[12] = 0x30 return 13, nil } // NewVideoChat returns a new VideoChat instance based on given config. func NewVideoChat(ctx context.Context, config interface{}) (interface{}, error) { return &VideoChat{ - sn: int(dice.RollUint16()), + sn: uint32(dice.RollUint16()), }, nil } diff --git a/transport/internet/kcp/crypt.go b/transport/internet/kcp/crypt.go index 61d2677e6..028cc65cb 100644 --- a/transport/internet/kcp/crypt.go +++ b/transport/internet/kcp/crypt.go @@ -2,6 +2,7 @@ package kcp import ( "crypto/cipher" + "encoding/binary" "hash/fnv" "v2ray.com/core/common" @@ -63,11 +64,11 @@ func (a *SimpleAuthenticator) Open(dst, nonce, cipherText, extra []byte) ([]byte fnvHash := fnv.New32a() common.Must2(fnvHash.Write(dst[4:])) - if serial.BytesToUint32(dst[:4]) != fnvHash.Sum32() { + if binary.BigEndian.Uint32(dst[:4]) != fnvHash.Sum32() { return nil, newError("invalid auth") } - length := serial.BytesToUint16(dst[4:6]) + length := binary.BigEndian.Uint16(dst[4:6]) if len(dst)-6 != int(length) { return nil, newError("invalid auth") } diff --git a/transport/internet/kcp/segment.go b/transport/internet/kcp/segment.go index ce8ee09ca..22fdef723 100755 --- a/transport/internet/kcp/segment.go +++ b/transport/internet/kcp/segment.go @@ -1,6 +1,8 @@ package kcp import ( + "encoding/binary" + "v2ray.com/core/common/buf" "v2ray.com/core/common/serial" ) @@ -60,16 +62,16 @@ func (s *DataSegment) parse(conv uint16, cmd Command, opt SegmentOption, buf []b if len(buf) < 15 { return false, nil } - s.Timestamp = serial.BytesToUint32(buf) + s.Timestamp = binary.BigEndian.Uint32(buf) buf = buf[4:] - s.Number = serial.BytesToUint32(buf) + s.Number = binary.BigEndian.Uint32(buf) buf = buf[4:] - s.SendingNext = serial.BytesToUint32(buf) + s.SendingNext = binary.BigEndian.Uint32(buf) buf = buf[4:] - dataLen := int(serial.BytesToUint16(buf)) + dataLen := int(binary.BigEndian.Uint16(buf)) buf = buf[2:] if len(buf) < dataLen { @@ -147,13 +149,13 @@ func (s *AckSegment) parse(conv uint16, cmd Command, opt SegmentOption, buf []by return false, nil } - s.ReceivingWindow = serial.BytesToUint32(buf) + s.ReceivingWindow = binary.BigEndian.Uint32(buf) buf = buf[4:] - s.ReceivingNext = serial.BytesToUint32(buf) + s.ReceivingNext = binary.BigEndian.Uint32(buf) buf = buf[4:] - s.Timestamp = serial.BytesToUint32(buf) + s.Timestamp = binary.BigEndian.Uint32(buf) buf = buf[4:] count := int(buf[0]) @@ -163,7 +165,7 @@ func (s *AckSegment) parse(conv uint16, cmd Command, opt SegmentOption, buf []by return false, nil } for i := 0; i < count; i++ { - s.PutNumber(serial.BytesToUint32(buf)) + s.PutNumber(binary.BigEndian.Uint32(buf)) buf = buf[4:] } @@ -240,13 +242,13 @@ func (s *CmdOnlySegment) parse(conv uint16, cmd Command, opt SegmentOption, buf return false, nil } - s.SendingNext = serial.BytesToUint32(buf) + s.SendingNext = binary.BigEndian.Uint32(buf) buf = buf[4:] - s.ReceivingNext = serial.BytesToUint32(buf) + s.ReceivingNext = binary.BigEndian.Uint32(buf) buf = buf[4:] - s.PeerRTO = serial.BytesToUint32(buf) + s.PeerRTO = binary.BigEndian.Uint32(buf) buf = buf[4:] return true, buf @@ -282,7 +284,7 @@ func ReadSegment(buf []byte) (Segment, []byte) { return nil, nil } - conv := serial.BytesToUint16(buf) + conv := binary.BigEndian.Uint16(buf) buf = buf[2:] cmd := Command(buf[0])