function to compare byte array

pull/1524/head^2
Darien Raymond 2018-07-12 23:38:10 +02:00
parent eb2bd40157
commit 29ad2cbbdb
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
12 changed files with 132 additions and 70 deletions

29
common/compare/bytes.go Normal file
View File

@ -0,0 +1,29 @@
package compare
import "v2ray.com/core/common/errors"
func BytesEqualWithDetail(a []byte, b []byte) error {
if len(a) != len(b) {
return errors.New("mismatch array length ", len(a), " vs ", len(b))
}
for idx, v := range a {
if b[idx] != v {
return errors.New("mismatch array value at index [", idx, "]: ", v, " vs ", b[idx])
}
}
return nil
}
func BytesEqual(a []byte, b []byte) bool {
return BytesEqualWithDetail(a, b) == nil
}
func BytesAll(arr []byte, value byte) bool {
for _, v := range arr {
if v != value {
return false
}
}
return true
}

View File

@ -0,0 +1,43 @@
package compare_test
import (
"testing"
. "v2ray.com/core/common/compare"
)
func TestBytesEqual(t *testing.T) {
testCases := []struct {
Input1 []byte
Input2 []byte
Result bool
}{
{
Input1: []byte{},
Input2: []byte{1},
Result: false,
},
{
Input1: nil,
Input2: []byte{},
Result: true,
},
{
Input1: []byte{1},
Input2: []byte{1},
Result: true,
},
{
Input1: []byte{1, 2},
Input2: []byte{1, 3},
Result: false,
},
}
for _, testCase := range testCases {
cmp := BytesEqual(testCase.Input1, testCase.Input2)
if cmp != testCase.Result {
t.Errorf("unexpected result %v from %v", cmp, testCase)
}
}
}

View File

@ -4,7 +4,7 @@ import (
"net" "net"
"strings" "strings"
"v2ray.com/core/common/predicate" "v2ray.com/core/common/compare"
) )
var ( var (
@ -94,7 +94,7 @@ func IPAddress(ip []byte) Address {
var addr ipv4Address = [4]byte{ip[0], ip[1], ip[2], ip[3]} var addr ipv4Address = [4]byte{ip[0], ip[1], ip[2], ip[3]}
return addr return addr
case net.IPv6len: case net.IPv6len:
if predicate.BytesAll(ip[0:10], 0) && predicate.BytesAll(ip[10:12], 0xff) { if compare.BytesAll(ip[0:10], 0) && compare.BytesAll(ip[10:12], 0xff) {
return IPAddress(ip[12:16]) return IPAddress(ip[12:16])
} }
var addr ipv6Address = [16]byte{ var addr ipv6Address = [16]byte{

30
common/peer/latency.go Normal file
View File

@ -0,0 +1,30 @@
package peer
import (
"sync"
)
type Latency interface {
Value() uint64
}
type HasLatency interface {
ConnectionLatency() Latency
HandshakeLatency() Latency
}
type AverageLatency struct {
access sync.Mutex
value uint64
}
func (al *AverageLatency) Update(newValue uint64) {
al.access.Lock()
defer al.access.Unlock()
al.value = (al.value + newValue*2) / 3
}
func (al *AverageLatency) Value() uint64 {
return al.value
}

1
common/peer/peer.go Normal file
View File

@ -0,0 +1 @@
package peer

View File

@ -1,10 +0,0 @@
package predicate
func BytesAll(array []byte, b byte) bool {
for _, val := range array {
if val != b {
return false
}
}
return true
}

View File

@ -1,39 +0,0 @@
package predicate // import "v2ray.com/core/common/predicate"
type Predicate func() bool
func (v Predicate) And(predicate Predicate) Predicate {
return All(v, predicate)
}
func (v Predicate) Or(predicate Predicate) Predicate {
return Any(v, predicate)
}
func All(predicates ...Predicate) Predicate {
return func() bool {
for _, p := range predicates {
if !p() {
return false
}
}
return true
}
}
func Any(predicates ...Predicate) Predicate {
return func() bool {
for _, p := range predicates {
if p() {
return true
}
}
return false
}
}
func Not(predicate Predicate) Predicate {
return func() bool {
return !predicate()
}
}

View File

@ -56,7 +56,7 @@ func NewID(uuid uuid.UUID) *ID {
return id return id
} }
func nextId(u *uuid.UUID) uuid.UUID { func nextID(u *uuid.UUID) uuid.UUID {
md5hash := md5.New() md5hash := md5.New()
common.Must2(md5hash.Write(u.Bytes())) common.Must2(md5hash.Write(u.Bytes()))
common.Must2(md5hash.Write([]byte("16167dc8-16b6-4e6d-b8bb-65dd68113a81"))) common.Must2(md5hash.Write([]byte("16167dc8-16b6-4e6d-b8bb-65dd68113a81")))
@ -74,8 +74,7 @@ func NewAlterIDs(primary *ID, alterIDCount uint16) []*ID {
alterIDs := make([]*ID, alterIDCount) alterIDs := make([]*ID, alterIDCount)
prevID := primary.UUID() prevID := primary.UUID()
for idx := range alterIDs { for idx := range alterIDs {
newid := nextId(&prevID) newid := nextID(&prevID)
// TODO: check duplicates
alterIDs[idx] = NewID(newid) alterIDs[idx] = NewID(newid)
prevID = newid prevID = newid
} }

View File

@ -3,7 +3,7 @@ package protocol_test
import ( import (
"testing" "testing"
"v2ray.com/core/common/predicate" "v2ray.com/core/common/compare"
. "v2ray.com/core/common/protocol" . "v2ray.com/core/common/protocol"
"v2ray.com/core/common/uuid" "v2ray.com/core/common/uuid"
. "v2ray.com/ext/assert" . "v2ray.com/ext/assert"
@ -13,7 +13,7 @@ func TestCmdKey(t *testing.T) {
assert := With(t) assert := With(t)
id := NewID(uuid.New()) id := NewID(uuid.New())
assert(predicate.BytesAll(id.CmdKey(), 0), IsFalse) assert(compare.BytesAll(id.CmdKey(), 0), IsFalse)
} }
func TestIdEquals(t *testing.T) { func TestIdEquals(t *testing.T) {

View File

@ -7,9 +7,9 @@ import (
"v2ray.com/core" "v2ray.com/core"
"v2ray.com/core/common" "v2ray.com/core/common"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
"v2ray.com/core/common/compare"
"v2ray.com/core/common/crypto" "v2ray.com/core/common/crypto"
"v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/predicate"
"v2ray.com/core/common/protocol" "v2ray.com/core/common/protocol"
"v2ray.com/core/common/session" "v2ray.com/core/common/session"
"v2ray.com/core/common/signal" "v2ray.com/core/common/signal"
@ -85,7 +85,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn internet
decryptor := crypto.NewAesCTRStream(auth.DecodingKey[:], auth.DecodingNonce[:]) decryptor := crypto.NewAesCTRStream(auth.DecodingKey[:], auth.DecodingNonce[:])
decryptor.XORKeyStream(auth.Header[:], auth.Header[:]) decryptor.XORKeyStream(auth.Header[:], auth.Header[:])
if !predicate.BytesAll(auth.Header[56:60], 0xef) { if !compare.BytesAll(auth.Header[56:60], 0xef) {
return newError("invalid connection type: ", auth.Header[56:60]) return newError("invalid connection type: ", auth.Header[56:60])
} }

View File

@ -18,6 +18,7 @@ import (
"v2ray.com/core/app/router" "v2ray.com/core/app/router"
"v2ray.com/core/app/stats" "v2ray.com/core/app/stats"
statscmd "v2ray.com/core/app/stats/command" statscmd "v2ray.com/core/app/stats/command"
"v2ray.com/core/common/compare"
"v2ray.com/core/common/net" "v2ray.com/core/common/net"
"v2ray.com/core/common/protocol" "v2ray.com/core/common/protocol"
"v2ray.com/core/common/serial" "v2ray.com/core/common/serial"
@ -101,12 +102,17 @@ func TestCommanderRemoveHandler(t *testing.T) {
servers, err := InitializeServerConfigs(clientConfig) servers, err := InitializeServerConfigs(clientConfig)
assert(err, IsNil) assert(err, IsNil)
defer CloseAllServers(servers)
{ {
conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
IP: []byte{127, 0, 0, 1}, IP: []byte{127, 0, 0, 1},
Port: int(clientPort), Port: int(clientPort),
}) })
assert(err, IsNil) if err != nil {
t.Fatal(err)
}
defer conn.Close() // nolint: errcheck
payload := "commander request." payload := "commander request."
nBytes, err := conn.Write([]byte(payload)) nBytes, err := conn.Write([]byte(payload))
@ -116,8 +122,9 @@ func TestCommanderRemoveHandler(t *testing.T) {
response := make([]byte, 1024) response := make([]byte, 1024)
nBytes, err = conn.Read(response) nBytes, err = conn.Read(response)
assert(err, IsNil) assert(err, IsNil)
assert(response[:nBytes], Equals, xor([]byte(payload))) if err := compare.BytesEqualWithDetail(response[:nBytes], xor([]byte(payload))); err != nil {
assert(conn.Close(), IsNil) t.Fatal(err)
}
} }
cmdConn, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", cmdPort), grpc.WithInsecure(), grpc.WithBlock()) cmdConn, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", cmdPort), grpc.WithInsecure(), grpc.WithBlock())
@ -137,8 +144,6 @@ func TestCommanderRemoveHandler(t *testing.T) {
}) })
assert(err, IsNotNil) assert(err, IsNotNil)
} }
CloseAllServers(servers)
} }
func TestCommanderAddRemoveUser(t *testing.T) { func TestCommanderAddRemoveUser(t *testing.T) {
@ -487,7 +492,10 @@ func TestCommanderStats(t *testing.T) {
} }
servers, err := InitializeServerConfigs(serverConfig, clientConfig) servers, err := InitializeServerConfigs(serverConfig, clientConfig)
assert(err, IsNil) if err != nil {
t.Fatal("Failed to create all servers", err)
}
defer CloseAllServers(servers)
conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{ conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{
IP: []byte{127, 0, 0, 1}, IP: []byte{127, 0, 0, 1},

View File

@ -8,7 +8,6 @@ import (
"time" "time"
"v2ray.com/core/common/buf" "v2ray.com/core/common/buf"
"v2ray.com/core/common/predicate"
"v2ray.com/core/common/signal" "v2ray.com/core/common/signal"
"v2ray.com/core/common/signal/semaphore" "v2ray.com/core/common/signal/semaphore"
) )
@ -119,13 +118,13 @@ func (info *RoundTripInfo) SmoothedTime() uint32 {
type Updater struct { type Updater struct {
interval int64 interval int64
shouldContinue predicate.Predicate shouldContinue func() bool
shouldTerminate predicate.Predicate shouldTerminate func() bool
updateFunc func() updateFunc func()
notifier *semaphore.Instance notifier *semaphore.Instance
} }
func NewUpdater(interval uint32, shouldContinue predicate.Predicate, shouldTerminate predicate.Predicate, updateFunc func()) *Updater { func NewUpdater(interval uint32, shouldContinue func() bool, shouldTerminate func() bool, updateFunc func()) *Updater {
u := &Updater{ u := &Updater{
interval: int64(time.Duration(interval) * time.Millisecond), interval: int64(time.Duration(interval) * time.Millisecond),
shouldContinue: shouldContinue, shouldContinue: shouldContinue,
@ -230,12 +229,14 @@ func NewConnection(meta ConnMetadata, writer PacketWriter, closer io.Closer, con
} }
conn.dataUpdater = NewUpdater( conn.dataUpdater = NewUpdater(
config.GetTTIValue(), config.GetTTIValue(),
predicate.Not(isTerminating).And(predicate.Any(conn.sendingWorker.UpdateNecessary, conn.receivingWorker.UpdateNecessary)), func() bool {
return !isTerminating() && (conn.sendingWorker.UpdateNecessary() || conn.receivingWorker.UpdateNecessary())
},
isTerminating, isTerminating,
conn.updateTask) conn.updateTask)
conn.pingUpdater = NewUpdater( conn.pingUpdater = NewUpdater(
5000, // 5 seconds 5000, // 5 seconds
predicate.Not(isTerminated), func() bool { return !isTerminated() },
isTerminated, isTerminated,
conn.updateTask) conn.updateTask)
conn.pingUpdater.WakeUp() conn.pingUpdater.WakeUp()