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

📄 client_side.c

📁 -
💻 C
📖 第 1 页 / 共 5 页
字号:
{    clientHttpRequest *http = data;    StoreEntry *entry = http->entry;    int done;    http->out.size += size;    debug(33, 5) ("clientWriteComplete: FD %d, sz %d, err %d, off %d, len %d\n",	fd, size, errflag, (int) http->out.offset, entry ? objectLen(entry) : 0);    if (size > 0) {	kb_incr(&Counter.client_http.kbytes_out, size);	if (isTcpHit(http->log_type))	    kb_incr(&Counter.client_http.hit_kbytes_out, size);    }    if (errflag) {	/*	 * just close the socket, httpRequestFree will abort if needed	 */	comm_close(fd);    } else if (NULL == entry) {	comm_close(fd);		/* yuk */    } else if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {	comm_close(fd);    } else if ((done = clientCheckTransferDone(http)) != 0 || size == 0) {	debug(33, 5) ("clientWriteComplete: FD %d transfer is DONE\n", fd);	/* We're finished case */	if (http->entry->mem_obj->reply->content_length < 0) {	    debug(33, 5) ("clientWriteComplete: closing, content_length < 0\n");	    comm_close(fd);	} else if (!done) {	    debug(33, 5) ("clientWriteComplete: closing, !done\n");	    comm_close(fd);	} else if (clientGotNotEnough(http)) {	    debug(33, 5) ("clientWriteComplete: client didn't get all it expected\n");	    comm_close(fd);	} else if (http->request->flags.proxy_keepalive) {	    debug(33, 5) ("clientWriteComplete: FD %d Keeping Alive\n", fd);	    clientKeepaliveNextRequest(http);	} else {	    comm_close(fd);	}    } else {	/* More data will be coming from primary server; register with 	 * storage manager. */	if (EBIT_TEST(entry->flags, ENTRY_ABORTED))	    debug(33, 0) ("clientWriteComplete 2: ENTRY_ABORTED\n");	storeClientCopy(entry,	    http->out.offset,	    http->out.offset,	    CLIENT_SOCK_SZ,	    memAllocate(MEM_CLIENT_SOCK_BUF),	    clientSendMoreData,	    http);    }}/* * client issued a request with an only-if-cached cache-control directive; * we did not find a cached object that can be returned without *     contacting other servers; * respond with a 504 (Gateway Timeout) as suggested in [RFC 2068] */static voidclientProcessOnlyIfCachedMiss(clientHttpRequest * http){    char *url = http->uri;    request_t *r = http->request;    ErrorState *err = NULL;    debug(33, 4) ("clientProcessOnlyIfCachedMiss: '%s %s'\n",	RequestMethodStr[r->method], url);    http->al.http.code = HTTP_GATEWAY_TIMEOUT;    err = errorCon(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT);    err->request = requestLink(r);    err->src_addr = http->conn->peer.sin_addr;    if (http->entry) {	storeUnregister(http->entry, http);	storeUnlockObject(http->entry);    }    http->entry = clientCreateStoreEntry(http, r->method, null_request_flags);    errorAppendEntry(http->entry, err);}static log_typeclientProcessRequest2(clientHttpRequest * http){    request_t *r = http->request;    StoreEntry *e;    e = http->entry = storeGetPublic(http->uri, r->method);    if (r->method == METHOD_HEAD && e == NULL) {	/* We can generate a HEAD reply from a cached GET object */	e = http->entry = storeGetPublic(http->uri, METHOD_GET);    }#if USE_CACHE_DIGESTS    http->lookup_type = e ? "HIT" : "MISS";#endif    if (NULL == e) {	/* this object isn't in the cache */	debug(33, 3) ("clientProcessRequest2: storeGet() MISS\n");	return LOG_TCP_MISS;    }    if (Config.onoff.offline) {	debug(33, 3) ("clientProcessRequest2: offline HIT\n");	http->entry = e;	return LOG_TCP_HIT;    }    if (!storeEntryValidToSend(e)) {	debug(33, 3) ("clientProcessRequest2: !storeEntryValidToSend MISS\n");	http->entry = NULL;	return LOG_TCP_MISS;    }    if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {	/* Special entries are always hits, no matter what the client says */	debug(33, 3) ("clientProcessRequest2: ENTRY_SPECIAL HIT\n");	http->entry = e;	return LOG_TCP_HIT;    }#if HTTP_VIOLATIONS    if (r->flags.nocache_hack) {	/* if nocache_hack is set, nocache should always be clear, right? */	assert(!r->flags.nocache);	ipcacheReleaseInvalid(r->host);	/* continue! */    }    if (e->store_status == STORE_PENDING) {	if (r->flags.nocache || r->flags.nocache_hack) {	    debug(33, 3) ("Clearing no-cache for STORE_PENDING request\n\t%s\n",		storeUrl(e));	    r->flags.nocache = 0;	    r->flags.nocache_hack = 0;	}    }#endif    if (r->flags.nocache) {	debug(33, 3) ("clientProcessRequest2: no-cache REFRESH MISS\n");	http->entry = NULL;	ipcacheReleaseInvalid(r->host);	return LOG_TCP_CLIENT_REFRESH_MISS;    }    if (r->range && httpHdrRangeWillBeComplex(r->range)) {	/*	 * Some clients break if we return "200 OK" for a Range	 * request.  We would have to return "200 OK" for a _complex_	 * Range request that is also a HIT. Thus, let's prevent HITs	 * on complex Range requests	 */	debug(33, 3) ("clientProcessRequest2: complex range MISS\n");	http->entry = NULL;	return LOG_TCP_MISS;    }    debug(33, 3) ("clientProcessRequest2: default HIT\n");    http->entry = e;    return LOG_TCP_HIT;}static voidclientProcessRequest(clientHttpRequest * http){    char *url = http->uri;    request_t *r = http->request;    int fd = http->conn->fd;    HttpReply *rep;    debug(33, 4) ("clientProcessRequest: %s '%s'\n",	RequestMethodStr[r->method],	url);    if (r->method == METHOD_CONNECT) {	http->log_type = LOG_TCP_MISS;	sslStart(fd, url, r, &http->out.size);	return;    } else if (r->method == METHOD_PURGE) {	clientPurgeRequest(http);	return;    } else if (r->method == METHOD_TRACE) {	if (r->max_forwards == 0) {	    http->entry = clientCreateStoreEntry(http, r->method, null_request_flags);	    storeReleaseRequest(http->entry);	    storeBuffer(http->entry);	    rep = httpReplyCreate();	    httpReplySetHeaders(rep, 1.0, HTTP_OK, NULL, "text/plain",		httpRequestPrefixLen(r), 0, squid_curtime);	    httpReplySwapOut(rep, http->entry);	    httpReplyDestroy(rep);	    httpRequestSwapOut(r, http->entry);	    storeComplete(http->entry);	    return;	}	/* yes, continue */	http->log_type = LOG_TCP_MISS;    } else if (pumpMethod(r->method)) {	http->log_type = LOG_TCP_MISS;	/* XXX oof, POST can be cached! */	pumpInit(fd, r, http->uri);    } else {	http->log_type = clientProcessRequest2(http);    }    debug(33, 4) ("clientProcessRequest: %s for '%s'\n",	log_tags[http->log_type],	http->uri);    http->out.offset = 0;    if (NULL != http->entry) {	storeLockObject(http->entry);	storeCreateMemObject(http->entry, http->uri, http->log_uri);	storeClientListAdd(http->entry, http);#if DELAY_POOLS	delaySetStoreClient(http->entry, http, delayClient(r));#endif	http->entry->refcount++;	storeClientCopy(http->entry,	    http->out.offset,	    http->out.offset,	    CLIENT_SOCK_SZ,	    memAllocate(MEM_CLIENT_SOCK_BUF),	    clientCacheHit,	    http);    } else {	/* MISS CASE */	http->log_type = LOG_TCP_MISS;	clientProcessMiss(http);    }}/* * Prepare to fetch the object as it's a cache miss of some kind. */static voidclientProcessMiss(clientHttpRequest * http){    char *url = http->uri;    request_t *r = http->request;    ErrorState *err = NULL;    debug(33, 4) ("clientProcessMiss: '%s %s'\n",	RequestMethodStr[r->method], url);    /*     * We might have a left-over StoreEntry from a failed cache hit     * or IMS request.     */    if (http->entry) {	if (EBIT_TEST(http->entry->flags, ENTRY_SPECIAL))	    debug(33, 0) ("clientProcessMiss: miss on a special object (%s).\n", url);	storeUnregister(http->entry, http);	storeUnlockObject(http->entry);	http->entry = NULL;    }    if (clientOnlyIfCached(http)) {	clientProcessOnlyIfCachedMiss(http);	return;    }    /*     * Deny loops when running in accelerator/transproxy mode.     */    if (http->flags.accel && r->flags.loopdetect) {	http->al.http.code = HTTP_FORBIDDEN;	err = errorCon(ERR_ACCESS_DENIED, HTTP_FORBIDDEN);	err->request = requestLink(r);	err->src_addr = http->conn->peer.sin_addr;	http->entry = clientCreateStoreEntry(http, r->method, null_request_flags);	errorAppendEntry(http->entry, err);	return;    }    assert(http->out.offset == 0);    http->entry = clientCreateStoreEntry(http, r->method, r->flags);    http->entry->refcount++;    if (http->redirect.status) {	HttpReply *rep = httpReplyCreate();	storeReleaseRequest(http->entry);	httpRedirectReply(rep, http->redirect.status, http->redirect.location);	httpReplySwapOut(rep, http->entry);	httpReplyDestroy(rep);	storeComplete(http->entry);	return;    }    if (http->flags.internal)	r->protocol = PROTO_INTERNAL;    fwdStart(http->conn->fd, http->entry, r,	http->conn->peer.sin_addr, http->conn->me.sin_addr);}static clientHttpRequest *parseHttpRequestAbort(ConnStateData * conn, const char *uri){    clientHttpRequest *http = xcalloc(1, sizeof(clientHttpRequest));    cbdataAdd(http, cbdataXfree, 0);    http->conn = conn;    http->start = current_time;    http->req_sz = conn->in.offset;    http->uri = xstrdup(uri);    http->log_uri = xstrndup(uri, MAX_URL);    http->range_iter.boundary = StringNull;    dlinkAdd(http, &http->active, &ClientActiveRequests);    return http;}/* *  parseHttpRequest() *  *  Returns *   NULL on error or incomplete request *    a clientHttpRequest structure on success */static clientHttpRequest *parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status,    char **prefix_p, size_t * req_line_sz_p){    char *inbuf = NULL;    char *mstr = NULL;    char *url = NULL;    char *req_hdr = NULL;    float http_ver;    char *token = NULL;    char *t = NULL;    char *end;    int free_request = 0;    size_t header_sz;		/* size of headers, not including first line */    size_t prefix_sz;		/* size of whole request (req-line + headers) */    size_t url_sz;    size_t req_sz;    method_t method;    clientHttpRequest *http = NULL;#if IPF_TRANSPARENT    struct natlookup natLookup;    static int natfd = -1;#endif    if ((req_sz = headersEnd(conn->in.buf, conn->in.offset)) == 0) {	debug(33, 5) ("Incomplete request, waiting for end of headers\n");	*status = 0;	*prefix_p = NULL;	*method_p = METHOD_NONE;	return NULL;    }    assert(req_sz <= conn->in.offset);    /* Use memcpy, not strdup! */    inbuf = xmalloc(req_sz + 1);    xmemcpy(inbuf, conn->in.buf, req_sz);    *(inbuf + req_sz) = '\0';    /* pre-set these values to make aborting simpler */    *prefix_p = inbuf;    *method_p = METHOD_NONE;    *status = -1;    /* Barf on NULL characters in the headers */    if (strlen(inbuf) != req_sz) {	debug(33, 1) ("parseHttpRequest: Requestheader contains NULL characters\n");	return parseHttpRequestAbort(conn, "error:invalid-request");    }    /* Look for request method */    if ((mstr = strtok(inbuf, "\t ")) == NULL) {	debug(33, 1) ("parseHttpRequest: Can't get request method\n");	return parseHttpRequestAbort(conn, "error:invalid-request-method");    }    method = urlParseMethod(mstr);    if (method == METHOD_NONE) {	debug(33, 1) ("parseHttpRequest: Unsupported method '%s'\n", mstr);	return parseHttpRequestAbort(conn, "error:unsupported-request-method");    }    debug(33, 5) ("parseHttpRequest: Method is '%s'\n", mstr);    *method_p = method;    /* look for URL+HTTP/x.x */    if ((url = strtok(NULL, "\n")) == NULL) {	debug(33, 1) ("parseHttpRequest: Missing URL\n");	return parseHttpRequestAbort(conn, "error:missing-url");    }    while (xisspace(*url))	url++;    t = url + strlen(url);    assert(*t == '\0');    token = NULL;    while (t > url) {	t--;	if (xisspace(*t) && !strncmp(t + 1, "HTTP/", 5)) {	    token = t + 1;	    break;	}    }    while (t > url && xisspace(*t))	*(t--) = '\0';    debug(33, 5) ("parseHttpRequest: URI is '%s'\n", url);    if (token == NULL) {	debug(33, 3) ("parseHttpRequest: Missing HTTP identifier\n");#if RELAXED_HTTP_PARSER	http_ver = (float) 0.9;	/* wild guess */#else	return parseHttpRequestAbort(conn, "error:missing-http-ident");#endif    } else {	http_ver = (float) atof(token + 5);    }    /*     * Process headers after request line     */    req_hdr = strtok(NULL, null_string);    header_sz = req_sz - (req_hdr - inbuf);    if (0 == header_sz) {	debug(33, 3) ("parseHttpRequest: header_sz == 0\n");	*status = 0;	return NULL;    }    assert(header_sz > 0);    debug(33, 3) ("parseHttpRequest: req_

⌨️ 快捷键说明

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