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