📄 client_side.c
字号:
debug(33, 3) ("clientHandleIMSReply: Incomplete headers for '%s'\n", url); if (size >= CLIENT_SOCK_SZ) { /* will not get any bigger than that */ debug(33, 3) ("clientHandleIMSReply: Reply is too large '%s', using old entry\n", url); /* use old entry, this repeats the code abovez */ http->log_type = LOG_TCP_REFRESH_FAIL_HIT; storeUnregister(entry, http); storeUnlockObject(entry); entry = http->entry = http->old_entry; entry->refcount++; /* continue */ } else { storeClientCopy(entry, http->out.offset + size, http->out.offset, CLIENT_SOCK_SZ, buf, clientHandleIMSReply, http); return; } } else if (clientGetsOldEntry(entry, http->old_entry, http->request)) { /* We initiated the IMS request, the client is not expecting * 304, so put the good one back. First, make sure the old entry * headers have been loaded from disk. */ oldentry = http->old_entry; http->log_type = LOG_TCP_REFRESH_HIT; if (oldentry->mem_obj->request == NULL) { oldentry->mem_obj->request = requestLink(mem->request); unlink_request = 1; } /* Don't memcpy() the whole reply structure here. For example, * www.thegist.com (Netscape/1.13) returns a content-length for * 304's which seems to be the length of the 304 HEADERS!!! and * not the body they refer to. */ httpReplyUpdateOnNotModified(oldentry->mem_obj->reply, mem->reply); storeTimestampsSet(oldentry); storeUnregister(entry, http); storeUnlockObject(entry); entry = http->entry = oldentry; entry->timestamp = squid_curtime; if (unlink_request) { requestUnlink(entry->mem_obj->request); entry->mem_obj->request = NULL; } } else { /* the client can handle this reply, whatever it is */ http->log_type = LOG_TCP_REFRESH_MISS; if (HTTP_NOT_MODIFIED == mem->reply->sline.status) { http->old_entry->timestamp = squid_curtime; http->old_entry->refcount++; http->log_type = LOG_TCP_REFRESH_HIT; } storeUnregister(http->old_entry, http); storeUnlockObject(http->old_entry); recopy = 0; } http->old_entry = NULL; /* done with old_entry */ assert(!EBIT_TEST(entry->flags, ENTRY_ABORTED)); if (recopy) { storeClientCopy(entry, http->out.offset, http->out.offset, CLIENT_SOCK_SZ, buf, clientSendMoreData, http); } else { clientSendMoreData(data, buf, size); }}intmodifiedSince(StoreEntry * entry, request_t * request){ int object_length; MemObject *mem = entry->mem_obj; time_t mod_time = entry->lastmod; debug(33, 3) ("modifiedSince: '%s'\n", storeUrl(entry)); if (mod_time < 0) mod_time = entry->timestamp; debug(33, 3) ("modifiedSince: mod_time = %d\n", (int) mod_time); if (mod_time < 0) return 1; /* Find size of the object */ object_length = mem->reply->content_length; if (object_length < 0) object_length = contentLen(entry); if (mod_time > request->ims) { debug(33, 3) ("--> YES: entry newer than client\n"); return 1; } else if (mod_time < request->ims) { debug(33, 3) ("--> NO: entry older than client\n"); return 0; } else if (request->imslen < 0) { debug(33, 3) ("--> NO: same LMT, no client length\n"); return 0; } else if (request->imslen == object_length) { debug(33, 3) ("--> NO: same LMT, same length\n"); return 0; } else { debug(33, 3) ("--> YES: same LMT, different length\n"); return 1; }}voidclientPurgeRequest(clientHttpRequest * http){ StoreEntry *entry; ErrorState *err = NULL; HttpReply *r; debug(33, 3) ("Config.onoff.enable_purge = %d\n", Config.onoff.enable_purge); if (!Config.onoff.enable_purge) { http->log_type = LOG_TCP_DENIED; err = errorCon(ERR_ACCESS_DENIED, HTTP_FORBIDDEN); err->request = requestLink(http->request); err->src_addr = http->conn->peer.sin_addr; http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags); errorAppendEntry(http->entry, err); return; } http->log_type = LOG_TCP_MISS; if ((entry = storeGetPublic(http->uri, METHOD_GET)) == NULL) { http->http_code = HTTP_NOT_FOUND; } else { storeRelease(entry); http->http_code = HTTP_OK; } debug(33, 4) ("clientPurgeRequest: Not modified '%s'\n", storeUrl(entry)); /* * Make a new entry to hold the reply to be written * to the client. */ http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags); httpReplyReset(r = http->entry->mem_obj->reply); httpReplySetHeaders(r, 1.0, http->http_code, NULL, NULL, 0, 0, -1); httpReplySwapOut(r, http->entry); storeComplete(http->entry);}intcheckNegativeHit(StoreEntry * e){ if (!EBIT_TEST(e->flags, ENTRY_NEGCACHED)) return 0; if (e->expires <= squid_curtime) return 0; if (e->store_status != STORE_OK) return 0; return 1;}voidclientUpdateCounters(clientHttpRequest * http){ int svc_time = tvSubMsec(http->start, current_time); ping_data *i; HierarchyLogEntry *H; Counter.client_http.requests++; if (isTcpHit(http->log_type)) Counter.client_http.hits++; if (http->request->err_type != ERR_NONE) Counter.client_http.errors++; statHistCount(&Counter.client_http.all_svc_time, svc_time); /* * The idea here is not to be complete, but to get service times * for only well-defined types. For example, we don't include * LOG_TCP_REFRESH_FAIL_HIT because its not really a cache hit * (we *tried* to validate it, but failed). */ switch (http->log_type) { case LOG_TCP_REFRESH_HIT: statHistCount(&Counter.client_http.nh_svc_time, svc_time); break; case LOG_TCP_IMS_HIT: statHistCount(&Counter.client_http.nm_svc_time, svc_time); break; case LOG_TCP_HIT: case LOG_TCP_MEM_HIT: case LOG_TCP_OFFLINE_HIT: statHistCount(&Counter.client_http.hit_svc_time, svc_time); break; case LOG_TCP_MISS: case LOG_TCP_CLIENT_REFRESH_MISS: statHistCount(&Counter.client_http.miss_svc_time, svc_time); break; default: /* make compiler warnings go away */ break; } H = &http->request->hier; switch (H->alg) { case PEER_SA_DIGEST: Counter.cd.times_used++; break; case PEER_SA_ICP: Counter.icp.times_used++; i = &H->ping; if (0 != i->stop.tv_sec && 0 != i->start.tv_sec) statHistCount(&Counter.icp.query_svc_time, tvSubUsec(i->start, i->stop)); if (i->timeout) Counter.icp.query_timeouts++; break; case PEER_SA_NETDB: Counter.netdb.times_used++; break; default: break; }}static voidhttpRequestFree(void *data){ clientHttpRequest *http = data; clientHttpRequest **H; ConnStateData *conn = http->conn; StoreEntry *e; request_t *request = http->request; MemObject *mem = NULL; debug(33, 3) ("httpRequestFree: %s\n", storeUrl(http->entry)); if (!clientCheckTransferDone(http)) { if ((e = http->entry)) { http->entry = NULL; storeUnregister(e, http); storeUnlockObject(e); } if (http->entry && http->entry->ping_status == PING_WAITING) storeReleaseRequest(http->entry); } assert(http->log_type < LOG_TYPE_MAX); if (http->entry) mem = http->entry->mem_obj; if (http->out.size || http->log_type) { http->al.icp.opcode = ICP_INVALID; http->al.url = http->log_uri; debug(33, 9) ("httpRequestFree: al.url='%s'\n", http->al.url); if (mem) { http->al.http.code = mem->reply->sline.status; http->al.http.content_type = strBuf(mem->reply->content_type); } http->al.cache.caddr = conn->log_addr; http->al.cache.size = http->out.size; http->al.cache.code = http->log_type; http->al.cache.msec = tvSubMsec(http->start, current_time); if (request->user_ident[0]) http->al.cache.ident = request->user_ident; else http->al.cache.ident = conn->ident; if (request) { Packer p; MemBuf mb; memBufDefInit(&mb); packerToMemInit(&p, &mb); httpHeaderPackInto(&request->header, &p); http->al.http.method = request->method; http->al.http.version = request->http_ver; http->al.headers.request = xstrdup(mb.buf); http->al.hier = request->hier; packerClean(&p); memBufClean(&mb); } accessLogLog(&http->al); clientUpdateCounters(http); clientdbUpdate(conn->peer.sin_addr, http->log_type, PROTO_HTTP, http->out.size); } if (http->acl_checklist) aclChecklistFree(http->acl_checklist); if (request) checkFailureRatio(request->err_type, http->al.hier.code); safe_free(http->uri); safe_free(http->log_uri); safe_free(http->al.headers.request); safe_free(http->al.headers.reply); safe_free(http->redirect.location); stringClean(&http->range_iter.boundary); if ((e = http->entry)) { http->entry = NULL; storeUnregister(e, http); storeUnlockObject(e); } /* old_entry might still be set if we didn't yet get the reply * code in clientHandleIMSReply() */ if ((e = http->old_entry)) { http->old_entry = NULL; storeUnregister(e, http); storeUnlockObject(e); } requestUnlink(http->request); assert(http != http->next); assert(http->conn->chr != NULL); H = &http->conn->chr; while (*H) { if (*H == http) break; H = &(*H)->next; } assert(*H != NULL); *H = http->next; http->next = NULL; dlinkDelete(&http->active, &ClientActiveRequests); cbdataFree(http);}/* This is a handler normally called by comm_close() */static voidconnStateFree(int fd, void *data){ ConnStateData *connState = data; clientHttpRequest *http; debug(33, 3) ("connStateFree: FD %d\n", fd); assert(connState != NULL); while ((http = connState->chr) != NULL) { assert(http->conn == connState); assert(connState->chr != connState->chr->next); httpRequestFree(http); } safe_free(connState->in.buf); /* XXX account connState->in.buf */ pconnHistCount(0, connState->nrequests); cbdataFree(connState);#ifdef _SQUID_LINUX_ /* prevent those nasty RST packets */ { char buf[SQUID_TCP_SO_RCVBUF]; while (read(fd, buf, SQUID_TCP_SO_RCVBUF) > 0); }#endif}static voidclientInterpretRequestHeaders(clientHttpRequest * http){ request_t *request = http->request; const HttpHeader *req_hdr = &request->header; int no_cache = 0;#if USE_USERAGENT_LOG const char *str;#endif request->imslen = -1; request->ims = httpHeaderGetTime(req_hdr, HDR_IF_MODIFIED_SINCE); if (request->ims > 0) request->flags.ims = 1; if (httpHeaderHas(req_hdr, HDR_PRAGMA)) { String s = httpHeaderGetList(req_hdr, HDR_PRAGMA); if (strListIsMember(&s, "no-cache", ',')) no_cache++; stringClean(&s); } if (request->cache_control) if (EBIT_TEST(request->cache_control->mask, CC_NO_CACHE)) no_cache++; if (no_cache) {#if HTTP_VIOLATIONS if (Config.onoff.reload_into_ims) request->flags.nocache_hack = 1; else if (refresh_nocache_hack) request->flags.nocache_hack = 1; else#endif request->flags.nocache = 1; } /* ignore range header in non-GETs */ if (request->method == METHOD_GET) { request->range = httpHeaderGetRange(req_hdr); if (request->range) request->flags.range = 1; } if (httpHeaderHas(req_hdr, HDR_AUTHORIZATION)) request->flags.auth = 1; if (request->login[0] != '\0') request->flags.auth = 1; if (httpHeaderHas(req_hdr, HDR_VIA)) { String s = httpHeaderGetList(req_hdr, HDR_VIA); /* * ThisCache cannot be a member of Via header, "1.0 ThisCache" can. * Note ThisCache2 has a space prepended to the hostname so we don't * accidentally match super-domains. */ if (strListIsSubstr(&s, ThisCache2, ',')) { debugObj(33, 1, "WARNING: Forwarding loop detected for:\n", request, (ObjPackMethod) & httpRequestPack); request->flags.loopdetect = 1; }#if FORW_VIA_DB fvdbCountVia(strBuf(s));#endif stringClean(&s); }#if USE_USERAGENT_LOG if ((str = httpHeaderGetStr(req_hdr, HDR_USER_AGENT))) logUserAgent(fqdnFromAddr(http->conn->peer.sin_addr), str);#endif#if FORW_VIA_DB if (httpHeaderHas(req_hdr, HDR_X_FORWARDED_FOR)) { String s = httpHeaderGetList(req_hdr, HDR_X_FORWARDED_FOR); fvdbCountForw(strBuf(s)); stringClean(&s); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -