github.com/alejandroesc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy3/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  	Slot          byte
    23  	Header        http.Header
    24  	rawHeader     []byte
    25  }
    26  
    27  func (frame *SYN_STREAM) Compress(com common.Compressor) error {
    28  	if frame.rawHeader != nil {
    29  		return nil
    30  	}
    31  
    32  	data, err := com.Compress(frame.Header)
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	frame.rawHeader = data
    38  	return nil
    39  }
    40  
    41  func (frame *SYN_STREAM) Decompress(decom common.Decompressor) error {
    42  	if frame.Header != nil {
    43  		return nil
    44  	}
    45  
    46  	header, err := decom.Decompress(frame.rawHeader)
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	frame.Header = header
    52  	frame.rawHeader = nil
    53  	return nil
    54  }
    55  
    56  func (frame *SYN_STREAM) Name() string {
    57  	return "SYN_STREAM"
    58  }
    59  
    60  func (frame *SYN_STREAM) ReadFrom(reader io.Reader) (int64, error) {
    61  	c := common.ReadCounter{R: reader}
    62  	data, err := common.ReadExactly(&c, 18)
    63  	if err != nil {
    64  		return c.N, err
    65  	}
    66  
    67  	err = controlFrameCommonProcessing(data[:5], _SYN_STREAM, common.FLAG_FIN|common.FLAG_UNIDIRECTIONAL)
    68  	if err != nil {
    69  		return c.N, err
    70  	}
    71  
    72  	// Get and check length.
    73  	length := int(common.BytesToUint24(data[5:8]))
    74  	if length < 10 {
    75  		return c.N, common.IncorrectDataLength(length, 10)
    76  	} else if length > common.MAX_FRAME_SIZE-18 {
    77  		return c.N, common.FrameTooLarge
    78  	}
    79  
    80  	// Read in data.
    81  	header, err := common.ReadExactly(&c, length-10)
    82  	if err != nil {
    83  		return c.N, err
    84  	}
    85  
    86  	frame.Flags = common.Flags(data[4])
    87  	frame.StreamID = common.StreamID(common.BytesToUint32(data[8:12]))
    88  	frame.AssocStreamID = common.StreamID(common.BytesToUint32(data[12:16]))
    89  	frame.Priority = common.Priority(data[16] >> 5)
    90  	frame.Slot = data[17]
    91  	frame.rawHeader = header
    92  
    93  	if !frame.StreamID.Valid() {
    94  		return c.N, common.StreamIdTooLarge
    95  	}
    96  	if frame.StreamID.Zero() {
    97  		return c.N, common.StreamIdIsZero
    98  	}
    99  	if !frame.AssocStreamID.Valid() {
   100  		return c.N, common.StreamIdTooLarge
   101  	}
   102  
   103  	return c.N, nil
   104  }
   105  
   106  func (frame *SYN_STREAM) String() string {
   107  	buf := new(bytes.Buffer)
   108  	flags := ""
   109  	if frame.Flags.FIN() {
   110  		flags += " common.FLAG_FIN"
   111  	}
   112  	if frame.Flags.UNIDIRECTIONAL() {
   113  		flags += " FLAG_UNIDIRECTIONAL"
   114  	}
   115  	if flags == "" {
   116  		flags = "[NONE]"
   117  	} else {
   118  		flags = flags[1:]
   119  	}
   120  
   121  	buf.WriteString("SYN_STREAM {\n\t")
   122  	buf.WriteString(fmt.Sprintf("Version:              3\n\t"))
   123  	buf.WriteString(fmt.Sprintf("Flags:                %s\n\t", flags))
   124  	buf.WriteString(fmt.Sprintf("Stream ID:            %d\n\t", frame.StreamID))
   125  	buf.WriteString(fmt.Sprintf("Associated Stream ID: %d\n\t", frame.AssocStreamID))
   126  	buf.WriteString(fmt.Sprintf("Priority:             %d\n\t", frame.Priority))
   127  	buf.WriteString(fmt.Sprintf("Slot:                 %d\n\t", frame.Slot))
   128  	buf.WriteString(fmt.Sprintf("Header:               %#v\n}\n", frame.Header))
   129  
   130  	return buf.String()
   131  }
   132  
   133  func (frame *SYN_STREAM) WriteTo(writer io.Writer) (int64, error) {
   134  	c := common.WriteCounter{W: writer}
   135  	if frame.rawHeader == nil {
   136  		return c.N, errors.New("Error: Headers not written.")
   137  	}
   138  	if !frame.StreamID.Valid() {
   139  		return c.N, common.StreamIdTooLarge
   140  	}
   141  	if frame.StreamID.Zero() {
   142  		return c.N, common.StreamIdIsZero
   143  	}
   144  	if !frame.AssocStreamID.Valid() {
   145  		return c.N, common.StreamIdTooLarge
   146  	}
   147  
   148  	header := frame.rawHeader
   149  	length := 10 + len(header)
   150  	out := make([]byte, 18)
   151  
   152  	out[0] = 128                       // Control bit and Version
   153  	out[1] = 3                         // Version
   154  	out[2] = 0                         // Type
   155  	out[3] = 1                         // Type
   156  	out[4] = byte(frame.Flags)         // Flags
   157  	out[5] = byte(length >> 16)        // Length
   158  	out[6] = byte(length >> 8)         // Length
   159  	out[7] = byte(length)              // Length
   160  	out[8] = frame.StreamID.B1()       // Stream ID
   161  	out[9] = frame.StreamID.B2()       // Stream ID
   162  	out[10] = frame.StreamID.B3()      // Stream ID
   163  	out[11] = frame.StreamID.B4()      // Stream ID
   164  	out[12] = frame.AssocStreamID.B1() // Associated Stream ID
   165  	out[13] = frame.AssocStreamID.B2() // Associated Stream ID
   166  	out[14] = frame.AssocStreamID.B3() // Associated Stream ID
   167  	out[15] = frame.AssocStreamID.B4() // Associated Stream ID
   168  	out[16] = frame.Priority.Byte(3)   // Priority and unused
   169  	out[17] = frame.Slot               // Slot
   170  
   171  	err := common.WriteExactly(&c, out)
   172  	if err != nil {
   173  		return c.N, err
   174  	}
   175  
   176  	err = common.WriteExactly(&c, header)
   177  	if err != nil {
   178  		return c.N, err
   179  	}
   180  
   181  	return c.N, nil
   182  }
   183  
   184  // SPDY/3.1
   185  type SYN_STREAMV3_1 struct {
   186  	Flags         common.Flags
   187  	StreamID      common.StreamID
   188  	AssocStreamID common.StreamID
   189  	Priority      common.Priority
   190  	Header        http.Header
   191  	rawHeader     []byte
   192  }
   193  
   194  func (frame *SYN_STREAMV3_1) Compress(com common.Compressor) error {
   195  	if frame.rawHeader != nil {
   196  		return nil
   197  	}
   198  
   199  	data, err := com.Compress(frame.Header)
   200  	if err != nil {
   201  		return err
   202  	}
   203  
   204  	frame.rawHeader = data
   205  	return nil
   206  }
   207  
   208  func (frame *SYN_STREAMV3_1) Decompress(decom common.Decompressor) error {
   209  	if frame.Header != nil {
   210  		return nil
   211  	}
   212  
   213  	header, err := decom.Decompress(frame.rawHeader)
   214  	if err != nil {
   215  		return err
   216  	}
   217  
   218  	frame.Header = header
   219  	frame.rawHeader = nil
   220  	return nil
   221  }
   222  
   223  func (frame *SYN_STREAMV3_1) Name() string {
   224  	return "SYN_STREAM"
   225  }
   226  
   227  func (frame *SYN_STREAMV3_1) ReadFrom(reader io.Reader) (int64, error) {
   228  	c := common.ReadCounter{R: reader}
   229  	data, err := common.ReadExactly(&c, 18)
   230  	if err != nil {
   231  		return c.N, err
   232  	}
   233  
   234  	err = controlFrameCommonProcessing(data[:5], _SYN_STREAM, common.FLAG_FIN|common.FLAG_UNIDIRECTIONAL)
   235  	if err != nil {
   236  		return c.N, err
   237  	}
   238  
   239  	// Get and check length.
   240  	length := int(common.BytesToUint24(data[5:8]))
   241  	if length < 10 {
   242  		return c.N, common.IncorrectDataLength(length, 10)
   243  	} else if length > common.MAX_FRAME_SIZE-18 {
   244  		return c.N, common.FrameTooLarge
   245  	}
   246  
   247  	// Read in data.
   248  	header, err := common.ReadExactly(&c, length-10)
   249  	if err != nil {
   250  		return c.N, err
   251  	}
   252  
   253  	frame.Flags = common.Flags(data[4])
   254  	frame.StreamID = common.StreamID(common.BytesToUint32(data[8:12]))
   255  	frame.AssocStreamID = common.StreamID(common.BytesToUint32(data[12:16]))
   256  	frame.Priority = common.Priority(data[16] >> 5)
   257  	frame.rawHeader = header
   258  
   259  	if !frame.StreamID.Valid() {
   260  		return c.N, common.StreamIdTooLarge
   261  	}
   262  	if frame.StreamID.Zero() {
   263  		return c.N, common.StreamIdIsZero
   264  	}
   265  	if !frame.AssocStreamID.Valid() {
   266  		return c.N, common.StreamIdTooLarge
   267  	}
   268  
   269  	return c.N, nil
   270  }
   271  
   272  func (frame *SYN_STREAMV3_1) String() string {
   273  	buf := new(bytes.Buffer)
   274  	flags := ""
   275  	if frame.Flags.FIN() {
   276  		flags += " common.FLAG_FIN"
   277  	}
   278  	if frame.Flags.UNIDIRECTIONAL() {
   279  		flags += " FLAG_UNIDIRECTIONAL"
   280  	}
   281  	if flags == "" {
   282  		flags = "[NONE]"
   283  	} else {
   284  		flags = flags[1:]
   285  	}
   286  
   287  	buf.WriteString("SYN_STREAM {\n\t")
   288  	buf.WriteString(fmt.Sprintf("Version:              3\n\t"))
   289  	buf.WriteString(fmt.Sprintf("Flags:                %s\n\t", flags))
   290  	buf.WriteString(fmt.Sprintf("Stream ID:            %d\n\t", frame.StreamID))
   291  	buf.WriteString(fmt.Sprintf("Associated Stream ID: %d\n\t", frame.AssocStreamID))
   292  	buf.WriteString(fmt.Sprintf("Priority:             %d\n\t", frame.Priority))
   293  	buf.WriteString(fmt.Sprintf("Header:               %#v\n}\n", frame.Header))
   294  
   295  	return buf.String()
   296  }
   297  
   298  func (frame *SYN_STREAMV3_1) WriteTo(writer io.Writer) (int64, error) {
   299  	c := common.WriteCounter{W: writer}
   300  	if frame.rawHeader == nil {
   301  		return c.N, errors.New("Error: Headers not written.")
   302  	}
   303  	if !frame.StreamID.Valid() {
   304  		return c.N, common.StreamIdTooLarge
   305  	}
   306  	if frame.StreamID.Zero() {
   307  		return c.N, common.StreamIdIsZero
   308  	}
   309  	if !frame.AssocStreamID.Valid() {
   310  		return c.N, common.StreamIdTooLarge
   311  	}
   312  
   313  	header := frame.rawHeader
   314  	length := 10 + len(header)
   315  	out := make([]byte, 18)
   316  
   317  	out[0] = 128                       // Control bit and Version
   318  	out[1] = 3                         // Version
   319  	out[2] = 0                         // Type
   320  	out[3] = 1                         // Type
   321  	out[4] = byte(frame.Flags)         // Flags
   322  	out[5] = byte(length >> 16)        // Length
   323  	out[6] = byte(length >> 8)         // Length
   324  	out[7] = byte(length)              // Length
   325  	out[8] = frame.StreamID.B1()       // Stream ID
   326  	out[9] = frame.StreamID.B2()       // Stream ID
   327  	out[10] = frame.StreamID.B3()      // Stream ID
   328  	out[11] = frame.StreamID.B4()      // Stream ID
   329  	out[12] = frame.AssocStreamID.B1() // Associated Stream ID
   330  	out[13] = frame.AssocStreamID.B2() // Associated Stream ID
   331  	out[14] = frame.AssocStreamID.B3() // Associated Stream ID
   332  	out[15] = frame.AssocStreamID.B4() // Associated Stream ID
   333  	out[16] = frame.Priority.Byte(3)   // Priority and unused
   334  	out[17] = 0                        // Reserved
   335  
   336  	err := common.WriteExactly(&c, out)
   337  	if err != nil {
   338  		return c.N, err
   339  	}
   340  
   341  	err = common.WriteExactly(&c, header)
   342  	if err != nil {
   343  		return c.N, err
   344  	}
   345  
   346  	return c.N, nil
   347  }