108 lines
2.2 KiB
Go
108 lines
2.2 KiB
Go
|
package pingtunnel
|
||
|
|
||
|
import (
|
||
|
"container/list"
|
||
|
"github.com/esrrhs/go-engine/src/rbuffergo"
|
||
|
"math/rand"
|
||
|
"sync"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
type FrameMgr struct {
|
||
|
sendb *rbuffergo.RBuffergo
|
||
|
recvb *rbuffergo.RBuffergo
|
||
|
sendlock sync.Locker
|
||
|
recvlock sync.Locker
|
||
|
windowsize int
|
||
|
resend_timems int
|
||
|
win *list.List
|
||
|
sendid int
|
||
|
sendlist *list.List
|
||
|
}
|
||
|
|
||
|
func NewFrameMgr(buffersize int, windowsize int, resend_timems int) *FrameMgr {
|
||
|
|
||
|
sendb := rbuffergo.New(buffersize, false)
|
||
|
recvb := rbuffergo.New(buffersize, false)
|
||
|
|
||
|
fm := &FrameMgr{sendb: sendb, recvb: recvb,
|
||
|
sendlock: &sync.Mutex{}, recvlock: &sync.Mutex{},
|
||
|
windowsize: windowsize, win: list.New(), sendid: rand.Int() % (FRAME_MAX_ID + 1),
|
||
|
resend_timems: resend_timems, sendlist: list.New()}
|
||
|
|
||
|
return fm
|
||
|
}
|
||
|
|
||
|
func (fm *FrameMgr) GetSendBufferLeft() int {
|
||
|
left := fm.sendb.Capacity() - fm.sendb.Size()
|
||
|
return left
|
||
|
}
|
||
|
|
||
|
func (fm *FrameMgr) WriteSendBuffer(data []byte) {
|
||
|
fm.sendlock.Lock()
|
||
|
defer fm.sendlock.Unlock()
|
||
|
fm.sendb.Write(data)
|
||
|
}
|
||
|
|
||
|
func (fm *FrameMgr) Update() {
|
||
|
fm.cutSendBufferToWindow()
|
||
|
fm.calSendList()
|
||
|
}
|
||
|
|
||
|
func (fm *FrameMgr) cutSendBufferToWindow() {
|
||
|
fm.sendlock.Lock()
|
||
|
defer fm.sendlock.Unlock()
|
||
|
|
||
|
sendall := false
|
||
|
|
||
|
if fm.sendb.Size() < FRAME_MAX_SIZE {
|
||
|
sendall = true
|
||
|
}
|
||
|
|
||
|
for fm.sendb.Size() > FRAME_MAX_SIZE && fm.win.Len() < fm.windowsize {
|
||
|
f := Frame{resend: false, sendtime: 0,
|
||
|
id: fm.sendid, size: FRAME_MAX_SIZE,
|
||
|
data: make([]byte, FRAME_MAX_SIZE)}
|
||
|
fm.sendb.Read(f.data)
|
||
|
|
||
|
fm.sendid++
|
||
|
if fm.sendid > FRAME_MAX_ID {
|
||
|
fm.sendid = 0
|
||
|
}
|
||
|
|
||
|
fm.win.PushBack(f)
|
||
|
}
|
||
|
|
||
|
if sendall && fm.sendb.Size() > 0 && fm.win.Len() < fm.windowsize {
|
||
|
f := Frame{resend: false, sendtime: 0,
|
||
|
id: fm.sendid, size: fm.sendb.Size(),
|
||
|
data: make([]byte, fm.sendb.Size())}
|
||
|
fm.sendb.Read(f.data)
|
||
|
|
||
|
fm.sendid++
|
||
|
if fm.sendid > FRAME_MAX_ID {
|
||
|
fm.sendid = 0
|
||
|
}
|
||
|
|
||
|
fm.win.PushBack(f)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (fm *FrameMgr) calSendList() {
|
||
|
cur := time.Now().UnixNano()
|
||
|
|
||
|
fm.sendlist.Init()
|
||
|
|
||
|
for e := fm.win.Front(); e != nil; e = e.Next() {
|
||
|
f := e.Value.(Frame)
|
||
|
if f.resend || cur-f.sendtime > int64(fm.resend_timems*1000) {
|
||
|
f.sendtime = cur
|
||
|
fm.sendlist.PushBack(&f)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (fm *FrameMgr) getSendList() *list.List {
|
||
|
return fm.sendlist
|
||
|
}
|