github.com/alejandroEsc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy3/frames/common.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  	"bufio"
     9  	"errors"
    10  	"fmt"
    11  
    12  	"github.com/SlyMarbo/spdy/common"
    13  )
    14  
    15  // ReadFrame reads and parses a frame from reader.
    16  func ReadFrame(reader *bufio.Reader, subversion int) (frame common.Frame, err error) {
    17  	start, err := reader.Peek(4)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  
    22  	if start[0] != 128 {
    23  		frame = new(DATA)
    24  		_, err = frame.ReadFrom(reader)
    25  		return frame, err
    26  	}
    27  
    28  	switch common.BytesToUint16(start[2:4]) {
    29  	case _SYN_STREAM:
    30  		switch subversion {
    31  		case 0:
    32  			frame = new(SYN_STREAM)
    33  		case 1:
    34  			frame = new(SYN_STREAMV3_1)
    35  		default:
    36  			return nil, fmt.Errorf("Error: Given subversion %d is unrecognised.", subversion)
    37  		}
    38  	case _SYN_REPLY:
    39  		frame = new(SYN_REPLY)
    40  	case _RST_STREAM:
    41  		frame = new(RST_STREAM)
    42  	case _SETTINGS:
    43  		frame = new(SETTINGS)
    44  	case _PING:
    45  		frame = new(PING)
    46  	case _GOAWAY:
    47  		frame = new(GOAWAY)
    48  	case _HEADERS:
    49  		frame = new(HEADERS)
    50  	case _WINDOW_UPDATE:
    51  		frame = &WINDOW_UPDATE{subversion: subversion}
    52  	case _CREDENTIAL:
    53  		frame = new(CREDENTIAL)
    54  
    55  	default:
    56  		return nil, errors.New("Error Failed to parse frame type.")
    57  	}
    58  
    59  	_, err = frame.ReadFrom(reader)
    60  	return frame, err
    61  }
    62  
    63  // controlFrameCommonProcessing performs checks identical between
    64  // all control frames. This includes the control bit, the version
    65  // number, the type byte (which is checked against the byte
    66  // provided), and the flags (which are checked against the bitwise
    67  // OR of valid flags provided).
    68  func controlFrameCommonProcessing(data []byte, frameType uint16, flags byte) error {
    69  	// Check it's a control frame.
    70  	if data[0] != 128 {
    71  		return common.IncorrectFrame(_DATA_FRAME, int(frameType), 3)
    72  	}
    73  
    74  	// Check version.
    75  	version := (uint16(data[0]&0x7f) << 8) + uint16(data[1])
    76  	if version != 3 {
    77  		return common.UnsupportedVersion(version)
    78  	}
    79  
    80  	// Check its type.
    81  	realType := common.BytesToUint16(data[2:])
    82  	if realType != frameType {
    83  		return common.IncorrectFrame(int(realType), int(frameType), 3)
    84  	}
    85  
    86  	// Check the flags.
    87  	if data[4] & ^flags != 0 {
    88  		return common.InvalidField("flags", int(data[4]), int(flags))
    89  	}
    90  
    91  	return nil
    92  }
    93  
    94  // Frame types in SPDY/3
    95  const (
    96  	_SYN_STREAM    = 1
    97  	_SYN_REPLY     = 2
    98  	_RST_STREAM    = 3
    99  	_SETTINGS      = 4
   100  	_PING          = 6
   101  	_GOAWAY        = 7
   102  	_HEADERS       = 8
   103  	_WINDOW_UPDATE = 9
   104  	_CREDENTIAL    = 10
   105  	_CONTROL_FRAME = -1
   106  	_DATA_FRAME    = -2
   107  )
   108  
   109  // frameNames provides the name for a particular SPDY/3
   110  // frame type.
   111  var frameNames = map[int]string{
   112  	_SYN_STREAM:    "SYN_STREAM",
   113  	_SYN_REPLY:     "SYN_REPLY",
   114  	_RST_STREAM:    "RST_STREAM",
   115  	_SETTINGS:      "SETTINGS",
   116  	_PING:          "PING",
   117  	_GOAWAY:        "GOAWAY",
   118  	_HEADERS:       "HEADERS",
   119  	_WINDOW_UPDATE: "WINDOW_UPDATE",
   120  	_CREDENTIAL:    "CREDENTIAL",
   121  	_CONTROL_FRAME: "CONTROL_FRAME",
   122  	_DATA_FRAME:    "DATA_FRAME",
   123  }