apr_status_t round_robin_postprocess()

in flood_round_robin.c [1069:1265]


apr_status_t round_robin_postprocess(profile_t *profile,
                                     request_t *req,
                                     response_t *resp)
{
    round_robin_profile_t *rp;
    char *cookieheader, *cookievalue, *cookieend;

    rp = (round_robin_profile_t*)profile;

    /* FIXME: This algorithm sucks.  I need to be shot for writing such 
     * atrocious code.  Grr.  */
    cookieheader = strstr(resp->rbuf, "Set-Cookie: ");
    if (cookieheader)
    {
        /* Point to the value */
        cookieheader += 12;
        cookievalue = (char*) memchr(cookieheader, '=', 
                      resp->rbufsize - (int)(cookieheader - (int)(resp->rbuf)));
        if (cookievalue)
        {
            cookie_t * cookie = apr_pcalloc(rp->pool, sizeof(cookie_t));

            ++cookievalue;
            cookie->name = apr_palloc(rp->pool, cookievalue - cookieheader);
            apr_cpystrn(cookie->name, cookieheader, cookievalue - cookieheader);

            cookieheader = cookievalue;
            cookieend = (char*) memchr(cookieheader, '\r', 
                      resp->rbufsize - (int)(cookieheader - (int)(resp->rbuf)));
            cookievalue = (char*) memchr(cookieheader, ';', 
                                  cookieend - cookieheader);
            if (!cookievalue)
                cookievalue = cookieend;
            
            ++cookievalue;
            
            cookie->value = apr_palloc(rp->pool, cookievalue - cookieheader);
            apr_cpystrn(cookie->value, cookieheader, 
                        cookievalue - cookieheader);
            cookie->next = rp->cookie;
            rp->cookie = cookie;
        }
    }
    if (rp->url[rp->current_url].responsetemplate)
    {
        int status, size;
        char *expanded, *newValue;
        regmatch_t match[10];
        regex_t re;

        expanded = expand_param_string(rp, 
                                    rp->url[rp->current_url].responsetemplate);
        regcomp(&re, expanded, REG_EXTENDED);
        status = regexec(&re, resp->rbuf, 10, match, 0);

        if (status != REG_OK) {
            apr_file_printf(local_stderr,
                            "Regular expression match failed (%s)\n",
                            rp->url[rp->current_url].responsetemplate);
            return APR_EGENERAL;
        }

        size = match[1].rm_eo - match[1].rm_so + 1;
        newValue = apr_palloc(rp->pool, size);
        apr_cpystrn(newValue, resp->rbuf + match[1].rm_so, size);
        apr_hash_set(rp->state, rp->url[rp->current_url].responsename,
                     rp->url[rp->current_url].responselen, newValue);
        regfree(&re);
    }
    if (rp->url[rp->current_url].responsescript)
    {
        int exitcode = 0;
        apr_status_t rv;
        apr_proc_t *proc;
        apr_pollfd_t pipeout;
        apr_pollset_t *pollset;
        apr_procattr_t *procattr;
        apr_size_t nbytes, wbytes;
        char buf[255];

        char **args;
        const char *progname;
        

        if ((rv = apr_procattr_create(&procattr, rp->pool)) != APR_SUCCESS) {
            apr_file_printf(local_stderr,
                            "apr_procattr_create failed for '%s': %s\n",
                            rp->url[rp->current_url].responsescript,
                            apr_strerror(rv, buf, sizeof(buf)));
            return rv;
        }

        if ((rv = apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_NO_PIPE,
                                      APR_NO_PIPE)) != APR_SUCCESS) {
            apr_file_printf(local_stderr,
                            "apr_procattr_io_set failed for '%s': %s\n",
                            rp->url[rp->current_url].responsescript,
                            apr_strerror(rv, buf, sizeof(buf)));
            return rv;
        }

        if ((rv = apr_procattr_error_check_set(procattr, 1)) != APR_SUCCESS) {
            apr_file_printf(local_stderr,
                            "apr_procattr_error_check_set failed "
                            "for '%s': %s\n",
                            rp->url[rp->current_url].responsescript,
                            apr_strerror(rv, buf, sizeof(buf)));
            return rv;
        }

        apr_tokenize_to_argv(rp->url[rp->current_url].responsescript, &args,
                                rp->pool);
        progname = apr_pstrdup(rp->pool, args[0]);

        proc = (apr_proc_t *)apr_pcalloc(rp->pool, sizeof(*proc));

        /* create process */
        if ((rv = apr_proc_create(proc, progname, (const char * const *)args,
                                  NULL, procattr, rp->pool)) != APR_SUCCESS) {
            apr_file_printf(local_stderr,
                            "Can't spawn postprocess script '%s': %s\n",
                            rp->url[rp->current_url].responsescript,
                            apr_strerror(rv, buf, sizeof(buf)));
            return rv;
        }

        if ((rv = apr_file_pipe_timeout_set(proc->in, apr_time_from_sec(10)))
                                    != APR_SUCCESS) {
            apr_file_printf(local_stderr,
                            "apr_file_pipe_timeout_set failed for '%s': %s\n",
                            rp->url[rp->current_url].responsescript,
                            apr_strerror(rv, buf, sizeof(buf)));
            return rv;
        }

        apr_pollset_create(&pollset, 1, rp->pool, 0);

        pipeout.desc_type = APR_POLL_FILE;
        pipeout.reqevents = APR_POLLOUT;
        pipeout.desc.f = proc->in;
        pipeout.client_data = NULL;

        apr_pollset_add(pollset, &pipeout);

        wbytes = 0;
        nbytes = strlen(resp->rbuf);

        while (wbytes < nbytes) {

            apr_size_t bytes;
            apr_int32_t nrdes;
            const apr_pollfd_t *ardes = NULL;
            const apr_pollfd_t *rdes;

            if ((rv = apr_pollset_poll(pollset, apr_time_from_sec(10),
                                       &nrdes, &ardes)) != APR_SUCCESS) {
                apr_file_printf(local_stderr,
                                "error writing data to script '%s': %s\n",
                                rp->url[rp->current_url].responsescript,
                                apr_strerror(rv, buf, sizeof(buf)));
                return rv;
            }

            /* there can be only one descriptor... */
            rdes = &(ardes[0]);

            bytes = nbytes;
            apr_file_write(rdes->desc.f, resp->rbuf, &bytes);

            wbytes += bytes;

        }

        apr_pollset_remove(pollset, &pipeout);
        apr_file_close(proc->in);


        if ((rv = apr_proc_wait(proc, &exitcode, NULL, APR_WAIT))
                                                    != APR_CHILD_DONE) {
            apr_file_printf(local_stderr,
                            "apr_proc_wait failed for '%s': %s\n",
                            rp->url[rp->current_url].responsescript,
                            apr_strerror(rv, buf, sizeof(buf)));
            return rv;
        }

        if (exitcode != 0) {
            apr_file_printf(local_stderr,
                            "Postprocess script '%s' failed, exit code '%i'\n",
                            rp->url[rp->current_url].responsescript, exitcode);
            return APR_EGENERAL;
        }

    }

    return APR_SUCCESS;
}