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  }