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

📄 http.c

📁 -
💻 C
📖 第 1 页 / 共 3 页
字号:
	httpReplyParse(reply, httpState->reply_hdr);	/* httpState->eof); */	storeTimestampsSet(entry);	/* Check if object is cacheable or not based on reply code */	debug(11, 3) ("httpProcessReplyHeader: HTTP CODE: %d\n", reply->sline.status);	if (neighbors_do_private_keys)	    httpMaybeRemovePublic(entry, reply->sline.status);	switch (httpCachableReply(httpState)) {	case 1:	    httpMakePublic(entry);	    break;	case 0:	    httpMakePrivate(entry);	    break;	case -1:	    httpCacheNegatively(entry);	    break;	default:	    assert(0);	    break;	}	if (reply->cache_control) {	    if (EBIT_TEST(reply->cache_control->mask, CC_PROXY_REVALIDATE))		EBIT_SET(entry->flags, ENTRY_REVALIDATE);	    else if (EBIT_TEST(reply->cache_control->mask, CC_MUST_REVALIDATE))		EBIT_SET(entry->flags, ENTRY_REVALIDATE);	}	if (httpState->flags.keepalive)	    if (httpState->peer)		httpState->peer->stats.n_keepalives_sent++;	if (reply->keep_alive)	    if (httpState->peer)		httpState->peer->stats.n_keepalives_recv++;	ctx_exit(ctx);	if (reply->date > -1 && !httpState->peer) {	    int skew = abs(reply->date - squid_curtime);	    if (skew > 86400)		debug(11, 3) ("%s's clock is skewed by %d seconds!\n",		    httpState->request->host, skew);	}    }}static inthttpPconnTransferDone(HttpStateData * httpState){    /* return 1 if we got the last of the data on a persistent connection */    MemObject *mem = httpState->entry->mem_obj;    HttpReply *reply = mem->reply;    debug(11, 3) ("httpPconnTransferDone: FD %d\n", httpState->fd);    /*     * If we didn't send a keep-alive request header, then this     * can not be a persistent connection.     */    if (!httpState->flags.keepalive)	return 0;    /*     * What does the reply have to say about keep-alive?     */    /*     * XXX BUG?     * If the origin server (HTTP/1.0) does not send a keep-alive     * header, but keeps the connection open anyway, what happens?     * We'll return here and http.c waits for an EOF before changing     * store_status to STORE_OK.   Combine this with ENTRY_FWD_HDR_WAIT     * and an error status code, and we might have to wait until     * the server times out the socket.     */    if (!reply->keep_alive)	return 0;    debug(11, 5) ("httpPconnTransferDone: content_length=%d\n",	reply->content_length);    /*     * Deal with gross HTTP stuff     *    - If we haven't seen the end of the reply headers, we can't     *      be persistent.     *    - For HEAD requests we're done.     *    - For "200 OK" check the content-length in the next block.     *    - For "204 No Content" (even with content-length) we're done.     *    - For "304 Not Modified" (even with content-length) we're done.     *    - 1XX replies never have a body; we're done.     *    - For all other replies, check content length in next block.     */    if (httpState->reply_hdr_state < 2)	return 0;    else if (httpState->request->method == METHOD_HEAD)	return 1;    else if (reply->sline.status == HTTP_OK)	(void) 0;		/* common case, continue */    else if (reply->sline.status == HTTP_NO_CONTENT)	return 1;    else if (reply->sline.status == HTTP_NOT_MODIFIED)	return 1;    else if (reply->sline.status < HTTP_OK)	return 1;    /*     * If there is no content-length, then we can't be     * persistent.  If there is a content length, then we must     * wait until we've seen the end of the body.     */    if (reply->content_length < 0)	return 0;    else if (mem->inmem_hi < reply->content_length + reply->hdr_sz)	return 0;    else	return 1;}/* This will be called when data is ready to be read from fd.  Read until * error or connection closed. *//* XXX this function is too long! */static voidhttpReadReply(int fd, void *data){    HttpStateData *httpState = data;    LOCAL_ARRAY(char, buf, SQUID_TCP_SO_RCVBUF);    StoreEntry *entry = httpState->entry;    const request_t *request = httpState->request;    int len;    int bin;    int clen;    size_t read_sz;#if DELAY_POOLS    delay_id delay_id;    /* special "if" only for http (for nodelay proxy conns) */    if (delayIsNoDelay(fd))	delay_id = 0;    else	delay_id = delayMostBytesAllowed(entry->mem_obj);#endif    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {	comm_close(fd);	return;    }    /* check if we want to defer reading */    errno = 0;    read_sz = SQUID_TCP_SO_RCVBUF;#if DELAY_POOLS    read_sz = delayBytesWanted(delay_id, 1, read_sz);#endif    Counter.syscalls.sock.reads++;    len = read(fd, buf, read_sz);    debug(11, 5) ("httpReadReply: FD %d: len %d.\n", fd, len);    if (len > 0) {	fd_bytes(fd, len, FD_READ);#if DELAY_POOLS	delayBytesIn(delay_id, len);#endif	kb_incr(&Counter.server.all.kbytes_in, len);	kb_incr(&Counter.server.http.kbytes_in, len);	commSetTimeout(fd, Config.Timeout.read, NULL, NULL);	IOStats.Http.reads++;	for (clen = len - 1, bin = 0; clen; bin++)	    clen >>= 1;	IOStats.Http.read_hist[bin]++;    }    if (!httpState->reply_hdr && len > 0) {	/* Skip whitespace */	while (len > 0 && xisspace(*buf))	    xmemmove(buf, buf + 1, len--);	if (len == 0) {	    /* Continue to read... */	    commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);	    return;	}    }    if (len < 0) {	debug(50, 2) ("httpReadReply: FD %d: read failure: %s.\n",	    fd, xstrerror());	if (ignoreErrno(errno)) {	    commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);	} else if (entry->mem_obj->inmem_hi == 0) {	    ErrorState *err;	    err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);	    err->xerrno = errno;	    fwdFail(httpState->fwd, err);	    comm_close(fd);	} else {	    comm_close(fd);	}    } else if (len == 0 && entry->mem_obj->inmem_hi == 0) {	ErrorState *err;	err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);	err->xerrno = errno;	fwdFail(httpState->fwd, err);	httpState->eof = 1;	comm_close(fd);    } else if (len == 0) {	/* Connection closed; retrieval done. */	httpState->eof = 1;	if (httpState->reply_hdr_state < 2)	    /*	     * Yes Henrik, there is a point to doing this.  When we	     * called httpProcessReplyHeader() before, we didn't find	     * the end of headers, but now we are definately at EOF, so	     * we want to process the reply headers.	     */	    httpProcessReplyHeader(httpState, buf, len);	fwdComplete(httpState->fwd);	comm_close(fd);    } else {	if (httpState->reply_hdr_state < 2) {	    httpProcessReplyHeader(httpState, buf, len);	    if (httpState->reply_hdr_state == 2) {		http_status s = entry->mem_obj->reply->sline.status;		/*		 * If its not a reply that we will re-forward, then		 * allow the client to get it.		 */		if (!fwdReforwardableStatus(s))		    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);	    }	}	storeAppend(entry, buf, len);	if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {	    /*	     * the above storeAppend() call could ABORT this entry,	     * in that case, the server FD should already be closed.	     * there's nothing for us to do.	     */	    (void) 0;	} else if (httpPconnTransferDone(httpState)) {	    /* yes we have to clear all these! */	    commSetDefer(fd, NULL, NULL);	    commSetTimeout(fd, -1, NULL, NULL);	    commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);#if DELAY_POOLS	    delayClearNoDelay(fd);#endif	    comm_remove_close_handler(fd, httpStateFree, httpState);	    fwdUnregister(fd, httpState->fwd);	    pconnPush(fd, request->host, request->port);	    fwdComplete(httpState->fwd);	    httpState->fd = -1;	    httpStateFree(fd, httpState);	} else {	    /* Wait for EOF condition */	    commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);	}    }}/* This will be called when request write is complete. Schedule read of * reply. */static voidhttpSendComplete(int fd, char *bufnotused, size_t size, int errflag, void *data){    HttpStateData *httpState = data;    StoreEntry *entry = httpState->entry;    ErrorState *err;    debug(11, 5) ("httpSendComplete: FD %d: size %d: errflag %d.\n",	fd, size, errflag);    if (size > 0) {	fd_bytes(fd, size, FD_WRITE);	kb_incr(&Counter.server.all.kbytes_out, size);	kb_incr(&Counter.server.http.kbytes_out, size);    }    if (errflag == COMM_ERR_CLOSING)	return;    if (errflag) {	err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);	err->xerrno = errno;	err->request = requestLink(httpState->orig_request);	errorAppendEntry(entry, err);	comm_close(fd);	return;    } else {	/* Schedule read reply. */	commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);	/*	 * Set the read timeout here because it hasn't been set yet.	 * We only set the read timeout after the request has been	 * fully written to the server-side.  If we start the timeout	 * after connection establishment, then we are likely to hit	 * the timeout for POST/PUT requests that have very large	 * request bodies.	 */	commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState);	commSetDefer(fd, fwdCheckDeferRead, entry);    }}/* * build request headers and append them to a given MemBuf  * used by httpBuildRequestPrefix() * note: calls httpHeaderInit(), the caller is responsible for Clean()-ing */voidhttpBuildRequestHeader(request_t * request,    request_t * orig_request,    StoreEntry * entry,    HttpHeader * hdr_out,    int cfd,    http_state_flags flags){    /* building buffer for complex strings */#define BBUF_SZ (MAX_URL+32)    LOCAL_ARRAY(char, bbuf, BBUF_SZ);    String strConnection = StringNull;    const HttpHeader *hdr_in = &orig_request->header;    int we_do_ranges;    const HttpHeaderEntry *e;    HttpHeaderPos pos = HttpHeaderInitPos;    httpHeaderInit(hdr_out, hoRequest);    /* append our IMS header */    if (entry && entry->lastmod > -1 && request->method == METHOD_GET)	httpHeaderPutTime(hdr_out, HDR_IF_MODIFIED_SINCE, entry->lastmod);    /* decide if we want to do Ranges ourselves      * (and fetch the whole object now)     * We want to handle Ranges ourselves iff     *    - we can actually parse client Range specs     *    - the specs are expected to be simple enough (e.g. no out-of-order ranges)     *    - reply will be cachable     * (If the reply will be uncachable we have to throw it away after      *  serving this request, so it is better to forward ranges to      *  the server and fetch only the requested content)      */    we_do_ranges =	orig_request->range && orig_request->flags.cachable && !httpHdrRangeWillBeComplex(orig_request->range) && (Config.rangeOffsetLimit == -1 || httpHdrRangeFirstOffset(orig_request->range) <= Config.rangeOffsetLimit);    debug(11, 8) ("httpBuildRequestHeader: range specs: %p, cachable: %d; we_do_ranges: %d\n",	orig_request->range, orig_request->flags.cachable, we_do_ranges);    strConnection = httpHeaderGetList(hdr_in, HDR_CONNECTION);    while ((e = httpHeaderGetEntry(hdr_in, &pos))) {	debug(11, 5) ("httpBuildRequestHeader: %s: %s\n",	    strBuf(e->name), strBuf(e->value));	if (!httpRequestHdrAllowed(e, &strConnection))

⌨️ 快捷键说明

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