1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-09-30 07:46:41 -04:00

avoid copying segment structure

This commit is contained in:
v2ray 2016-06-18 19:08:02 +02:00
parent ee0c25b0f3
commit 8cd32a8267

View File

@ -123,6 +123,11 @@ func (seg *Segment) encode(ptr []byte) []byte {
return ptr return ptr
} }
func (this *Segment) Release() {
this.data.Release()
this.data = nil
}
// NewSegment creates a KCP segment // NewSegment creates a KCP segment
func NewSegment() *Segment { func NewSegment() *Segment {
return &Segment{ return &Segment{
@ -142,10 +147,10 @@ type KCP struct {
ts_probe, probe_wait uint32 ts_probe, probe_wait uint32
dead_link, incr uint32 dead_link, incr uint32
snd_queue []Segment snd_queue []*Segment
rcv_queue []Segment rcv_queue []*Segment
snd_buf []Segment snd_buf []*Segment
rcv_buf []Segment rcv_buf []*Segment
acklist []uint32 acklist []uint32
@ -190,13 +195,13 @@ func (kcp *KCP) Recv(buffer []byte) (n int) {
// merge fragment // merge fragment
count := 0 count := 0
for k := range kcp.rcv_queue { for _, seg := range kcp.rcv_queue {
seg := &kcp.rcv_queue[k]
dataLen := seg.data.Len() dataLen := seg.data.Len()
if dataLen > len(buffer) { if dataLen > len(buffer) {
break break
} }
copy(buffer, seg.data.Value) copy(buffer, seg.data.Value)
seg.Release()
buffer = buffer[dataLen:] buffer = buffer[dataLen:]
n += dataLen n += dataLen
count++ count++
@ -205,10 +210,9 @@ func (kcp *KCP) Recv(buffer []byte) (n int) {
// move available data from rcv_buf -> rcv_queue // move available data from rcv_buf -> rcv_queue
count = 0 count = 0
for k := range kcp.rcv_buf { for _, seg := range kcp.rcv_buf {
seg := &kcp.rcv_buf[k]
if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) { if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
kcp.rcv_queue = append(kcp.rcv_queue, *seg) kcp.rcv_queue = append(kcp.rcv_queue, seg)
kcp.rcv_nxt++ kcp.rcv_nxt++
count++ count++
} else { } else {
@ -257,7 +261,7 @@ func (kcp *KCP) Send(buffer []byte) int {
seg := NewSegment() seg := NewSegment()
seg.data.Append(buffer[:size]) seg.data.Append(buffer[:size])
seg.frg = uint32(count - i - 1) seg.frg = uint32(count - i - 1)
kcp.snd_queue = append(kcp.snd_queue, *seg) kcp.snd_queue = append(kcp.snd_queue, seg)
buffer = buffer[size:] buffer = buffer[size:]
} }
return 0 return 0
@ -292,7 +296,7 @@ func (kcp *KCP) update_ack(rtt int32) {
func (kcp *KCP) shrink_buf() { func (kcp *KCP) shrink_buf() {
if len(kcp.snd_buf) > 0 { if len(kcp.snd_buf) > 0 {
seg := &kcp.snd_buf[0] seg := kcp.snd_buf[0]
kcp.snd_una = seg.sn kcp.snd_una = seg.sn
} else { } else {
kcp.snd_una = kcp.snd_nxt kcp.snd_una = kcp.snd_nxt
@ -304,10 +308,10 @@ func (kcp *KCP) parse_ack(sn uint32) {
return return
} }
for k := range kcp.snd_buf { for k, seg := range kcp.snd_buf {
seg := &kcp.snd_buf[k]
if sn == seg.sn { if sn == seg.sn {
kcp.snd_buf = append(kcp.snd_buf[:k], kcp.snd_buf[k+1:]...) kcp.snd_buf = append(kcp.snd_buf[:k], kcp.snd_buf[k+1:]...)
seg.Release()
break break
} }
if _itimediff(sn, seg.sn) < 0 { if _itimediff(sn, seg.sn) < 0 {
@ -321,8 +325,7 @@ func (kcp *KCP) parse_fastack(sn uint32) {
return return
} }
for k := range kcp.snd_buf { for _, seg := range kcp.snd_buf {
seg := &kcp.snd_buf[k]
if _itimediff(sn, seg.sn) < 0 { if _itimediff(sn, seg.sn) < 0 {
break break
} else if sn != seg.sn { } else if sn != seg.sn {
@ -333,9 +336,9 @@ func (kcp *KCP) parse_fastack(sn uint32) {
func (kcp *KCP) parse_una(una uint32) { func (kcp *KCP) parse_una(una uint32) {
count := 0 count := 0
for k := range kcp.snd_buf { for _, seg := range kcp.snd_buf {
seg := &kcp.snd_buf[k]
if _itimediff(una, seg.sn) > 0 { if _itimediff(una, seg.sn) > 0 {
seg.Release()
count++ count++
} else { } else {
break break
@ -364,7 +367,7 @@ func (kcp *KCP) parse_data(newseg *Segment) {
insert_idx := 0 insert_idx := 0
repeat := false repeat := false
for i := n; i >= 0; i-- { for i := n; i >= 0; i-- {
seg := &kcp.rcv_buf[i] seg := kcp.rcv_buf[i]
if seg.sn == sn { if seg.sn == sn {
repeat = true repeat = true
break break
@ -377,18 +380,17 @@ func (kcp *KCP) parse_data(newseg *Segment) {
if !repeat { if !repeat {
if insert_idx == n+1 { if insert_idx == n+1 {
kcp.rcv_buf = append(kcp.rcv_buf, *newseg) kcp.rcv_buf = append(kcp.rcv_buf, newseg)
} else { } else {
kcp.rcv_buf = append(kcp.rcv_buf, Segment{}) kcp.rcv_buf = append(kcp.rcv_buf, &Segment{})
copy(kcp.rcv_buf[insert_idx+1:], kcp.rcv_buf[insert_idx:]) copy(kcp.rcv_buf[insert_idx+1:], kcp.rcv_buf[insert_idx:])
kcp.rcv_buf[insert_idx] = *newseg kcp.rcv_buf[insert_idx] = newseg
} }
} }
// move available data from rcv_buf -> rcv_queue // move available data from rcv_buf -> rcv_queue
count := 0 count := 0
for k := range kcp.rcv_buf { for k, seg := range kcp.rcv_buf {
seg := &kcp.rcv_buf[k]
if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) { if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[k]) kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[k])
kcp.rcv_nxt++ kcp.rcv_nxt++
@ -636,8 +638,7 @@ func (kcp *KCP) flush() {
} }
// flush data segments // flush data segments
for k := range kcp.snd_buf { for _, segment := range kcp.snd_buf {
segment := &kcp.snd_buf[k]
needsend := false needsend := false
if segment.xmit == 0 { if segment.xmit == 0 {
needsend = true needsend = true
@ -680,8 +681,6 @@ func (kcp *KCP) flush() {
copy(ptr, segment.data.Value) copy(ptr, segment.data.Value)
ptr = ptr[segment.data.Len():] ptr = ptr[segment.data.Len():]
segment.data.Release()
if segment.xmit >= kcp.dead_link { if segment.xmit >= kcp.dead_link {
kcp.state = 0xFFFFFFFF kcp.state = 0xFFFFFFFF
} }
@ -778,8 +777,7 @@ func (kcp *KCP) Check(current uint32) uint32 {
tm_flush = _itimediff(ts_flush, current) tm_flush = _itimediff(ts_flush, current)
for k := range kcp.snd_buf { for _, seg := range kcp.snd_buf {
seg := &kcp.snd_buf[k]
diff := _itimediff(seg.resendts, current) diff := _itimediff(seg.resendts, current)
if diff <= 0 { if diff <= 0 {
return current return current