github.com/alejandroEsc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy3/frames/data.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  
    13  	"github.com/SlyMarbo/spdy/common"
    14  )
    15  
    16  type DATA struct {
    17  	StreamID common.StreamID
    18  	Flags    common.Flags
    19  	Data     []byte
    20  }
    21  
    22  func (frame *DATA) Compress(comp common.Compressor) error {
    23  	return nil
    24  }
    25  
    26  func (frame *DATA) Decompress(decomp common.Decompressor) error {
    27  	return nil
    28  }
    29  
    30  func (frame *DATA) Name() string {
    31  	return "DATA"
    32  }
    33  
    34  func (frame *DATA) ReadFrom(reader io.Reader) (int64, error) {
    35  	c := common.ReadCounter{R: reader}
    36  	data, err := common.ReadExactly(&c, 8)
    37  	if err != nil {
    38  		return c.N, err
    39  	}
    40  
    41  	// Check it's a data frame.
    42  	if data[0]&0x80 == 1 {
    43  		return c.N, common.IncorrectFrame(_CONTROL_FRAME, _DATA_FRAME, 3)
    44  	}
    45  
    46  	// Check flags.
    47  	if data[4] & ^byte(common.FLAG_FIN) != 0 {
    48  		return c.N, common.InvalidField("flags", int(data[4]), common.FLAG_FIN)
    49  	}
    50  
    51  	// Get and check length.
    52  	length := int(common.BytesToUint24(data[5:8]))
    53  	if length == 0 && data[4] == 0 {
    54  		return c.N, common.IncorrectDataLength(length, 1)
    55  	} else if length > common.MAX_FRAME_SIZE-8 {
    56  		return c.N, common.FrameTooLarge
    57  	}
    58  
    59  	// Read in data.
    60  	if length != 0 {
    61  		frame.Data, err = common.ReadExactly(&c, length)
    62  		if err != nil {
    63  			return c.N, err
    64  		}
    65  	}
    66  
    67  	frame.StreamID = common.StreamID(common.BytesToUint32(data[0:4]))
    68  	frame.Flags = common.Flags(data[4])
    69  	if frame.Data == nil {
    70  		frame.Data = []byte{}
    71  	}
    72  
    73  	return c.N, nil
    74  }
    75  
    76  func (frame *DATA) String() string {
    77  	buf := new(bytes.Buffer)
    78  
    79  	flags := ""
    80  	if frame.Flags.FIN() {
    81  		flags += " common.FLAG_FIN"
    82  	}
    83  	if flags == "" {
    84  		flags = "[NONE]"
    85  	} else {
    86  		flags = flags[1:]
    87  	}
    88  
    89  	buf.WriteString("DATA {\n\t")
    90  	buf.WriteString(fmt.Sprintf("Stream ID:            %d\n\t", frame.StreamID))
    91  	buf.WriteString(fmt.Sprintf("Flags:                %s\n\t", flags))
    92  	buf.WriteString(fmt.Sprintf("Length:               %d\n\t", len(frame.Data)))
    93  	if common.VerboseLogging || len(frame.Data) <= 21 {
    94  		buf.WriteString(fmt.Sprintf("Data:                 [% x]\n}\n", frame.Data))
    95  	} else {
    96  		buf.WriteString(fmt.Sprintf("Data:                 [% x ... % x]\n}\n", frame.Data[:9],
    97  			frame.Data[len(frame.Data)-9:]))
    98  	}
    99  
   100  	return buf.String()
   101  }
   102  
   103  func (frame *DATA) WriteTo(writer io.Writer) (int64, error) {
   104  	c := common.WriteCounter{W: writer}
   105  	length := len(frame.Data)
   106  	if length > common.MAX_DATA_SIZE {
   107  		return c.N, errors.New("Error: Data size too large.")
   108  	}
   109  	if length == 0 && !frame.Flags.FIN() {
   110  		return c.N, errors.New("Error: Data is empty.")
   111  	}
   112  
   113  	out := make([]byte, 8)
   114  
   115  	out[0] = frame.StreamID.B1() // Control bit and Stream ID
   116  	out[1] = frame.StreamID.B2() // Stream ID
   117  	out[2] = frame.StreamID.B3() // Stream ID
   118  	out[3] = frame.StreamID.B4() // Stream ID
   119  	out[4] = byte(frame.Flags)   // Flags
   120  	out[5] = byte(length >> 16)  // Length
   121  	out[6] = byte(length >> 8)   // Length
   122  	out[7] = byte(length)        // Length
   123  
   124  	if err := common.WriteExactly(&c, out); err != nil {
   125  		return c.N, err
   126  	}
   127  
   128  	if err := common.WriteExactly(&c, frame.Data); err != nil {
   129  		return c.N, err
   130  	}
   131  
   132  	return c.N, nil
   133  }