blob: 9359a95015cc6ffe9a760a67a0bb373d52fb4b66 [file] [log] [blame]
Russ Cox3294cb52012-01-25 15:31:30 -05001// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package spdy
6
7import (
8 "compress/zlib"
9 "encoding/binary"
10 "io"
11 "net/http"
12 "strings"
13)
14
15func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) error {
16 return f.readSynStreamFrame(h, frame)
17}
18
19func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) error {
20 return f.readSynReplyFrame(h, frame)
21}
22
23func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) error {
24 frame.CFHeader = h
25 if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
26 return err
27 }
28 if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
29 return err
30 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +090031 if frame.Status == 0 {
32 return &Error{InvalidControlFrame, frame.StreamId}
33 }
Jeff Hodges6fefb5e2012-10-30 16:12:50 +090034 if frame.StreamId == 0 {
35 return &Error{ZeroStreamId, 0}
36 }
Russ Cox3294cb52012-01-25 15:31:30 -050037 return nil
38}
39
40func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error {
41 frame.CFHeader = h
42 var numSettings uint32
43 if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
44 return err
45 }
46 frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
47 for i := uint32(0); i < numSettings; i++ {
48 if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
49 return err
50 }
51 frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
52 frame.FlagIdValues[i].Id &= 0xffffff
53 if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
54 return err
55 }
56 }
57 return nil
58}
59
Russ Cox3294cb52012-01-25 15:31:30 -050060func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) error {
61 frame.CFHeader = h
62 if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
63 return err
64 }
Jeff Hodges6fefb5e2012-10-30 16:12:50 +090065 if frame.Id == 0 {
66 return &Error{ZeroStreamId, 0}
67 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +090068 if frame.CFHeader.Flags != 0 {
69 return &Error{InvalidControlFrame, StreamId(frame.Id)}
70 }
Russ Cox3294cb52012-01-25 15:31:30 -050071 return nil
72}
73
74func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) error {
75 frame.CFHeader = h
76 if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
77 return err
78 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +090079 if frame.CFHeader.Flags != 0 {
80 return &Error{InvalidControlFrame, frame.LastGoodStreamId}
81 }
82 if frame.CFHeader.length != 8 {
83 return &Error{InvalidControlFrame, frame.LastGoodStreamId}
84 }
85 if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
86 return err
87 }
Russ Cox3294cb52012-01-25 15:31:30 -050088 return nil
89}
90
91func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) error {
92 return f.readHeadersFrame(h, frame)
93}
94
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +090095func (frame *WindowUpdateFrame) read(h ControlFrameHeader, f *Framer) error {
96 frame.CFHeader = h
97 if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
98 return err
99 }
100 if frame.CFHeader.Flags != 0 {
101 return &Error{InvalidControlFrame, frame.StreamId}
102 }
103 if frame.CFHeader.length != 8 {
104 return &Error{InvalidControlFrame, frame.StreamId}
105 }
106 if err := binary.Read(f.r, binary.BigEndian, &frame.DeltaWindowSize); err != nil {
107 return err
108 }
109 return nil
110}
111
Russ Cox3294cb52012-01-25 15:31:30 -0500112func newControlFrame(frameType ControlFrameType) (controlFrame, error) {
113 ctor, ok := cframeCtor[frameType]
114 if !ok {
115 return nil, &Error{Err: InvalidControlFrame}
116 }
117 return ctor(), nil
118}
119
120var cframeCtor = map[ControlFrameType]func() controlFrame{
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900121 TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
122 TypeSynReply: func() controlFrame { return new(SynReplyFrame) },
123 TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
124 TypeSettings: func() controlFrame { return new(SettingsFrame) },
125 TypePing: func() controlFrame { return new(PingFrame) },
126 TypeGoAway: func() controlFrame { return new(GoAwayFrame) },
127 TypeHeaders: func() controlFrame { return new(HeadersFrame) },
128 TypeWindowUpdate: func() controlFrame { return new(WindowUpdateFrame) },
Russ Cox3294cb52012-01-25 15:31:30 -0500129}
130
131func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) error {
132 if f.headerDecompressor != nil {
133 f.headerReader.N = payloadSize
134 return nil
135 }
136 f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900137 decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(headerDictionary))
Russ Cox3294cb52012-01-25 15:31:30 -0500138 if err != nil {
139 return err
140 }
141 f.headerDecompressor = decompressor
142 return nil
143}
144
145// ReadFrame reads SPDY encoded data and returns a decompressed Frame.
146func (f *Framer) ReadFrame() (Frame, error) {
147 var firstWord uint32
148 if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
149 return nil, err
150 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900151 if firstWord&0x80000000 != 0 {
Russ Cox3294cb52012-01-25 15:31:30 -0500152 frameType := ControlFrameType(firstWord & 0xffff)
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900153 version := uint16(firstWord >> 16 & 0x7fff)
Russ Cox3294cb52012-01-25 15:31:30 -0500154 return f.parseControlFrame(version, frameType)
155 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900156 return f.parseDataFrame(StreamId(firstWord & 0x7fffffff))
Russ Cox3294cb52012-01-25 15:31:30 -0500157}
158
159func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, error) {
160 var length uint32
161 if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
162 return nil, err
163 }
164 flags := ControlFlags((length & 0xff000000) >> 24)
165 length &= 0xffffff
166 header := ControlFrameHeader{version, frameType, flags, length}
167 cframe, err := newControlFrame(frameType)
168 if err != nil {
169 return nil, err
170 }
171 if err = cframe.read(header, f); err != nil {
172 return nil, err
173 }
174 return cframe, nil
175}
176
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900177func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) {
178 var numHeaders uint32
Russ Cox3294cb52012-01-25 15:31:30 -0500179 if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
180 return nil, err
181 }
182 var e error
183 h := make(http.Header, int(numHeaders))
184 for i := 0; i < int(numHeaders); i++ {
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900185 var length uint32
Russ Cox3294cb52012-01-25 15:31:30 -0500186 if err := binary.Read(r, binary.BigEndian, &length); err != nil {
187 return nil, err
188 }
189 nameBytes := make([]byte, length)
190 if _, err := io.ReadFull(r, nameBytes); err != nil {
191 return nil, err
192 }
193 name := string(nameBytes)
194 if name != strings.ToLower(name) {
195 e = &Error{UnlowercasedHeaderName, streamId}
196 name = strings.ToLower(name)
197 }
198 if h[name] != nil {
199 e = &Error{DuplicateHeaders, streamId}
200 }
201 if err := binary.Read(r, binary.BigEndian, &length); err != nil {
202 return nil, err
203 }
204 value := make([]byte, length)
205 if _, err := io.ReadFull(r, value); err != nil {
206 return nil, err
207 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900208 valueList := strings.Split(string(value), headerValueSeparator)
Russ Cox3294cb52012-01-25 15:31:30 -0500209 for _, v := range valueList {
210 h.Add(name, v)
211 }
212 }
213 if e != nil {
214 return h, e
215 }
216 return h, nil
217}
218
219func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) error {
220 frame.CFHeader = h
221 var err error
222 if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
223 return err
224 }
225 if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
226 return err
227 }
228 if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
229 return err
230 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900231 frame.Priority >>= 5
232 if err = binary.Read(f.r, binary.BigEndian, &frame.Slot); err != nil {
233 return err
234 }
Russ Cox3294cb52012-01-25 15:31:30 -0500235 reader := f.r
236 if !f.headerCompressionDisabled {
Jeff Hodges06fe5ee2012-10-29 10:23:10 -0400237 err := f.uncorkHeaderDecompressor(int64(h.length - 10))
238 if err != nil {
239 return err
240 }
Russ Cox3294cb52012-01-25 15:31:30 -0500241 reader = f.headerDecompressor
242 }
Russ Cox3294cb52012-01-25 15:31:30 -0500243 frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900244 if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
Russ Cox3294cb52012-01-25 15:31:30 -0500245 err = &Error{WrongCompressedPayloadSize, 0}
246 }
247 if err != nil {
248 return err
249 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900250 for h := range frame.Headers {
251 if invalidReqHeaders[h] {
252 return &Error{InvalidHeaderPresent, frame.StreamId}
Russ Cox3294cb52012-01-25 15:31:30 -0500253 }
254 }
Jeff Hodges6fefb5e2012-10-30 16:12:50 +0900255 if frame.StreamId == 0 {
256 return &Error{ZeroStreamId, 0}
257 }
Russ Cox3294cb52012-01-25 15:31:30 -0500258 return nil
259}
260
261func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) error {
262 frame.CFHeader = h
263 var err error
264 if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
265 return err
266 }
Russ Cox3294cb52012-01-25 15:31:30 -0500267 reader := f.r
268 if !f.headerCompressionDisabled {
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900269 err := f.uncorkHeaderDecompressor(int64(h.length - 4))
Jeff Hodges06fe5ee2012-10-29 10:23:10 -0400270 if err != nil {
271 return err
272 }
Russ Cox3294cb52012-01-25 15:31:30 -0500273 reader = f.headerDecompressor
274 }
275 frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900276 if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
Russ Cox3294cb52012-01-25 15:31:30 -0500277 err = &Error{WrongCompressedPayloadSize, 0}
278 }
279 if err != nil {
280 return err
281 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900282 for h := range frame.Headers {
283 if invalidRespHeaders[h] {
284 return &Error{InvalidHeaderPresent, frame.StreamId}
Russ Cox3294cb52012-01-25 15:31:30 -0500285 }
286 }
Jeff Hodges6fefb5e2012-10-30 16:12:50 +0900287 if frame.StreamId == 0 {
288 return &Error{ZeroStreamId, 0}
289 }
Russ Cox3294cb52012-01-25 15:31:30 -0500290 return nil
291}
292
293func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) error {
294 frame.CFHeader = h
295 var err error
296 if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
297 return err
298 }
Russ Cox3294cb52012-01-25 15:31:30 -0500299 reader := f.r
300 if !f.headerCompressionDisabled {
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900301 err := f.uncorkHeaderDecompressor(int64(h.length - 4))
Jeff Hodges06fe5ee2012-10-29 10:23:10 -0400302 if err != nil {
303 return err
304 }
Russ Cox3294cb52012-01-25 15:31:30 -0500305 reader = f.headerDecompressor
306 }
307 frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900308 if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
Russ Cox3294cb52012-01-25 15:31:30 -0500309 err = &Error{WrongCompressedPayloadSize, 0}
310 }
311 if err != nil {
312 return err
313 }
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900314 var invalidHeaders map[string]bool
315 if frame.StreamId%2 == 0 {
316 invalidHeaders = invalidReqHeaders
317 } else {
318 invalidHeaders = invalidRespHeaders
319 }
320 for h := range frame.Headers {
321 if invalidHeaders[h] {
322 return &Error{InvalidHeaderPresent, frame.StreamId}
Russ Cox3294cb52012-01-25 15:31:30 -0500323 }
324 }
Jeff Hodges6fefb5e2012-10-30 16:12:50 +0900325 if frame.StreamId == 0 {
326 return &Error{ZeroStreamId, 0}
327 }
Russ Cox3294cb52012-01-25 15:31:30 -0500328 return nil
329}
330
Yusuke Kagiwada10d81ae2013-02-06 19:24:32 +0900331func (f *Framer) parseDataFrame(streamId StreamId) (*DataFrame, error) {
Russ Cox3294cb52012-01-25 15:31:30 -0500332 var length uint32
333 if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
334 return nil, err
335 }
336 var frame DataFrame
337 frame.StreamId = streamId
338 frame.Flags = DataFlags(length >> 24)
339 length &= 0xffffff
340 frame.Data = make([]byte, length)
341 if _, err := io.ReadFull(f.r, frame.Data); err != nil {
342 return nil, err
343 }
Jeff Hodges6fefb5e2012-10-30 16:12:50 +0900344 if frame.StreamId == 0 {
345 return nil, &Error{ZeroStreamId, 0}
346 }
Russ Cox3294cb52012-01-25 15:31:30 -0500347 return &frame, nil
348}