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  }