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

📄 proxy_util.c

📁 apache 安装教程 apache 安装教程
💻 C
📖 第 1 页 / 共 4 页
字号:
    long total_bytes_rcvd;    register int n = 0, o, w;    conn_rec *con = r->connection;    int alternate_timeouts = 1; /* 1 if we alternate between soft & hard                                 * timeouts */    /* allocate a buffer to store the bytes in */    /*     * make sure it is at least IOBUFSIZE, as recv_buffer_size may be zero     * for system default     */    buf_size = MAX(recv_buffer_size, IOBUFSIZE);    buf = ap_palloc(r->pool, buf_size);    total_bytes_rcvd = 0;    if (c != NULL)        c->written = 0;#ifdef CHARSET_EBCDIC    /* The cache copy is ASCII, not EBCDIC, even for text/html) */    ap_bsetflag(f, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0);    ap_bsetflag(con->client, B_ASCII2EBCDIC | B_EBCDIC2ASCII, 0);#endif    /*     * Since we are reading from one buffer and writing to another, it is     * unsafe to do a soft_timeout here, at least until the proxy has its own     * timeout handler which can set both buffers to EOUT.     */    ap_kill_timeout(r);#if defined(WIN32) || defined(TPF) || defined(NETWARE)    /* works fine under win32, so leave it */    ap_hard_timeout("proxy send body", r);    alternate_timeouts = 0;#else    /*     * CHECKME! Since hard_timeout won't work in unix on sends with partial     * cache completion, we have to alternate between hard_timeout for reads,     * and soft_timeout for send.  This is because we need to get a return     * from ap_bwrite to be able to continue caching. BUT, if we *can't*     * continue anyway, just use hard_timeout. (Also, if no cache file is     * written, use hard timeouts)     */    if (c == NULL || c->len <= 0 || c->cache_completion == 1.0) {        ap_hard_timeout("proxy send body", r);        alternate_timeouts = 0;    }#endif    /*     * Loop and ap_bread() while we can successfully read and write, or     * (after the client aborted) while we can successfully read and finish     * the configured cache_completion.     */    for (end_of_chunk = ok = 1; ok;) {        if (alternate_timeouts)            ap_hard_timeout("proxy recv body from upstream server", r);        /* read a chunked block */        if (chunked) {            long chunk_start = 0;            n = 0;            /* start of a new chunk */            if (end_of_chunk) {                end_of_chunk = 0;                /* get the chunk size from the stream */                chunk_start = ap_getline(buf, buf_size, f, 0);                if ((chunk_start <= 0) || ((size_t)chunk_start + 1 >= buf_size) || !ap_isxdigit(*buf)) {                    n = -1;                }                /* parse the chunk size */                else {                    remaining = ap_get_chunk_size(buf);                    if (remaining == 0) { /* Last chunk indicated, get footers */                        /* as we are a proxy, we discard the footers, as the headers                         * have already been sent at this point.                         */                        if (NULL == ap_proxy_read_headers(r, buf, buf_size, f)) {                            n = -1;                        }                    }                    else if (remaining < 0) {                        n = -1;                        ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,                                      "proxy: remote protocol error, invalid chunk size");                    }                }            }            /* read the chunk */            if (remaining > 0) {                n = ap_bread(f, buf, MIN((int)buf_size, (int)remaining));                if (n > -1) {                    remaining -= n;                    end_of_chunk = (remaining == 0);                }            }            /* soak up trailing CRLF */            if (end_of_chunk) {                int ch; /* int because it may hold an EOF */                /*                 * For EBCDIC, the proxy has configured the BUFF layer to                 * transparently pass the ascii characters thru (also writing                 * an ASCII copy to the cache, where appropriate).                 * Therefore, we see here an ASCII-CRLF (\015\012),                 * not an EBCDIC-CRLF (\r\n).                 */                if ((ch = ap_bgetc(f)) == EOF) {                    /* Protocol error: EOF detected within chunk */                    n = -1;                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,                                  "proxy: remote protocol error, eof while reading chunked from proxy");                }                else                {                    if (ch == '\015') { /* _ASCII_ CR */                        ch = ap_bgetc(f);                    }                    if (ch != '\012') {                        n = -1;                    }                }            }        }        /* otherwise read block normally */        else {            if (-1 == len) {                n = ap_bread(f, buf, buf_size);            }            else {                n = ap_bread(f, buf, MIN((int)buf_size,                                         (int)(len - total_bytes_rcvd)));            }        }        if (alternate_timeouts)            ap_kill_timeout(r);        else            ap_reset_timeout(r);        if (n == -1) {          /* input error */            if (c != NULL) {                ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,                              "proxy: error reading from %s", c->url);                c = ap_proxy_cache_error(c);            }            break;        }        if (n == 0)            break;              /* EOF */        o = 0;        total_bytes_rcvd += n;        /* if we've received everything... */        /*         * in the case of slow frontends and expensive backends, we want to         * avoid leaving a backend connection hanging while the frontend         * takes it's time to absorb the bytes. so: if we just read the last         * block, we close the backend connection now instead of later - it's         * no longer needed.         */        if (total_bytes_rcvd == len) {            ap_bclose(f);            f = NULL;        }        /* Write to cache first. */        /*         * @@@ XXX FIXME: Assuming that writing the cache file won't time         * out?!!?         */        if (c != NULL && c->fp != NULL) {            if (ap_bwrite(c->fp, &buf[0], n) != n) {                ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,                              "proxy: error writing to %s", c->tempfile);                c = ap_proxy_cache_error(c);            }            else {                c->written += n;            }        }        /* Write the block to the client, detect aborted transfers */        while (!nowrite && !con->aborted && n > 0) {            if (alternate_timeouts)                ap_soft_timeout("proxy send body", r);            w = ap_bwrite(con->client, &buf[o], n);            if (alternate_timeouts)                ap_kill_timeout(r);            else                ap_reset_timeout(r);            if (w <= 0) {                if (c != NULL) {                    /*                     * when a send failure occurs, we need to decide whether                     * to continue loading and caching the document, or to                     * abort the whole thing                     */                    ok = (c->len > 0) &&                        (c->cache_completion > 0) &&                        (c->len * c->cache_completion < total_bytes_rcvd);                    if (!ok) {                        if (c->fp != NULL) {                            ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR));                            c->fp = NULL;                        }                        unlink(c->tempfile);                        c = NULL;                    }                }                con->aborted = 1;                break;            }            n -= w;            o += w;        }                       /* while client alive and more data to send */        /* if we've received everything, leave now */        if (total_bytes_rcvd == len)            break;    }                           /* loop and ap_bread while "ok" */    /* if the backend connection is still open, close it */    if (f) {        ap_bclose(f);    }    if (!con->aborted) {        ap_bflush(con->client);    }    ap_kill_timeout(r);    r->bytes_sent += total_bytes_rcvd;    return total_bytes_rcvd;}/* * Writes response line and headers to the cache file. * * If respline is NULL, no response line will be written. */void ap_proxy_write_headers(cache_req *c, const char *respline, table *t){    /* write status line */    if (respline && c->fp != NULL &&        ap_bvputs(c->fp, respline, CRLF, NULL) == -1) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,                      "proxy: error writing status line to %s", c->tempfile);        c = ap_proxy_cache_error(c);        return;    }    /* write response headers to the cache file */    ap_table_do(ap_proxy_send_hdr_line, c, t, NULL);    /* write terminating CRLF */    if (c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,                      "proxy: error writing CRLF to %s", c->tempfile);        c = ap_proxy_cache_error(c);    }}/* * list is a comma-separated list of case-insensitive tokens, with * optional whitespace around the tokens. * The return returns 1 if the token val is found in the list, or 0 * otherwise. */int ap_proxy_liststr(const char *list, const char *key, char **val){    int len, i;    const char *p;    char valbuf[HUGE_STRING_LEN];    valbuf[sizeof(valbuf) - 1] = 0;     /* safety terminating zero */    len = strlen(key);    while (list != NULL) {        p = strchr(list, ',');        if (p != NULL) {            i = p - list;            do                p++;            while (ap_isspace(*p));        }        else            i = strlen(list);        while (i > 0 && ap_isspace(list[i - 1]))            i--;        if (i == len && strncasecmp(list, key, len) == 0) {            if (val) {                p = strchr(list, ',');                while (ap_isspace(*list)) {                    list++;                }                if ('=' == list[0])                    list++;                while (ap_isspace(*list)) {                    list++;                }                strncpy(valbuf, list, MIN(p - list, sizeof(valbuf) - 1));                *val = valbuf;            }            return 1;        }        list = p;    }    return 0;}#ifdef CASE_BLIND_FILESYSTEM/* * On some platforms, the file system is NOT case sensitive. So, a == A * need to map to smaller set of characters */void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength){    AP_MD5_CTX context;    unsigned char digest[16];    char tmp[26];    int i, k, d;    unsigned int x;    static const char enc_table[32] = "abcdefghijklmnopqrstuvwxyz012345";    ap_MD5Init(&context);    ap_MD5Update(&context, (const unsigned char *)it, strlen(it));    ap_MD5Final(digest, &context);/* encode 128 bits as 26 characters, using a modified uuencoding *//* the encoding is 5 bytes -> 8 characters * i.e. 128 bits is 3 x 5 bytes + 1 byte -> 3 * 8 characters + 2 characters */    for (i = 0, k = 0; i < 15; i += 5) {        x = (digest[i] << 24) | (digest[i + 1] << 16) | (digest[i + 2] << 8) | digest[i + 3];        tmp[k++] = enc_table[x >> 27];        tmp[k++] = enc_table[(x >> 22) & 0x1f];        tmp[k++] = enc_table[(x >> 17) & 0x1f];        tmp[k++] = enc_table[(x >> 12) & 0x1f];        tmp[k++] = enc_table[(x >> 7) & 0x1f];        tmp[k++] = enc_table[(x >> 2) & 0x1f];        x = ((x & 0x3) << 8) | digest[i + 4];        tmp[k++] = enc_table[x >> 5];        tmp[k++] = enc_table[x & 0x1f];    }/* one byte left */    x = digest[15];    tmp[k++] = enc_table[x >> 3];       /* use up 5 bits */    tmp[k++] = enc_table[x & 0x7];    /* now split into directory levels */    for (i = k = d = 0; d < ndepth; ++d) {        memcpy(&val[i], &tmp[k], nlength);        k += nlength;        val[i + nlength] = '/';        i += nlength + 1;    }    memcpy(&val[i], &tmp[k], 26 - k);    val[i + 26 - k] = '\0';}#elsevoid ap_proxy_hash(const char *it, char *val, int ndepth, int nlength){    AP_MD5_CTX context;    unsigned char digest[16];    char tmp[22];    int i, k, d;    unsigned int x;#if defined(MPE) || (defined(AIX) && defined(__ps2__))    /*     * Believe it or not, AIX 1.x does not allow you to name a file '@', so     * hack around it in the encoding.     */    static const char enc_table[64] =    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_%";#else    static const char enc_table[64] =    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";#endif    ap_MD5Init(&context);    ap_MD5Update(&context, (const unsigned char *)it, strlen(it));    ap_MD5Final(digest, &context);/* encode 128 bits as 22 characters, using a modified uuencoding *//* the encoding is 3 bytes -> 4 characters * i.e. 128 bits is 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters */    for (i = 0, k = 0; i < 15; i += 3) {

⌨️ 快捷键说明

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