github.com/alejandroEsc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy3/frames/common.go (about) 1 // Copyright 2014 Jamie Hall. 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 5 package frames 6 7 import ( 8 "bufio" 9 "errors" 10 "fmt" 11 12 "github.com/SlyMarbo/spdy/common" 13 ) 14 15 // ReadFrame reads and parses a frame from reader. 16 func ReadFrame(reader *bufio.Reader, subversion int) (frame common.Frame, err error) { 17 start, err := reader.Peek(4) 18 if err != nil { 19 return nil, err 20 } 21 22 if start[0] != 128 { 23 frame = new(DATA) 24 _, err = frame.ReadFrom(reader) 25 return frame, err 26 } 27 28 switch common.BytesToUint16(start[2:4]) { 29 case _SYN_STREAM: 30 switch subversion { 31 case 0: 32 frame = new(SYN_STREAM) 33 case 1: 34 frame = new(SYN_STREAMV3_1) 35 default: 36 return nil, fmt.Errorf("Error: Given subversion %d is unrecognised.", subversion) 37 } 38 case _SYN_REPLY: 39 frame = new(SYN_REPLY) 40 case _RST_STREAM: 41 frame = new(RST_STREAM) 42 case _SETTINGS: 43 frame = new(SETTINGS) 44 case _PING: 45 frame = new(PING) 46 case _GOAWAY: 47 frame = new(GOAWAY) 48 case _HEADERS: 49 frame = new(HEADERS) 50 case _WINDOW_UPDATE: 51 frame = &WINDOW_UPDATE{subversion: subversion} 52 case _CREDENTIAL: 53 frame = new(CREDENTIAL) 54 55 default: 56 return nil, errors.New("Error Failed to parse frame type.") 57 } 58 59 _, err = frame.ReadFrom(reader) 60 return frame, err 61 } 62 63 // controlFrameCommonProcessing performs checks identical between 64 // all control frames. This includes the control bit, the version 65 // number, the type byte (which is checked against the byte 66 // provided), and the flags (which are checked against the bitwise 67 // OR of valid flags provided). 68 func controlFrameCommonProcessing(data []byte, frameType uint16, flags byte) error { 69 // Check it's a control frame. 70 if data[0] != 128 { 71 return common.IncorrectFrame(_DATA_FRAME, int(frameType), 3) 72 } 73 74 // Check version. 75 version := (uint16(data[0]&0x7f) << 8) + uint16(data[1]) 76 if version != 3 { 77 return common.UnsupportedVersion(version) 78 } 79 80 // Check its type. 81 realType := common.BytesToUint16(data[2:]) 82 if realType != frameType { 83 return common.IncorrectFrame(int(realType), int(frameType), 3) 84 } 85 86 // Check the flags. 87 if data[4] & ^flags != 0 { 88 return common.InvalidField("flags", int(data[4]), int(flags)) 89 } 90 91 return nil 92 } 93 94 // Frame types in SPDY/3 95 const ( 96 _SYN_STREAM = 1 97 _SYN_REPLY = 2 98 _RST_STREAM = 3 99 _SETTINGS = 4 100 _PING = 6 101 _GOAWAY = 7 102 _HEADERS = 8 103 _WINDOW_UPDATE = 9 104 _CREDENTIAL = 10 105 _CONTROL_FRAME = -1 106 _DATA_FRAME = -2 107 ) 108 109 // frameNames provides the name for a particular SPDY/3 110 // frame type. 111 var frameNames = map[int]string{ 112 _SYN_STREAM: "SYN_STREAM", 113 _SYN_REPLY: "SYN_REPLY", 114 _RST_STREAM: "RST_STREAM", 115 _SETTINGS: "SETTINGS", 116 _PING: "PING", 117 _GOAWAY: "GOAWAY", 118 _HEADERS: "HEADERS", 119 _WINDOW_UPDATE: "WINDOW_UPDATE", 120 _CREDENTIAL: "CREDENTIAL", 121 _CONTROL_FRAME: "CONTROL_FRAME", 122 _DATA_FRAME: "DATA_FRAME", 123 }