| 698 | } |
| 699 | |
| 700 | Http2Error |
| 701 | Http2ConnectionState::rcv_settings_frame(const Http2Frame &frame) |
| 702 | { |
| 703 | Http2SettingsParameter param; |
| 704 | char buf[HTTP2_SETTINGS_PARAMETER_LEN]; |
| 705 | unsigned nbytes = 0; |
| 706 | const Http2StreamId stream_id = frame.header().streamid; |
| 707 | |
| 708 | Http2StreamDebug(this->session, stream_id, "Received SETTINGS frame"); |
| 709 | |
| 710 | if (this->get_zombie_event()) { |
| 711 | Warning("Setting frame for zombied session %" PRId64, this->session->get_connection_id()); |
| 712 | } |
| 713 | |
| 714 | // Update SETTINGS frame count per minute |
| 715 | this->increment_received_settings_frame_count(); |
| 716 | // Close this connection if its SETTINGS frame count exceeds a limit |
| 717 | if (configured_max_settings_frames_per_minute >= 0 && |
| 718 | this->get_received_settings_frame_count() > static_cast<uint32_t>(configured_max_settings_frames_per_minute)) { |
| 719 | Metrics::Counter::increment(http2_rsb.max_settings_frames_per_minute_exceeded); |
| 720 | Http2StreamDebug(this->session, stream_id, "Observed too frequent SETTINGS frames: %u frames within a last minute", |
| 721 | this->get_received_settings_frame_count()); |
| 722 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM, |
| 723 | "recv settings too frequent SETTINGS frames"); |
| 724 | } |
| 725 | |
| 726 | // [RFC 7540] 6.5. The stream identifier for a SETTINGS frame MUST be zero. |
| 727 | // If an endpoint receives a SETTINGS frame whose stream identifier field is |
| 728 | // anything other than 0x0, the endpoint MUST respond with a connection |
| 729 | // error (Section 5.4.1) of type PROTOCOL_ERROR. |
| 730 | if (stream_id != 0) { |
| 731 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR, |
| 732 | "recv settings stream not 0"); |
| 733 | } |
| 734 | |
| 735 | // [RFC 7540] 6.5. Receipt of a SETTINGS frame with the ACK flag set and a |
| 736 | // length field value other than 0 MUST be treated as a connection |
| 737 | // error of type FRAME_SIZE_ERROR. |
| 738 | if (frame.header().flags & HTTP2_FLAGS_SETTINGS_ACK) { |
| 739 | if (frame.header().length == 0) { |
| 740 | this->_process_incoming_settings_ack_frame(); |
| 741 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE); |
| 742 | } else { |
| 743 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR, |
| 744 | "recv settings ACK header length not 0"); |
| 745 | } |
| 746 | } |
| 747 | |
| 748 | // A SETTINGS frame with a length other than a multiple of 6 octets MUST |
| 749 | // be treated as a connection error (Section 5.4.1) of type |
| 750 | // FRAME_SIZE_ERROR. |
| 751 | if (frame.header().length % 6 != 0) { |
| 752 | return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR, |
| 753 | "recv settings header wrong length"); |
| 754 | } |
| 755 | |
| 756 | uint32_t n_settings = 0; |
| 757 | while (nbytes < frame.header().length) { |
nothing calls this directly
no test coverage detected