github.com/alejandroesc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy2/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, 2) 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 > common.MAX_FRAME_SIZE-8 { 54 return c.N, common.FrameTooLarge 55 } 56 57 // Read in data. 58 if length != 0 { 59 frame.Data, err = common.ReadExactly(&c, length) 60 if err != nil { 61 return c.N, err 62 } 63 } 64 65 frame.StreamID = common.StreamID(common.BytesToUint32(data[0:4])) 66 frame.Flags = common.Flags(data[4]) 67 if frame.Data == nil { 68 frame.Data = []byte{} 69 } 70 71 return c.N, nil 72 } 73 74 func (frame *DATA) String() string { 75 buf := new(bytes.Buffer) 76 77 flags := "" 78 if frame.Flags.FIN() { 79 flags += " common.FLAG_FIN" 80 } 81 if flags == "" { 82 flags = "[NONE]" 83 } else { 84 flags = flags[1:] 85 } 86 87 buf.WriteString("DATA {\n\t") 88 buf.WriteString(fmt.Sprintf("Stream ID: %d\n\t", frame.StreamID)) 89 buf.WriteString(fmt.Sprintf("Flags: %s\n\t", flags)) 90 buf.WriteString(fmt.Sprintf("Length: %d\n\t", len(frame.Data))) 91 if common.VerboseLogging || len(frame.Data) <= 21 { 92 buf.WriteString(fmt.Sprintf("Data: [% x]\n}\n", frame.Data)) 93 } else { 94 buf.WriteString(fmt.Sprintf("Data: [% x ... % x]\n}\n", frame.Data[:9], 95 frame.Data[len(frame.Data)-9:])) 96 } 97 98 return buf.String() 99 } 100 101 func (frame *DATA) WriteTo(writer io.Writer) (int64, error) { 102 c := common.WriteCounter{W: writer} 103 length := len(frame.Data) 104 if length > common.MAX_DATA_SIZE { 105 return c.N, errors.New("Error: Data size too large.") 106 } 107 if length == 0 && !frame.Flags.FIN() { 108 return c.N, errors.New("Error: Data is empty.") 109 } 110 111 out := make([]byte, 8) 112 113 out[0] = frame.StreamID.B1() // Control bit and Stream ID 114 out[1] = frame.StreamID.B2() // Stream ID 115 out[2] = frame.StreamID.B3() // Stream ID 116 out[3] = frame.StreamID.B4() // Stream ID 117 out[4] = byte(frame.Flags) // Flags 118 out[5] = byte(length >> 16) // Length 119 out[6] = byte(length >> 8) // Length 120 out[7] = byte(length) // Length 121 122 err := common.WriteExactly(&c, out) 123 if err != nil { 124 return c.N, err 125 } 126 127 err = common.WriteExactly(&c, frame.Data) 128 if err != nil { 129 return c.N, err 130 } 131 132 return c.N, nil 133 }