mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-01-14 14:47:01 +08:00
Compare commits
3 Commits
fix-vision
...
v25.12.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e403abe360 | ||
|
|
c123f163c2 | ||
|
|
93312d29e5 |
@@ -19,7 +19,7 @@ import (
|
||||
var (
|
||||
Version_x byte = 25
|
||||
Version_y byte = 12
|
||||
Version_z byte = 1
|
||||
Version_z byte = 2
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -395,65 +395,54 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
|
||||
// IsCompleteRecord Is complete tls data record
|
||||
func IsCompleteRecord(buffer buf.MultiBuffer) bool {
|
||||
mb2 := make(buf.MultiBuffer, 0, len(buffer))
|
||||
for _, buffer1 := range buffer {
|
||||
buffer2 := buf.New()
|
||||
buffer2.Write(buffer1.Bytes())
|
||||
mb2 = append(mb2, buffer2)
|
||||
b := make([]byte, buffer.Len())
|
||||
if buffer.Copy(b) != int(buffer.Len()) {
|
||||
panic("impossible bytes allocation")
|
||||
}
|
||||
isComplete := true
|
||||
var headerLen int32 = 5
|
||||
var recordLen int32
|
||||
for _, buffer2 := range mb2 {
|
||||
for buffer2.Len() > 0 {
|
||||
if headerLen > 0 {
|
||||
data, _ := buffer2.ReadByte()
|
||||
switch headerLen {
|
||||
case 5:
|
||||
if data != 0x17 {
|
||||
isComplete = false
|
||||
break
|
||||
}
|
||||
case 4:
|
||||
if data != 0x03 {
|
||||
isComplete = false
|
||||
break
|
||||
}
|
||||
case 3:
|
||||
if data != 0x03 {
|
||||
isComplete = false
|
||||
break
|
||||
}
|
||||
case 2:
|
||||
recordLen = int32(data) << 8
|
||||
case 1:
|
||||
recordLen = recordLen | int32(data)
|
||||
var headerLen int = 5
|
||||
var recordLen int
|
||||
|
||||
totalLen := len(b)
|
||||
i := 0
|
||||
for i < totalLen {
|
||||
// record header: 0x17 0x3 0x3 + 2 bytes length
|
||||
if headerLen > 0 {
|
||||
data := b[i]
|
||||
i++
|
||||
switch headerLen {
|
||||
case 5:
|
||||
if data != 0x17 {
|
||||
return false
|
||||
}
|
||||
headerLen--
|
||||
} else if recordLen > 0 {
|
||||
var len = recordLen
|
||||
if buffer2.Len() < recordLen{
|
||||
len = buffer2.Len()
|
||||
case 4:
|
||||
if data != 0x03 {
|
||||
return false
|
||||
}
|
||||
buffer2.Advance(len)
|
||||
recordLen -= len
|
||||
if recordLen == 0 {
|
||||
headerLen = 5
|
||||
case 3:
|
||||
if data != 0x03 {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
isComplete = false
|
||||
case 2:
|
||||
recordLen = int(data) << 8
|
||||
case 1:
|
||||
recordLen = recordLen | int(data)
|
||||
}
|
||||
}
|
||||
if !isComplete {
|
||||
break
|
||||
headerLen--
|
||||
} else if recordLen > 0 {
|
||||
remaining := totalLen - i
|
||||
if remaining < recordLen {
|
||||
return false
|
||||
} else {
|
||||
i += recordLen
|
||||
recordLen = 0
|
||||
headerLen = 5
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, buffer2 := range mb2 {
|
||||
buffer2.Release()
|
||||
buffer2 = nil
|
||||
}
|
||||
if headerLen == 5 && recordLen == 0 && isComplete {
|
||||
return true
|
||||
if headerLen == 5 && recordLen == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -57,7 +57,12 @@ type Handler struct {
|
||||
|
||||
testpre uint32
|
||||
initpre sync.Once
|
||||
preConns chan stat.Connection
|
||||
preConns chan *ConnExpire
|
||||
}
|
||||
|
||||
type ConnExpire struct {
|
||||
Conn stat.Connection
|
||||
Expire time.Time
|
||||
}
|
||||
|
||||
// New creates a new VLess outbound handler.
|
||||
@@ -141,25 +146,33 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
|
||||
if h.testpre > 0 && h.reverse == nil {
|
||||
h.initpre.Do(func() {
|
||||
h.preConns = make(chan stat.Connection)
|
||||
h.preConns = make(chan *ConnExpire)
|
||||
for range h.testpre { // TODO: randomize
|
||||
go func() {
|
||||
defer func() { recover() }()
|
||||
ctx := xctx.ContextWithID(context.Background(), session.NewID())
|
||||
for {
|
||||
time.Sleep(time.Millisecond * 200) // TODO: randomize
|
||||
conn, err := dialer.Dial(ctx, rec.Destination)
|
||||
if err != nil {
|
||||
errors.LogWarningInner(ctx, err, "pre-connect failed")
|
||||
continue
|
||||
}
|
||||
h.preConns <- conn
|
||||
h.preConns <- &ConnExpire{Conn: conn, Expire: time.Now().Add(time.Minute * 2)} // TODO: customize & randomize
|
||||
time.Sleep(time.Millisecond * 200) // TODO: customize & randomize
|
||||
}
|
||||
}()
|
||||
}
|
||||
})
|
||||
if conn = <-h.preConns; conn == nil {
|
||||
return errors.New("closed handler").AtWarning()
|
||||
for {
|
||||
connTime := <-h.preConns
|
||||
if connTime == nil {
|
||||
return errors.New("closed handler").AtWarning()
|
||||
}
|
||||
if time.Now().Before(connTime.Expire) {
|
||||
conn = connTime.Conn
|
||||
break
|
||||
}
|
||||
connTime.Conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user