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") } }