| 352 | } |
| 353 | |
| 354 | int |
| 355 | Http2CommonSession::do_process_frame_read(int /* event ATS_UNUSED */, VIO *vio, bool inside_frame) |
| 356 | { |
| 357 | Http2SsnDebug("do_process_frame_read %" PRId64 " bytes ready", this->_read_buffer_reader->read_avail()); |
| 358 | |
| 359 | if (inside_frame) { |
| 360 | do_complete_frame_read(); |
| 361 | } |
| 362 | |
| 363 | while (this->_read_buffer_reader->read_avail() >= static_cast<int64_t>(HTTP2_FRAME_HEADER_LEN)) { |
| 364 | // Cancel reading if there was an error or connection is closed |
| 365 | if (connection_state.tx_error_code.code != static_cast<uint32_t>(Http2ErrorCode::HTTP2_ERROR_NO_ERROR) || |
| 366 | connection_state.is_state_closed()) { |
| 367 | Http2SsnDebug("reading a frame has been canceled (%u)", connection_state.tx_error_code.code); |
| 368 | break; |
| 369 | } |
| 370 | |
| 371 | Http2ErrorCode err = Http2ErrorCode::HTTP2_ERROR_NO_ERROR; |
| 372 | if (this->connection_state.get_stream_error_rate() > std::min(1.0, Http2::stream_error_rate_threshold * 2.0)) { |
| 373 | ip_port_text_buffer ipb; |
| 374 | const char *peer_ip = ats_ip_ntop(this->get_proxy_session()->get_remote_addr(), ipb, sizeof(ipb)); |
| 375 | SiteThrottledWarning("HTTP/2 session error peer_ip=%s session_id=%" PRId64 |
| 376 | " closing a connection, because its stream error rate (%f) exceeded the threshold (%f)", |
| 377 | peer_ip, this->get_connection_id(), this->connection_state.get_stream_error_rate(), |
| 378 | Http2::stream_error_rate_threshold); |
| 379 | err = Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM; |
| 380 | } |
| 381 | |
| 382 | // Return if there was an error |
| 383 | if (err > Http2ErrorCode::HTTP2_ERROR_NO_ERROR || do_start_frame_read(err) < 0) { |
| 384 | // send an error if specified. Otherwise, just go away |
| 385 | this->connection_state.restart_receiving(nullptr); |
| 386 | if (err > Http2ErrorCode::HTTP2_ERROR_NO_ERROR) { |
| 387 | if (!this->connection_state.is_state_closed()) { |
| 388 | this->connection_state.send_goaway_frame(this->connection_state.get_latest_stream_id_in(), err); |
| 389 | this->set_half_close_local_flag(true); |
| 390 | } |
| 391 | } |
| 392 | return 0; |
| 393 | } |
| 394 | |
| 395 | // If there is no more data to finish the frame, set up the event handler and reenable |
| 396 | if (this->_read_buffer_reader->read_avail() < this->current_hdr.length) { |
| 397 | HTTP2_SET_SESSION_HANDLER(&Http2CommonSession::state_complete_frame_read); |
| 398 | break; |
| 399 | } |
| 400 | do_complete_frame_read(); |
| 401 | |
| 402 | if (this->_should_do_something_else()) { |
| 403 | if (this->_reenable_event == nullptr) { |
| 404 | this->connection_state.restart_receiving(nullptr); |
| 405 | vio->disable(); |
| 406 | this->_reenable_event = this->get_mutex()->thread_holding->schedule_in(this->get_proxy_session(), HRTIME_MSECONDS(1), |
| 407 | HTTP2_SESSION_EVENT_REENABLE, vio); |
| 408 | return 0; |
| 409 | } |
| 410 | } |
| 411 | } |
nothing calls this directly
no test coverage detected