github.com/spotmaxtech/k8s-apimachinery-v0260@v0.0.1/pkg/util/framer/framer.go (about) 1 /* 2 Copyright 2015 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // Package framer implements simple frame decoding techniques for an io.ReadCloser 18 package framer 19 20 import ( 21 "encoding/binary" 22 "encoding/json" 23 "io" 24 ) 25 26 type lengthDelimitedFrameWriter struct { 27 w io.Writer 28 h [4]byte 29 } 30 31 func NewLengthDelimitedFrameWriter(w io.Writer) io.Writer { 32 return &lengthDelimitedFrameWriter{w: w} 33 } 34 35 // Write writes a single frame to the nested writer, prepending it with the length in 36 // in bytes of data (as a 4 byte, bigendian uint32). 37 func (w *lengthDelimitedFrameWriter) Write(data []byte) (int, error) { 38 binary.BigEndian.PutUint32(w.h[:], uint32(len(data))) 39 n, err := w.w.Write(w.h[:]) 40 if err != nil { 41 return 0, err 42 } 43 if n != len(w.h) { 44 return 0, io.ErrShortWrite 45 } 46 return w.w.Write(data) 47 } 48 49 type lengthDelimitedFrameReader struct { 50 r io.ReadCloser 51 remaining int 52 } 53 54 // NewLengthDelimitedFrameReader returns an io.Reader that will decode length-prefixed 55 // frames off of a stream. 56 // 57 // The protocol is: 58 // 59 // stream: message ... 60 // message: prefix body 61 // prefix: 4 byte uint32 in BigEndian order, denotes length of body 62 // body: bytes (0..prefix) 63 // 64 // If the buffer passed to Read is not long enough to contain an entire frame, io.ErrShortRead 65 // will be returned along with the number of bytes read. 66 func NewLengthDelimitedFrameReader(r io.ReadCloser) io.ReadCloser { 67 return &lengthDelimitedFrameReader{r: r} 68 } 69 70 // Read attempts to read an entire frame into data. If that is not possible, io.ErrShortBuffer 71 // is returned and subsequent calls will attempt to read the last frame. A frame is complete when 72 // err is nil. 73 func (r *lengthDelimitedFrameReader) Read(data []byte) (int, error) { 74 if r.remaining <= 0 { 75 header := [4]byte{} 76 n, err := io.ReadAtLeast(r.r, header[:4], 4) 77 if err != nil { 78 return 0, err 79 } 80 if n != 4 { 81 return 0, io.ErrUnexpectedEOF 82 } 83 frameLength := int(binary.BigEndian.Uint32(header[:])) 84 r.remaining = frameLength 85 } 86 87 expect := r.remaining 88 max := expect 89 if max > len(data) { 90 max = len(data) 91 } 92 n, err := io.ReadAtLeast(r.r, data[:max], int(max)) 93 r.remaining -= n 94 if err == io.ErrShortBuffer || r.remaining > 0 { 95 return n, io.ErrShortBuffer 96 } 97 if err != nil { 98 return n, err 99 } 100 if n != expect { 101 return n, io.ErrUnexpectedEOF 102 } 103 104 return n, nil 105 } 106 107 func (r *lengthDelimitedFrameReader) Close() error { 108 return r.r.Close() 109 } 110 111 type jsonFrameReader struct { 112 r io.ReadCloser 113 decoder *json.Decoder 114 remaining []byte 115 } 116 117 // NewJSONFramedReader returns an io.Reader that will decode individual JSON objects off 118 // of a wire. 119 // 120 // The boundaries between each frame are valid JSON objects. A JSON parsing error will terminate 121 // the read. 122 func NewJSONFramedReader(r io.ReadCloser) io.ReadCloser { 123 return &jsonFrameReader{ 124 r: r, 125 decoder: json.NewDecoder(r), 126 } 127 } 128 129 // ReadFrame decodes the next JSON object in the stream, or returns an error. The returned 130 // byte slice will be modified the next time ReadFrame is invoked and should not be altered. 131 func (r *jsonFrameReader) Read(data []byte) (int, error) { 132 // Return whatever remaining data exists from an in progress frame 133 if n := len(r.remaining); n > 0 { 134 if n <= len(data) { 135 //nolint:staticcheck // SA4006,SA4010 underlying array of data is modified here. 136 data = append(data[0:0], r.remaining...) 137 r.remaining = nil 138 return n, nil 139 } 140 141 n = len(data) 142 //nolint:staticcheck // SA4006,SA4010 underlying array of data is modified here. 143 data = append(data[0:0], r.remaining[:n]...) 144 r.remaining = r.remaining[n:] 145 return n, io.ErrShortBuffer 146 } 147 148 // RawMessage#Unmarshal appends to data - we reset the slice down to 0 and will either see 149 // data written to data, or be larger than data and a different array. 150 n := len(data) 151 m := json.RawMessage(data[:0]) 152 if err := r.decoder.Decode(&m); err != nil { 153 return 0, err 154 } 155 156 // If capacity of data is less than length of the message, decoder will allocate a new slice 157 // and set m to it, which means we need to copy the partial result back into data and preserve 158 // the remaining result for subsequent reads. 159 if len(m) > n { 160 //nolint:staticcheck // SA4006,SA4010 underlying array of data is modified here. 161 data = append(data[0:0], m[:n]...) 162 r.remaining = m[n:] 163 return n, io.ErrShortBuffer 164 } 165 return len(m), nil 166 } 167 168 func (r *jsonFrameReader) Close() error { 169 return r.r.Close() 170 }