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  }