github.com/alejandroesc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy2/frames/syn_stream.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 "bytes" 9 "errors" 10 "fmt" 11 "io" 12 "net/http" 13 14 "github.com/SlyMarbo/spdy/common" 15 ) 16 17 type SYN_STREAM struct { 18 Flags common.Flags 19 StreamID common.StreamID 20 AssocStreamID common.StreamID 21 Priority common.Priority 22 Header http.Header 23 rawHeader []byte 24 } 25 26 func (frame *SYN_STREAM) Compress(com common.Compressor) error { 27 if frame.rawHeader != nil { 28 return nil 29 } 30 31 data, err := com.Compress(frame.Header) 32 if err != nil { 33 return err 34 } 35 36 frame.rawHeader = data 37 return nil 38 } 39 40 func (frame *SYN_STREAM) Decompress(decom common.Decompressor) error { 41 if frame.Header != nil { 42 return nil 43 } 44 45 header, err := decom.Decompress(frame.rawHeader) 46 if err != nil { 47 return err 48 } 49 50 frame.Header = header 51 frame.rawHeader = nil 52 return nil 53 } 54 55 func (frame *SYN_STREAM) Name() string { 56 return "SYN_STREAM" 57 } 58 59 func (frame *SYN_STREAM) ReadFrom(reader io.Reader) (int64, error) { 60 c := common.ReadCounter{R: reader} 61 data, err := common.ReadExactly(&c, 18) 62 if err != nil { 63 return c.N, err 64 } 65 66 err = controlFrameCommonProcessing(data[:5], _SYN_STREAM, common.FLAG_FIN|common.FLAG_UNIDIRECTIONAL) 67 if err != nil { 68 return c.N, err 69 } 70 71 // Get and check length. 72 length := int(common.BytesToUint24(data[5:8])) 73 if length < 12 { 74 return c.N, common.IncorrectDataLength(length, 12) 75 } else if length > common.MAX_FRAME_SIZE-18 { 76 return c.N, common.FrameTooLarge 77 } 78 79 // Read in data. 80 header, err := common.ReadExactly(&c, length-10) 81 if err != nil { 82 return c.N, err 83 } 84 85 frame.Flags = common.Flags(data[4]) 86 frame.StreamID = common.StreamID(common.BytesToUint32(data[8:12])) 87 frame.AssocStreamID = common.StreamID(common.BytesToUint32(data[12:16])) 88 frame.Priority = common.Priority(data[16] >> 6) 89 frame.rawHeader = header 90 91 if !frame.StreamID.Valid() { 92 return c.N, common.StreamIdTooLarge 93 } 94 if frame.StreamID.Zero() { 95 return c.N, common.StreamIdIsZero 96 } 97 if !frame.AssocStreamID.Valid() { 98 return c.N, common.StreamIdTooLarge 99 } 100 101 return c.N, nil 102 } 103 104 func (frame *SYN_STREAM) String() string { 105 buf := new(bytes.Buffer) 106 flags := "" 107 if frame.Flags.FIN() { 108 flags += " common.FLAG_FIN" 109 } 110 if frame.Flags.UNIDIRECTIONAL() { 111 flags += " FLAG_UNIDIRECTIONAL" 112 } 113 if flags == "" { 114 flags = "[NONE]" 115 } else { 116 flags = flags[1:] 117 } 118 119 buf.WriteString("SYN_STREAM {\n\t") 120 buf.WriteString(fmt.Sprintf("Version: 2\n\t")) 121 buf.WriteString(fmt.Sprintf("Flags: %s\n\t", flags)) 122 buf.WriteString(fmt.Sprintf("Stream ID: %d\n\t", frame.StreamID)) 123 buf.WriteString(fmt.Sprintf("Associated Stream ID: %d\n\t", frame.AssocStreamID)) 124 buf.WriteString(fmt.Sprintf("Priority: %d\n\t", frame.Priority)) 125 buf.WriteString(fmt.Sprintf("Header: %v\n}\n", frame.Header)) 126 127 return buf.String() 128 } 129 130 func (frame *SYN_STREAM) WriteTo(writer io.Writer) (int64, error) { 131 c := common.WriteCounter{W: writer} 132 if frame.rawHeader == nil { 133 return c.N, errors.New("Error: Headers not written.") 134 } 135 if !frame.StreamID.Valid() { 136 return c.N, common.StreamIdTooLarge 137 } 138 if frame.StreamID.Zero() { 139 return c.N, common.StreamIdIsZero 140 } 141 if !frame.AssocStreamID.Valid() { 142 return c.N, common.StreamIdTooLarge 143 } 144 145 header := frame.rawHeader 146 length := 10 + len(header) 147 out := make([]byte, 18) 148 149 out[0] = 128 // Control bit and Version 150 out[1] = 2 // Version 151 out[2] = 0 // Type 152 out[3] = 1 // Type 153 out[4] = byte(frame.Flags) // Flags 154 out[5] = byte(length >> 16) // Length 155 out[6] = byte(length >> 8) // Length 156 out[7] = byte(length) // Length 157 out[8] = frame.StreamID.B1() // Stream ID 158 out[9] = frame.StreamID.B2() // Stream ID 159 out[10] = frame.StreamID.B3() // Stream ID 160 out[11] = frame.StreamID.B4() // Stream ID 161 out[12] = frame.AssocStreamID.B1() // Associated Stream ID 162 out[13] = frame.AssocStreamID.B2() // Associated Stream ID 163 out[14] = frame.AssocStreamID.B3() // Associated Stream ID 164 out[15] = frame.AssocStreamID.B4() // Associated Stream ID 165 out[16] = frame.Priority.Byte(2) // Priority and Unused 166 out[17] = 0 // Unused 167 168 err := common.WriteExactly(&c, out) 169 if err != nil { 170 return c.N, err 171 } 172 173 err = common.WriteExactly(&c, header) 174 if err != nil { 175 return c.N, err 176 } 177 178 return c.N, nil 179 }