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