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