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