From 46c0d457d99c1657fdc3e5f5c880ff1f73adb605 Mon Sep 17 00:00:00 2001 From: V2Ray Date: Sat, 31 Oct 2015 09:39:45 +0100 Subject: [PATCH] User settings for trusted user --- common/net/timed_io.go | 54 ++++++++++++++++++++++-------- proxy/vmess/protocol/vmess.go | 8 ++--- proxy/vmess/protocol/vmess_test.go | 20 ++++++----- proxy/vmess/vmessin.go | 3 +- proxy/vmess/vmessout.go | 2 +- 5 files changed, 59 insertions(+), 28 deletions(-) diff --git a/common/net/timed_io.go b/common/net/timed_io.go index a5603463..b2690ea1 100644 --- a/common/net/timed_io.go +++ b/common/net/timed_io.go @@ -1,6 +1,7 @@ package net import ( + "io" "net" "time" ) @@ -10,27 +11,21 @@ var ( ) type TimeOutReader struct { - timeout int + timeout int connection net.Conn + worker io.Reader } func NewTimeOutReader(timeout int, connection net.Conn) *TimeOutReader { - return &TimeOutReader{ - timeout: timeout, + reader := &TimeOutReader{ connection: connection, } + reader.SetTimeOut(timeout) + return reader } -func (reader *TimeOutReader) Read(p []byte) (n int, err error) { - if reader.timeout > 0 { - deadline := time.Duration(reader.timeout) * time.Second - reader.connection.SetReadDeadline(time.Now().Add(deadline)) - } - n, err = reader.connection.Read(p) - if reader.timeout > 0 { - reader.connection.SetReadDeadline(emptyTime) - } - return +func (reader *TimeOutReader) Read(p []byte) (int, error) { + return reader.worker.Read(p) } func (reader *TimeOutReader) GetTimeOut() int { @@ -38,5 +33,36 @@ func (reader *TimeOutReader) GetTimeOut() int { } func (reader *TimeOutReader) SetTimeOut(value int) { - reader.timeout = value + reader.timeout = value + if value > 0 { + reader.worker = &timedReaderWorker{ + timeout: value, + connection: reader.connection, + } + } else { + reader.worker = &noOpReaderWorker{ + connection: reader.connection, + } + } +} + +type timedReaderWorker struct { + timeout int + connection net.Conn +} + +func (this *timedReaderWorker) Read(p []byte) (int, error) { + deadline := time.Duration(this.timeout) * time.Second + this.connection.SetReadDeadline(time.Now().Add(deadline)) + nBytes, err := this.connection.Read(p) + this.connection.SetReadDeadline(emptyTime) + return nBytes, err +} + +type noOpReaderWorker struct { + connection net.Conn +} + +func (this *noOpReaderWorker) Read(p []byte) (int, error) { + return this.connection.Read(p) } diff --git a/proxy/vmess/protocol/vmess.go b/proxy/vmess/protocol/vmess.go index 2ac5a269..550a6a84 100644 --- a/proxy/vmess/protocol/vmess.go +++ b/proxy/vmess/protocol/vmess.go @@ -37,7 +37,7 @@ const ( // streaming. type VMessRequest struct { Version byte - UserId config.ID + User config.User RequestIV []byte RequestKey []byte ResponseHeader []byte @@ -98,7 +98,7 @@ func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) { bufferLen := nBytes request := &VMessRequest{ - UserId: *userObj.ID(), + User: userObj, Version: buffer.Value[0], } @@ -167,7 +167,7 @@ func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 u } counter := randomRangeInt64(time.Now().Unix(), 30) - hash := idHash.Hash(request.UserId.Bytes[:], counter) + hash := idHash.Hash(request.User.ID().Bytes[:], counter) buffer.Append(hash) @@ -201,7 +201,7 @@ func (request *VMessRequest) ToBytes(idHash user.CounterHash, randomRangeInt64 u buffer.AppendBytes(byte(fnvHash>>24), byte(fnvHash>>16), byte(fnvHash>>8), byte(fnvHash)) encryptionEnd += 4 - aesCipher, err := aes.NewCipher(request.UserId.CmdKey()) + aesCipher, err := aes.NewCipher(request.User.ID().CmdKey()) if err != nil { return nil, err } diff --git a/proxy/vmess/protocol/vmess_test.go b/proxy/vmess/protocol/vmess_test.go index ec462a63..43377510 100644 --- a/proxy/vmess/protocol/vmess_test.go +++ b/proxy/vmess/protocol/vmess_test.go @@ -32,15 +32,17 @@ func TestVMessSerialization(t *testing.T) { if err != nil { t.Fatal(err) } + + testUser := &TestUser { + id: userId, + } userSet := mocks.MockUserSet{[]config.User{}, make(map[string]int), make(map[string]int64)} - userSet.AddUser(&TestUser{ - id: userId, - }) + userSet.AddUser(testUser) request := new(VMessRequest) request.Version = byte(0x01) - request.UserId = *userId + request.User = testUser randBytes := make([]byte, 36) _, err = rand.Read(randBytes) @@ -69,7 +71,7 @@ func TestVMessSerialization(t *testing.T) { } assert.Byte(actualRequest.Version).Named("Version").Equals(byte(0x01)) - assert.String(actualRequest.UserId.String).Named("UserId").Equals(request.UserId.String) + assert.String(actualRequest.User.ID().String).Named("UserId").Equals(request.User.ID().String) assert.Bytes(actualRequest.RequestIV).Named("RequestIV").Equals(request.RequestIV[:]) assert.Bytes(actualRequest.RequestKey).Named("RequestKey").Equals(request.RequestKey[:]) assert.Bytes(actualRequest.ResponseHeader).Named("ResponseHeader").Equals(request.ResponseHeader[:]) @@ -80,13 +82,15 @@ func TestVMessSerialization(t *testing.T) { func BenchmarkVMessRequestWriting(b *testing.B) { userId, _ := config.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51") userSet := mocks.MockUserSet{[]config.User{}, make(map[string]int), make(map[string]int64)} - userSet.AddUser(&TestUser{ + + testUser := &TestUser{ id: userId, - }) + } + userSet.AddUser(testUser) request := new(VMessRequest) request.Version = byte(0x01) - request.UserId = *userId + request.User = testUser randBytes := make([]byte, 36) rand.Read(randBytes) diff --git a/proxy/vmess/vmessin.go b/proxy/vmess/vmessin.go index 2ebc4412..6e049c5d 100644 --- a/proxy/vmess/vmessin.go +++ b/proxy/vmess/vmessin.go @@ -91,7 +91,8 @@ func (handler *VMessInboundHandler) HandleConnection(connection *net.TCPConn) er readFinish.Lock() writeFinish.Lock() - connReader.SetTimeOut(120) + userSettings := config.GetUserSettings(request.User.Level()) + connReader.SetTimeOut(userSettings.PayloadReadTimeout) go handleInput(request, connReader, input, &readFinish) responseKey := md5.Sum(request.RequestKey) diff --git a/proxy/vmess/vmessout.go b/proxy/vmess/vmessout.go index eacf879a..bf67e692 100644 --- a/proxy/vmess/vmessout.go +++ b/proxy/vmess/vmessout.go @@ -67,7 +67,7 @@ func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray. } request := &protocol.VMessRequest{ Version: protocol.Version, - UserId: *vNextUser.ID(), + User: vNextUser, Command: command, Address: firstPacket.Destination().Address(), }