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