|
- package aoiprxkit
-
- import (
- "encoding/binary"
- "fmt"
- "net"
- )
-
- const (
- DefaultSAPGroup = "224.2.127.254"
- DefaultSAPPort = 9875
- )
-
- type SAPPacket struct {
- Version uint8
- AddressTypeIPv6 bool
- IsDelete bool
- Encrypted bool
- Compressed bool
- AuthLenWords uint8
- MessageIDHash uint16
- OriginSource net.IP
- PayloadType string
- Payload []byte
- }
-
- type SAPAnnouncement struct {
- ReceivedAt string `json:"receivedAt"`
- SourceAddr string `json:"sourceAddr"`
- MessageID uint16 `json:"messageIdHash"`
- Delete bool `json:"delete"`
- PayloadType string `json:"payloadType"`
- SDP string `json:"sdp"`
- ParsedSDP SDPInfo `json:"parsedSdp"`
- }
-
- func ParseSAPPacket(buf []byte) (SAPPacket, error) {
- if len(buf) < 8 {
- return SAPPacket{}, fmt.Errorf("SAP packet too short")
- }
-
- b0 := buf[0]
- version := b0 >> 5
- if version != 1 {
- return SAPPacket{}, fmt.Errorf("unsupported SAP version %d", version)
- }
-
- addrTypeIPv6 := (b0 & 0x10) != 0
- isDelete := (b0 & 0x04) != 0
- encrypted := (b0 & 0x02) != 0
- compressed := (b0 & 0x01) != 0
- authLenWords := buf[1]
- msgID := binary.BigEndian.Uint16(buf[2:4])
-
- hdrLen := 4
- var origin net.IP
- if addrTypeIPv6 {
- if len(buf) < hdrLen+16 {
- return SAPPacket{}, fmt.Errorf("SAP packet too short for IPv6 source")
- }
- origin = net.IP(buf[hdrLen : hdrLen+16])
- hdrLen += 16
- } else {
- if len(buf) < hdrLen+4 {
- return SAPPacket{}, fmt.Errorf("SAP packet too short for IPv4 source")
- }
- origin = net.IP(buf[hdrLen : hdrLen+4])
- hdrLen += 4
- }
-
- authBytes := int(authLenWords) * 4
- if len(buf) < hdrLen+authBytes {
- return SAPPacket{}, fmt.Errorf("SAP packet too short for auth section")
- }
- hdrLen += authBytes
-
- if encrypted || compressed {
- return SAPPacket{}, fmt.Errorf("encrypted/compressed SAP payloads are not supported")
- }
-
- payloadType := "application/sdp"
- payloadStart := hdrLen
-
- if len(buf) > payloadStart && !(len(buf)-payloadStart >= 4 && string(buf[payloadStart:payloadStart+4]) == "v=0\n" || len(buf)-payloadStart >= 5 && string(buf[payloadStart:payloadStart+5]) == "v=0\r\n") {
- nul := -1
- for i := payloadStart; i < len(buf); i++ {
- if buf[i] == 0 {
- nul = i
- break
- }
- }
- if nul == -1 {
- return SAPPacket{}, fmt.Errorf("SAP payload type missing NUL terminator")
- }
- payloadType = string(buf[payloadStart:nul])
- payloadStart = nul + 1
- }
-
- if payloadStart > len(buf) {
- return SAPPacket{}, fmt.Errorf("invalid SAP payload start")
- }
-
- return SAPPacket{
- Version: version,
- AddressTypeIPv6: addrTypeIPv6,
- IsDelete: isDelete,
- Encrypted: encrypted,
- Compressed: compressed,
- AuthLenWords: authLenWords,
- MessageIDHash: msgID,
- OriginSource: origin,
- PayloadType: payloadType,
- Payload: append([]byte(nil), buf[payloadStart:]...),
- }, nil
- }
|