* [RFC 7540] 6.3 PRIORITY * */
| 543 | * |
| 544 | */ |
| 545 | Http2Error |
| 546 | Http2ConnectionState::rcv_priority_frame(const Http2Frame &frame) |
| 547 | { |
| 548 | const Http2StreamId stream_id = frame.header().streamid; |
| 549 | const uint32_t payload_length = frame.header().length; |
| 550 | |
| 551 | Http2StreamDebug(this->session, stream_id, "Received PRIORITY frame"); |
| 552 | |
| 553 | if (this->get_zombie_event()) { |
| 554 | Warning("Priority frame for zombied session %" PRId64, this->session->get_connection_id()); |
| 555 | } |
| 556 | |
| 557 | // If a PRIORITY frame is received with a stream identifier of 0x0, the |
| 558 | // recipient MUST respond with a connection error of type PROTOCOL_ERROR. |
| 559 | if (stream_id == HTTP2_CONNECTION_CONTROL_STREAM) { |
| 560 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR, |
| 561 | "priority 0 stream_id"); |
| 562 | } |
| 563 | |
| 564 | // A PRIORITY frame with a length other than 5 octets MUST be treated as |
| 565 | // a stream error (Section 5.4.2) of type FRAME_SIZE_ERROR. |
| 566 | if (payload_length != HTTP2_PRIORITY_LEN) { |
| 567 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR, |
| 568 | "priority bad length"); |
| 569 | } |
| 570 | |
| 571 | uint8_t buf[HTTP2_PRIORITY_LEN] = {0}; |
| 572 | frame.reader()->memcpy(buf, HTTP2_PRIORITY_LEN, 0); |
| 573 | |
| 574 | Http2Priority priority; |
| 575 | if (!http2_parse_priority_parameter(make_iovec(buf, HTTP2_PRIORITY_LEN), priority)) { |
| 576 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR, |
| 577 | "priority parse error"); |
| 578 | } |
| 579 | |
| 580 | // A stream cannot depend on itself. An endpoint MUST treat this as a stream error of type PROTOCOL_ERROR. |
| 581 | if (stream_id == priority.stream_dependency) { |
| 582 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR, |
| 583 | "PRIORITY frame depends on itself"); |
| 584 | } |
| 585 | |
| 586 | if (!Http2::stream_priority_enabled) { |
| 587 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE); |
| 588 | } |
| 589 | |
| 590 | // Update PRIORITY frame count per minute |
| 591 | this->increment_received_priority_frame_count(); |
| 592 | // Close this connection if its priority frame count received exceeds a limit |
| 593 | if (configured_max_priority_frames_per_minute >= 0 && |
| 594 | this->get_received_priority_frame_count() > static_cast<uint32_t>(configured_max_priority_frames_per_minute)) { |
| 595 | Metrics::Counter::increment(http2_rsb.max_priority_frames_per_minute_exceeded); |
| 596 | Http2StreamDebug(this->session, stream_id, "Observed too frequent priority changes: %u priority changes within a last minute", |
| 597 | this->get_received_priority_frame_count()); |
| 598 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM, |
| 599 | "recv priority too frequent priority changes"); |
| 600 | } |
| 601 | |
| 602 | Http2StreamDebug(this->session, stream_id, "PRIORITY - dep: %d, weight: %d, excl: %d, tree size: %d", priority.stream_dependency, |
nothing calls this directly
no test coverage detected