1
16
17
18
19
20
21 package spdy
22
23 import (
24 "encoding/binary"
25 "io"
26 "net/http"
27 "strings"
28 )
29
30 func (frame *SynStreamFrame) write(f *Framer) error {
31 return f.writeSynStreamFrame(frame)
32 }
33
34 func (frame *SynReplyFrame) write(f *Framer) error {
35 return f.writeSynReplyFrame(frame)
36 }
37
38 func (frame *RstStreamFrame) write(f *Framer) (err error) {
39 if frame.StreamId == 0 {
40 return &Error{ZeroStreamId, 0}
41 }
42 frame.CFHeader.version = Version
43 frame.CFHeader.frameType = TypeRstStream
44 frame.CFHeader.Flags = 0
45 frame.CFHeader.length = 8
46
47
48 if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
49 return
50 }
51 if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
52 return
53 }
54 if frame.Status == 0 {
55 return &Error{InvalidControlFrame, frame.StreamId}
56 }
57 if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
58 return
59 }
60 return
61 }
62
63 func (frame *SettingsFrame) write(f *Framer) (err error) {
64 frame.CFHeader.version = Version
65 frame.CFHeader.frameType = TypeSettings
66 frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
67
68
69 if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
70 return
71 }
72 if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
73 return
74 }
75 for _, flagIdValue := range frame.FlagIdValues {
76 flagId := uint32(flagIdValue.Flag)<<24 | uint32(flagIdValue.Id)
77 if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil {
78 return
79 }
80 if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil {
81 return
82 }
83 }
84 return
85 }
86
87 func (frame *PingFrame) write(f *Framer) (err error) {
88 if frame.Id == 0 {
89 return &Error{ZeroStreamId, 0}
90 }
91 frame.CFHeader.version = Version
92 frame.CFHeader.frameType = TypePing
93 frame.CFHeader.Flags = 0
94 frame.CFHeader.length = 4
95
96
97 if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
98 return
99 }
100 if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil {
101 return
102 }
103 return
104 }
105
106 func (frame *GoAwayFrame) write(f *Framer) (err error) {
107 frame.CFHeader.version = Version
108 frame.CFHeader.frameType = TypeGoAway
109 frame.CFHeader.Flags = 0
110 frame.CFHeader.length = 8
111
112
113 if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
114 return
115 }
116 if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil {
117 return
118 }
119 if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
120 return
121 }
122 return nil
123 }
124
125 func (frame *HeadersFrame) write(f *Framer) error {
126 return f.writeHeadersFrame(frame)
127 }
128
129 func (frame *WindowUpdateFrame) write(f *Framer) (err error) {
130 frame.CFHeader.version = Version
131 frame.CFHeader.frameType = TypeWindowUpdate
132 frame.CFHeader.Flags = 0
133 frame.CFHeader.length = 8
134
135
136 if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
137 return
138 }
139 if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
140 return
141 }
142 if err = binary.Write(f.w, binary.BigEndian, frame.DeltaWindowSize); err != nil {
143 return
144 }
145 return nil
146 }
147
148 func (frame *DataFrame) write(f *Framer) error {
149 return f.writeDataFrame(frame)
150 }
151
152
153 func (f *Framer) WriteFrame(frame Frame) error {
154 return frame.write(f)
155 }
156
157 func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error {
158 if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil {
159 return err
160 }
161 if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil {
162 return err
163 }
164 flagsAndLength := uint32(h.Flags)<<24 | h.length
165 if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil {
166 return err
167 }
168 return nil
169 }
170
171 func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) {
172 n = 0
173 if err = binary.Write(w, binary.BigEndian, uint32(len(h))); err != nil {
174 return
175 }
176 n += 2
177 for name, values := range h {
178 if err = binary.Write(w, binary.BigEndian, uint32(len(name))); err != nil {
179 return
180 }
181 n += 2
182 name = strings.ToLower(name)
183 if _, err = io.WriteString(w, name); err != nil {
184 return
185 }
186 n += len(name)
187 v := strings.Join(values, headerValueSeparator)
188 if err = binary.Write(w, binary.BigEndian, uint32(len(v))); err != nil {
189 return
190 }
191 n += 2
192 if _, err = io.WriteString(w, v); err != nil {
193 return
194 }
195 n += len(v)
196 }
197 return
198 }
199
200 func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) {
201 if frame.StreamId == 0 {
202 return &Error{ZeroStreamId, 0}
203 }
204
205 var writer io.Writer = f.headerBuf
206 if !f.headerCompressionDisabled {
207 writer = f.headerCompressor
208 }
209 if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
210 return
211 }
212 if !f.headerCompressionDisabled {
213 f.headerCompressor.Flush()
214 }
215
216
217 frame.CFHeader.version = Version
218 frame.CFHeader.frameType = TypeSynStream
219 frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
220
221
222 if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
223 return err
224 }
225 if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
226 return err
227 }
228 if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil {
229 return err
230 }
231 if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<5); err != nil {
232 return err
233 }
234 if err = binary.Write(f.w, binary.BigEndian, frame.Slot); err != nil {
235 return err
236 }
237 if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
238 return err
239 }
240 f.headerBuf.Reset()
241 return nil
242 }
243
244 func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) {
245 if frame.StreamId == 0 {
246 return &Error{ZeroStreamId, 0}
247 }
248
249 var writer io.Writer = f.headerBuf
250 if !f.headerCompressionDisabled {
251 writer = f.headerCompressor
252 }
253 if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
254 return
255 }
256 if !f.headerCompressionDisabled {
257 f.headerCompressor.Flush()
258 }
259
260
261 frame.CFHeader.version = Version
262 frame.CFHeader.frameType = TypeSynReply
263 frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
264
265
266 if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
267 return
268 }
269 if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
270 return
271 }
272 if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
273 return
274 }
275 f.headerBuf.Reset()
276 return
277 }
278
279 func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) {
280 if frame.StreamId == 0 {
281 return &Error{ZeroStreamId, 0}
282 }
283
284 var writer io.Writer = f.headerBuf
285 if !f.headerCompressionDisabled {
286 writer = f.headerCompressor
287 }
288 if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
289 return
290 }
291 if !f.headerCompressionDisabled {
292 f.headerCompressor.Flush()
293 }
294
295
296 frame.CFHeader.version = Version
297 frame.CFHeader.frameType = TypeHeaders
298 frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
299
300
301 if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
302 return
303 }
304 if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
305 return
306 }
307 if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
308 return
309 }
310 f.headerBuf.Reset()
311 return
312 }
313
314 func (f *Framer) writeDataFrame(frame *DataFrame) (err error) {
315 if frame.StreamId == 0 {
316 return &Error{ZeroStreamId, 0}
317 }
318 if frame.StreamId&0x80000000 != 0 || len(frame.Data) > MaxDataLength {
319 return &Error{InvalidDataFrame, frame.StreamId}
320 }
321
322
323 if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
324 return
325 }
326 flagsAndLength := uint32(frame.Flags)<<24 | uint32(len(frame.Data))
327 if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
328 return
329 }
330 if _, err = f.w.Write(frame.Data); err != nil {
331 return
332 }
333 return nil
334 }
335
View as plain text