2019-10-19 17:36:17 +03:00
|
|
|
package pingtunnel
|
|
|
|
|
|
|
|
import (
|
|
|
|
"container/list"
|
|
|
|
"github.com/esrrhs/go-engine/src/rbuffergo"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type FrameMgr struct {
|
2019-10-23 15:36:13 +03:00
|
|
|
sendb *rbuffergo.RBuffergo
|
|
|
|
recvb *rbuffergo.RBuffergo
|
|
|
|
|
2019-10-19 17:36:17 +03:00
|
|
|
recvlock sync.Locker
|
|
|
|
windowsize int
|
|
|
|
resend_timems int
|
2019-10-23 15:36:13 +03:00
|
|
|
|
|
|
|
sendwin *list.List
|
|
|
|
sendlist *list.List
|
|
|
|
sendid int
|
|
|
|
|
|
|
|
recvwin *list.List
|
|
|
|
recvlist *list.List
|
|
|
|
recvid int
|
2019-10-19 17:36:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2019-10-23 15:36:13 +03:00
|
|
|
recvlock: &sync.Mutex{},
|
|
|
|
windowsize: windowsize, resend_timems: resend_timems,
|
|
|
|
sendwin: list.New(), sendlist: list.New(), sendid: 0,
|
|
|
|
recvwin: list.New(), recvlist: list.New(), recvid: 0}
|
2019-10-19 17:36:17 +03:00
|
|
|
|
|
|
|
return fm
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fm *FrameMgr) GetSendBufferLeft() int {
|
|
|
|
left := fm.sendb.Capacity() - fm.sendb.Size()
|
|
|
|
return left
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fm *FrameMgr) WriteSendBuffer(data []byte) {
|
|
|
|
fm.sendb.Write(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fm *FrameMgr) Update() {
|
|
|
|
fm.cutSendBufferToWindow()
|
2019-10-23 15:36:13 +03:00
|
|
|
|
|
|
|
fm.sendlist.Init()
|
|
|
|
tmpreq, tmpack, tmpackto := fm.preProcessRecvList()
|
|
|
|
fm.processRecvList(tmpreq, tmpack, tmpackto)
|
|
|
|
|
2019-10-19 17:36:17 +03:00
|
|
|
fm.calSendList()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fm *FrameMgr) cutSendBufferToWindow() {
|
|
|
|
|
|
|
|
sendall := false
|
|
|
|
|
|
|
|
if fm.sendb.Size() < FRAME_MAX_SIZE {
|
|
|
|
sendall = true
|
|
|
|
}
|
|
|
|
|
2019-10-23 15:36:13 +03:00
|
|
|
for fm.sendb.Size() >= FRAME_MAX_SIZE && fm.sendwin.Len() < fm.windowsize {
|
|
|
|
f := &Frame{Type: (int32)(Frame_DATA), Resend: false, Sendtime: 0,
|
2019-10-22 16:04:25 +03:00
|
|
|
Id: (int32)(fm.sendid),
|
|
|
|
Data: make([]byte, FRAME_MAX_SIZE)}
|
|
|
|
fm.sendb.Read(f.Data)
|
2019-10-19 17:36:17 +03:00
|
|
|
|
|
|
|
fm.sendid++
|
|
|
|
if fm.sendid > FRAME_MAX_ID {
|
|
|
|
fm.sendid = 0
|
|
|
|
}
|
|
|
|
|
2019-10-23 15:36:13 +03:00
|
|
|
fm.sendwin.PushBack(f)
|
2019-10-19 17:36:17 +03:00
|
|
|
}
|
|
|
|
|
2019-10-23 15:36:13 +03:00
|
|
|
if sendall && fm.sendb.Size() > 0 && fm.sendwin.Len() < fm.windowsize {
|
|
|
|
f := &Frame{Type: (int32)(Frame_DATA), Resend: false, Sendtime: 0,
|
2019-10-22 16:04:25 +03:00
|
|
|
Id: (int32)(fm.sendid),
|
|
|
|
Data: make([]byte, fm.sendb.Size())}
|
|
|
|
fm.sendb.Read(f.Data)
|
2019-10-19 17:36:17 +03:00
|
|
|
|
|
|
|
fm.sendid++
|
|
|
|
if fm.sendid > FRAME_MAX_ID {
|
|
|
|
fm.sendid = 0
|
|
|
|
}
|
|
|
|
|
2019-10-23 15:36:13 +03:00
|
|
|
fm.sendwin.PushBack(f)
|
2019-10-19 17:36:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fm *FrameMgr) calSendList() {
|
|
|
|
cur := time.Now().UnixNano()
|
2019-10-23 15:36:13 +03:00
|
|
|
for e := fm.sendwin.Front(); e != nil; e = e.Next() {
|
|
|
|
f := e.Value.(*Frame)
|
2019-10-22 16:04:25 +03:00
|
|
|
if f.Resend || cur-f.Sendtime > int64(fm.resend_timems*1000) {
|
|
|
|
f.Sendtime = cur
|
2019-10-23 15:36:13 +03:00
|
|
|
fm.sendlist.PushBack(f)
|
|
|
|
f.Resend = false
|
2019-10-19 17:36:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fm *FrameMgr) getSendList() *list.List {
|
|
|
|
return fm.sendlist
|
|
|
|
}
|
2019-10-23 15:36:13 +03:00
|
|
|
|
|
|
|
func (fm *FrameMgr) OnRecvFrame(f *Frame) {
|
|
|
|
fm.recvlock.Lock()
|
|
|
|
defer fm.recvlock.Unlock()
|
|
|
|
|
|
|
|
fm.recvlist.PushBack(f)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fm *FrameMgr) preProcessRecvList() (map[int32]int, map[int32]int, map[int32]*Frame) {
|
|
|
|
fm.recvlock.Lock()
|
|
|
|
defer fm.recvlock.Unlock()
|
|
|
|
|
|
|
|
tmpreq := make(map[int32]int)
|
|
|
|
tmpack := make(map[int32]int)
|
|
|
|
tmpackto := make(map[int32]*Frame)
|
|
|
|
for e := fm.recvlist.Front(); e != nil; e = e.Next() {
|
|
|
|
f := e.Value.(*Frame)
|
|
|
|
if f.Type == (int32)(Frame_REQ) {
|
|
|
|
for _, id := range f.Dataid {
|
|
|
|
tmpreq[id]++
|
|
|
|
}
|
|
|
|
} else if f.Type == (int32)(Frame_ACK) {
|
|
|
|
for _, id := range f.Dataid {
|
|
|
|
tmpack[id]++
|
|
|
|
}
|
|
|
|
} else if f.Type == (int32)(Frame_DATA) {
|
|
|
|
tmpackto[f.Id] = f
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fm.recvlist.Init()
|
|
|
|
return tmpreq, tmpack, tmpackto
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fm *FrameMgr) processRecvList(tmpreq map[int32]int, tmpack map[int32]int, tmpackto map[int32]*Frame) {
|
|
|
|
|
|
|
|
for id, _ := range tmpreq {
|
|
|
|
for e := fm.sendwin.Front(); e != nil; e = e.Next() {
|
|
|
|
f := e.Value.(*Frame)
|
|
|
|
if f.Id == id {
|
|
|
|
f.Resend = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for id, _ := range tmpack {
|
|
|
|
for e := fm.sendwin.Front(); e != nil; e = e.Next() {
|
|
|
|
f := e.Value.(*Frame)
|
|
|
|
if f.Id == id {
|
|
|
|
fm.sendwin.Remove(e)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(tmpackto) > 0 {
|
|
|
|
f := &Frame{Type: (int32)(Frame_ACK), Resend: false, Sendtime: 0,
|
|
|
|
Id: 0,
|
|
|
|
Dataid: make([]int32, len(tmpackto))}
|
|
|
|
index := 0
|
|
|
|
for id, rf := range tmpackto {
|
|
|
|
f.Dataid[index] = id
|
|
|
|
index++
|
|
|
|
fm.addToRecvWin(rf)
|
|
|
|
}
|
|
|
|
fm.sendlist.PushBack(f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fm *FrameMgr) addToRecvWin(rf *Frame) {
|
|
|
|
|
|
|
|
for e := fm.recvwin.Front(); e != nil; e = e.Next() {
|
|
|
|
f := e.Value.(*Frame)
|
|
|
|
if f.Id == rf.Id {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for e := fm.recvwin.Front(); e != nil; e = e.Next() {
|
|
|
|
f := e.Value.(*Frame)
|
|
|
|
if rf.Id < f.Id {
|
|
|
|
fm.recvwin.InsertBefore(rf, e)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if fm.recvwin.Len() > 0 {
|
|
|
|
fm.recvwin.PushBack(rf)
|
|
|
|
} else {
|
|
|
|
fm.recvwin.PushBack(rf)
|
|
|
|
}
|
|
|
|
}
|