Control.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. package framestream
  2. import (
  3. "bufio"
  4. "bytes"
  5. "encoding/binary"
  6. "io"
  7. )
  8. const CONTROL_ACCEPT = 0x01
  9. const CONTROL_START = 0x02
  10. const CONTROL_STOP = 0x03
  11. const CONTROL_READY = 0x04
  12. const CONTROL_FINISH = 0x05
  13. const CONTROL_FIELD_CONTENT_TYPE = 0x01
  14. const CONTROL_FRAME_LENGTH_MAX = 512
  15. type ControlFrame struct {
  16. ControlType uint32
  17. ContentTypes [][]byte
  18. }
  19. var ControlStart = ControlFrame{ControlType: CONTROL_START}
  20. var ControlStop = ControlFrame{ControlType: CONTROL_STOP}
  21. var ControlReady = ControlFrame{ControlType: CONTROL_READY}
  22. var ControlAccept = ControlFrame{ControlType: CONTROL_ACCEPT}
  23. var ControlFinish = ControlFrame{ControlType: CONTROL_FINISH}
  24. func (c *ControlFrame) Encode(w io.Writer) (err error) {
  25. var buf bytes.Buffer
  26. err = binary.Write(&buf, binary.BigEndian, c.ControlType)
  27. if err != nil {
  28. return
  29. }
  30. for _, ctype := range c.ContentTypes {
  31. err = binary.Write(&buf, binary.BigEndian, uint32(CONTROL_FIELD_CONTENT_TYPE))
  32. if err != nil {
  33. return
  34. }
  35. err = binary.Write(&buf, binary.BigEndian, uint32(len(ctype)))
  36. if err != nil {
  37. return
  38. }
  39. _, err = buf.Write(ctype)
  40. if err != nil {
  41. return
  42. }
  43. }
  44. err = binary.Write(w, binary.BigEndian, uint32(0))
  45. if err != nil {
  46. return
  47. }
  48. err = binary.Write(w, binary.BigEndian, uint32(buf.Len()))
  49. if err != nil {
  50. return
  51. }
  52. _, err = buf.WriteTo(w)
  53. return
  54. }
  55. func (c *ControlFrame) EncodeFlush(w *bufio.Writer) error {
  56. if err := c.Encode(w); err != nil {
  57. return err
  58. }
  59. return w.Flush()
  60. }
  61. func (c *ControlFrame) Decode(r io.Reader) (err error) {
  62. var cflen uint32
  63. err = binary.Read(r, binary.BigEndian, &cflen)
  64. if err != nil {
  65. return
  66. }
  67. if cflen > CONTROL_FRAME_LENGTH_MAX {
  68. return ErrDecode
  69. }
  70. if cflen < 4 {
  71. return ErrDecode
  72. }
  73. err = binary.Read(r, binary.BigEndian, &c.ControlType)
  74. if err != nil {
  75. return
  76. }
  77. cflen -= 4
  78. if cflen > 0 {
  79. cfields := make([]byte, int(cflen))
  80. _, err = io.ReadFull(r, cfields)
  81. if err != nil {
  82. return
  83. }
  84. for len(cfields) > 8 {
  85. cftype := binary.BigEndian.Uint32(cfields[:4])
  86. cfields = cfields[4:]
  87. if cftype != CONTROL_FIELD_CONTENT_TYPE {
  88. return ErrDecode
  89. }
  90. cflen := int(binary.BigEndian.Uint32(cfields[:4]))
  91. cfields = cfields[4:]
  92. if cflen > len(cfields) {
  93. return ErrDecode
  94. }
  95. c.ContentTypes = append(c.ContentTypes, cfields[:cflen])
  96. cfields = cfields[cflen:]
  97. }
  98. if len(cfields) > 0 {
  99. return ErrDecode
  100. }
  101. }
  102. return
  103. }
  104. func (c *ControlFrame) DecodeEscape(r io.Reader) error {
  105. var zero uint32
  106. err := binary.Read(r, binary.BigEndian, &zero)
  107. if err != nil {
  108. return err
  109. }
  110. if zero != 0 {
  111. return ErrDecode
  112. }
  113. return c.Decode(r)
  114. }
  115. func (c *ControlFrame) DecodeTypeEscape(r io.Reader, ctype uint32) error {
  116. err := c.DecodeEscape(r)
  117. if err != nil {
  118. return err
  119. }
  120. if ctype != c.ControlType {
  121. return ErrDecode
  122. }
  123. return nil
  124. }
  125. // ChooseContentType selects a content type from the ControlFrame which
  126. // also exists in the supplied ctypes. Preference is given to values occurring
  127. // earliest in ctypes.
  128. //
  129. // ChooseContentType returns the chosen content type, which may be nil, and
  130. // a bool value indicating whether a matching type was found.
  131. //
  132. // If either the ControlFrame types or ctypes is empty, ChooseContentType
  133. // returns nil as a matching content type.
  134. func (c *ControlFrame) ChooseContentType(ctypes [][]byte) (typ []byte, found bool) {
  135. if c.ContentTypes == nil || ctypes == nil {
  136. return nil, true
  137. }
  138. tm := make(map[string]bool)
  139. for _, cfctype := range c.ContentTypes {
  140. tm[string(cfctype)] = true
  141. }
  142. for _, ctype := range ctypes {
  143. if tm[string(ctype)] {
  144. return ctype, true
  145. }
  146. }
  147. return nil, false
  148. }
  149. func (c *ControlFrame) MatchContentType(ctype []byte) bool {
  150. for _, cfctype := range c.ContentTypes {
  151. if bytes.Compare(ctype, cfctype) == 0 {
  152. return true
  153. }
  154. }
  155. return len(c.ContentTypes) == 0
  156. }
  157. func (c *ControlFrame) SetContentTypes(ctypes [][]byte) {
  158. c.ContentTypes = ctypes
  159. }
  160. func (c *ControlFrame) SetContentType(ctype []byte) {
  161. if ctype != nil {
  162. c.SetContentTypes([][]byte{ctype})
  163. } else {
  164. c.ContentTypes = nil
  165. }
  166. }