⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 perchild.c

📁 Apache 2.0.63 is the current stable version of the 2.0 series, and is recommended over any previous
💻 C
📖 第 1 页 / 共 5 页
字号:
    }

    return OK;
}

static int pass_request(request_rec *r)
{
    int rv;
    apr_socket_t *thesock = ap_get_module_config(r->connection->conn_config, &core_module);
    struct msghdr msg;
    struct cmsghdr *cmsg;
    int sfd;
    struct iovec iov[2];
    conn_rec *c = r->connection;
    apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
    apr_bucket_brigade *sockbb;
    char request_body[HUGE_STRING_LEN] = "\0";
    apr_size_t l = sizeof(request_body);
    perchild_header h;
    apr_bucket *sockbuck;
    perchild_server_conf *sconf = (perchild_server_conf *)
                            ap_get_module_config(r->server->module_config, 
                                                 &mpm_perchild_module);

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
                 "passing request to another child.  Vhost: %s, child %d %d",
                 apr_table_get(r->headers_in, "Host"), child_num, sconf->output);
    ap_get_brigade(r->connection->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_NONBLOCK_READ,
                   0);

    for (sockbuck = APR_BRIGADE_FIRST(bb); sockbuck != APR_BRIGADE_SENTINEL(bb);
         sockbuck = APR_BUCKET_NEXT(sockbuck)) {
        if (APR_BUCKET_IS_SOCKET(sockbuck)) {
            break;
        }
    }
    
    if (!sockbuck) {
    }
    sockbb = apr_brigade_split(bb, sockbuck); 

    if (apr_brigade_flatten(bb, request_body, &l) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
                     "Unable to flatten brigade, declining request");
        return DECLINED;
    }

    apr_os_sock_get(&sfd, thesock);

    h.p = r->pool;
    h.headers = apr_pstrcat(h.p, r->the_request, CRLF, "Host: ", r->hostname, 
                            CRLF, NULL);
    apr_table_do((int (*) (void *, const char *, const char *))
                 perchild_header_field, (void *) &h, r->headers_in, NULL); 
    h.headers = apr_pstrcat(h.p, h.headers, CRLF, NULL);

    iov[0].iov_base = h.headers;
    iov[0].iov_len = strlen(h.headers) + 1;
    iov[1].iov_base = request_body;
    iov[1].iov_len = l + 1;

    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = 2;

    cmsg = apr_palloc(r->pool, sizeof(*cmsg) + sizeof(sfd));
    cmsg->cmsg_len = sizeof(*cmsg) + sizeof(sfd);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;

    memcpy(CMSG_DATA(cmsg), &sfd, sizeof(sfd));

    msg.msg_control = cmsg;
    msg.msg_controllen = cmsg->cmsg_len;

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
                 "Writing message to %d, passing sd:  %d", sconf->output, sfd);

    if ((rv = sendmsg(sconf->output, &msg, 0)) == -1) {
        apr_pool_destroy(r->pool);
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
                 "Writing message failed %d %d", rv, errno);
        return -1;
    }

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
                 "Writing message succeeded %d", rv);

    apr_pool_destroy(r->pool);
    return 1;
}

static char *make_perchild_socket(const char *fullsockname, int sd[2])
{
    socketpair(PF_UNIX, SOCK_STREAM, 0, sd);
    return NULL;
}

static int perchild_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
    int i;
    server_rec *sr;
    perchild_server_conf *sconf;
    int def_sd[2];

    def_sd[0] = -1;
    def_sd[1] = -1;

    for (sr = s; sr; sr = sr->next) {
        sconf = (perchild_server_conf *)ap_get_module_config(sr->module_config,
                                                      &mpm_perchild_module);

        if (sconf->input == -1) {
            sconf->fullsockname = apr_pstrcat(sr->process->pool, 
                                             sconf->sockname, ".DEFAULT", NULL);
            if (def_sd[0] == -1) {
                if (!make_perchild_socket(sconf->fullsockname, def_sd)) {
                    /* log error */
                }
            }
            sconf->input = def_sd[0];
            sconf->output = def_sd[1];
        }
    }

    for (i = 0; i < num_daemons; i++) {
        if (child_info_table[i].uid == -1) {
            child_info_table[i].input = def_sd[0];
            child_info_table[i].output = def_sd[1];
        }
    }

    thread_socket_table = (int *)apr_pcalloc(p, thread_limit * sizeof(int));
    for (i = 0; i < thread_limit; i++) {
        thread_socket_table[i] = AP_PERCHILD_THISCHILD;
    }
    ap_child_table = (ap_ctable *)apr_pcalloc(p, server_limit * sizeof(ap_ctable));

    return OK;
}

static int perchild_post_read(request_rec *r)
{
    int thread_num = r->connection->id % thread_limit;
    perchild_server_conf *sconf = (perchild_server_conf *)
                            ap_get_module_config(r->server->module_config, 
                                                 &mpm_perchild_module);

    if (thread_socket_table[thread_num] != AP_PERCHILD_THISCHILD) {
        apr_socket_t *csd = NULL;

        apr_os_sock_put(&csd, &thread_socket_table[thread_num], 
                        r->connection->pool);
        ap_sock_disable_nagle(csd);
        ap_set_module_config(r->connection->conn_config, &core_module, csd);
        return OK;
    }
    else {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
                     "Determining if request should be passed. "
                     "Child Num: %d, SD: %d, sd from table: %d, hostname from server: %s", child_num, 
                     sconf->input, child_info_table[child_num].input, 
                     r->server->server_hostname);
        /* sconf is the server config for this vhost, so if our socket
         * is not the same that was set in the config, then the request
         * needs to be passed to another child. */
        if (sconf->input != child_info_table[child_num].input) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, 
                         "Passing request.");
            if (pass_request(r) == -1) {
                ap_log_error(APLOG_MARK, APLOG_ERR, 0,
                             ap_server_conf, "Could not pass request to proper "
                             "child, request will not be honored.");
            }
            longjmp(jmpbuffer, 1); 
        }
        return OK;
    }
    return OK;
}

static void perchild_hooks(apr_pool_t *p)
{
    /* The perchild open_logs phase must run before the core's, or stderr
     * will be redirected to a file, and the messages won't print to the
     * console.
     */
    static const char *const aszSucc[] = {"core.c", NULL};
    one_process = 0;

    ap_hook_open_logs(perchild_open_logs, NULL, aszSucc, APR_HOOK_MIDDLE);
    ap_hook_pre_config(perchild_pre_config, NULL, NULL, APR_HOOK_MIDDLE); 
    ap_hook_post_config(perchild_post_config, NULL, NULL, APR_HOOK_MIDDLE); 

    /* Both of these must be run absolutely first.  If this request isn't for 
     * this server then we need to forward it to the proper child.  No sense
     * tying up this server running more post_read request hooks if it is
     * just going to be forwarded along.  The process_connection hook allows
     * perchild to receive the passed request correctly, by automatically
     * filling in the core_input_filter's ctx pointer.
     */
    ap_hook_post_read_request(perchild_post_read, NULL, NULL,
                              APR_HOOK_REALLY_FIRST);
    ap_hook_process_connection(perchild_process_connection, NULL, NULL, 
                               APR_HOOK_REALLY_FIRST);
}

static const char *set_num_daemons(cmd_parms *cmd, void *dummy,
                                   const char *arg) 
{
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    if (err != NULL) {
        return err;
    }

    num_daemons = atoi(arg);
    if (num_daemons > server_limit) {
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    "WARNING: NumServers of %d exceeds ServerLimit value "
                    "of %d servers,", num_daemons, server_limit);
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    " lowering NumServers to %d.  To increase, please "
                    "see the", server_limit);
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    " ServerLimit directive.");
       num_daemons = server_limit;
    } 
    else if (num_daemons < 1) {
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                     "WARNING: Require NumServers > 0, setting to 1");
        num_daemons = 1;
    }
    return NULL;
}

static const char *set_threads_to_start(cmd_parms *cmd, void *dummy,
                                        const char *arg) 
{
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    if (err != NULL) {
        return err;
    }

    threads_to_start = atoi(arg);
    if (threads_to_start > thread_limit) {
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                     "WARNING: StartThreads of %d exceeds ThreadLimit value"
                     " of %d threads,", threads_to_start,
                     thread_limit);
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                     " lowering StartThreads to %d. To increase, please"
                     " see the", thread_limit);
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                     " ThreadLimit directive.");
    }
    else if (threads_to_start < 1) {
        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                     "WARNING: Require StartThreads > 0, setting to 1");
        threads_to_start = 1;
    }
    return NULL;
}

static const char *set_min_spare_threads(cmd_parms *cmd, void *dummy,
                                         const char *arg)
{
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    if (err != NULL) {
        return err;
    }

    min_spare_threads = atoi(arg);
    if (min_spare_threads <= 0) {
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    "WARNING: detected MinSpareThreads set to non-positive.");
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    "Resetting to 1 to avoid almost certain Apache failure.");
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    "Please read the documentation.");
       min_spare_threads = 1;
    }
       
    return NULL;
}

static const char *set_max_spare_threads(cmd_parms *cmd, void *dummy,
                                         const char *arg)
{
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    if (err != NULL) {
        return err;
    }

    max_spare_threads = atoi(arg);
    if (max_spare_threads >= thread_limit) {
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    "WARNING: detected MinSpareThreads set higher than");
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    "ThreadLimit. Resetting to %d", thread_limit);
       max_spare_threads = thread_limit;
    }
    return NULL;
}

static const char *set_max_threads(cmd_parms *cmd, void *dummy, const char *arg)
{
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    if (err != NULL) {
        return err;
    }

    max_threads = atoi(arg);
    if (max_threads > thread_limit) {
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    "WARNING: detected MaxThreadsPerChild set higher than");
       ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, 
                    "ThreadLimit. Resetting to %d", thread_limit);
       max_threads = thread_limit;
    }
    return NULL;
}

static const char *set_child_per_uid(cmd_parms *cmd, void *dummy, const char *u,
                                     const char *g, const char *num)
{
    int i;
    int max_this_time = atoi(num) + curr_child_num;
    

    for (i = curr_child_num; i < max_this_time; i++, curr_child_num++) {
        if (i > num_daemons) {
            return "Trying to use more child ID's than NumServers.  Increase "
                   "NumServers in your config file.";
        }
    
        child_info_table[i].uid = ap_uname2id(u);
        child_info_table[i].gid = ap_gname2id(g); 

#ifndef BIG_SECURITY_HOLE
        if (child_info_table[i].uid == 0 || child_info_table[i].gid == 0) {
            return "Assigning root user/group to a child.";
        }
#endif
    }
    return NULL;
}

static const char *assign_childuid(cmd_parms *cmd, void *dummy, const char *uid,
                                   const char *gid)
{
    int i;
    int matching = 0;
    int u = ap_uname2id(uid);
    int g = ap_gname2id(gid);
    const char *errstr;
    int socks[2];
    perchild_server_conf *sconf = (perchild_server_conf *)
                            ap_get_module_config(cmd->server->module_config, 
                                                 &mpm_perchild_module);

    sconf->fullsockname = apr_pstrcat(cmd->pool, sconf->sockname, ".", uid,
                                      ":", gid, NULL);

    if ((errstr = make_perchild_socket(sconf->fullsockname, socks))) {
        return errstr;
    }

    sconf->input = socks[0]; 
    sconf->output = socks[1];

    for (i = 0; i < num_daemons; i++) {
        if (u == child_info_table[i].uid && g == child_info_table[i].gid) {
            child_info_table[i].input = sconf->input;
            child_info_table[i].output = sconf->output;
            matching++;
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, 
                         "filling out child_info_table; UID: %d, GID: %d, "
                         "SD: %d %d, OUTPUT: %d %d, Child Num: %d", 
                         child_info_tabl

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -