stream-server/srt/protocol.go

89 lines
1.8 KiB
Go

package srt
import (
"time"
"net"
"crypto/sha256"
"fmt"
"errors"
)
const (
INDUCTION uint8 = iota
CONCLUSION
DATA_LOOP
)
type SRTManager struct {
state uint8
init time.Time
syn_cookie uint32
socket net.PacketConn
ctrl_sock_peer uint32
}
func NewSRTManager(l net.PacketConn) (*SRTManager) {
agent := new(SRTManager)
agent.init = time.Now()
agent.socket = l
return agent
}
func (agent *SRTManager) create_induction_resp() (*Packet) {
packet := new(Packet)
packet.timestamp = uint32(time.Now().Sub(agent.init).Milliseconds())
packet.dest_sock = agent.ctrl_sock_peer
packet.packet_type = HANDSHAKE
info := new(ControlHeader)
packet.header_info = info
cif := new(HandshakeCIF)
cif.version = 5
cif.ext_field = 0x4a17
cif.hs_type = 1
cif.syn_cookie = agent.syn_cookie
cif.sock_id = 1
cif.mtu = 1500
cif.max_flow = 8192
ip := agent.socket.LocalAddr().(*net.UDPAddr).IP
for i := 0; i < len(ip); i++ {
cif.peer_ip[i] = ip[i]
}
packet.cif = cif
return packet
}
func (agent *SRTManager) make_syn_cookie(peer net.Addr) {
t := uint32(time.Now().Unix()) >> 6
s := sha256.New()
s.Write([]byte(peer.String() + fmt.Sprintf("%d", t)))
agent.syn_cookie = (agent.syn_cookie + t % 32) << 3
for _, v := range s.Sum(nil)[29:] {
agent.syn_cookie = (agent.syn_cookie << 8) + uint32(v)
}
}
func (agent *SRTManager) process_induction(packet *Packet) (*Packet) {
if packet.packet_type == HANDSHAKE {
hs_cif := packet.cif.(*HandshakeCIF)
if hs_cif.hs_type == 1 {
agent.state = 1
agent.ctrl_sock_peer = hs_cif.sock_id
return agent.create_induction_resp()
}
}
return nil
}
func (agent *SRTManager) Process(packet *Packet) (*Packet, error) {
switch agent.state {
case 0:
return agent.process_induction(packet), nil
default:
return nil, errors.New("State not implemented")
}
}