123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- // Copyright 2011 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package spdy
- import (
- "encoding/binary"
- "io"
- "net/http"
- "strings"
- )
- func (frame *SynStreamFrame) write(f *Framer) error {
- return f.writeSynStreamFrame(frame)
- }
- func (frame *SynReplyFrame) write(f *Framer) error {
- return f.writeSynReplyFrame(frame)
- }
- func (frame *RstStreamFrame) write(f *Framer) (err error) {
- if frame.StreamId == 0 {
- return &Error{ZeroStreamId, 0}
- }
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeRstStream
- frame.CFHeader.Flags = 0
- frame.CFHeader.length = 8
- // Serialize frame to Writer.
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return
- }
- if frame.Status == 0 {
- return &Error{InvalidControlFrame, frame.StreamId}
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
- return
- }
- return
- }
- func (frame *SettingsFrame) write(f *Framer) (err error) {
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeSettings
- frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4)
- // Serialize frame to Writer.
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil {
- return
- }
- for _, flagIdValue := range frame.FlagIdValues {
- flagId := uint32(flagIdValue.Flag)<<24 | uint32(flagIdValue.Id)
- if err = binary.Write(f.w, binary.BigEndian, flagId); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, flagIdValue.Value); err != nil {
- return
- }
- }
- return
- }
- func (frame *PingFrame) write(f *Framer) (err error) {
- if frame.Id == 0 {
- return &Error{ZeroStreamId, 0}
- }
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypePing
- frame.CFHeader.Flags = 0
- frame.CFHeader.length = 4
- // Serialize frame to Writer.
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.Id); err != nil {
- return
- }
- return
- }
- func (frame *GoAwayFrame) write(f *Framer) (err error) {
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeGoAway
- frame.CFHeader.Flags = 0
- frame.CFHeader.length = 8
- // Serialize frame to Writer.
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.LastGoodStreamId); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.Status); err != nil {
- return
- }
- return nil
- }
- func (frame *HeadersFrame) write(f *Framer) error {
- return f.writeHeadersFrame(frame)
- }
- func (frame *WindowUpdateFrame) write(f *Framer) (err error) {
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeWindowUpdate
- frame.CFHeader.Flags = 0
- frame.CFHeader.length = 8
- // Serialize frame to Writer.
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.DeltaWindowSize); err != nil {
- return
- }
- return nil
- }
- func (frame *DataFrame) write(f *Framer) error {
- return f.writeDataFrame(frame)
- }
- // WriteFrame writes a frame.
- func (f *Framer) WriteFrame(frame Frame) error {
- return frame.write(f)
- }
- func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error {
- if err := binary.Write(w, binary.BigEndian, 0x8000|h.version); err != nil {
- return err
- }
- if err := binary.Write(w, binary.BigEndian, h.frameType); err != nil {
- return err
- }
- flagsAndLength := uint32(h.Flags)<<24 | h.length
- if err := binary.Write(w, binary.BigEndian, flagsAndLength); err != nil {
- return err
- }
- return nil
- }
- func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) {
- n = 0
- if err = binary.Write(w, binary.BigEndian, uint32(len(h))); err != nil {
- return
- }
- n += 2
- for name, values := range h {
- if err = binary.Write(w, binary.BigEndian, uint32(len(name))); err != nil {
- return
- }
- n += 2
- name = strings.ToLower(name)
- if _, err = io.WriteString(w, name); err != nil {
- return
- }
- n += len(name)
- v := strings.Join(values, headerValueSeparator)
- if err = binary.Write(w, binary.BigEndian, uint32(len(v))); err != nil {
- return
- }
- n += 2
- if _, err = io.WriteString(w, v); err != nil {
- return
- }
- n += len(v)
- }
- return
- }
- func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) {
- if frame.StreamId == 0 {
- return &Error{ZeroStreamId, 0}
- }
- // Marshal the headers.
- var writer io.Writer = f.headerBuf
- if !f.headerCompressionDisabled {
- writer = f.headerCompressor
- }
- if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
- return
- }
- if !f.headerCompressionDisabled {
- f.headerCompressor.Flush()
- }
- // Set ControlFrameHeader.
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeSynStream
- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10)
- // Serialize frame to Writer.
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return err
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return err
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.AssociatedToStreamId); err != nil {
- return err
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.Priority<<5); err != nil {
- return err
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.Slot); err != nil {
- return err
- }
- if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
- return err
- }
- f.headerBuf.Reset()
- return nil
- }
- func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) {
- if frame.StreamId == 0 {
- return &Error{ZeroStreamId, 0}
- }
- // Marshal the headers.
- var writer io.Writer = f.headerBuf
- if !f.headerCompressionDisabled {
- writer = f.headerCompressor
- }
- if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
- return
- }
- if !f.headerCompressionDisabled {
- f.headerCompressor.Flush()
- }
- // Set ControlFrameHeader.
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeSynReply
- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
- // Serialize frame to Writer.
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return
- }
- if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
- return
- }
- f.headerBuf.Reset()
- return
- }
- func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) {
- if frame.StreamId == 0 {
- return &Error{ZeroStreamId, 0}
- }
- // Marshal the headers.
- var writer io.Writer = f.headerBuf
- if !f.headerCompressionDisabled {
- writer = f.headerCompressor
- }
- if _, err = writeHeaderValueBlock(writer, frame.Headers); err != nil {
- return
- }
- if !f.headerCompressionDisabled {
- f.headerCompressor.Flush()
- }
- // Set ControlFrameHeader.
- frame.CFHeader.version = Version
- frame.CFHeader.frameType = TypeHeaders
- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4)
- // Serialize frame to Writer.
- if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil {
- return
- }
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return
- }
- if _, err = f.w.Write(f.headerBuf.Bytes()); err != nil {
- return
- }
- f.headerBuf.Reset()
- return
- }
- func (f *Framer) writeDataFrame(frame *DataFrame) (err error) {
- if frame.StreamId == 0 {
- return &Error{ZeroStreamId, 0}
- }
- if frame.StreamId&0x80000000 != 0 || len(frame.Data) > MaxDataLength {
- return &Error{InvalidDataFrame, frame.StreamId}
- }
- // Serialize frame to Writer.
- if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil {
- return
- }
- flagsAndLength := uint32(frame.Flags)<<24 | uint32(len(frame.Data))
- if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil {
- return
- }
- if _, err = f.w.Write(frame.Data); err != nil {
- return
- }
- return nil
- }
|