mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-22 10:08:15 -05:00
reduce ack packet size and send peer RTO
This commit is contained in:
parent
c42ed62fd5
commit
00841583d2
@ -50,13 +50,26 @@ func nowMillisec() int64 {
|
|||||||
|
|
||||||
type RountTripInfo struct {
|
type RountTripInfo struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
variation uint32
|
variation uint32
|
||||||
srtt uint32
|
srtt uint32
|
||||||
rto uint32
|
rto uint32
|
||||||
minRtt uint32
|
minRtt uint32
|
||||||
|
updatedTimestamp uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RountTripInfo) Update(rtt uint32) {
|
func (this *RountTripInfo) UpdatePeerRTO(rto uint32, current uint32) {
|
||||||
|
this.Lock()
|
||||||
|
defer this.Unlock()
|
||||||
|
|
||||||
|
if current-this.updatedTimestamp < 5000 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updatedTimestamp = current
|
||||||
|
this.rto = rto
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *RountTripInfo) Update(rtt uint32, current uint32) {
|
||||||
if rtt > 0x7FFFFFFF {
|
if rtt > 0x7FFFFFFF {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -89,6 +102,7 @@ func (this *RountTripInfo) Update(rtt uint32) {
|
|||||||
rto = 10000
|
rto = 10000
|
||||||
}
|
}
|
||||||
this.rto = rto * 3 / 2
|
this.rto = rto * 3 / 2
|
||||||
|
this.updatedTimestamp = current
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *RountTripInfo) Timeout() uint32 {
|
func (this *RountTripInfo) Timeout() uint32 {
|
||||||
@ -449,6 +463,7 @@ func (this *Connection) Input(data []byte) int {
|
|||||||
}
|
}
|
||||||
this.sendingWorker.ProcessReceivingNext(seg.ReceivinNext)
|
this.sendingWorker.ProcessReceivingNext(seg.ReceivinNext)
|
||||||
this.receivingWorker.ProcessSendingNext(seg.SendingNext)
|
this.receivingWorker.ProcessSendingNext(seg.SendingNext)
|
||||||
|
this.roundTrip.UpdatePeerRTO(seg.PeerRTO, current)
|
||||||
seg.Release()
|
seg.Release()
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@ -503,6 +518,7 @@ func (this *Connection) flush() {
|
|||||||
seg.Command = CommandPing
|
seg.Command = CommandPing
|
||||||
seg.ReceivinNext = this.receivingWorker.nextNumber
|
seg.ReceivinNext = this.receivingWorker.nextNumber
|
||||||
seg.SendingNext = this.sendingWorker.firstUnacknowledged
|
seg.SendingNext = this.sendingWorker.firstUnacknowledged
|
||||||
|
seg.PeerRTO = this.roundTrip.Timeout()
|
||||||
if this.State() == StateReadyToClose {
|
if this.State() == StateReadyToClose {
|
||||||
seg.Option = SegmentOptionClose
|
seg.Option = SegmentOptionClose
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,8 @@ func (this *AckList) Flush(current uint32, rto uint32) {
|
|||||||
seg := NewAckSegment()
|
seg := NewAckSegment()
|
||||||
for i := 0; i < len(this.numbers) && !seg.IsFull(); i++ {
|
for i := 0; i < len(this.numbers) && !seg.IsFull(); i++ {
|
||||||
if this.nextFlush[i] <= current {
|
if this.nextFlush[i] <= current {
|
||||||
seg.PutNumber(this.numbers[i], this.timestamps[i])
|
seg.PutNumber(this.numbers[i])
|
||||||
|
seg.PutTimestamp(this.timestamps[i])
|
||||||
this.nextFlush[i] = current + rto/2
|
this.nextFlush[i] = current + rto/2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,19 +74,24 @@ type AckSegment struct {
|
|||||||
Option SegmentOption
|
Option SegmentOption
|
||||||
ReceivingWindow uint32
|
ReceivingWindow uint32
|
||||||
ReceivingNext uint32
|
ReceivingNext uint32
|
||||||
|
Timestamp uint32
|
||||||
Count byte
|
Count byte
|
||||||
NumberList []uint32
|
NumberList []uint32
|
||||||
TimestampList []uint32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAckSegment() *AckSegment {
|
func NewAckSegment() *AckSegment {
|
||||||
return new(AckSegment)
|
return new(AckSegment)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *AckSegment) PutNumber(number uint32, timestamp uint32) {
|
func (this *AckSegment) PutTimestamp(timestamp uint32) {
|
||||||
|
if timestamp-this.Timestamp < 0x7FFFFFFF {
|
||||||
|
this.Timestamp = timestamp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *AckSegment) PutNumber(number uint32) {
|
||||||
this.Count++
|
this.Count++
|
||||||
this.NumberList = append(this.NumberList, number)
|
this.NumberList = append(this.NumberList, number)
|
||||||
this.TimestampList = append(this.TimestampList, timestamp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *AckSegment) IsFull() bool {
|
func (this *AckSegment) IsFull() bool {
|
||||||
@ -94,7 +99,7 @@ func (this *AckSegment) IsFull() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *AckSegment) ByteSize() int {
|
func (this *AckSegment) ByteSize() int {
|
||||||
return 2 + 1 + 1 + 4 + 4 + 1 + int(this.Count)*4 + int(this.Count)*4
|
return 2 + 1 + 1 + 4 + 4 + 4 + 1 + int(this.Count)*4
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *AckSegment) Bytes(b []byte) []byte {
|
func (this *AckSegment) Bytes(b []byte) []byte {
|
||||||
@ -102,17 +107,16 @@ func (this *AckSegment) Bytes(b []byte) []byte {
|
|||||||
b = append(b, byte(CommandACK), byte(this.Option))
|
b = append(b, byte(CommandACK), byte(this.Option))
|
||||||
b = serial.Uint32ToBytes(this.ReceivingWindow, b)
|
b = serial.Uint32ToBytes(this.ReceivingWindow, b)
|
||||||
b = serial.Uint32ToBytes(this.ReceivingNext, b)
|
b = serial.Uint32ToBytes(this.ReceivingNext, b)
|
||||||
|
b = serial.Uint32ToBytes(this.Timestamp, b)
|
||||||
b = append(b, this.Count)
|
b = append(b, this.Count)
|
||||||
for i := byte(0); i < this.Count; i++ {
|
for i := byte(0); i < this.Count; i++ {
|
||||||
b = serial.Uint32ToBytes(this.NumberList[i], b)
|
b = serial.Uint32ToBytes(this.NumberList[i], b)
|
||||||
b = serial.Uint32ToBytes(this.TimestampList[i], b)
|
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *AckSegment) Release() {
|
func (this *AckSegment) Release() {
|
||||||
this.NumberList = nil
|
this.NumberList = nil
|
||||||
this.TimestampList = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CmdOnlySegment struct {
|
type CmdOnlySegment struct {
|
||||||
@ -121,6 +125,7 @@ type CmdOnlySegment struct {
|
|||||||
Option SegmentOption
|
Option SegmentOption
|
||||||
SendingNext uint32
|
SendingNext uint32
|
||||||
ReceivinNext uint32
|
ReceivinNext uint32
|
||||||
|
PeerRTO uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCmdOnlySegment() *CmdOnlySegment {
|
func NewCmdOnlySegment() *CmdOnlySegment {
|
||||||
@ -128,7 +133,7 @@ func NewCmdOnlySegment() *CmdOnlySegment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *CmdOnlySegment) ByteSize() int {
|
func (this *CmdOnlySegment) ByteSize() int {
|
||||||
return 2 + 1 + 1 + 4 + 4
|
return 2 + 1 + 1 + 4 + 4 + 4
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *CmdOnlySegment) Bytes(b []byte) []byte {
|
func (this *CmdOnlySegment) Bytes(b []byte) []byte {
|
||||||
@ -136,6 +141,7 @@ func (this *CmdOnlySegment) Bytes(b []byte) []byte {
|
|||||||
b = append(b, byte(this.Command), byte(this.Option))
|
b = append(b, byte(this.Command), byte(this.Option))
|
||||||
b = serial.Uint32ToBytes(this.SendingNext, b)
|
b = serial.Uint32ToBytes(this.SendingNext, b)
|
||||||
b = serial.Uint32ToBytes(this.ReceivinNext, b)
|
b = serial.Uint32ToBytes(this.ReceivinNext, b)
|
||||||
|
b = serial.Uint32ToBytes(this.PeerRTO, b)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +192,7 @@ func ReadSegment(buf []byte) (Segment, []byte) {
|
|||||||
seg := NewAckSegment()
|
seg := NewAckSegment()
|
||||||
seg.Conv = conv
|
seg.Conv = conv
|
||||||
seg.Option = opt
|
seg.Option = opt
|
||||||
if len(buf) < 9 {
|
if len(buf) < 13 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,15 +202,18 @@ func ReadSegment(buf []byte) (Segment, []byte) {
|
|||||||
seg.ReceivingNext = serial.BytesToUint32(buf)
|
seg.ReceivingNext = serial.BytesToUint32(buf)
|
||||||
buf = buf[4:]
|
buf = buf[4:]
|
||||||
|
|
||||||
|
seg.Timestamp = serial.BytesToUint32(buf)
|
||||||
|
buf = buf[4:]
|
||||||
|
|
||||||
count := int(buf[0])
|
count := int(buf[0])
|
||||||
buf = buf[1:]
|
buf = buf[1:]
|
||||||
|
|
||||||
if len(buf) < count*8 {
|
if len(buf) < count*4 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
seg.PutNumber(serial.BytesToUint32(buf), serial.BytesToUint32(buf[4:]))
|
seg.PutNumber(serial.BytesToUint32(buf))
|
||||||
buf = buf[8:]
|
buf = buf[4:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return seg, buf
|
return seg, buf
|
||||||
@ -215,7 +224,7 @@ func ReadSegment(buf []byte) (Segment, []byte) {
|
|||||||
seg.Command = cmd
|
seg.Command = cmd
|
||||||
seg.Option = opt
|
seg.Option = opt
|
||||||
|
|
||||||
if len(buf) < 8 {
|
if len(buf) < 12 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,5 +234,8 @@ func ReadSegment(buf []byte) (Segment, []byte) {
|
|||||||
seg.ReceivinNext = serial.BytesToUint32(buf)
|
seg.ReceivinNext = serial.BytesToUint32(buf)
|
||||||
buf = buf[4:]
|
buf = buf[4:]
|
||||||
|
|
||||||
|
seg.PeerRTO = serial.BytesToUint32(buf)
|
||||||
|
buf = buf[4:]
|
||||||
|
|
||||||
return seg, buf
|
return seg, buf
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,9 @@ func TestACKSegment(t *testing.T) {
|
|||||||
Conv: 1,
|
Conv: 1,
|
||||||
ReceivingWindow: 2,
|
ReceivingWindow: 2,
|
||||||
ReceivingNext: 3,
|
ReceivingNext: 3,
|
||||||
|
Timestamp: 10,
|
||||||
Count: 5,
|
Count: 5,
|
||||||
NumberList: []uint32{1, 3, 5, 7, 9},
|
NumberList: []uint32{1, 3, 5, 7, 9},
|
||||||
TimestampList: []uint32{2, 4, 6, 8, 10},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nBytes := seg.ByteSize()
|
nBytes := seg.ByteSize()
|
||||||
@ -64,8 +64,8 @@ func TestACKSegment(t *testing.T) {
|
|||||||
assert.Uint32(seg2.ReceivingWindow).Equals(seg.ReceivingWindow)
|
assert.Uint32(seg2.ReceivingWindow).Equals(seg.ReceivingWindow)
|
||||||
assert.Uint32(seg2.ReceivingNext).Equals(seg.ReceivingNext)
|
assert.Uint32(seg2.ReceivingNext).Equals(seg.ReceivingNext)
|
||||||
assert.Byte(seg2.Count).Equals(seg.Count)
|
assert.Byte(seg2.Count).Equals(seg.Count)
|
||||||
|
assert.Uint32(seg2.Timestamp).Equals(seg.Timestamp)
|
||||||
for i := byte(0); i < seg2.Count; i++ {
|
for i := byte(0); i < seg2.Count; i++ {
|
||||||
assert.Uint32(seg2.TimestampList[i]).Equals(seg.TimestampList[i])
|
|
||||||
assert.Uint32(seg2.NumberList[i]).Equals(seg.NumberList[i])
|
assert.Uint32(seg2.NumberList[i]).Equals(seg.NumberList[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -317,14 +317,14 @@ func (this *SendingWorker) ProcessSegment(current uint32, seg *AckSegment) {
|
|||||||
this.remoteNextNumber = seg.ReceivingWindow
|
this.remoteNextNumber = seg.ReceivingWindow
|
||||||
}
|
}
|
||||||
this.ProcessReceivingNextWithoutLock(seg.ReceivingNext)
|
this.ProcessReceivingNextWithoutLock(seg.ReceivingNext)
|
||||||
|
if current-seg.Timestamp < 10000 {
|
||||||
|
this.conn.roundTrip.Update(current-seg.Timestamp, current)
|
||||||
|
}
|
||||||
|
|
||||||
var maxack uint32
|
var maxack uint32
|
||||||
for i := 0; i < int(seg.Count); i++ {
|
for i := 0; i < int(seg.Count); i++ {
|
||||||
timestamp := seg.TimestampList[i]
|
|
||||||
number := seg.NumberList[i]
|
number := seg.NumberList[i]
|
||||||
if current-timestamp < 10000 {
|
|
||||||
this.conn.roundTrip.Update(current - timestamp)
|
|
||||||
}
|
|
||||||
this.ProcessAck(number)
|
this.ProcessAck(number)
|
||||||
if maxack < number {
|
if maxack < number {
|
||||||
maxack = number
|
maxack = number
|
||||||
|
Loading…
Reference in New Issue
Block a user