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

📄 protocol.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 4 页
字号:
    apr_read_type_e eblock = APR_NONBLOCK_READ;    ctx = f->ctx;    if (!ctx) {        f->ctx = ctx = apr_palloc(r->pool, sizeof(*ctx));        ctx->data_sent = 0;    }    /* Loop through this set of buckets to compute their length     */    e = APR_BRIGADE_FIRST(b);    while (e != APR_BRIGADE_SENTINEL(b)) {        if (APR_BUCKET_IS_EOS(e)) {            eos = 1;            break;        }        if (e->length == (apr_size_t)-1) {            apr_size_t len;            const char *ignored;            apr_status_t rv;            /* This is probably a pipe bucket.  Send everything             * prior to this, and then read the data for this bucket.             */            rv = apr_bucket_read(e, &ignored, &len, eblock);            if (rv == APR_SUCCESS) {                /* Attempt a nonblocking read next time through */                eblock = APR_NONBLOCK_READ;                r->bytes_sent += len;            }            else if (APR_STATUS_IS_EAGAIN(rv)) {                /* Output everything prior to this bucket, and then                 * do a blocking read on the next batch.                 */                if (e != APR_BRIGADE_FIRST(b)) {                    apr_bucket_brigade *split = apr_brigade_split(b, e);                    apr_bucket *flush = apr_bucket_flush_create(r->connection->bucket_alloc);                    APR_BRIGADE_INSERT_TAIL(b, flush);                    rv = ap_pass_brigade(f->next, b);                    if (rv != APR_SUCCESS || f->c->aborted) {                        apr_brigade_destroy(split);                        return rv;                    }                    b = split;                    e = APR_BRIGADE_FIRST(b);                    ctx->data_sent = 1;                }                eblock = APR_BLOCK_READ;                continue;            }            else {                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                              "ap_content_length_filter: "                              "apr_bucket_read() failed");                return rv;            }        }        else {            r->bytes_sent += e->length;        }        e = APR_BUCKET_NEXT(e);    }    /* If we've now seen the entire response and it's otherwise     * okay to set the C-L in the response header, then do so now.     *     * We can only set a C-L in the response header if we haven't already     * sent any buckets on to the next output filter for this request.     */    if (ctx->data_sent == 0 && eos) {        ap_set_content_length(r, r->bytes_sent);    }    ctx->data_sent = 1;    return ap_pass_brigade(f->next, b);}/* * Send the body of a response to the client. */AP_DECLARE(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r,                                    apr_off_t offset, apr_size_t len,                                    apr_size_t *nbytes){    conn_rec *c = r->connection;    apr_bucket_brigade *bb = NULL;    apr_bucket *b;    apr_status_t rv;    bb = apr_brigade_create(r->pool, c->bucket_alloc);    b = apr_bucket_file_create(fd, offset, len, r->pool, c->bucket_alloc);    APR_BRIGADE_INSERT_TAIL(bb, b);    rv = ap_pass_brigade(r->output_filters, bb);    if (rv != APR_SUCCESS) {        *nbytes = 0; /* no way to tell how many were actually sent */    }    else {        *nbytes = len;    }    return rv;}#if APR_HAS_MMAP/* send data from an in-memory buffer */AP_DECLARE(size_t) ap_send_mmap(apr_mmap_t *mm, request_rec *r, size_t offset,                                size_t length){    conn_rec *c = r->connection;    apr_bucket_brigade *bb = NULL;    apr_bucket *b;    bb = apr_brigade_create(r->pool, c->bucket_alloc);    b = apr_bucket_mmap_create(mm, offset, length, c->bucket_alloc);    APR_BRIGADE_INSERT_TAIL(bb, b);    ap_pass_brigade(r->output_filters, bb);    return mm->size; /* XXX - change API to report apr_status_t? */}#endif /* APR_HAS_MMAP */typedef struct {    apr_bucket_brigade *bb;} old_write_filter_ctx;AP_CORE_DECLARE_NONSTD(apr_status_t) ap_old_write_filter(    ap_filter_t *f, apr_bucket_brigade *bb){    old_write_filter_ctx *ctx = f->ctx;    AP_DEBUG_ASSERT(ctx);    if (ctx->bb != 0) {        /* whatever is coming down the pipe (we don't care), we         * can simply insert our buffered data at the front and         * pass the whole bundle down the chain.         */        APR_BRIGADE_CONCAT(ctx->bb, bb);        bb = ctx->bb;        ctx->bb = NULL;    }    return ap_pass_brigade(f->next, bb);}static apr_status_t buffer_output(request_rec *r,                                  const char *str, apr_size_t len){    conn_rec *c = r->connection;    ap_filter_t *f;    old_write_filter_ctx *ctx;    if (len == 0)        return APR_SUCCESS;    /* future optimization: record some flags in the request_rec to     * say whether we've added our filter, and whether it is first.     */    /* this will typically exit on the first test */    for (f = r->output_filters; f != NULL; f = f->next) {        if (ap_old_write_func == f->frec)            break;    }    if (f == NULL) {        /* our filter hasn't been added yet */        ctx = apr_pcalloc(r->pool, sizeof(*ctx));        ap_add_output_filter("OLD_WRITE", ctx, r, r->connection);        f = r->output_filters;    }    /* if the first filter is not our buffering filter, then we have to     * deliver the content through the normal filter chain     */    if (f != r->output_filters) {        apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);        apr_bucket *b = apr_bucket_transient_create(str, len, c->bucket_alloc);        APR_BRIGADE_INSERT_TAIL(bb, b);        return ap_pass_brigade(r->output_filters, bb);    }    /* grab the context from our filter */    ctx = r->output_filters->ctx;    if (ctx->bb == NULL) {        ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);    }    return ap_fwrite(f->next, ctx->bb, str, len);}AP_DECLARE(int) ap_rputc(int c, request_rec *r){    char c2 = (char)c;    if (r->connection->aborted) {        return -1;    }    if (buffer_output(r, &c2, 1) != APR_SUCCESS)        return -1;    return c;}AP_DECLARE(int) ap_rputs(const char *str, request_rec *r){    apr_size_t len;    if (r->connection->aborted)        return -1;    if (buffer_output(r, str, len = strlen(str)) != APR_SUCCESS)        return -1;    return len;}AP_DECLARE(int) ap_rwrite(const void *buf, int nbyte, request_rec *r){    if (r->connection->aborted)        return -1;    if (buffer_output(r, buf, nbyte) != APR_SUCCESS)        return -1;    return nbyte;}struct ap_vrprintf_data {    apr_vformatter_buff_t vbuff;    request_rec *r;    char *buff;};static apr_status_t r_flush(apr_vformatter_buff_t *buff){    /* callback function passed to ap_vformatter to be called when     * vformatter needs to write into buff and buff.curpos > buff.endpos */    /* ap_vrprintf_data passed as a apr_vformatter_buff_t, which is then     * "downcast" to an ap_vrprintf_data */    struct ap_vrprintf_data *vd = (struct ap_vrprintf_data*)buff;    if (vd->r->connection->aborted)        return -1;    /* r_flush is called when vbuff is completely full */    if (buffer_output(vd->r, vd->buff, AP_IOBUFSIZE)) {        return -1;    }    /* reset the buffer position */    vd->vbuff.curpos = vd->buff;    vd->vbuff.endpos = vd->buff + AP_IOBUFSIZE;    return APR_SUCCESS;}AP_DECLARE(int) ap_vrprintf(request_rec *r, const char *fmt, va_list va){    apr_size_t written;    struct ap_vrprintf_data vd;    char vrprintf_buf[AP_IOBUFSIZE];    vd.vbuff.curpos = vrprintf_buf;    vd.vbuff.endpos = vrprintf_buf + AP_IOBUFSIZE;    vd.r = r;    vd.buff = vrprintf_buf;    if (r->connection->aborted)        return -1;    written = apr_vformatter(r_flush, &vd.vbuff, fmt, va);    /* tack on null terminator on remaining string */    *(vd.vbuff.curpos) = '\0';    if (written != -1) {        int n = vd.vbuff.curpos - vrprintf_buf;        /* last call to buffer_output, to finish clearing the buffer */        if (buffer_output(r, vrprintf_buf,n) != APR_SUCCESS)            return -1;        written += n;    }    return written;}AP_DECLARE_NONSTD(int) ap_rprintf(request_rec *r, const char *fmt, ...){    va_list va;    int n;    if (r->connection->aborted)        return -1;    va_start(va, fmt);    n = ap_vrprintf(r, fmt, va);    va_end(va);    return n;}AP_DECLARE_NONSTD(int) ap_rvputs(request_rec *r, ...){    va_list va;    const char *s;    apr_size_t len;    apr_size_t written = 0;    if (r->connection->aborted)        return -1;    /* ### TODO: if the total output is large, put all the strings     * ### into a single brigade, rather than flushing each time we     * ### fill the buffer     */    va_start(va, r);    while (1) {        s = va_arg(va, const char *);        if (s == NULL)            break;        len = strlen(s);        if (buffer_output(r, s, len) != APR_SUCCESS) {            return -1;        }        written += len;    }    va_end(va);    return written;}AP_DECLARE(int) ap_rflush(request_rec *r){    conn_rec *c = r->connection;    apr_bucket_brigade *bb;    apr_bucket *b;    bb = apr_brigade_create(r->pool, c->bucket_alloc);    b = apr_bucket_flush_create(c->bucket_alloc);    APR_BRIGADE_INSERT_TAIL(bb, b);    if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS)        return -1;    return 0;}/* * This function sets the Last-Modified output header field to the value * of the mtime field in the request structure - rationalized to keep it from * being in the future. */AP_DECLARE(void) ap_set_last_modified(request_rec *r){    if (!r->assbackwards) {        apr_time_t mod_time = ap_rationalize_mtime(r, r->mtime);        char *datestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);        apr_rfc822_date(datestr, mod_time);        apr_table_setn(r->headers_out, "Last-Modified", datestr);    }}AP_IMPLEMENT_HOOK_RUN_ALL(int,post_read_request,                          (request_rec *r), (r), OK, DECLINED)AP_IMPLEMENT_HOOK_RUN_ALL(int,log_transaction,                          (request_rec *r), (r), OK, DECLINED)AP_IMPLEMENT_HOOK_RUN_FIRST(const char *,http_method,                            (const request_rec *r), (r), NULL)AP_IMPLEMENT_HOOK_RUN_FIRST(unsigned short,default_port,                            (const request_rec *r), (r), 0)

⌨️ 快捷键说明

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