github.com/alejandroesc/spdy@v0.0.0-20200317064415-01a02f0eb389/spdy3/response_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 spdy3 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "net/http" 12 "strconv" 13 "sync" 14 15 "github.com/SlyMarbo/spdy/common" 16 "github.com/SlyMarbo/spdy/spdy3/frames" 17 ) 18 19 // ResponseStream is a structure that implements the 20 // Stream interface. This is used for responding to 21 // client requests. 22 type ResponseStream struct { 23 sync.Mutex 24 25 shutdownOnce sync.Once 26 conn *Conn 27 streamID common.StreamID 28 flow *flowControl 29 requestBody *bytes.Buffer 30 state *common.StreamState 31 output chan<- common.Frame 32 request *http.Request 33 handler http.Handler 34 header http.Header 35 priority common.Priority 36 unidirectional bool 37 responseCode int 38 stop chan bool 39 ready chan struct{} 40 wroteHeader bool 41 } 42 43 func NewResponseStream(conn *Conn, frame *frames.SYN_STREAM, output chan<- common.Frame, handler http.Handler, request *http.Request) *ResponseStream { 44 out := new(ResponseStream) 45 out.conn = conn 46 out.streamID = frame.StreamID 47 out.output = output 48 out.handler = handler 49 if out.handler == nil { 50 out.handler = http.DefaultServeMux 51 } 52 out.request = request 53 out.priority = frame.Priority 54 out.stop = conn.stop 55 out.unidirectional = frame.Flags.UNIDIRECTIONAL() 56 out.requestBody = new(bytes.Buffer) 57 out.state = new(common.StreamState) 58 out.header = make(http.Header) 59 out.responseCode = 0 60 out.ready = make(chan struct{}) 61 out.wroteHeader = false 62 if frame.Flags.FIN() { 63 close(out.ready) 64 out.state.CloseThere() 65 } 66 out.request.Body = &common.ReadCloser{out.requestBody} 67 return out 68 } 69 70 /*********************** 71 * http.ResponseWriter * 72 ***********************/ 73 74 func (s *ResponseStream) Header() http.Header { 75 return s.header 76 } 77 78 // Write is the main method with which data is sent. 79 func (s *ResponseStream) Write(inputData []byte) (int, error) { 80 if s.unidirectional { 81 return 0, errors.New("Error: Stream is unidirectional.") 82 } 83 84 if s.closed() || s.state.ClosedHere() { 85 return 0, errors.New("Error: Stream already closed.") 86 } 87 88 // Copy the data locally to avoid any pointer issues. 89 data := make([]byte, len(inputData)) 90 copy(data, inputData) 91 92 // Default to 200 response. 93 if !s.wroteHeader { 94 s.WriteHeader(http.StatusOK) 95 } 96 97 // Send any new headers. 98 s.writeHeader() 99 100 // Chunk the response if necessary. 101 // Data is sent to the flow control to 102 // ensure that the protocol is followed. 103 written := 0 104 for len(data) > common.MAX_DATA_SIZE { 105 n, err := s.flow.Write(data[:common.MAX_DATA_SIZE]) 106 if err != nil { 107 return written, err 108 } 109 written += n 110 data = data[common.MAX_DATA_SIZE:] 111 } 112 113 n, err := s.flow.Write(data) 114 written += n 115 116 return written, err 117 } 118 119 // WriteHeader is used to set the HTTP status code. 120 func (s *ResponseStream) WriteHeader(code int) { 121 if s.unidirectional { 122 log.Println("Error: Stream is unidirectional.") 123 return 124 } 125 126 if s.wroteHeader { 127 log.Println("Error: Multiple calls to ResponseWriter.WriteHeader.") 128 return 129 } 130 131 s.wroteHeader = true 132 s.responseCode = code 133 s.header.Set(":status", strconv.Itoa(code)) 134 s.header.Set(":version", "HTTP/1.1") 135 136 // Create the response SYN_REPLY. 137 synReply := new(frames.SYN_REPLY) 138 synReply.StreamID = s.streamID 139 synReply.Header = make(http.Header) 140 141 // Clear the headers that have been sent. 142 for name, values := range s.header { 143 for _, value := range values { 144 synReply.Header.Add(name, value) 145 } 146 s.header.Del(name) 147 } 148 149 // These responses have no body, so close the stream now. 150 if code == 204 || code == 304 || code/100 == 1 { 151 synReply.Flags = common.FLAG_FIN 152 s.state.CloseHere() 153 } 154 155 s.output <- synReply 156 } 157 158 /***************** 159 * io.Closer * 160 *****************/ 161 162 func (s *ResponseStream) Close() error { 163 defer common.Recover() 164 s.Lock() 165 s.shutdownOnce.Do(s.shutdown) 166 s.Unlock() 167 return nil 168 } 169 170 func (s *ResponseStream) shutdown() { 171 s.writeHeader() 172 if s.state != nil { 173 s.state.Close() 174 } 175 if s.flow != nil { 176 s.flow.Close() 177 } 178 if s.requestBody != nil { 179 s.requestBody.Reset() 180 s.requestBody = nil 181 } 182 s.conn.requestStreamLimit.Close() 183 s.request = nil 184 s.handler = nil 185 s.stop = nil 186 187 s.conn.streamsLock.Lock() 188 delete(s.conn.streams, s.streamID) 189 s.conn.streamsLock.Unlock() 190 } 191 192 /********** 193 * Stream * 194 **********/ 195 196 func (s *ResponseStream) Conn() common.Conn { 197 return s.conn 198 } 199 200 func (s *ResponseStream) ReceiveFrame(frame common.Frame) error { 201 s.Lock() 202 defer s.Unlock() 203 204 if frame == nil { 205 return errors.New("Error: Nil frame received.") 206 } 207 208 // Process the frame depending on its type. 209 switch frame := frame.(type) { 210 case *frames.DATA: 211 s.requestBody.Write(frame.Data) 212 s.flow.Receive(frame.Data) 213 if frame.Flags.FIN() { 214 select { 215 case <-s.ready: 216 default: 217 close(s.ready) 218 } 219 s.state.CloseThere() 220 } 221 222 case *frames.SYN_REPLY: 223 if frame.Flags.FIN() { 224 select { 225 case <-s.ready: 226 default: 227 close(s.ready) 228 } 229 s.state.CloseThere() 230 } 231 232 case *frames.HEADERS: 233 return errors.New("Received unexpected HEADERS frame") 234 235 case *frames.WINDOW_UPDATE: 236 err := s.flow.UpdateWindow(frame.DeltaWindowSize) 237 if err != nil { 238 reply := new(frames.RST_STREAM) 239 reply.StreamID = s.streamID 240 reply.Status = common.RST_STREAM_FLOW_CONTROL_ERROR 241 s.output <- reply 242 return err 243 } 244 245 default: 246 return errors.New(fmt.Sprintf("Received unknown frame of type %T.", frame)) 247 } 248 249 return nil 250 } 251 252 func (s *ResponseStream) CloseNotify() <-chan bool { 253 return s.stop 254 } 255 256 // run is the main control path of 257 // the stream. It is prepared, the 258 // registered handler is called, 259 // and then the stream is cleaned 260 // up and closed. 261 func (s *ResponseStream) Run() error { 262 // Catch any panics. 263 defer func() { 264 if v := recover(); v != nil { 265 if s != nil && s.state != nil && !s.state.Closed() { 266 log.Printf("Encountered stream error: %v (%[1]T)\n", v) 267 } 268 } 269 }() 270 271 // Make sure Request is prepared. 272 if s.requestBody == nil || s.request.Body == nil { 273 s.requestBody = new(bytes.Buffer) 274 s.request.Body = &common.ReadCloser{s.requestBody} 275 } 276 277 // Wait until the full request has been received. 278 <-s.ready 279 280 /*************** 281 *** HANDLER *** 282 ***************/ 283 s.handler.ServeHTTP(s, s.request) 284 285 // Make sure any queued data has been sent. 286 if err := s.flow.Wait(); err != nil { 287 log.Println(err) 288 } 289 290 // Close the stream with a SYN_REPLY if 291 // none has been sent, or an empty DATA 292 // frame, if a SYN_REPLY has been sent 293 // already. 294 // If the stream is already closed at 295 // this end, then nothing happens. 296 if !s.unidirectional { 297 if s.state.OpenHere() && !s.wroteHeader { 298 h := s.header 299 if h == nil { 300 h = make(http.Header) 301 } 302 303 h.Set(":status", "200") 304 h.Set(":version", "HTTP/1.1") 305 306 // Create the response SYN_REPLY. 307 synReply := new(frames.SYN_REPLY) 308 synReply.Flags = common.FLAG_FIN 309 synReply.StreamID = s.streamID 310 synReply.Header = make(http.Header) 311 312 for name, values := range h { 313 for _, value := range values { 314 synReply.Header.Add(name, value) 315 } 316 h.Del(name) 317 } 318 319 s.output <- synReply 320 } else if s.state.OpenHere() { 321 // Create the DATA. 322 data := new(frames.DATA) 323 data.StreamID = s.streamID 324 data.Flags = common.FLAG_FIN 325 data.Data = []byte{} 326 327 s.output <- data 328 } 329 } 330 331 // Clean up state. 332 s.state.CloseHere() 333 334 if s.state.Closed() { 335 return s.Close() 336 } 337 338 return nil 339 } 340 341 func (s *ResponseStream) State() *common.StreamState { 342 return s.state 343 } 344 345 func (s *ResponseStream) StreamID() common.StreamID { 346 return s.streamID 347 } 348 349 func (s *ResponseStream) closed() bool { 350 if s.conn == nil || s.state == nil || s.handler == nil { 351 return true 352 } 353 select { 354 case _ = <-s.stop: 355 return true 356 default: 357 return false 358 } 359 } 360 361 // writeHeader is used to flush HTTP headers. 362 func (s *ResponseStream) writeHeader() { 363 if len(s.header) == 0 || s.unidirectional { 364 return 365 } 366 367 // Create the HEADERS frame. 368 header := new(frames.HEADERS) 369 header.StreamID = s.streamID 370 header.Header = make(http.Header) 371 372 // Clear the headers that have been sent. 373 for name, values := range s.header { 374 for _, value := range values { 375 header.Header.Add(name, value) 376 } 377 s.header.Del(name) 378 } 379 380 s.output <- header 381 } 382 383 /****************** 384 * PriorityStream * 385 ******************/ 386 387 func (s *ResponseStream) Priority() common.Priority { 388 return s.priority 389 }