Example #1
0
func (t *http2Client) handleData(f *http2.DataFrame) {
	size := len(f.Data())
	if err := t.fc.onData(uint32(size)); err != nil {
		t.notifyError(ConnectionErrorf("%v", err))
		return
	}
	// Select the right stream to dispatch.
	s, ok := t.getStream(f)
	if !ok {
		if w := t.fc.onRead(uint32(size)); w > 0 {
			t.controlBuf.put(&windowUpdate{0, w})
		}
		return
	}
	if size > 0 {
		s.mu.Lock()
		if s.state == streamDone {
			s.mu.Unlock()
			// The stream has been closed. Release the corresponding quota.
			if w := t.fc.onRead(uint32(size)); w > 0 {
				t.controlBuf.put(&windowUpdate{0, w})
			}
			return
		}
		if err := s.fc.onData(uint32(size)); err != nil {
			s.state = streamDone
			s.statusCode = codes.Internal
			s.statusDesc = err.Error()
			close(s.done)
			s.mu.Unlock()
			s.write(recvMsg{err: io.EOF})
			t.controlBuf.put(&resetStream{s.id, http2.ErrCodeFlowControl})
			return
		}
		s.mu.Unlock()
		// TODO(bradfitz, zhaoq): A copy is required here because there is no
		// guarantee f.Data() is consumed before the arrival of next frame.
		// Can this copy be eliminated?
		data := make([]byte, size)
		copy(data, f.Data())
		s.write(recvMsg{data: data})
	}
	// The server has closed the stream without sending trailers.  Record that
	// the read direction is closed, and set the status appropriately.
	if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) {
		s.mu.Lock()
		if s.state == streamDone {
			s.mu.Unlock()
			return
		}
		s.state = streamDone
		s.statusCode = codes.Internal
		s.statusDesc = "server closed the stream without sending trailers"
		close(s.done)
		s.mu.Unlock()
		s.write(recvMsg{err: io.EOF})
	}
}
Example #2
0
func (t *http2Server) handleData(f *http2.DataFrame) {
	size := len(f.Data())
	if err := t.fc.onData(uint32(size)); err != nil {
		grpclog.Printf("transport: http2Server %v", err)
		t.Close()
		return
	}
	// Select the right stream to dispatch.
	s, ok := t.getStream(f)
	if !ok {
		if w := t.fc.onRead(uint32(size)); w > 0 {
			t.controlBuf.put(&windowUpdate{0, w})
		}
		return
	}
	if size > 0 {
		s.mu.Lock()
		if s.state == streamDone {
			s.mu.Unlock()
			// The stream has been closed. Release the corresponding quota.
			if w := t.fc.onRead(uint32(size)); w > 0 {
				t.controlBuf.put(&windowUpdate{0, w})
			}
			return
		}
		if err := s.fc.onData(uint32(size)); err != nil {
			s.mu.Unlock()
			t.closeStream(s)
			t.controlBuf.put(&resetStream{s.id, http2.ErrCodeFlowControl})
			return
		}
		s.mu.Unlock()
		// TODO(bradfitz, zhaoq): A copy is required here because there is no
		// guarantee f.Data() is consumed before the arrival of next frame.
		// Can this copy be eliminated?
		data := make([]byte, size)
		copy(data, f.Data())
		s.write(recvMsg{data: data})
	}
	if f.Header().Flags.Has(http2.FlagDataEndStream) {
		// Received the end of stream from the client.
		s.mu.Lock()
		if s.state != streamDone {
			if s.state == streamWriteDone {
				s.state = streamDone
			} else {
				s.state = streamReadDone
			}
		}
		s.mu.Unlock()
		s.write(recvMsg{err: io.EOF})
	}
}
Example #3
0
func (conn *http2Connection) handleData(frame *http2.DataFrame) {
	stream, ok := conn.getStream(frame)
	if !ok {
		return
	}
	size := len(frame.Data())
	err := stream.flowControl.onData(uint32(size))
	if err != nil {
		conn.close(err)
		return
	}

	data := make([]byte, size)
	copy(data, frame.Data())
	endStream := frame.Header().Flags.Has(http2.FlagDataEndStream)

	doClose := false
	if endStream {
		stream.lock.Lock()
		if stream.state != streamStateDone {
			if stream.state == streamStateWriteDone {
				doClose = true
			} else {
				stream.state = streamStateReadDone
			}
		}
		stream.lock.Unlock()
	}
	afterRead := func() {
		conn.updateWindow(stream, uint32(size))
	}
	stream.receiveBuffer.Put(&MsgBytes{
		Data:      data,
		EndStream: endStream,
		AfterRead: afterRead,
	})

	if doClose {
		conn.closeStream(stream, nil)
	}
}