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 }