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

📄 http_protocol.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 5 页
字号:
            ctx->state = BODY_LENGTH;            errno = 0;            ctx->remaining = strtol(lenp, &endstr, 10);	/* we depend on ANSI */            /* This protects us from over/underflow (the errno check),             * non-digit chars in the string (excluding leading space)             * (the endstr checks) and a negative number. Depending             * on the strtol implementation, the errno check may also             * trigger on an all whitespace string */            if (errno || (endstr && *endstr) || (ctx->remaining < 0)) {                 conversion_error = 1;             }            if (conversion_error) {                apr_bucket_brigade *bb;                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,                              "Invalid Content-Length");                bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);                e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,                                           f->r->pool, f->c->bucket_alloc);                APR_BRIGADE_INSERT_TAIL(bb, e);                e = apr_bucket_eos_create(f->c->bucket_alloc);                APR_BRIGADE_INSERT_TAIL(bb, e);                ctx->eos_sent = 1;                return ap_pass_brigade(f->r->output_filters, bb);            }                        /* If we have a limit in effect and we know the C-L ahead of             * time, stop it here if it is invalid.              */             if (ctx->limit && ctx->limit < ctx->remaining) {                apr_bucket_brigade *bb;                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,                          "Requested content-length of %" APR_OFF_T_FMT                           " is larger than the configured limit"                          " of %" APR_OFF_T_FMT, ctx->remaining, ctx->limit);                bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);                e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,                                           f->r->pool, f->c->bucket_alloc);                APR_BRIGADE_INSERT_TAIL(bb, e);                e = apr_bucket_eos_create(f->c->bucket_alloc);                APR_BRIGADE_INSERT_TAIL(bb, e);                ctx->eos_sent = 1;                return ap_pass_brigade(f->r->output_filters, bb);            }        }        /* If we don't have a request entity indicated by the headers, EOS.         * (BODY_NONE is a valid intermediate state due to trailers,         *  but it isn't a valid starting state.)         *         * RFC 2616 Section 4.4 note 5 states that connection-close         * is invalid for a request entity - request bodies must be         * denoted by C-L or T-E: chunked.         *         * Note that since the proxy uses this filter to handle the         * proxied *response*, proxy responses MUST be exempt.         */        if (ctx->state == BODY_NONE && f->r->proxyreq != PROXYREQ_RESPONSE) {            e = apr_bucket_eos_create(f->c->bucket_alloc);            APR_BRIGADE_INSERT_TAIL(b, e);            ctx->eos_sent = 1;            return APR_SUCCESS;        }        /* Since we're about to read data, send 100-Continue if needed.         * Only valid on chunked and C-L bodies where the C-L is > 0. */        if ((ctx->state == BODY_CHUNK ||             (ctx->state == BODY_LENGTH && ctx->remaining > 0)) &&            f->r->expecting_100 && f->r->proto_num >= HTTP_VERSION(1,1)) {            char *tmp;            apr_bucket_brigade *bb;            tmp = apr_pstrcat(f->r->pool, AP_SERVER_PROTOCOL, " ",                              status_lines[0], CRLF CRLF, NULL);            bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);            e = apr_bucket_pool_create(tmp, strlen(tmp), f->r->pool,                                       f->c->bucket_alloc);            APR_BRIGADE_INSERT_HEAD(bb, e);            e = apr_bucket_flush_create(f->c->bucket_alloc);            APR_BRIGADE_INSERT_TAIL(bb, e);            ap_pass_brigade(f->c->output_filters, bb);        }        /* We can't read the chunk until after sending 100 if required. */        if (ctx->state == BODY_CHUNK) {            char line[30];            apr_bucket_brigade *bb;            apr_size_t len = 30;            bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);            rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,                                APR_BLOCK_READ, 0);            if (rv == APR_SUCCESS) {                rv = apr_brigade_flatten(bb, line, &len);                if (rv == APR_SUCCESS) {                    ctx->remaining = get_chunk_size(line);                }            }            apr_brigade_cleanup(bb);            /* Detect chunksize error (such as overflow) */            if (rv != APR_SUCCESS || ctx->remaining < 0) {                ctx->remaining = 0; /* Reset it in case we have to                                     * come back here later */                e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,                                           f->r->pool,                                           f->c->bucket_alloc);                APR_BRIGADE_INSERT_TAIL(bb, e);                e = apr_bucket_eos_create(f->c->bucket_alloc);                APR_BRIGADE_INSERT_TAIL(bb, e);                ctx->eos_sent = 1;                return ap_pass_brigade(f->r->output_filters, bb);            }            if (!ctx->remaining) {                /* Handle trailers by calling ap_get_mime_headers again! */                ctx->state = BODY_NONE;                ap_get_mime_headers(f->r);                e = apr_bucket_eos_create(f->c->bucket_alloc);                APR_BRIGADE_INSERT_TAIL(b, e);                ctx->eos_sent = 1;                return APR_SUCCESS;            }        }     }    if (ctx->eos_sent) {        e = apr_bucket_eos_create(f->c->bucket_alloc);        APR_BRIGADE_INSERT_TAIL(b, e);        return APR_SUCCESS;    }            if (!ctx->remaining) {        switch (ctx->state) {        case BODY_NONE:            break;        case BODY_LENGTH:            e = apr_bucket_eos_create(f->c->bucket_alloc);            APR_BRIGADE_INSERT_TAIL(b, e);            ctx->eos_sent = 1;            return APR_SUCCESS;        case BODY_CHUNK:            {                char line[30];                apr_bucket_brigade *bb;                apr_size_t len = 30;                bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);                /* We need to read the CRLF after the chunk.  */                rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,                                    APR_BLOCK_READ, 0);                apr_brigade_cleanup(bb);                if (rv == APR_SUCCESS) {                    /* Read the real chunk line. */                    rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,                                        APR_BLOCK_READ, 0);                    if (rv == APR_SUCCESS) {                        rv = apr_brigade_flatten(bb, line, &len);                        if (rv == APR_SUCCESS) {                            ctx->remaining = get_chunk_size(line);                        }                    }                    apr_brigade_cleanup(bb);                }                /* Detect chunksize error (such as overflow) */                if (rv != APR_SUCCESS || ctx->remaining < 0) {                    ctx->remaining = 0; /* Reset it in case we have to                                         * come back here later */                    e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE,                                               NULL, f->r->pool,                                               f->c->bucket_alloc);                    APR_BRIGADE_INSERT_TAIL(bb, e);                    e = apr_bucket_eos_create(f->c->bucket_alloc);                    APR_BRIGADE_INSERT_TAIL(bb, e);                    ctx->eos_sent = 1;                    return ap_pass_brigade(f->r->output_filters, bb);                }                if (!ctx->remaining) {                    /* Handle trailers by calling ap_get_mime_headers again! */                    ctx->state = BODY_NONE;                    ap_get_mime_headers(f->r);                    e = apr_bucket_eos_create(f->c->bucket_alloc);                    APR_BRIGADE_INSERT_TAIL(b, e);                    ctx->eos_sent = 1;                    return APR_SUCCESS;                }            }            break;        }    }    /* Ensure that the caller can not go over our boundary point. */    if (ctx->state == BODY_LENGTH || ctx->state == BODY_CHUNK) {        if (ctx->remaining < readbytes) {            readbytes = ctx->remaining;        }        AP_DEBUG_ASSERT(readbytes > 0);    }    rv = ap_get_brigade(f->next, b, mode, block, readbytes);    if (rv != APR_SUCCESS) {        return rv;    }    /* How many bytes did we just read? */    apr_brigade_length(b, 0, &totalread);    /* If this happens, we have a bucket of unknown length.  Die because     * it means our assumptions have changed. */    AP_DEBUG_ASSERT(totalread >= 0);    if (ctx->state != BODY_NONE) {        ctx->remaining -= totalread;    }    /* If we have no more bytes remaining on a C-L request,      * save the callter a roundtrip to discover EOS.     */    if (ctx->state == BODY_LENGTH && ctx->remaining == 0) {        e = apr_bucket_eos_create(f->c->bucket_alloc);        APR_BRIGADE_INSERT_TAIL(b, e);    }    /* We have a limit in effect. */    if (ctx->limit) {        /* FIXME: Note that we might get slightly confused on chunked inputs         * as we'd need to compensate for the chunk lengths which may not         * really count.  This seems to be up for interpretation.  */        ctx->limit_used += totalread;        if (ctx->limit < ctx->limit_used) {            apr_bucket_brigade *bb;            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,                          "Read content-length of %" APR_OFF_T_FMT                           " is larger than the configured limit"                          " of %" APR_OFF_T_FMT, ctx->limit_used, ctx->limit);            bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);            e = ap_bucket_error_create(HTTP_REQUEST_ENTITY_TOO_LARGE, NULL,                                       f->r->pool,                                       f->c->bucket_alloc);            APR_BRIGADE_INSERT_TAIL(bb, e);            e = apr_bucket_eos_create(f->c->bucket_alloc);            APR_BRIGADE_INSERT_TAIL(bb, e);            ctx->eos_sent = 1;            return ap_pass_brigade(f->r->output_filters, bb);        }    }    return APR_SUCCESS;}/* The index is found by its offset from the x00 code of each level. * Although this is fast, it will need to be replaced if some nutcase * decides to define a high-numbered code before the lower numbers. * If that sad event occurs, replace the code below with a linear search * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1]; */AP_DECLARE(int) ap_index_of_response(int status){    static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,    LEVEL_500, RESPONSE_CODES};    int i, pos;    if (status < 100) {               /* Below 100 is illegal for HTTP status */        return LEVEL_500;    }    for (i = 0; i < 5; i++) {        status -= 100;        if (status < 100) {            pos = (status + shortcut[i]);            if (pos < shortcut[i + 1]) {                return pos;            }            else {                return LEVEL_500;            /* status unknown (falls in gap) */            }        }    }    return LEVEL_500;                         /* 600 or above is also illegal */}AP_DECLARE(const char *) ap_get_status_line(int status){    return status_lines[ap_index_of_response(status)];}typedef struct header_struct {    apr_pool_t *pool;    apr_bucket_brigade *bb;} header_struct;/* Send a single HTTP header field to the client.  Note that this function * is used in calls to table_do(), so their interfaces are co-dependent. * In other words, don't change this one without checking table_do in alloc.c. * It returns true unless there was a write error of some kind. */static int form_header_field(header_struct *h,                             const char *fieldname, const char *fieldval){#if APR_CHARSET_EBCDIC    char *headfield;    apr_size_t len;    apr_size_t name_len;    apr_size_t val_len;    char *next;    name_len = strlen(fieldname);    val_len = strlen(fieldval);    len = name_len + val_len + 4; /* 4 for ": " plus CRLF */    headfield = (char *)apr_palloc(h->pool, len + 1);    memcpy(headfield, fieldname, name_len);    next = headfield + name_len;    *next++ = ':';    *next++ = ' ';    memcpy(next, fieldval, val_len);    next += val_len;    *next++ = CR;    *next++ = LF;    *next = 0;    ap_xlate_proto_to_ascii(headfield, len);    apr_brigade_write(h->bb, NULL, NULL, headfield, len);#else    struct iovec vec[4];    struct iovec *v = vec;    v->iov_base = (void *)fieldname;    v->iov_len = strlen(fieldname);    v++;    v->iov_base = ": ";    v->iov_len = sizeof(": ") - 1;    v++;    v->iov_base = (void *)fieldval;    v->iov_len = strlen(fieldval);    v++;    v->iov_base = CRLF;    v->iov_len = sizeof(CRLF) - 1;    apr_brigade_writev(h->bb, NULL, NULL, vec, 4);#endif /* !APR_CHARSET_EBCDIC */    return 1;}/* Send a request's HTTP response headers to the client. */static apr_status_t send_all_header_fields(header_struct *h,                                           const request_rec *r){    const apr_array_header_t *elts;    const apr_table_entry_t *t_elt;    const apr_table_entry_t *t_end;    struct iovec *vec;    struct iovec *vec_next;    elts = apr_table_elts(r->headers_out);    if (elts->nelts == 0) {        return APR_SUCCESS;    }    t_elt = (const apr_table_entry_t *)(elts->elts);    t_end = t_elt + elts->nelts;    vec = (struct iovec *)apr_palloc(h->pool, 4 * elts->nelts *                                     sizeof(struct iovec));    vec_next = vec;    /* For each field, generate     *    name ": " value CRLF     */    do {        vec_next->iov_base = (void*)(t_elt->key);        vec_next->iov_len = strlen(t_elt->key);        vec_next++;        vec_next->iov_base = ": ";        vec_next->iov_len = sizeof(": ") - 1;        vec_next++;        vec_next->iov_base = (void*)(t_elt->val);        vec_next->iov_len = strlen(t_elt->val);        vec_next++;

⌨️ 快捷键说明

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