goodbye.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package rtcp
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. )
  6. // The Goodbye packet indicates that one or more sources are no longer active.
  7. type Goodbye struct {
  8. // The SSRC/CSRC identifiers that are no longer active
  9. Sources []uint32
  10. // Optional text indicating the reason for leaving, e.g., "camera malfunction" or "RTP loop detected"
  11. Reason string
  12. }
  13. // Marshal encodes the Goodbye packet in binary
  14. func (g Goodbye) Marshal() ([]byte, error) {
  15. /*
  16. * 0 1 2 3
  17. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  18. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  19. * |V=2|P| SC | PT=BYE=203 | length |
  20. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  21. * | SSRC/CSRC |
  22. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  23. * : ... :
  24. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  25. * (opt) | length | reason for leaving ...
  26. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  27. */
  28. rawPacket := make([]byte, g.len())
  29. packetBody := rawPacket[headerLength:]
  30. if len(g.Sources) > countMax {
  31. return nil, errTooManySources
  32. }
  33. for i, s := range g.Sources {
  34. binary.BigEndian.PutUint32(packetBody[i*ssrcLength:], s)
  35. }
  36. if g.Reason != "" {
  37. reason := []byte(g.Reason)
  38. if len(reason) > sdesMaxOctetCount {
  39. return nil, errReasonTooLong
  40. }
  41. reasonOffset := len(g.Sources) * ssrcLength
  42. packetBody[reasonOffset] = uint8(len(reason))
  43. copy(packetBody[reasonOffset+1:], reason)
  44. }
  45. hData, err := g.Header().Marshal()
  46. if err != nil {
  47. return nil, err
  48. }
  49. copy(rawPacket, hData)
  50. return rawPacket, nil
  51. }
  52. // Unmarshal decodes the Goodbye packet from binary
  53. func (g *Goodbye) Unmarshal(rawPacket []byte) error {
  54. /*
  55. * 0 1 2 3
  56. * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  57. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  58. * |V=2|P| SC | PT=BYE=203 | length |
  59. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  60. * | SSRC/CSRC |
  61. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  62. * : ... :
  63. * +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  64. * (opt) | length | reason for leaving ...
  65. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  66. */
  67. var header Header
  68. if err := header.Unmarshal(rawPacket); err != nil {
  69. return err
  70. }
  71. if header.Type != TypeGoodbye {
  72. return errWrongType
  73. }
  74. if getPadding(len(rawPacket)) != 0 {
  75. return errPacketTooShort
  76. }
  77. g.Sources = make([]uint32, header.Count)
  78. reasonOffset := int(headerLength + header.Count*ssrcLength)
  79. if reasonOffset > len(rawPacket) {
  80. return errPacketTooShort
  81. }
  82. for i := 0; i < int(header.Count); i++ {
  83. offset := headerLength + i*ssrcLength
  84. g.Sources[i] = binary.BigEndian.Uint32(rawPacket[offset:])
  85. }
  86. if reasonOffset < len(rawPacket) {
  87. reasonLen := int(rawPacket[reasonOffset])
  88. reasonEnd := reasonOffset + 1 + reasonLen
  89. if reasonEnd > len(rawPacket) {
  90. return errPacketTooShort
  91. }
  92. g.Reason = string(rawPacket[reasonOffset+1 : reasonEnd])
  93. }
  94. return nil
  95. }
  96. // Header returns the Header associated with this packet.
  97. func (g *Goodbye) Header() Header {
  98. return Header{
  99. Padding: false,
  100. Count: uint8(len(g.Sources)),
  101. Type: TypeGoodbye,
  102. Length: uint16((g.len() / 4) - 1),
  103. }
  104. }
  105. func (g *Goodbye) len() int {
  106. srcsLength := len(g.Sources) * ssrcLength
  107. reasonLength := len(g.Reason) + 1
  108. l := headerLength + srcsLength + reasonLength
  109. // align to 32-bit boundary
  110. return l + getPadding(l)
  111. }
  112. // DestinationSSRC returns an array of SSRC values that this packet refers to.
  113. func (g *Goodbye) DestinationSSRC() []uint32 {
  114. out := make([]uint32, len(g.Sources))
  115. copy(out, g.Sources)
  116. return out
  117. }
  118. func (g Goodbye) String() string {
  119. out := "Goodbye\n"
  120. for i, s := range g.Sources {
  121. out += fmt.Sprintf("\tSource %d: %x\n", i, s)
  122. }
  123. out += fmt.Sprintf("\tReason: %s\n", g.Reason)
  124. return out
  125. }