pingtunnel/framemgr.go
2019-10-22 21:27:21 +08:00

107 lines
2.1 KiB
Go

package pingtunnel
import (
"container/list"
"github.com/esrrhs/go-engine/src/rbuffergo"
"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: 0,
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: (int32)(fm.sendid),
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: (int32)(fm.sendid),
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
}