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

📄 request.c

📁 boa:Linux系统中的轻量级Web服务
💻 C
📖 第 1 页 / 共 2 页
字号:
 * return value from handler functions, all of which return -1 * to indicate a block, 0 on completion and 1 to remain on the * ready list for more procesing. */void process_requests(int server_s){    int retval = 0;    request *current, *trailer;    if (pending_requests) {        get_request(server_s);#ifdef ORIGINAL_BEHAVIOR        pending_requests = 0;#endif    }    current = request_ready;    while (current) {        time(&current_time);        if (current->buffer_end && /* there is data in the buffer */            current->status != DEAD && current->status != DONE) {            retval = req_flush(current);            /*             * retval can be -2=error, -1=blocked, or bytes left             */            if (retval == -2) { /* error */                current->status = DEAD;                retval = 0;            } else if (retval >= 0) {                /* notice the >= which is different from below?                   Here, we may just be flushing headers.                   We don't want to return 0 because we are not DONE                   or DEAD */                retval = 1;            }        } else {            switch (current->status) {            case READ_HEADER:            case ONE_CR:            case ONE_LF:            case TWO_CR:                retval = read_header(current);                break;            case BODY_READ:                retval = read_body(current);                break;            case BODY_WRITE:                retval = write_body(current);                break;            case WRITE:                retval = process_get(current);                break;            case PIPE_READ:                retval = read_from_pipe(current);                break;            case PIPE_WRITE:                retval = write_from_pipe(current);                break;            case DONE:                /* a non-status that will terminate the request */                retval = req_flush(current);                /*                 * retval can be -2=error, -1=blocked, or bytes left                 */                if (retval == -2) { /* error */                    current->status = DEAD;                    retval = 0;                } else if (retval > 0) {                    retval = 1;                }                break;            case DEAD:                retval = 0;                current->buffer_end = 0;                SQUASH_KA(current);                break;            default:                retval = 0;                fprintf(stderr, "Unknown status (%d), "                        "closing!\n", current->status);                current->status = DEAD;                break;            }        }        if (sigterm_flag)            SQUASH_KA(current);        /* we put this here instead of after the switch so that         * if we are on the last request, and get_request is successful,         * current->next is valid!         */        if (pending_requests)            get_request(server_s);        switch (retval) {        case -1:               /* request blocked */            trailer = current;            current = current->next;            block_request(trailer);            break;        case 0:                /* request complete */            current->time_last = current_time;            trailer = current;            current = current->next;            free_request(&request_ready, trailer);            break;        case 1:                /* more to do */            current->time_last = current_time;            current = current->next;            break;        default:            log_error_time();            fprintf(stderr, "Unknown retval in process.c - "                    "Status: %d, retval: %d\n", current->status, retval);            current = current->next;            break;        }    }}/* * Name: process_logline * * Description: This is called with the first req->header_line received * by a request, called "logline" because it is logged to a file. * It is parsed to determine request type and method, then passed to * translate_uri for further parsing.  Also sets up CGI environment if * needed. */int process_logline(request * req){    char *stop, *stop2;    static char *SIMPLE_HTTP_VERSION = "HTTP/0.9";    req->logline = req->client_stream;    if (!memcmp(req->logline, "GET ", 4))        req->method = M_GET;    else if (!memcmp(req->logline, "HEAD ", 5))        /* head is just get w/no body */        req->method = M_HEAD;    else if (!memcmp(req->logline, "POST ", 5))        req->method = M_POST;    else {        log_error_time();        fprintf(stderr, "malformed request: \"%s\"\n", req->logline);        send_r_not_implemented(req);        return 0;    }    req->http_version = SIMPLE_HTTP_VERSION;    req->simple = 1;    /* Guaranteed to find ' ' since we matched a method above */    stop = req->logline + 3;    if (*stop != ' ')        ++stop;    /* scan to start of non-whitespace */    while (*(++stop) == ' ');    stop2 = stop;    /* scan to end of non-whitespace */    while (*stop2 != '\0' && *stop2 != ' ')        ++stop2;    if (stop2 - stop > MAX_HEADER_LENGTH) {        log_error_time();        fprintf(stderr, "URI too long %d: \"%s\"\n", MAX_HEADER_LENGTH,                req->logline);        send_r_bad_request(req);        return 0;    }    memcpy(req->request_uri, stop, stop2 - stop);    req->request_uri[stop2 - stop] = '\0';    if (*stop2 == ' ') {        /* if found, we should get an HTTP/x.x */        unsigned int p1, p2;        /* scan to end of whitespace */        ++stop2;        while (*stop2 == ' ' && *stop2 != '\0')            ++stop2;        /* scan in HTTP/major.minor */        if (sscanf(stop2, "HTTP/%u.%u", &p1, &p2) == 2) {            /* HTTP/{0.9,1.0,1.1} */            if (p1 == 1 && (p2 == 0 || p2 == 1)) {                req->http_version = stop2;                req->simple = 0;            } else if (p1 > 1 || (p1 != 0 && p2 > 1)) {                goto BAD_VERSION;            }        } else {            goto BAD_VERSION;        }    }    if (req->method == M_HEAD && req->simple) {        send_r_bad_request(req);        return 0;    }    req->cgi_env_index = COMMON_CGI_COUNT;    return 1;BAD_VERSION:    log_error_time();    fprintf(stderr, "bogus HTTP version: \"%s\"\n", stop2);    send_r_bad_request(req);    return 0;}/* * Name: process_header_end * * Description: takes a request and performs some final checking before * init_cgi or init_get * Returns 0 for error or NPH, or 1 for success */int process_header_end(request * req){    if (!req->logline) {        send_r_error(req);        return 0;    }    /* Percent-decode request */    if (unescape_uri(req->request_uri, &(req->query_string)) == 0) {        log_error_doc(req);        fputs("Problem unescaping uri\n", stderr);        send_r_bad_request(req);        return 0;    }    /* clean pathname */    clean_pathname(req->request_uri);    if (req->request_uri[0] != '/') {        send_r_bad_request(req);        return 0;    }    if (translate_uri(req) == 0) { /* unescape, parse uri */        SQUASH_KA(req);        return 0;               /* failure, close down */    }    if (req->method == M_POST) {        req->post_data_fd = create_temporary_file(1, NULL, 0);        if (req->post_data_fd == 0)            return(0);        return(1); /* success */    }    if (req->is_cgi) {        return init_cgi(req);    }    req->status = WRITE;    return init_get(req);       /* get and head */}/* * Name: process_option_line * * Description: Parses the contents of req->header_line and takes * appropriate action. */int process_option_line(request * req){    char c, *value, *line = req->header_line;    /* Start by aggressively hacking the in-place copy of the header line */#ifdef FASCIST_LOGGING    log_error_time();    fprintf(stderr, "%s:%d - Parsing \"%s\"\n", __FILE__, __LINE__, line);#endif    value = strchr(line, ':');    if (value == NULL)        return 0;    *value++ = '\0';            /* overwrite the : */    to_upper(line);             /* header types are case-insensitive */    while ((c = *value) && (c == ' ' || c == '\t'))        value++;    if (!memcmp(line, "IF_MODIFIED_SINCE", 18) && !req->if_modified_since)        req->if_modified_since = value;    else if (!memcmp(line, "CONTENT_TYPE", 13) && !req->content_type)        req->content_type = value;    else if (!memcmp(line, "CONTENT_LENGTH", 15) && !req->content_length)        req->content_length = value;    else if (!memcmp(line, "CONNECTION", 11) &&             ka_max && req->keepalive != KA_STOPPED) {        req->keepalive = (!strncasecmp(value, "Keep-Alive", 10) ?                          KA_ACTIVE : KA_STOPPED);    }    /* #ifdef ACCEPT_ON */    else if (!memcmp(line, "ACCEPT", 7))        add_accept_header(req, value);    /* #endif */    /* Need agent and referer for logs */    else if (!memcmp(line, "REFERER", 8)) {        req->header_referer = value;        if (!add_cgi_env(req, "REFERER", value, 1))            return 0;    } else if (!memcmp(line, "USER_AGENT", 11)) {        req->header_user_agent = value;        if (!add_cgi_env(req, "USER_AGENT", value, 1))            return 0;    } else {        if (!add_cgi_env(req, line, value, 1))            return 0;    }    return 1;}/* * Name: add_accept_header * Description: Adds a mime_type to a requests accept char buffer *   silently ignore any that don't fit - *   shouldn't happen because of relative buffer sizes */void add_accept_header(request * req, char *mime_type){#ifdef ACCEPT_ON    int l = strlen(req->accept);    int l2 = strlen(mime_type);    if ((l + l2 + 2) >= MAX_HEADER_LENGTH)        return;    if (req->accept[0] == '\0')        strcpy(req->accept, mime_type);    else {        req->accept[l] = ',';        req->accept[l + 1] = ' ';        memcpy(req->accept + l + 2, mime_type, l2 + 1);        /* the +1 is for the '\0' */        /*           sprintf(req->accept + l, ", %s", mime_type);         */    }#endif}void free_requests(void){    request *ptr, *next;    ptr = request_free;    while (ptr != NULL) {        next = ptr->next;        free(ptr);        ptr = next;    }    request_free = NULL;}

⌨️ 快捷键说明

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