Files
core/udt/udtsocket_cc.go

215 lines
5.0 KiB
Go

package udt
import (
"time"
"github.com/PeernetOfficial/core/udt/packet"
)
type congMsgType int
const (
congInit congMsgType = iota
congClose
congOnACK
congOnNAK
congOnTimeout
congOnDataPktSent
congOnPktSent
congOnPktRecv
congOnCustomMsg
)
type congMsg struct {
mtyp congMsgType
pktID packet.PacketID
arg interface{}
}
type udtSocketCc struct {
// channels
sockClosed <-chan struct{} // closed when socket is closed
socket *udtSocket
congestion CongestionControl // congestion control object for this socket
msgs chan congMsg
sendPktSeq packet.PacketID // packetID of most recently sent packet
congWindow uint // size of congestion window (in packets)
sndPeriod time.Duration // delay between sending packets
}
func newUdtSocketCc(s *udtSocket) *udtSocketCc {
newCongestion := s.Config.CongestionForSocket
if newCongestion == nil {
newCongestion = DefaultConfig().CongestionForSocket
}
sc := &udtSocketCc{
socket: s,
sockClosed: s.sockClosed,
congestion: newCongestion(s),
msgs: make(chan congMsg, 100),
}
go sc.goCongestionEvent()
return sc
}
func (s *udtSocketCc) goCongestionEvent() {
msgs := s.msgs
sockClosed := s.sockClosed
for {
select {
case evt, ok := <-msgs:
if !ok {
return
}
switch evt.mtyp {
case congInit:
s.sendPktSeq = evt.pktID
s.congestion.Init(s, s.socket.Config.SynTime)
case congClose:
s.congestion.Close(s)
case congOnACK:
s.congestion.OnACK(s, evt.pktID)
case congOnNAK:
s.congestion.OnNAK(s, evt.arg.([]packet.PacketID))
case congOnTimeout:
s.congestion.OnTimeout(s)
case congOnDataPktSent:
s.sendPktSeq = evt.pktID
case congOnPktSent:
s.congestion.OnPktSent(s, evt.arg.(packet.Packet))
case congOnPktRecv:
s.congestion.OnPktRecv(s, evt.arg.(packet.DataPacket))
case congOnCustomMsg:
s.congestion.OnCustomMsg(s, evt.arg.(packet.UserDefControlPacket))
}
case _, _ = <-sockClosed:
return
}
}
}
// Init to be called (only) at the start of a UDT connection.
func (s *udtSocketCc) init(sendPktSeq packet.PacketID) {
s.msgs <- congMsg{
mtyp: congInit,
pktID: sendPktSeq,
}
}
// Close to be called when a UDT connection is closed.
func (s *udtSocketCc) close() {
s.msgs <- congMsg{
mtyp: congClose,
}
}
// OnACK to be called when an ACK packet is received
func (s *udtSocketCc) onACK(pktID packet.PacketID) {
s.msgs <- congMsg{
mtyp: congOnACK,
pktID: pktID,
}
}
// OnNAK to be called when a loss report is received
func (s *udtSocketCc) onNAK(loss []packet.PacketID) {
s.msgs <- congMsg{
mtyp: congOnNAK,
arg: loss,
}
}
// OnTimeout to be called when a timeout event occurs
func (s *udtSocketCc) onTimeout() {
s.msgs <- congMsg{
mtyp: congOnTimeout,
}
}
// OnPktSent to be called when data is sent
func (s *udtSocketCc) onDataPktSent(pktID packet.PacketID) {
s.msgs <- congMsg{
mtyp: congOnDataPktSent,
pktID: pktID,
}
}
// OnPktSent to be called when data is sent
func (s *udtSocketCc) onPktSent(p packet.Packet) {
s.msgs <- congMsg{
mtyp: congOnPktSent,
arg: p,
}
}
// OnPktRecv to be called when data is received
func (s *udtSocketCc) onPktRecv(p packet.DataPacket) {
s.msgs <- congMsg{
mtyp: congOnPktRecv,
arg: p,
}
}
// OnCustomMsg to process a user-defined packet
func (s *udtSocketCc) onCustomMsg(p packet.UserDefControlPacket) {
s.msgs <- congMsg{
mtyp: congOnCustomMsg,
arg: p,
}
}
// GetSndCurrSeqNo is the most recently sent packet ID
func (s *udtSocketCc) GetSndCurrSeqNo() packet.PacketID {
return s.sendPktSeq
}
// SetCongestionWindowSize sets the size of the congestion window (in packets)
func (s *udtSocketCc) SetCongestionWindowSize(pkt uint) {
s.congWindow = pkt
s.socket.send.congestWindow.set(uint32(pkt))
}
// GetCongestionWindowSize gets the size of the congestion window (in packets)
func (s *udtSocketCc) GetCongestionWindowSize() uint {
return s.congWindow
}
// GetPacketSendPeriod gets the current delay between sending packets
func (s *udtSocketCc) GetPacketSendPeriod() time.Duration {
return s.sndPeriod
}
// SetPacketSendPeriod sets the current delay between sending packets
func (s *udtSocketCc) SetPacketSendPeriod(snd time.Duration) {
s.sndPeriod = snd
s.socket.send.SetPacketSendPeriod(snd)
}
// GetMaxFlowWindow is the largest number of unacknowledged packets we can receive (in packets)
func (s *udtSocketCc) GetMaxFlowWindow() uint {
return s.socket.maxFlowWinSize
}
// GetReceiveRates is the current calculated receive rate and bandwidth (in packets/sec)
func (s *udtSocketCc) GetReceiveRates() (uint, uint) {
return s.socket.getRcvSpeeds()
}
// GetRTT is the current calculated roundtrip time between peers
func (s *udtSocketCc) GetRTT() time.Duration {
rtt, _ := s.socket.getRTT()
return time.Duration(rtt) * time.Microsecond
}
// GetMSS is the largest packet size we can currently send (in bytes)
func (s *udtSocketCc) GetMSS() uint {
return uint(s.socket.maxPacketSize)
}
// SetACKPerid sets the time between ACKs sent to the peer
func (s *udtSocketCc) SetACKPeriod(ack time.Duration) {
s.socket.recv.ackPeriod.set(ack)
}