Esempio n. 1
0
AP_CORE_DECLARE(void) ap_process_connection(conn_rec *c, void *csd)
{
    int rc;
    ap_update_vhost_given_ip(c);

    rc = ap_run_pre_connection(c, csd);
    if (rc != OK && rc != DONE) {
        c->aborted = 1;
    }
    
    if (!c->aborted) {
        ap_run_process_connection(c);
    }
}
Esempio n. 2
0
apr_status_t h2_task_do(h2_task *task, apr_thread_t *thread, int worker_id)
{
    conn_rec *c;
    
    ap_assert(task);
    c = task->c;
    task->worker_started = 1;
    task->started_at = apr_time_now();
    
    if (c->master) {
        /* Each conn_rec->id is supposed to be unique at a point in time. Since
         * some modules (and maybe external code) uses this id as an identifier
         * for the request_rec they handle, it needs to be unique for slave 
         * connections also.
         * The connection id is generated by the MPM and most MPMs use the formula
         *    id := (child_num * max_threads) + thread_num
         * which means that there is a maximum id of about
         *    idmax := max_child_count * max_threads
         * If we assume 2024 child processes with 2048 threads max, we get
         *    idmax ~= 2024 * 2048 = 2 ** 22
         * On 32 bit systems, we have not much space left, but on 64 bit systems
         * (and higher?) we can use the upper 32 bits without fear of collision.
         * 32 bits is just what we need, since a connection can only handle so
         * many streams. 
         */
        int slave_id, free_bits;
        
        task->id = apr_psprintf(task->pool, "%ld-%d", c->master->id, 
                                task->stream_id);
        if (sizeof(unsigned long) >= 8) {
            free_bits = 32;
            slave_id = task->stream_id;
        }
        else {
            /* Assume we have a more limited number of threads/processes
             * and h2 workers on a 32-bit system. Use the worker instead
             * of the stream id. */
            free_bits = 8;
            slave_id = worker_id; 
        }
        task->c->id = (c->master->id << free_bits)^slave_id;
        c->keepalive = AP_CONN_KEEPALIVE;
    }
        
    h2_beam_create(&task->output.beam, c->pool, task->stream_id, "output", 
                   H2_BEAM_OWNER_SEND, 0, task->timeout);
    if (!task->output.beam) {
        return APR_ENOMEM;
    }
    
    h2_beam_buffer_size_set(task->output.beam, task->output.max_buffer);
    h2_beam_send_from(task->output.beam, task->pool);
    
    h2_ctx_create_for(c, task);
    apr_table_setn(c->notes, H2_TASK_ID_NOTE, task->id);

    if (task->input.beam) {
        h2_beam_mutex_enable(task->input.beam);
    }
    
    h2_slave_run_pre_connection(c, ap_get_conn_socket(c));            

    task->input.bb = apr_brigade_create(task->pool, c->bucket_alloc);
    if (task->request->serialize) {
        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                      "h2_task(%s): serialize request %s %s", 
                      task->id, task->request->method, task->request->path);
        apr_brigade_printf(task->input.bb, NULL, 
                           NULL, "%s %s HTTP/1.1\r\n", 
                           task->request->method, task->request->path);
        apr_table_do(input_ser_header, task, task->request->headers, NULL);
        apr_brigade_puts(task->input.bb, NULL, NULL, "\r\n");
    }
    
    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                  "h2_task(%s): process connection", task->id);
                  
    task->c->current_thread = thread; 
    ap_run_process_connection(c);
    
    if (task->frozen) {
        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                      "h2_task(%s): process_conn returned frozen task", 
                      task->id);
        /* cleanup delayed */
        return APR_EAGAIN;
    }
    else {
        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
                      "h2_task(%s): processing done", task->id);
        return output_finish(task);
    }
}
Esempio n. 3
0
/*
 * worker_main()
 * Main entry point for the worker threads. Worker threads block in
 * win*_get_connection() awaiting a connection to service.
 */
static DWORD __stdcall worker_main(void *thread_num_val)
{
    apr_thread_t *thd;
    apr_os_thread_t osthd;
    static int requests_this_child = 0;
    winnt_conn_ctx_t *context = NULL;
    int thread_num = (int)thread_num_val;
    ap_sb_handle_t *sbh;
    apr_bucket *e;
    int rc;
    conn_rec *c;
    apr_int32_t disconnected;

    osthd = apr_os_thread_current();

    while (1) {

        ap_update_child_status_from_indexes(0, thread_num, SERVER_READY, NULL);

        /* Grab a connection off the network */
        context = winnt_get_connection(context);

        if (!context) {
            /* Time for the thread to exit */
            break;
        }

        /* Have we hit MaxConnectionsPerChild connections? */
        if (ap_max_requests_per_child) {
            requests_this_child++;
            if (requests_this_child > ap_max_requests_per_child) {
                SetEvent(max_requests_per_child_event);
            }
        }

        e = context->overlapped.Pointer;

        ap_create_sb_handle(&sbh, context->ptrans, 0, thread_num);
        c = ap_run_create_connection(context->ptrans, ap_server_conf,
                                     context->sock, thread_num, sbh,
                                     context->ba);

        if (!c)
        {
            /* ap_run_create_connection closes the socket on failure */
            context->accept_socket = INVALID_SOCKET;
            if (e)
                apr_bucket_free(e);
            continue;
        }

        thd = NULL;
        apr_os_thread_put(&thd, &osthd, context->ptrans);
        c->current_thread = thd;

        /* follow ap_process_connection(c, context->sock) logic
         * as it left us no chance to reinject our first data bucket.
         */
        ap_update_vhost_given_ip(c);

        rc = ap_run_pre_connection(c, context->sock);
        if (rc != OK && rc != DONE) {
            c->aborted = 1;
        }

        if (e && c->aborted)
        {
            apr_bucket_free(e);
        }
        else
        {
            ap_set_module_config(c->conn_config, &mpm_winnt_module, context);
        }

        if (!c->aborted)
        {
            ap_run_process_connection(c);

            apr_socket_opt_get(context->sock, APR_SO_DISCONNECTED,
                               &disconnected);

            if (!disconnected) {
                context->accept_socket = INVALID_SOCKET;
                ap_lingering_close(c);
            }
        }
    }

    ap_update_child_status_from_indexes(0, thread_num, SERVER_DEAD,
                                        (request_rec *) NULL);

    return 0;
}