mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-11-14 16:25:57 -05:00
send reuse option in header
This commit is contained in:
parent
b9c88b673b
commit
72fb5a256c
@ -13,13 +13,22 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RequestOptionChunkStream = RequestOption(0x01)
|
RequestOptionChunkStream = RequestOption(0x01)
|
||||||
|
RequestOptionConnectionReuse = RequestOption(0x02)
|
||||||
)
|
)
|
||||||
|
|
||||||
type RequestOption byte
|
type RequestOption byte
|
||||||
|
|
||||||
func (this RequestOption) IsChunkStream() bool {
|
func (this RequestOption) Has(option RequestOption) bool {
|
||||||
return (this & RequestOptionChunkStream) == RequestOptionChunkStream
|
return (this & option) == option
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RequestOption) Set(option RequestOption) {
|
||||||
|
*this = (*this | option)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RequestOption) Clear(option RequestOption) {
|
||||||
|
*this = (*this & (^option))
|
||||||
}
|
}
|
||||||
|
|
||||||
type RequestHeader struct {
|
type RequestHeader struct {
|
||||||
@ -38,9 +47,28 @@ func (this *RequestHeader) Destination() v2net.Destination {
|
|||||||
return v2net.TCPDestination(this.Address, this.Port)
|
return v2net.TCPDestination(this.Address, this.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResponseOption byte
|
||||||
|
|
||||||
|
var (
|
||||||
|
ResponseOptionConnectionReuse = ResponseOption(1)
|
||||||
|
)
|
||||||
|
|
||||||
|
func (this *ResponseOption) Set(option ResponseOption) {
|
||||||
|
*this = (*this | option)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this ResponseOption) Has(option ResponseOption) bool {
|
||||||
|
return (this | option) == option
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ResponseOption) Clear(option ResponseOption) {
|
||||||
|
*this = (*this & (^option))
|
||||||
|
}
|
||||||
|
|
||||||
type ResponseCommand interface{}
|
type ResponseCommand interface{}
|
||||||
|
|
||||||
type ResponseHeader struct {
|
type ResponseHeader struct {
|
||||||
|
Option ResponseOption
|
||||||
Command ResponseCommand
|
Command ResponseCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
|
34
common/protocol/headers_test.go
Normal file
34
common/protocol/headers_test.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package protocol_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/v2ray/v2ray-core/common/protocol"
|
||||||
|
"github.com/v2ray/v2ray-core/testing/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRequestOptionSet(t *testing.T) {
|
||||||
|
assert := assert.On(t)
|
||||||
|
|
||||||
|
option := new(RequestOption)
|
||||||
|
assert.Bool(option.Has(RequestOptionChunkStream)).IsFalse()
|
||||||
|
|
||||||
|
option.Set(RequestOptionChunkStream)
|
||||||
|
assert.Bool(option.Has(RequestOptionChunkStream)).IsTrue()
|
||||||
|
|
||||||
|
option.Set(RequestOptionConnectionReuse)
|
||||||
|
assert.Bool(option.Has(RequestOptionConnectionReuse)).IsTrue()
|
||||||
|
assert.Bool(option.Has(RequestOptionChunkStream)).IsTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRequestOptionClear(t *testing.T) {
|
||||||
|
assert := assert.On(t)
|
||||||
|
|
||||||
|
option := new(RequestOption)
|
||||||
|
option.Set(RequestOptionChunkStream)
|
||||||
|
option.Set(RequestOptionConnectionReuse)
|
||||||
|
|
||||||
|
option.Clear(RequestOptionChunkStream)
|
||||||
|
assert.Bool(option.Has(RequestOptionChunkStream)).IsFalse()
|
||||||
|
assert.Bool(option.Has(RequestOptionConnectionReuse)).IsTrue()
|
||||||
|
}
|
@ -118,7 +118,9 @@ func (this *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Res
|
|||||||
return nil, transport.ErrorCorruptedPacket
|
return nil, transport.ErrorCorruptedPacket
|
||||||
}
|
}
|
||||||
|
|
||||||
header := new(protocol.ResponseHeader)
|
header := &protocol.ResponseHeader{
|
||||||
|
Option: protocol.ResponseOption(buffer.Value[1]),
|
||||||
|
}
|
||||||
|
|
||||||
if buffer.Value[2] != 0 {
|
if buffer.Value[2] != 0 {
|
||||||
cmdId := buffer.Value[2]
|
cmdId := buffer.Value[2]
|
||||||
|
@ -159,7 +159,7 @@ func (this *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader,
|
|||||||
encryptionWriter := crypto.NewCryptionWriter(aesStream, writer)
|
encryptionWriter := crypto.NewCryptionWriter(aesStream, writer)
|
||||||
this.responseWriter = encryptionWriter
|
this.responseWriter = encryptionWriter
|
||||||
|
|
||||||
encryptionWriter.Write([]byte{this.responseHeader, 0x00})
|
encryptionWriter.Write([]byte{this.responseHeader, byte(header.Option)})
|
||||||
err := MarshalCommand(header.Command, encryptionWriter)
|
err := MarshalCommand(header.Command, encryptionWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
encryptionWriter.Write([]byte{0x00, 0x00})
|
encryptionWriter.Write([]byte{0x00, 0x00})
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/v2ray/v2ray-core/proxy"
|
"github.com/v2ray/v2ray-core/proxy"
|
||||||
"github.com/v2ray/v2ray-core/proxy/internal"
|
"github.com/v2ray/v2ray-core/proxy/internal"
|
||||||
vmessio "github.com/v2ray/v2ray-core/proxy/vmess/io"
|
vmessio "github.com/v2ray/v2ray-core/proxy/vmess/io"
|
||||||
|
"github.com/v2ray/v2ray-core/transport"
|
||||||
"github.com/v2ray/v2ray-core/transport/hub"
|
"github.com/v2ray/v2ray-core/transport/hub"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -145,7 +146,7 @@ func (this *VMessInboundHandler) HandleConnection(connection *hub.Connection) {
|
|||||||
log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, "")
|
log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, "")
|
||||||
log.Debug("VMessIn: Received request for ", request.Destination())
|
log.Debug("VMessIn: Received request for ", request.Destination())
|
||||||
|
|
||||||
if request.Option.IsChunkStream() {
|
if request.Option.Has(protocol.RequestOptionConnectionReuse) {
|
||||||
connection.SetReusable(true)
|
connection.SetReusable(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,10 +162,11 @@ func (this *VMessInboundHandler) HandleConnection(connection *hub.Connection) {
|
|||||||
userSettings := protocol.GetUserSettings(request.User.Level)
|
userSettings := protocol.GetUserSettings(request.User.Level)
|
||||||
connReader.SetTimeOut(userSettings.PayloadReadTimeout)
|
connReader.SetTimeOut(userSettings.PayloadReadTimeout)
|
||||||
reader.SetCached(false)
|
reader.SetCached(false)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
bodyReader := session.DecodeRequestBody(reader)
|
bodyReader := session.DecodeRequestBody(reader)
|
||||||
var requestReader v2io.Reader
|
var requestReader v2io.Reader
|
||||||
if request.Option.IsChunkStream() {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
requestReader = vmessio.NewAuthChunkReader(bodyReader)
|
requestReader = vmessio.NewAuthChunkReader(bodyReader)
|
||||||
} else {
|
} else {
|
||||||
requestReader = v2io.NewAdaptiveReader(bodyReader)
|
requestReader = v2io.NewAdaptiveReader(bodyReader)
|
||||||
@ -186,6 +188,10 @@ func (this *VMessInboundHandler) HandleConnection(connection *hub.Connection) {
|
|||||||
Command: this.generateCommand(request),
|
Command: this.generateCommand(request),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if request.Option.Has(protocol.RequestOptionConnectionReuse) && transport.IsConnectionReusable() {
|
||||||
|
response.Option.Set(protocol.ResponseOptionConnectionReuse)
|
||||||
|
}
|
||||||
|
|
||||||
session.EncodeResponseHeader(response, writer)
|
session.EncodeResponseHeader(response, writer)
|
||||||
|
|
||||||
bodyWriter := session.EncodeResponseBody(writer)
|
bodyWriter := session.EncodeResponseBody(writer)
|
||||||
@ -193,7 +199,7 @@ func (this *VMessInboundHandler) HandleConnection(connection *hub.Connection) {
|
|||||||
// Optimize for small response packet
|
// Optimize for small response packet
|
||||||
if data, err := output.Read(); err == nil {
|
if data, err := output.Read(); err == nil {
|
||||||
var v2writer v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
|
var v2writer v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
|
||||||
if request.Option.IsChunkStream() {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
v2writer = vmessio.NewAuthChunkWriter(v2writer)
|
v2writer = vmessio.NewAuthChunkWriter(v2writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +213,7 @@ func (this *VMessInboundHandler) HandleConnection(connection *hub.Connection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
output.Release()
|
output.Release()
|
||||||
if request.Option.IsChunkStream() {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
v2writer.Write(alloc.NewSmallBuffer().Clear())
|
v2writer.Write(alloc.NewSmallBuffer().Clear())
|
||||||
}
|
}
|
||||||
v2writer.Release()
|
v2writer.Release()
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/v2ray/v2ray-core/proxy"
|
"github.com/v2ray/v2ray-core/proxy"
|
||||||
"github.com/v2ray/v2ray-core/proxy/internal"
|
"github.com/v2ray/v2ray-core/proxy/internal"
|
||||||
vmessio "github.com/v2ray/v2ray-core/proxy/vmess/io"
|
vmessio "github.com/v2ray/v2ray-core/proxy/vmess/io"
|
||||||
|
"github.com/v2ray/v2ray-core/transport"
|
||||||
"github.com/v2ray/v2ray-core/transport/hub"
|
"github.com/v2ray/v2ray-core/transport/hub"
|
||||||
"github.com/v2ray/v2ray-core/transport/ray"
|
"github.com/v2ray/v2ray-core/transport/ray"
|
||||||
)
|
)
|
||||||
@ -49,7 +50,9 @@ func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *al
|
|||||||
log.Info("VMessOut: Tunneling request to ", request.Address, " via ", destination)
|
log.Info("VMessOut: Tunneling request to ", request.Address, " via ", destination)
|
||||||
|
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
if request.Option.IsChunkStream() {
|
|
||||||
|
if transport.IsConnectionReusable() {
|
||||||
|
request.Option.Set(protocol.RequestOptionConnectionReuse)
|
||||||
conn.SetReusable(true)
|
conn.SetReusable(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +82,7 @@ func (this *VMessOutboundHandler) handleRequest(session *raw.ClientSession, conn
|
|||||||
|
|
||||||
bodyWriter := session.EncodeRequestBody(writer)
|
bodyWriter := session.EncodeRequestBody(writer)
|
||||||
var streamWriter v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
|
var streamWriter v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
|
||||||
if request.Option.IsChunkStream() {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
streamWriter = vmessio.NewAuthChunkWriter(streamWriter)
|
streamWriter = vmessio.NewAuthChunkWriter(streamWriter)
|
||||||
}
|
}
|
||||||
streamWriter.Write(payload)
|
streamWriter.Write(payload)
|
||||||
@ -90,8 +93,11 @@ func (this *VMessOutboundHandler) handleRequest(session *raw.ClientSession, conn
|
|||||||
conn.SetReusable(false)
|
conn.SetReusable(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.Option.IsChunkStream() {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
streamWriter.Write(alloc.NewSmallBuffer().Clear())
|
err := streamWriter.Write(alloc.NewSmallBuffer().Clear())
|
||||||
|
if err != nil {
|
||||||
|
conn.SetReusable(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
streamWriter.Release()
|
streamWriter.Release()
|
||||||
return
|
return
|
||||||
@ -110,11 +116,15 @@ func (this *VMessOutboundHandler) handleResponse(session *raw.ClientSession, con
|
|||||||
}
|
}
|
||||||
go this.handleCommand(dest, header.Command)
|
go this.handleCommand(dest, header.Command)
|
||||||
|
|
||||||
|
if !header.Option.Has(protocol.ResponseOptionConnectionReuse) {
|
||||||
|
conn.SetReusable(false)
|
||||||
|
}
|
||||||
|
|
||||||
reader.SetCached(false)
|
reader.SetCached(false)
|
||||||
decryptReader := session.DecodeResponseBody(reader)
|
decryptReader := session.DecodeResponseBody(reader)
|
||||||
|
|
||||||
var bodyReader v2io.Reader
|
var bodyReader v2io.Reader
|
||||||
if request.Option.IsChunkStream() {
|
if request.Option.Has(protocol.RequestOptionChunkStream) {
|
||||||
bodyReader = vmessio.NewAuthChunkReader(decryptReader)
|
bodyReader = vmessio.NewAuthChunkReader(decryptReader)
|
||||||
} else {
|
} else {
|
||||||
bodyReader = v2io.NewAdaptiveReader(decryptReader)
|
bodyReader = v2io.NewAdaptiveReader(decryptReader)
|
||||||
|
Loading…
Reference in New Issue
Block a user