github.com/alejandroEsc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy2/frames/settings.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 "sort" 13 14 "github.com/SlyMarbo/spdy/common" 15 ) 16 17 type SETTINGS struct { 18 Flags common.Flags 19 Settings common.Settings 20 } 21 22 func (frame *SETTINGS) Add(Flags common.Flags, id uint32, value uint32) { 23 frame.Settings[id] = &common.Setting{Flags, id, value} 24 } 25 26 func (frame *SETTINGS) Compress(comp common.Compressor) error { 27 return nil 28 } 29 30 func (frame *SETTINGS) Decompress(decomp common.Decompressor) error { 31 return nil 32 } 33 34 func (frame *SETTINGS) Name() string { 35 return "SETTINGS" 36 } 37 38 func (frame *SETTINGS) ReadFrom(reader io.Reader) (int64, error) { 39 c := common.ReadCounter{R: reader} 40 data, err := common.ReadExactly(&c, 12) 41 if err != nil { 42 return c.N, err 43 } 44 45 err = controlFrameCommonProcessing(data[:5], _SETTINGS, common.FLAG_SETTINGS_CLEAR_SETTINGS) 46 if err != nil { 47 return c.N, err 48 } 49 50 // Get and check length. 51 length := int(common.BytesToUint24(data[5:8])) 52 if length < 4 { 53 return c.N, common.IncorrectDataLength(length, 8) 54 } else if length > common.MAX_FRAME_SIZE-8 { 55 return c.N, common.FrameTooLarge 56 } 57 58 // Check size. 59 numSettings := int(common.BytesToUint32(data[8:12])) 60 if length != 4+(8*numSettings) { 61 return c.N, common.IncorrectDataLength(length, 4+(8*numSettings)) 62 } 63 64 // Read in data. 65 settings, err := common.ReadExactly(&c, 8*numSettings) 66 if err != nil { 67 return c.N, err 68 } 69 70 frame.Flags = common.Flags(data[4]) 71 frame.Settings = make(common.Settings) 72 for i := 0; i < numSettings; i++ { 73 j := i * 8 74 setting := decodeSetting(settings[j:]) 75 if setting == nil { 76 return c.N, errors.New("Error: Failed to parse settings.") 77 } 78 frame.Settings[setting.ID] = setting 79 } 80 81 return c.N, nil 82 } 83 84 func (frame *SETTINGS) String() string { 85 buf := new(bytes.Buffer) 86 flags := "" 87 if frame.Flags.CLEAR_SETTINGS() { 88 flags += " FLAG_SETTINGS_CLEAR_SETTINGS" 89 } 90 if flags == "" { 91 flags = "[NONE]" 92 } else { 93 flags = flags[1:] 94 } 95 96 buf.WriteString("SETTINGS {\n\t") 97 buf.WriteString(fmt.Sprintf("Version: 2\n\t")) 98 buf.WriteString(fmt.Sprintf("Flags: %s\n\t", flags)) 99 buf.WriteString(fmt.Sprintf("Settings:\n")) 100 settings := frame.Settings.Settings() 101 for _, setting := range settings { 102 buf.WriteString("\t\t" + setting.String() + "\n") 103 } 104 buf.WriteString("}\n") 105 106 return buf.String() 107 } 108 109 func (frame *SETTINGS) WriteTo(writer io.Writer) (int64, error) { 110 c := common.WriteCounter{W: writer} 111 settings := encodeSettings(frame.Settings) 112 numSettings := uint32(len(frame.Settings)) 113 length := 4 + len(settings) 114 out := make([]byte, 12) 115 116 out[0] = 128 // Control bit and Version 117 out[1] = 2 // Version 118 out[2] = 0 // Type 119 out[3] = 4 // Type 120 out[4] = byte(frame.Flags) // Flags 121 out[5] = byte(length >> 16) // Length 122 out[6] = byte(length >> 8) // Length 123 out[7] = byte(length) // Length 124 out[8] = byte(numSettings >> 24) // Number of Entries 125 out[9] = byte(numSettings >> 16) // Number of Entries 126 out[10] = byte(numSettings >> 8) // Number of Entries 127 out[11] = byte(numSettings) // Number of Entries 128 129 err := common.WriteExactly(&c, out) 130 if err != nil { 131 return c.N, err 132 } 133 134 err = common.WriteExactly(&c, settings) 135 if err != nil { 136 return c.N, err 137 } 138 139 return c.N, nil 140 } 141 142 func decodeSetting(data []byte) *common.Setting { 143 if len(data) < 8 { 144 return nil 145 } 146 147 setting := new(common.Setting) 148 setting.ID = common.BytesToUint24Reverse(data[0:]) // Might need to reverse this. 149 setting.Flags = common.Flags(data[3]) 150 setting.Value = common.BytesToUint32(data[4:]) 151 152 return setting 153 } 154 155 func encodeSettings(s common.Settings) []byte { 156 if len(s) == 0 { 157 return []byte{} 158 } 159 160 ids := make([]int, 0, len(s)) 161 for id := range s { 162 ids = append(ids, int(id)) 163 } 164 165 sort.Sort(sort.IntSlice(ids)) 166 167 out := make([]byte, 8*len(s)) 168 169 offset := 0 170 for _, id := range ids { 171 setting := s[uint32(id)] 172 out[offset] = byte(setting.ID) // Might need to reverse this. 173 out[offset+1] = byte(setting.ID >> 8) // Might need to reverse this. 174 out[offset+2] = byte(setting.ID >> 16) // Might need to reverse this. 175 out[offset+3] = byte(setting.Flags) 176 out[offset+4] = byte(setting.Value >> 24) 177 out[offset+5] = byte(setting.Value >> 16) 178 out[offset+6] = byte(setting.Value >> 8) 179 out[offset+7] = byte(setting.Value) 180 offset += 8 181 } 182 183 return out 184 }