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}) } }
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) } }