github.com/alejandroEsc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy3/frames/headers.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 HEADERS struct {
    18  	Flags     common.Flags
    19  	StreamID  common.StreamID
    20  	Header    http.Header
    21  	rawHeader []byte
    22  }
    23  
    24  func (frame *HEADERS) 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 *HEADERS) 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 *HEADERS) Name() string {
    54  	return "HEADERS"
    55  }
    56  
    57  func (frame *HEADERS) 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], _HEADERS, 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  	if !frame.StreamID.Valid() {
    88  		return c.N, common.StreamIdTooLarge
    89  	}
    90  	if frame.StreamID.Zero() {
    91  		return c.N, common.StreamIdIsZero
    92  	}
    93  
    94  	return c.N, nil
    95  }
    96  
    97  func (frame *HEADERS) String() string {
    98  	buf := new(bytes.Buffer)
    99  
   100  	flags := ""
   101  	if frame.Flags.FIN() {
   102  		flags += " common.FLAG_FIN"
   103  	}
   104  	if flags == "" {
   105  		flags = "[NONE]"
   106  	} else {
   107  		flags = flags[1:]
   108  	}
   109  
   110  	buf.WriteString("HEADERS {\n\t")
   111  	buf.WriteString(fmt.Sprintf("Version:              3\n\t"))
   112  	buf.WriteString(fmt.Sprintf("Flags:                %s\n\t", flags))
   113  	buf.WriteString(fmt.Sprintf("Stream ID:            %d\n\t", frame.StreamID))
   114  	buf.WriteString(fmt.Sprintf("Header:               %#v\n}\n", frame.Header))
   115  
   116  	return buf.String()
   117  }
   118  
   119  func (frame *HEADERS) WriteTo(writer io.Writer) (int64, error) {
   120  	c := common.WriteCounter{W: writer}
   121  	if frame.rawHeader == nil {
   122  		return c.N, errors.New("Error: Headers not written.")
   123  	}
   124  	if !frame.StreamID.Valid() {
   125  		return c.N, common.StreamIdTooLarge
   126  	}
   127  	if frame.StreamID.Zero() {
   128  		return c.N, common.StreamIdIsZero
   129  	}
   130  
   131  	header := frame.rawHeader
   132  	length := 4 + len(header)
   133  	out := make([]byte, 12)
   134  
   135  	out[0] = 128                  // Control bit and Version
   136  	out[1] = 3                    // Version
   137  	out[2] = 0                    // Type
   138  	out[3] = 8                    // Type
   139  	out[4] = byte(frame.Flags)    // Flags
   140  	out[5] = byte(length >> 16)   // Length
   141  	out[6] = byte(length >> 8)    // Length
   142  	out[7] = byte(length)         // Length
   143  	out[8] = frame.StreamID.B1()  // Stream ID
   144  	out[9] = frame.StreamID.B2()  // Stream ID
   145  	out[10] = frame.StreamID.B3() // Stream ID
   146  	out[11] = frame.StreamID.B4() // Stream ID
   147  
   148  	err := common.WriteExactly(&c, out)
   149  	if err != nil {
   150  		return c.N, err
   151  	}
   152  
   153  	err = common.WriteExactly(&c, header)
   154  	if err != nil {
   155  		return c.N, err
   156  	}
   157  
   158  	return c.N, nil
   159  }