operateHeaders takes action on the decoded headers. Returns an error if fatal error encountered and transport needs to close, otherwise returns nil.
(ctx context.Context, frame *http2.MetaHeadersFrame, handle func(*ServerStream))
| 375 | // operateHeaders takes action on the decoded headers. Returns an error if fatal |
| 376 | // error encountered and transport needs to close, otherwise returns nil. |
| 377 | func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeadersFrame, handle func(*ServerStream)) error { |
| 378 | // Acquire max stream ID lock for entire duration |
| 379 | t.maxStreamMu.Lock() |
| 380 | defer t.maxStreamMu.Unlock() |
| 381 | |
| 382 | streamID := frame.Header().StreamID |
| 383 | |
| 384 | // frame.Truncated is set to true when framer detects that the current header |
| 385 | // list size hits MaxHeaderListSize limit. |
| 386 | if frame.Truncated { |
| 387 | t.controlBuf.put(&cleanupStream{ |
| 388 | streamID: streamID, |
| 389 | rst: true, |
| 390 | rstCode: http2.ErrCodeFrameSize, |
| 391 | onWrite: func() {}, |
| 392 | }) |
| 393 | return nil |
| 394 | } |
| 395 | |
| 396 | if streamID%2 != 1 || streamID <= t.maxStreamID { |
| 397 | // illegal gRPC stream id. |
| 398 | return fmt.Errorf("received an illegal stream id: %v. headers frame: %+v", streamID, frame) |
| 399 | } |
| 400 | t.maxStreamID = streamID |
| 401 | |
| 402 | s := &ServerStream{ |
| 403 | Stream: Stream{ |
| 404 | id: streamID, |
| 405 | fc: inFlow{limit: uint32(t.initialWindowSize)}, |
| 406 | }, |
| 407 | st: t, |
| 408 | headerWireLength: int(frame.Header().Length), |
| 409 | } |
| 410 | s.Stream.buf.init() |
| 411 | var ( |
| 412 | // if false, content-type was missing or invalid |
| 413 | isGRPC = false |
| 414 | contentType = "" |
| 415 | mdata = make(metadata.MD, len(frame.Fields)) |
| 416 | httpMethod string |
| 417 | // these are set if an error is encountered while parsing the headers |
| 418 | protocolError bool |
| 419 | headerError *status.Status |
| 420 | |
| 421 | timeoutSet bool |
| 422 | timeout time.Duration |
| 423 | ) |
| 424 | |
| 425 | for _, hf := range frame.Fields { |
| 426 | switch hf.Name { |
| 427 | case "content-type": |
| 428 | contentSubtype, validContentType := grpcutil.ContentSubtype(hf.Value) |
| 429 | if !validContentType { |
| 430 | contentType = hf.Value |
| 431 | break |
| 432 | } |
| 433 | mdata[hf.Name] = append(mdata[hf.Name], hf.Value) |
| 434 | s.contentSubtype = contentSubtype |