mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-07-02 09:48:43 +00:00
mKCP transport: Make sure ACKs are limited within MTU (#5773)
https://github.com/XTLS/Xray-core/pull/5657#issuecomment-3984236113
This commit is contained in:
@@ -47,15 +47,18 @@ type AckList struct {
|
|||||||
|
|
||||||
flushCandidates []uint32
|
flushCandidates []uint32
|
||||||
dirty bool
|
dirty bool
|
||||||
|
|
||||||
|
mss uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAckList(writer SegmentWriter) *AckList {
|
func NewAckList(writer SegmentWriter, mss uint32) *AckList {
|
||||||
return &AckList{
|
return &AckList{
|
||||||
writer: writer,
|
writer: writer,
|
||||||
timestamps: make([]uint32, 0, 128),
|
timestamps: make([]uint32, 0, 128),
|
||||||
numbers: make([]uint32, 0, 128),
|
numbers: make([]uint32, 0, 128),
|
||||||
nextFlush: make([]uint32, 0, 128),
|
nextFlush: make([]uint32, 0, 128),
|
||||||
flushCandidates: make([]uint32, 0, 128),
|
flushCandidates: make([]uint32, 0, 128),
|
||||||
|
mss: mss,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +93,7 @@ func (l *AckList) Clear(una uint32) {
|
|||||||
func (l *AckList) Flush(current uint32, rto uint32) {
|
func (l *AckList) Flush(current uint32, rto uint32) {
|
||||||
l.flushCandidates = l.flushCandidates[:0]
|
l.flushCandidates = l.flushCandidates[:0]
|
||||||
|
|
||||||
seg := NewAckSegment()
|
seg := NewAckSegment((int(l.mss) - 17) / 4)
|
||||||
for i := 0; i < len(l.numbers); i++ {
|
for i := 0; i < len(l.numbers); i++ {
|
||||||
if l.nextFlush[i] > current {
|
if l.nextFlush[i] > current {
|
||||||
if len(l.flushCandidates) < cap(l.flushCandidates) {
|
if len(l.flushCandidates) < cap(l.flushCandidates) {
|
||||||
@@ -109,7 +112,7 @@ func (l *AckList) Flush(current uint32, rto uint32) {
|
|||||||
if seg.IsFull() {
|
if seg.IsFull() {
|
||||||
l.writer.Write(seg)
|
l.writer.Write(seg)
|
||||||
seg.Release()
|
seg.Release()
|
||||||
seg = NewAckSegment()
|
seg = NewAckSegment((int(l.mss) - 17) / 4)
|
||||||
l.dirty = false
|
l.dirty = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,7 +147,7 @@ func NewReceivingWorker(kcp *Connection) *ReceivingWorker {
|
|||||||
window: NewReceivingWindow(),
|
window: NewReceivingWindow(),
|
||||||
windowSize: kcp.Config.GetReceivingInFlightSize(),
|
windowSize: kcp.Config.GetReceivingInFlightSize(),
|
||||||
}
|
}
|
||||||
worker.acklist = NewAckList(worker)
|
worker.acklist = NewAckList(worker, kcp.mss+DataSegmentOverhead)
|
||||||
return worker
|
return worker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,12 +131,22 @@ type AckSegment struct {
|
|||||||
ReceivingNext uint32
|
ReceivingNext uint32
|
||||||
Timestamp uint32
|
Timestamp uint32
|
||||||
NumberList []uint32
|
NumberList []uint32
|
||||||
|
|
||||||
|
Limit int
|
||||||
}
|
}
|
||||||
|
|
||||||
const ackNumberLimit = 128
|
const ackNumberLimit = 128
|
||||||
|
|
||||||
func NewAckSegment() *AckSegment {
|
func NewAckSegment(limit int) *AckSegment {
|
||||||
return new(AckSegment)
|
if limit <= 0 {
|
||||||
|
limit = 1
|
||||||
|
}
|
||||||
|
if limit > ackNumberLimit {
|
||||||
|
limit = ackNumberLimit
|
||||||
|
}
|
||||||
|
return &AckSegment{
|
||||||
|
Limit: limit,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AckSegment) parse(conv uint16, cmd Command, opt SegmentOption, buf []byte) (bool, []byte) {
|
func (s *AckSegment) parse(conv uint16, cmd Command, opt SegmentOption, buf []byte) (bool, []byte) {
|
||||||
@@ -188,7 +198,7 @@ func (s *AckSegment) PutNumber(number uint32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *AckSegment) IsFull() bool {
|
func (s *AckSegment) IsFull() bool {
|
||||||
return len(s.NumberList) == ackNumberLimit
|
return len(s.NumberList) == s.Limit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AckSegment) IsEmpty() bool {
|
func (s *AckSegment) IsEmpty() bool {
|
||||||
@@ -290,7 +300,7 @@ func ReadSegment(buf []byte) (Segment, []byte) {
|
|||||||
case CommandData:
|
case CommandData:
|
||||||
seg = NewDataSegment()
|
seg = NewDataSegment()
|
||||||
case CommandACK:
|
case CommandACK:
|
||||||
seg = NewAckSegment()
|
seg = NewAckSegment(128)
|
||||||
default:
|
default:
|
||||||
seg = NewCmdOnlySegment()
|
seg = NewCmdOnlySegment()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ func TestACKSegment(t *testing.T) {
|
|||||||
ReceivingNext: 3,
|
ReceivingNext: 3,
|
||||||
Timestamp: 10,
|
Timestamp: 10,
|
||||||
NumberList: []uint32{1, 3, 5, 7, 9},
|
NumberList: []uint32{1, 3, 5, 7, 9},
|
||||||
|
Limit: 128,
|
||||||
}
|
}
|
||||||
|
|
||||||
nBytes := seg.ByteSize()
|
nBytes := seg.ByteSize()
|
||||||
|
|||||||
Reference in New Issue
Block a user