1
16
17
18
19
20
21 package spdy
22
23 import (
24 "compress/zlib"
25 "encoding/binary"
26 "io"
27 "net/http"
28 "strings"
29 )
30
31 func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) error {
32 return f.readSynStreamFrame(h, frame)
33 }
34
35 func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) error {
36 return f.readSynReplyFrame(h, frame)
37 }
38
39 func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) error {
40 frame.CFHeader = h
41 if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
42 return err
43 }
44 if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
45 return err
46 }
47 if frame.Status == 0 {
48 return &Error{InvalidControlFrame, frame.StreamId}
49 }
50 if frame.StreamId == 0 {
51 return &Error{ZeroStreamId, 0}
52 }
53 return nil
54 }
55
56 func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error {
57 frame.CFHeader = h
58 var numSettings uint32
59 if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
60 return err
61 }
62 frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
63 for i := uint32(0); i < numSettings; i++ {
64 if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
65 return err
66 }
67 frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
68 frame.FlagIdValues[i].Id &= 0xffffff
69 if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
70 return err
71 }
72 }
73 return nil
74 }
75
76 func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) error {
77 frame.CFHeader = h
78 if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
79 return err
80 }
81 if frame.Id == 0 {
82 return &Error{ZeroStreamId, 0}
83 }
84 if frame.CFHeader.Flags != 0 {
85 return &Error{InvalidControlFrame, StreamId(frame.Id)}
86 }
87 return nil
88 }
89
90 func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) error {
91 frame.CFHeader = h
92 if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
93 return err
94 }
95 if frame.CFHeader.Flags != 0 {
96 return &Error{InvalidControlFrame, frame.LastGoodStreamId}
97 }
98 if frame.CFHeader.length != 8 {
99 return &Error{InvalidControlFrame, frame.LastGoodStreamId}
100 }
101 if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
102 return err
103 }
104 return nil
105 }
106
107 func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) error {
108 return f.readHeadersFrame(h, frame)
109 }
110
111 func (frame *WindowUpdateFrame) read(h ControlFrameHeader, f *Framer) error {
112 frame.CFHeader = h
113 if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
114 return err
115 }
116 if frame.CFHeader.Flags != 0 {
117 return &Error{InvalidControlFrame, frame.StreamId}
118 }
119 if frame.CFHeader.length != 8 {
120 return &Error{InvalidControlFrame, frame.StreamId}
121 }
122 if err := binary.Read(f.r, binary.BigEndian, &frame.DeltaWindowSize); err != nil {
123 return err
124 }
125 return nil
126 }
127
128 func newControlFrame(frameType ControlFrameType) (controlFrame, error) {
129 ctor, ok := cframeCtor[frameType]
130 if !ok {
131 return nil, &Error{Err: InvalidControlFrame}
132 }
133 return ctor(), nil
134 }
135
136 var cframeCtor = map[ControlFrameType]func() controlFrame{
137 TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
138 TypeSynReply: func() controlFrame { return new(SynReplyFrame) },
139 TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
140 TypeSettings: func() controlFrame { return new(SettingsFrame) },
141 TypePing: func() controlFrame { return new(PingFrame) },
142 TypeGoAway: func() controlFrame { return new(GoAwayFrame) },
143 TypeHeaders: func() controlFrame { return new(HeadersFrame) },
144 TypeWindowUpdate: func() controlFrame { return new(WindowUpdateFrame) },
145 }
146
147 func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) error {
148 if f.headerDecompressor != nil {
149 f.headerReader.N = payloadSize
150 return nil
151 }
152 f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
153 decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(headerDictionary))
154 if err != nil {
155 return err
156 }
157 f.headerDecompressor = decompressor
158 return nil
159 }
160
161
162 func (f *Framer) ReadFrame() (Frame, error) {
163 var firstWord uint32
164 if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
165 return nil, err
166 }
167 if firstWord&0x80000000 != 0 {
168 frameType := ControlFrameType(firstWord & 0xffff)
169 version := uint16(firstWord >> 16 & 0x7fff)
170 return f.parseControlFrame(version, frameType)
171 }
172 return f.parseDataFrame(StreamId(firstWord & 0x7fffffff))
173 }
174
175 func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, error) {
176 var length uint32
177 if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
178 return nil, err
179 }
180 flags := ControlFlags((length & 0xff000000) >> 24)
181 length &= 0xffffff
182 header := ControlFrameHeader{version, frameType, flags, length}
183 cframe, err := newControlFrame(frameType)
184 if err != nil {
185 return nil, err
186 }
187 if err = cframe.read(header, f); err != nil {
188 return nil, err
189 }
190 return cframe, nil
191 }
192
193 func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) {
194 var numHeaders uint32
195 if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
196 return nil, err
197 }
198 var e error
199 h := make(http.Header, int(numHeaders))
200 for i := 0; i < int(numHeaders); i++ {
201 var length uint32
202 if err := binary.Read(r, binary.BigEndian, &length); err != nil {
203 return nil, err
204 }
205 nameBytes := make([]byte, length)
206 if _, err := io.ReadFull(r, nameBytes); err != nil {
207 return nil, err
208 }
209 name := string(nameBytes)
210 if name != strings.ToLower(name) {
211 e = &Error{UnlowercasedHeaderName, streamId}
212 name = strings.ToLower(name)
213 }
214 if h[name] != nil {
215 e = &Error{DuplicateHeaders, streamId}
216 }
217 if err := binary.Read(r, binary.BigEndian, &length); err != nil {
218 return nil, err
219 }
220 value := make([]byte, length)
221 if _, err := io.ReadFull(r, value); err != nil {
222 return nil, err
223 }
224 valueList := strings.Split(string(value), headerValueSeparator)
225 for _, v := range valueList {
226 h.Add(name, v)
227 }
228 }
229 if e != nil {
230 return h, e
231 }
232 return h, nil
233 }
234
235 func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) error {
236 frame.CFHeader = h
237 var err error
238 if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
239 return err
240 }
241 if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
242 return err
243 }
244 if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
245 return err
246 }
247 frame.Priority >>= 5
248 if err = binary.Read(f.r, binary.BigEndian, &frame.Slot); err != nil {
249 return err
250 }
251 reader := f.r
252 if !f.headerCompressionDisabled {
253 err := f.uncorkHeaderDecompressor(int64(h.length - 10))
254 if err != nil {
255 return err
256 }
257 reader = f.headerDecompressor
258 }
259 frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
260 if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
261 err = &Error{WrongCompressedPayloadSize, 0}
262 }
263 if err != nil {
264 return err
265 }
266 for h := range frame.Headers {
267 if invalidReqHeaders[h] {
268 return &Error{InvalidHeaderPresent, frame.StreamId}
269 }
270 }
271 if frame.StreamId == 0 {
272 return &Error{ZeroStreamId, 0}
273 }
274 return nil
275 }
276
277 func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) error {
278 frame.CFHeader = h
279 var err error
280 if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
281 return err
282 }
283 reader := f.r
284 if !f.headerCompressionDisabled {
285 err := f.uncorkHeaderDecompressor(int64(h.length - 4))
286 if err != nil {
287 return err
288 }
289 reader = f.headerDecompressor
290 }
291 frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
292 if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
293 err = &Error{WrongCompressedPayloadSize, 0}
294 }
295 if err != nil {
296 return err
297 }
298 for h := range frame.Headers {
299 if invalidRespHeaders[h] {
300 return &Error{InvalidHeaderPresent, frame.StreamId}
301 }
302 }
303 if frame.StreamId == 0 {
304 return &Error{ZeroStreamId, 0}
305 }
306 return nil
307 }
308
309 func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) error {
310 frame.CFHeader = h
311 var err error
312 if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
313 return err
314 }
315 reader := f.r
316 if !f.headerCompressionDisabled {
317 err := f.uncorkHeaderDecompressor(int64(h.length - 4))
318 if err != nil {
319 return err
320 }
321 reader = f.headerDecompressor
322 }
323 frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
324 if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
325 err = &Error{WrongCompressedPayloadSize, 0}
326 }
327 if err != nil {
328 return err
329 }
330 var invalidHeaders map[string]bool
331 if frame.StreamId%2 == 0 {
332 invalidHeaders = invalidReqHeaders
333 } else {
334 invalidHeaders = invalidRespHeaders
335 }
336 for h := range frame.Headers {
337 if invalidHeaders[h] {
338 return &Error{InvalidHeaderPresent, frame.StreamId}
339 }
340 }
341 if frame.StreamId == 0 {
342 return &Error{ZeroStreamId, 0}
343 }
344 return nil
345 }
346
347 func (f *Framer) parseDataFrame(streamId StreamId) (*DataFrame, error) {
348 var length uint32
349 if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
350 return nil, err
351 }
352 var frame DataFrame
353 frame.StreamId = streamId
354 frame.Flags = DataFlags(length >> 24)
355 length &= 0xffffff
356 frame.Data = make([]byte, length)
357 if _, err := io.ReadFull(f.r, frame.Data); err != nil {
358 return nil, err
359 }
360 if frame.StreamId == 0 {
361 return nil, &Error{ZeroStreamId, 0}
362 }
363 return &frame, nil
364 }
365
View as plain text