You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

146 lines
3.6 KiB

  1. // Copyright 2015 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package marbl
  15. import (
  16. "bufio"
  17. "encoding/binary"
  18. "fmt"
  19. "io"
  20. )
  21. // Header is either an HTTP header or meta-data pertaining to the request or response.
  22. type Header struct {
  23. ID string
  24. MessageType MessageType
  25. Name string
  26. Value string
  27. }
  28. // String returns the contents of a Header frame in a format appropriate for debugging and runtime logging.
  29. func (hf Header) String() string {
  30. return fmt.Sprintf("ID=%s; Type=%d; Name=%s; Value=%s", hf.ID, hf.MessageType, hf.Name, hf.Value)
  31. }
  32. // FrameType returns HeaderFrame
  33. func (hf Header) FrameType() FrameType {
  34. return HeaderFrame
  35. }
  36. // Data is the payload (body) of the request or response.
  37. type Data struct {
  38. ID string
  39. MessageType MessageType
  40. Index uint32
  41. Terminal bool
  42. Data []byte
  43. }
  44. // String returns the contents of a Data frame in a format appropriate for debugging and runtime logging. The
  45. // contents of the data content slice (df.Data) is not printed, instead the length of Data is printed.
  46. func (df Data) String() string {
  47. return fmt.Sprintf("ID=%s; Type=%d; Index=%d; Terminal=%t; Data length=%d",
  48. df.ID, df.MessageType, df.Index, df.Terminal, len(df.Data))
  49. }
  50. // FrameType returns DataFrame
  51. func (df Data) FrameType() FrameType {
  52. return DataFrame
  53. }
  54. // Frame describes the interface for a frame (either Data or Header).
  55. type Frame interface {
  56. String() string
  57. FrameType() FrameType
  58. }
  59. // Reader wraps a buffered Reader that reads from the io.Reader and emits Frames.
  60. type Reader struct {
  61. r io.Reader
  62. }
  63. // NewReader returns a Reader initialized with a buffered reader.
  64. func NewReader(r io.Reader) *Reader {
  65. return &Reader{
  66. r: bufio.NewReader(r),
  67. }
  68. }
  69. // ReadFrame reads from r, determines the FrameType, and returns either a Header or Data and an error.
  70. func (r *Reader) ReadFrame() (Frame, error) {
  71. fh := make([]byte, 10)
  72. if _, err := io.ReadFull(r.r, fh); err != nil {
  73. return nil, err
  74. }
  75. switch FrameType(fh[0]) {
  76. case HeaderFrame:
  77. hf := Header{
  78. ID: string(fh[2:]),
  79. MessageType: MessageType(fh[1]),
  80. }
  81. lens := make([]byte, 8)
  82. if _, err := io.ReadFull(r.r, lens); err != nil {
  83. return nil, err
  84. }
  85. nl := binary.BigEndian.Uint32(lens[:4])
  86. vl := binary.BigEndian.Uint32(lens[4:])
  87. nv := make([]byte, int(nl+vl))
  88. if _, err := io.ReadFull(r.r, nv); err != nil {
  89. return nil, err
  90. }
  91. hf.Name = string(nv[:nl])
  92. hf.Value = string(nv[nl:])
  93. return hf, nil
  94. case DataFrame:
  95. df := Data{
  96. ID: string(fh[2:]),
  97. MessageType: MessageType(fh[1]),
  98. }
  99. // Reading 9 bytes:
  100. // 4 bytes index
  101. // 1 byte terminal
  102. // 4 bytes data length
  103. desc := make([]byte, 9)
  104. if _, err := io.ReadFull(r.r, desc); err != nil {
  105. return nil, err
  106. }
  107. df.Index = binary.BigEndian.Uint32(desc[:4])
  108. df.Terminal = desc[4] == 1
  109. dl := binary.BigEndian.Uint32(desc[5:])
  110. data := make([]byte, int(dl))
  111. if _, err := io.ReadFull(r.r, data); err != nil {
  112. return nil, err
  113. }
  114. df.Data = data
  115. return df, nil
  116. default:
  117. return nil, fmt.Errorf("marbl: unknown type of frame")
  118. }
  119. }