github.com/alejandroesc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy2/request_stream.go (about) 1 // Copyright 2013 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 spdy2 6 7 import ( 8 "errors" 9 "fmt" 10 "net/http" 11 "sync" 12 13 "github.com/SlyMarbo/spdy/common" 14 "github.com/SlyMarbo/spdy/spdy2/frames" 15 ) 16 17 // RequestStream is a structure that implements 18 // the Stream and ResponseWriter interfaces. This 19 // is used for responding to client requests. 20 type RequestStream struct { 21 sync.Mutex 22 Request *http.Request 23 Receiver common.Receiver 24 25 recvMutex sync.Mutex 26 shutdownOnce sync.Once 27 conn *Conn 28 streamID common.StreamID 29 state *common.StreamState 30 output chan<- common.Frame 31 header http.Header 32 headerChan chan func() 33 responseCode int 34 stop <-chan bool 35 finished chan struct{} 36 } 37 38 func NewRequestStream(conn *Conn, streamID common.StreamID, output chan<- common.Frame) *RequestStream { 39 out := new(RequestStream) 40 out.conn = conn 41 out.streamID = streamID 42 out.output = output 43 out.stop = conn.stop 44 out.state = new(common.StreamState) 45 out.state.CloseHere() 46 out.header = make(http.Header) 47 out.finished = make(chan struct{}) 48 out.headerChan = make(chan func(), 5) 49 go out.processFrames() 50 return out 51 } 52 53 /*********************** 54 * http.ResponseWriter * 55 ***********************/ 56 57 func (s *RequestStream) Header() http.Header { 58 return s.header 59 } 60 61 // Write is one method with which request data is sent. 62 func (s *RequestStream) Write(inputData []byte) (int, error) { 63 if s.closed() || s.state.ClosedHere() { 64 return 0, errors.New("Error: Stream already closed.") 65 } 66 67 // Copy the data locally to avoid any pointer issues. 68 data := make([]byte, len(inputData)) 69 copy(data, inputData) 70 71 // Send any new headers. 72 s.writeHeader() 73 74 // Chunk the response if necessary. 75 written := 0 76 for len(data) > common.MAX_DATA_SIZE { 77 dataFrame := new(frames.DATA) 78 dataFrame.StreamID = s.streamID 79 dataFrame.Data = data[:common.MAX_DATA_SIZE] 80 s.output <- dataFrame 81 82 written += common.MAX_DATA_SIZE 83 } 84 85 n := len(data) 86 if n == 0 { 87 return written, nil 88 } 89 90 dataFrame := new(frames.DATA) 91 dataFrame.StreamID = s.streamID 92 dataFrame.Data = data 93 s.output <- dataFrame 94 95 return written + n, nil 96 } 97 98 // WriteHeader is used to set the HTTP status code. 99 func (s *RequestStream) WriteHeader(int) { 100 s.writeHeader() 101 } 102 103 /***************** 104 * io.Closer * 105 *****************/ 106 107 // Close is used to cancel a mid-air 108 // request. 109 func (s *RequestStream) Close() error { 110 defer common.Recover() 111 s.Lock() 112 s.shutdownOnce.Do(s.shutdown) 113 s.Unlock() 114 return nil 115 } 116 117 func (s *RequestStream) shutdown() { 118 s.writeHeader() 119 if s.state != nil { 120 if s.state.OpenThere() { 121 // Send the RST_STREAM. 122 rst := new(frames.RST_STREAM) 123 rst.StreamID = s.streamID 124 rst.Status = common.RST_STREAM_CANCEL 125 s.output <- rst 126 } 127 s.state.Close() 128 } 129 select { 130 case <-s.finished: 131 default: 132 close(s.finished) 133 } 134 select { 135 case <-s.headerChan: 136 default: 137 close(s.headerChan) 138 } 139 s.conn.requestStreamLimit.Close() 140 s.output = nil 141 s.Request = nil 142 s.Receiver = nil 143 s.header = nil 144 s.stop = nil 145 146 s.conn.streamsLock.Lock() 147 delete(s.conn.streams, s.streamID) 148 s.conn.streamsLock.Unlock() 149 } 150 151 /********** 152 * Stream * 153 **********/ 154 155 func (s *RequestStream) Conn() common.Conn { 156 return s.conn 157 } 158 159 func (s *RequestStream) ReceiveFrame(frame common.Frame) error { 160 s.recvMutex.Lock() 161 defer s.recvMutex.Unlock() 162 163 if frame == nil { 164 return errors.New("Nil frame received.") 165 } 166 167 // Process the frame depending on its type. 168 switch frame := frame.(type) { 169 case *frames.DATA: 170 171 // Extract the data. 172 data := frame.Data 173 if data == nil { 174 data = []byte{} 175 } 176 177 // Give to the client. 178 s.headerChan <- func() { 179 s.Receiver.ReceiveData(s.Request, data, frame.Flags.FIN()) 180 181 if frame.Flags.FIN() { 182 s.state.CloseThere() 183 s.Close() 184 } 185 } 186 187 case *frames.SYN_REPLY: 188 s.headerChan <- func() { 189 s.Receiver.ReceiveHeader(s.Request, frame.Header) 190 191 if frame.Flags.FIN() { 192 s.state.CloseThere() 193 s.Close() 194 } 195 } 196 197 case *frames.HEADERS: 198 s.headerChan <- func() { 199 s.Receiver.ReceiveHeader(s.Request, frame.Header) 200 201 if frame.Flags.FIN() { 202 s.state.CloseThere() 203 s.Close() 204 } 205 } 206 207 case *frames.WINDOW_UPDATE: 208 // Ignore. 209 210 default: 211 return errors.New(fmt.Sprintf("Received unknown frame of type %T.", frame)) 212 } 213 214 return nil 215 } 216 217 func (s *RequestStream) CloseNotify() <-chan bool { 218 return s.stop 219 } 220 221 // run is the main control path of 222 // the stream. Data is recieved, 223 // processed, and then the stream 224 // is cleaned up and closed. 225 func (s *RequestStream) Run() error { 226 // Receive and process inbound frames. 227 <-s.finished 228 229 // Clean up state. 230 s.state.CloseHere() 231 return nil 232 } 233 234 func (s *RequestStream) State() *common.StreamState { 235 return s.state 236 } 237 238 func (s *RequestStream) StreamID() common.StreamID { 239 return s.streamID 240 } 241 242 func (s *RequestStream) closed() bool { 243 if s.conn == nil || s.state == nil || s.Receiver == nil { 244 return true 245 } 246 select { 247 case _ = <-s.stop: 248 return true 249 default: 250 return false 251 } 252 } 253 254 // writeHeader is used to flush HTTP headers. 255 func (s *RequestStream) writeHeader() { 256 if len(s.header) == 0 { 257 return 258 } 259 260 // Create the HEADERS frame. 261 header := new(frames.HEADERS) 262 header.StreamID = s.streamID 263 header.Header = common.CloneHeader(s.header) 264 265 // Clear the headers that have been sent. 266 for name := range header.Header { 267 s.header.Del(name) 268 } 269 270 s.output <- header 271 } 272 273 func (s *RequestStream) processFrames() { 274 defer common.Recover() 275 for f := range s.headerChan { 276 f() 277 } 278 }