github.com/alejandroEsc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy3/frames/rst_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  	"fmt"
    10  	"io"
    11  
    12  	"github.com/SlyMarbo/spdy/common"
    13  )
    14  
    15  type RST_STREAM struct {
    16  	StreamID common.StreamID
    17  	Status   common.StatusCode
    18  }
    19  
    20  func (frame *RST_STREAM) Compress(comp common.Compressor) error {
    21  	return nil
    22  }
    23  
    24  func (frame *RST_STREAM) Decompress(decomp common.Decompressor) error {
    25  	return nil
    26  }
    27  
    28  func (frame *RST_STREAM) Error() string {
    29  	if err := frame.Status.String(); err != "" {
    30  		return err
    31  	}
    32  
    33  	return fmt.Sprintf("[unknown status code %d]", frame.Status)
    34  }
    35  
    36  func (frame *RST_STREAM) Name() string {
    37  	return "RST_STREAM"
    38  }
    39  
    40  func (frame *RST_STREAM) ReadFrom(reader io.Reader) (int64, error) {
    41  	c := common.ReadCounter{R: reader}
    42  	data, err := common.ReadExactly(&c, 16)
    43  	if err != nil {
    44  		return c.N, err
    45  	}
    46  
    47  	err = controlFrameCommonProcessing(data[:5], _RST_STREAM, 0)
    48  	if err != nil {
    49  		return c.N, err
    50  	}
    51  
    52  	// Get and check length.
    53  	length := int(common.BytesToUint24(data[5:8]))
    54  	if length != 8 {
    55  		return c.N, common.IncorrectDataLength(length, 8)
    56  	} else if length > common.MAX_FRAME_SIZE-8 {
    57  		return c.N, common.FrameTooLarge
    58  	}
    59  
    60  	frame.StreamID = common.StreamID(common.BytesToUint32(data[8:12]))
    61  	frame.Status = common.StatusCode(common.BytesToUint32(data[12:16]))
    62  
    63  	if !frame.StreamID.Valid() {
    64  		return c.N, common.StreamIdTooLarge
    65  	}
    66  
    67  	return c.N, nil
    68  }
    69  
    70  func (frame *RST_STREAM) String() string {
    71  	buf := new(bytes.Buffer)
    72  
    73  	buf.WriteString("RST_STREAM {\n\t")
    74  	buf.WriteString(fmt.Sprintf("Version:              3\n\t"))
    75  	buf.WriteString(fmt.Sprintf("Stream ID:            %d\n\t", frame.StreamID))
    76  	buf.WriteString(fmt.Sprintf("Status code:          %s\n}\n", frame.Status))
    77  
    78  	return buf.String()
    79  }
    80  
    81  func (frame *RST_STREAM) WriteTo(writer io.Writer) (int64, error) {
    82  	c := common.WriteCounter{W: writer}
    83  	if !frame.StreamID.Valid() {
    84  		return c.N, common.StreamIdTooLarge
    85  	}
    86  
    87  	out := make([]byte, 16)
    88  
    89  	out[0] = 128                  // Control bit and Version
    90  	out[1] = 3                    // Version
    91  	out[2] = 0                    // Type
    92  	out[3] = 3                    // Type
    93  	out[4] = 0                    // Flags
    94  	out[5] = 0                    // Length
    95  	out[6] = 0                    // Length
    96  	out[7] = 8                    // Length
    97  	out[8] = frame.StreamID.B1()  // Stream ID
    98  	out[9] = frame.StreamID.B2()  // Stream ID
    99  	out[10] = frame.StreamID.B3() // Stream ID
   100  	out[11] = frame.StreamID.B4() // Stream ID
   101  	out[12] = frame.Status.B1()   // Status
   102  	out[13] = frame.Status.B2()   // Status
   103  	out[14] = frame.Status.B3()   // Status
   104  	out[15] = frame.Status.B4()   // Status
   105  
   106  	err := common.WriteExactly(&c, out)
   107  	if err != nil {
   108  		return c.N, err
   109  	}
   110  
   111  	return c.N, nil
   112  }