| 1836 | } |
| 1837 | |
| 1838 | apr_status_t h2_session_process(h2_session *session, int async, |
| 1839 | int *pkeepalive) |
| 1840 | { |
| 1841 | apr_status_t status = APR_SUCCESS; |
| 1842 | conn_rec *c = session->c1; |
| 1843 | int rv, mpm_state, trace = APLOGctrace3(c); |
| 1844 | |
| 1845 | *pkeepalive = 0; |
| 1846 | if (trace) { |
| 1847 | ap_log_cerror( APLOG_MARK, APLOG_TRACE3, status, c, |
| 1848 | H2_SSSN_MSG(session, "process start, async=%d"), async); |
| 1849 | } |
| 1850 | |
| 1851 | if (H2_SESSION_ST_INIT == session->state) { |
| 1852 | if (!h2_protocol_is_acceptable_c1(c, session->r, 1)) { |
| 1853 | const char *msg = nghttp2_strerror(NGHTTP2_INADEQUATE_SECURITY); |
| 1854 | update_child_status(session, SERVER_BUSY_READ, msg, NULL); |
| 1855 | h2_session_shutdown(session, APR_EINVAL, msg, 1); |
| 1856 | } |
| 1857 | else { |
| 1858 | update_child_status(session, SERVER_BUSY_READ, "init", NULL); |
| 1859 | status = h2_session_start(session, &rv); |
| 1860 | ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, c, |
| 1861 | H2_SSSN_LOG(APLOGNO(03079), session, |
| 1862 | "started on %s:%d"), |
| 1863 | session->s->server_hostname, |
| 1864 | c->local_addr->port); |
| 1865 | if (status != APR_SUCCESS) { |
| 1866 | h2_session_dispatch_event(session, |
| 1867 | H2_SESSION_EV_CONN_ERROR, status, NULL); |
| 1868 | } |
| 1869 | else { |
| 1870 | h2_session_dispatch_event(session, H2_SESSION_EV_INIT, 0, NULL); |
| 1871 | } |
| 1872 | } |
| 1873 | } |
| 1874 | |
| 1875 | while (session->state != H2_SESSION_ST_DONE) { |
| 1876 | |
| 1877 | /* PR65731: we may get a new connection to process while the |
| 1878 | * MPM already is stopping. For example due to having reached |
| 1879 | * MaxRequestsPerChild limit. |
| 1880 | * Since this is supposed to handle things gracefully, we need to: |
| 1881 | * a) fully initialize the session before GOAWAYing |
| 1882 | * b) give the client the chance to submit at least one request |
| 1883 | */ |
| 1884 | if (session->state != H2_SESSION_ST_INIT /* no longer intializing */ |
| 1885 | && session->local.accepted_max > 0 /* have gotten at least one stream */ |
| 1886 | && session->local.accepting /* have not already locally shut down */ |
| 1887 | && !ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state)) { |
| 1888 | if (mpm_state == AP_MPMQ_STOPPING) { |
| 1889 | h2_session_dispatch_event(session, H2_SESSION_EV_MPM_STOPPING, 0, NULL); |
| 1890 | } |
| 1891 | } |
| 1892 | |
| 1893 | if (session->max_stream_errors && |
| 1894 | session->stream_errors > session->max_stream_errors) { |
| 1895 | h2_session_dispatch_event(session, H2_SESSION_EV_BAD_CLIENT, |
no test coverage detected