123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- // 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 (
- "compress/zlib"
- "encoding/binary"
- "io"
- "net/http"
- "strings"
- )
- func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) error {
- return f.readSynStreamFrame(h, frame)
- }
- func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) error {
- return f.readSynReplyFrame(h, frame)
- }
- func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
- return err
- }
- if frame.Status == 0 {
- return &Error{InvalidControlFrame, frame.StreamId}
- }
- if frame.StreamId == 0 {
- return &Error{ZeroStreamId, 0}
- }
- return nil
- }
- func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- var numSettings uint32
- if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
- return err
- }
- frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
- for i := uint32(0); i < numSettings; i++ {
- if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
- return err
- }
- frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
- frame.FlagIdValues[i].Id &= 0xffffff
- if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
- return err
- }
- }
- return nil
- }
- func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
- return err
- }
- if frame.Id == 0 {
- return &Error{ZeroStreamId, 0}
- }
- if frame.CFHeader.Flags != 0 {
- return &Error{InvalidControlFrame, StreamId(frame.Id)}
- }
- return nil
- }
- func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
- return err
- }
- if frame.CFHeader.Flags != 0 {
- return &Error{InvalidControlFrame, frame.LastGoodStreamId}
- }
- if frame.CFHeader.length != 8 {
- return &Error{InvalidControlFrame, frame.LastGoodStreamId}
- }
- if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
- return err
- }
- return nil
- }
- func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) error {
- return f.readHeadersFrame(h, frame)
- }
- func (frame *WindowUpdateFrame) read(h ControlFrameHeader, f *Framer) error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- if frame.CFHeader.Flags != 0 {
- return &Error{InvalidControlFrame, frame.StreamId}
- }
- if frame.CFHeader.length != 8 {
- return &Error{InvalidControlFrame, frame.StreamId}
- }
- if err := binary.Read(f.r, binary.BigEndian, &frame.DeltaWindowSize); err != nil {
- return err
- }
- return nil
- }
- func newControlFrame(frameType ControlFrameType) (controlFrame, error) {
- ctor, ok := cframeCtor[frameType]
- if !ok {
- return nil, &Error{Err: InvalidControlFrame}
- }
- return ctor(), nil
- }
- var cframeCtor = map[ControlFrameType]func() controlFrame{
- TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
- TypeSynReply: func() controlFrame { return new(SynReplyFrame) },
- TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
- TypeSettings: func() controlFrame { return new(SettingsFrame) },
- TypePing: func() controlFrame { return new(PingFrame) },
- TypeGoAway: func() controlFrame { return new(GoAwayFrame) },
- TypeHeaders: func() controlFrame { return new(HeadersFrame) },
- TypeWindowUpdate: func() controlFrame { return new(WindowUpdateFrame) },
- }
- func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) error {
- if f.headerDecompressor != nil {
- f.headerReader.N = payloadSize
- return nil
- }
- f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
- decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(headerDictionary))
- if err != nil {
- return err
- }
- f.headerDecompressor = decompressor
- return nil
- }
- // ReadFrame reads SPDY encoded data and returns a decompressed Frame.
- func (f *Framer) ReadFrame() (Frame, error) {
- var firstWord uint32
- if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
- return nil, err
- }
- if firstWord&0x80000000 != 0 {
- frameType := ControlFrameType(firstWord & 0xffff)
- version := uint16(firstWord >> 16 & 0x7fff)
- return f.parseControlFrame(version, frameType)
- }
- return f.parseDataFrame(StreamId(firstWord & 0x7fffffff))
- }
- func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, error) {
- var length uint32
- if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- flags := ControlFlags((length & 0xff000000) >> 24)
- length &= 0xffffff
- header := ControlFrameHeader{version, frameType, flags, length}
- cframe, err := newControlFrame(frameType)
- if err != nil {
- return nil, err
- }
- if err = cframe.read(header, f); err != nil {
- return nil, err
- }
- return cframe, nil
- }
- func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) {
- var numHeaders uint32
- if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
- return nil, err
- }
- var e error
- h := make(http.Header, int(numHeaders))
- for i := 0; i < int(numHeaders); i++ {
- var length uint32
- if err := binary.Read(r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- nameBytes := make([]byte, length)
- if _, err := io.ReadFull(r, nameBytes); err != nil {
- return nil, err
- }
- name := string(nameBytes)
- if name != strings.ToLower(name) {
- e = &Error{UnlowercasedHeaderName, streamId}
- name = strings.ToLower(name)
- }
- if h[name] != nil {
- e = &Error{DuplicateHeaders, streamId}
- }
- if err := binary.Read(r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- value := make([]byte, length)
- if _, err := io.ReadFull(r, value); err != nil {
- return nil, err
- }
- valueList := strings.Split(string(value), headerValueSeparator)
- for _, v := range valueList {
- h.Add(name, v)
- }
- }
- if e != nil {
- return h, e
- }
- return h, nil
- }
- func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) error {
- frame.CFHeader = h
- var err error
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
- return err
- }
- if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
- return err
- }
- frame.Priority >>= 5
- if err = binary.Read(f.r, binary.BigEndian, &frame.Slot); err != nil {
- return err
- }
- reader := f.r
- if !f.headerCompressionDisabled {
- err := f.uncorkHeaderDecompressor(int64(h.length - 10))
- if err != nil {
- return err
- }
- reader = f.headerDecompressor
- }
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
- if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
- err = &Error{WrongCompressedPayloadSize, 0}
- }
- if err != nil {
- return err
- }
- for h := range frame.Headers {
- if invalidReqHeaders[h] {
- return &Error{InvalidHeaderPresent, frame.StreamId}
- }
- }
- if frame.StreamId == 0 {
- return &Error{ZeroStreamId, 0}
- }
- return nil
- }
- func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) error {
- frame.CFHeader = h
- var err error
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- reader := f.r
- if !f.headerCompressionDisabled {
- err := f.uncorkHeaderDecompressor(int64(h.length - 4))
- if err != nil {
- return err
- }
- reader = f.headerDecompressor
- }
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
- if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
- err = &Error{WrongCompressedPayloadSize, 0}
- }
- if err != nil {
- return err
- }
- for h := range frame.Headers {
- if invalidRespHeaders[h] {
- return &Error{InvalidHeaderPresent, frame.StreamId}
- }
- }
- if frame.StreamId == 0 {
- return &Error{ZeroStreamId, 0}
- }
- return nil
- }
- func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) error {
- frame.CFHeader = h
- var err error
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- reader := f.r
- if !f.headerCompressionDisabled {
- err := f.uncorkHeaderDecompressor(int64(h.length - 4))
- if err != nil {
- return err
- }
- reader = f.headerDecompressor
- }
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
- if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) {
- err = &Error{WrongCompressedPayloadSize, 0}
- }
- if err != nil {
- return err
- }
- var invalidHeaders map[string]bool
- if frame.StreamId%2 == 0 {
- invalidHeaders = invalidReqHeaders
- } else {
- invalidHeaders = invalidRespHeaders
- }
- for h := range frame.Headers {
- if invalidHeaders[h] {
- return &Error{InvalidHeaderPresent, frame.StreamId}
- }
- }
- if frame.StreamId == 0 {
- return &Error{ZeroStreamId, 0}
- }
- return nil
- }
- func (f *Framer) parseDataFrame(streamId StreamId) (*DataFrame, error) {
- var length uint32
- if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- var frame DataFrame
- frame.StreamId = streamId
- frame.Flags = DataFlags(length >> 24)
- length &= 0xffffff
- frame.Data = make([]byte, length)
- if _, err := io.ReadFull(f.r, frame.Data); err != nil {
- return nil, err
- }
- if frame.StreamId == 0 {
- return nil, &Error{ZeroStreamId, 0}
- }
- return &frame, nil
- }
|