void urnStart(request_t * r, StoreEntry * e) { LOCAL_ARRAY(char, urlres, 4096); request_t *urlres_r = NULL; const char *t; char *host; UrnState *urnState; StoreEntry *urlres_e; ErrorState *err; debug(52, 3) ("urnStart: '%s'\n", storeUrl(e)); CBDATA_INIT_TYPE(UrnState); urnState = cbdataAlloc(UrnState); urnState->entry = e; urnState->request = requestLink(r); storeLockObject(urnState->entry); if (strncasecmp(strBuf(r->urlpath), "menu.", 5) == 0) { char *new_path = xstrdup(strBuf(r->urlpath) + 5); urnState->flags.force_menu = 1; stringReset(&r->urlpath, new_path); xfree(new_path); } if ((t = strChr(r->urlpath, ':')) != NULL) { strSet(r->urlpath, t, '\0'); host = xstrdup(strBuf(r->urlpath)); strSet(r->urlpath, t, ':'); } else { host = xstrdup(strBuf(r->urlpath)); } snprintf(urlres, 4096, "http://%s/uri-res/N2L?urn:%s", host, strBuf(r->urlpath)); safe_free(host); urlres_r = urlParse(METHOD_GET, urlres); if (urlres_r == NULL) { debug(52, 3) ("urnStart: Bad uri-res URL %s\n", urlres); err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND); err->url = xstrdup(urlres); errorAppendEntry(e, err); return; } httpHeaderPutStr(&urlres_r->header, HDR_ACCEPT, "text/plain"); if ((urlres_e = storeGetPublic(urlres, METHOD_GET)) == NULL) { urlres_e = storeCreateEntry(urlres, urlres, null_request_flags, METHOD_GET); urnState->sc = storeClientListAdd(urlres_e, urnState); fwdStart(-1, urlres_e, urlres_r); } else { storeLockObject(urlres_e); urnState->sc = storeClientListAdd(urlres_e, urnState); } urnState->urlres_e = urlres_e; urnState->urlres_r = requestLink(urlres_r); storeClientCopy(urnState->sc, urlres_e, 0, 0, 4096, memAllocate(MEM_4K_BUF), urnHandleReply, urnState); }
static void icapProcessHttpReplyHeader(IcapStateData * icap, const char *buf, int size) { if (NULL == icap->httpState) { icap->httpState = cbdataAlloc(HttpStateData); icap->httpState->request = requestLink(icap->request); icap->httpState->orig_request = requestLink(icap->request); icap->httpState->entry = icap->respmod.entry; storeLockObject(icap->httpState->entry); /* lock it */ } httpProcessReplyHeader(icap->httpState, buf, size); if (2 == icap->httpState->reply_hdr_state) EBIT_CLR(icap->httpState->entry->flags, ENTRY_FWD_HDR_WAIT); }
static void asnCacheStart(int as) { LOCAL_ARRAY(char, asres, 4096); StoreEntry *e; request_t *req; ASState *asState; method_t *method_get; method_get = urlMethodGetKnownByCode(METHOD_GET); asState = cbdataAlloc(ASState); debug(53, 3) ("asnCacheStart: AS %d\n", as); snprintf(asres, 4096, "whois://%s/!gAS%d", Config.as_whois_server, as); asState->as_number = as; req = urlParse(method_get, asres); assert(NULL != req); asState->request = requestLink(req); if ((e = storeGetPublic(asres, method_get)) == NULL) { e = storeCreateEntry(asres, null_request_flags, method_get); asState->sc = storeClientRegister(e, asState); fwdStart(-1, e, asState->request); } else { storeLockObject(e); asState->sc = storeClientRegister(e, asState); } asState->entry = e; asState->seen = 0; asState->offset = 0; storeClientRef(asState->sc, e, asState->seen, asState->offset, SM_PAGE_SIZE, asHandleReply, asState); }
/* starts swap out sequence for the digest */ static void storeDigestRewriteStart(void *datanotused) { request_flags flags; char *url; StoreEntry *e; assert(store_digest); /* prevent overlapping if rewrite schedule is too tight */ if (sd_state.rewrite_lock) { debug(71, 1) ("storeDigestRewriteStart: overlap detected, consider increasing rewrite period\n"); return; } debug(71, 2) ("storeDigestRewriteStart: start rewrite #%d\n", sd_state.rewrite_count + 1); /* make new store entry */ url = internalStoreUri("/squid-internal-periodic/", StoreDigestFileName); flags = null_request_flags; flags.cachable = 1; e = storeCreateEntry(url, flags, METHOD_GET); assert(e); sd_state.rewrite_lock = cbdataAlloc(generic_cbdata); sd_state.rewrite_lock->data = e; debug(71, 3) ("storeDigestRewriteStart: url: %s key: %s\n", url, storeKeyText(e->hash.key)); e->mem_obj->request = requestLink(urlParse(METHOD_GET, url)); /* wait for rebuild (if any) to finish */ if (sd_state.rebuild_lock) { debug(71, 2) ("storeDigestRewriteStart: waiting for rebuild to finish.\n"); return; } storeDigestRewriteResume(); }
void peerSelect(request_t * request, StoreEntry * entry, PSC * callback, void *callback_data) { ps_state *psstate; if (entry) debug(44, 3) ("peerSelect: %s\n", storeUrl(entry)); else debug(44, 3) ("peerSelect: %s\n", RequestMethods[request->method].str); psstate = cbdataAlloc(ps_state); psstate->request = requestLink(request); psstate->entry = entry; psstate->callback = callback; psstate->callback_data = callback_data; psstate->direct = DIRECT_UNKNOWN; #if USE_CACHE_DIGESTS request->hier.peer_select_start = current_time; #endif if (psstate->entry) storeLockObject(psstate->entry); cbdataLock(callback_data); peerSelectFoo(psstate); }
int errorMapStart(const errormap * map, request_t * client_req, HttpReply * reply, const char *aclname, ERRMAPCB * callback, void *callback_data) { char squid_error[100]; int len = 0; const char *errorUrl; ErrorMapState *state; const char *tmp; http_status status; request_t *req; HttpHeaderPos hdrpos; HttpHeaderEntry *hdr; if (!client_req || !reply) return 0; status = reply->sline.status; tmp = httpHeaderGetStr(&reply->header, HDR_X_SQUID_ERROR); squid_error[0] = '\0'; if (tmp) { xstrncpy(squid_error, tmp, sizeof(squid_error)); len = strcspn(squid_error, " "); } squid_error[len] = '\0'; errorUrl = getErrorMap(map, status, squid_error, aclname); if (!errorUrl) return 0; req = urlParse(urlMethodGetKnownByCode(METHOD_GET), (char *) errorUrl); if (!req) { debug(0, 0) ("errorMapStart: Invalid error URL '%s'\n", errorUrl); return 0; } req->urlgroup = xstrdup("error"); state = cbdataAlloc(ErrorMapState); state->req = requestLink(req); state->e = storeCreateEntry(errorUrl, req->flags, req->method); state->sc = storeClientRegister(state->e, state); state->callback = callback; state->callback_data = callback_data; cbdataLock(callback_data); hdrpos = HttpHeaderInitPos; while ((hdr = httpHeaderGetEntry(&client_req->header, &hdrpos)) != NULL) { if (CBIT_TEST(client_headers, hdr->id)) httpHeaderAddClone(&req->header, hdr); } hdrpos = HttpHeaderInitPos; while ((hdr = httpHeaderGetEntry(&reply->header, &hdrpos)) != NULL) { if (CBIT_TEST(server_headers, hdr->id)) httpHeaderAddClone(&req->header, hdr); } httpHeaderPutInt(&req->header, HDR_X_ERROR_STATUS, (int) reply->sline.status); httpHeaderPutStr(&req->header, HDR_X_REQUEST_URI, urlCanonical(client_req)); fwdStart(-1, state->e, req); storeClientRef(state->sc, state->e, 0, 0, SM_PAGE_SIZE, errorMapFetchHeaders, state); return 1; }
void netdbExchangeStart(void *data) { #if USE_ICMP peer *p = data; char *uri; netdbExchangeState *ex; method_t *method_get; CBDATA_INIT_TYPE(netdbExchangeState); ex = cbdataAlloc(netdbExchangeState); cbdataLock(p); ex->p = p; uri = internalRemoteUri(p->host, p->http_port, "/squid-internal-dynamic/", "netdb"); debug(38, 3) ("netdbExchangeStart: Requesting '%s'\n", uri); assert(NULL != uri); method_get = urlMethodGetKnownByCode(METHOD_GET); ex->r = urlParse(method_get, uri); if (NULL == ex->r) { debug(38, 1) ("netdbExchangeStart: Bad URI %s\n", uri); return; } requestLink(ex->r); assert(NULL != ex->r); httpBuildVersion(&ex->r->http_ver, 1, 0); ex->e = storeCreateEntry(uri, null_request_flags, method_get); assert(NULL != ex->e); ex->sc = storeClientRegister(ex->e, ex); storeClientRef(ex->sc, ex->e, ex->seen, ex->used, SM_PAGE_SIZE, netdbExchangeHandleReply, ex); ex->r->flags.loopdetect = 1; /* cheat! -- force direct */ if (p->login) xstrncpy(ex->r->login, p->login, MAX_LOGIN_SZ); fwdStart(-1, ex->e, ex->r); #endif }
static void mimeLoadIconFile(const char *icon) { int fd; int n; request_flags flags; struct stat sb; StoreEntry *e; LOCAL_ARRAY(char, path, MAXPATHLEN); LOCAL_ARRAY(char, url, MAX_URL); char *buf; const char *type = mimeGetContentType(icon); HttpReply *reply; if (type == NULL) fatal("Unknown icon format while reading mime.conf\n"); buf = internalLocalUri("/squid-internal-static/icons/", icon); xstrncpy(url, buf, MAX_URL); if (storeGetPublic(url, METHOD_GET)) return; snprintf(path, MAXPATHLEN, "%s/%s", Config.icons.directory, icon); fd = file_open(path, O_RDONLY); if (fd < 0) { debug(25, 0) ("mimeLoadIconFile: %s: %s\n", path, xstrerror()); return; } if (fstat(fd, &sb) < 0) { debug(50, 0) ("mimeLoadIconFile: FD %d: fstat: %s\n", fd, xstrerror()); return; } flags = null_request_flags; flags.cachable = 1; e = storeCreateEntry(url, url, flags, METHOD_GET); assert(e != NULL); storeSetPublicKey(e); storeBuffer(e); e->mem_obj->request = requestLink(urlParse(METHOD_GET, url)); httpReplyReset(reply = e->mem_obj->reply); httpReplySetHeaders(reply, 1.0, HTTP_OK, NULL, type, (int) sb.st_size, sb.st_mtime, -1); reply->cache_control = httpHdrCcCreate(); httpHdrCcSetMaxAge(reply->cache_control, 86400); httpHeaderPutCc(&reply->header, reply->cache_control); httpReplySwapOut(reply, e); reply->hdr_sz = e->mem_obj->inmem_hi; /* yuk */ /* read the file into the buffer and append it to store */ buf = memAllocate(MEM_4K_BUF); while ((n = read(fd, buf, 4096)) > 0) storeAppend(e, buf, n); file_close(fd); EBIT_SET(e->flags, ENTRY_SPECIAL); storeBufferFlush(e); storeComplete(e); storeTimestampsSet(e); debug(25, 3) ("Loaded icon %s\n", url); storeUnlockObject(e); memFree(buf, MEM_4K_BUF); }
static void peerCountMcastPeersStart(void *data) { peer *p = data; ps_state *psstate; StoreEntry *fake; MemObject *mem; icp_common_t *query; int reqnum; method_t *method_get; LOCAL_ARRAY(char, url, MAX_URL); assert(p->type == PEER_MULTICAST); method_get = urlMethodGetKnownByCode(METHOD_GET); p->mcast.flags.count_event_pending = 0; snprintf(url, MAX_URL, "http://%s/", inet_ntoa(p->in_addr.sin_addr)); fake = storeCreateEntry(url, null_request_flags, method_get); psstate = cbdataAlloc(ps_state); psstate->request = requestLink(urlParse(method_get, url)); psstate->entry = fake; psstate->callback = NULL; psstate->callback_data = p; cbdataLock(psstate->callback_data); psstate->ping.start = current_time; mem = fake->mem_obj; mem->request = requestLink(psstate->request); mem->start_ping = current_time; mem->ping_reply_callback = peerCountHandleIcpReply; mem->ircb_data = psstate; mcastSetTtl(theOutIcpConnection, p->mcast.ttl); p->mcast.id = mem->id; reqnum = icpSetCacheKey(fake->hash.key); query = icpCreateMessage(ICP_QUERY, 0, url, reqnum, 0); icpUdpSend(theOutIcpConnection, &p->in_addr, query, LOG_ICP_QUERY, 0); fake->ping_status = PING_WAITING; eventAdd("peerCountMcastPeersDone", peerCountMcastPeersDone, psstate, Config.Timeout.mcast_icp_query / 1000.0, 1); p->mcast.flags.counting = 1; peerCountMcastPeersSchedule(p, MCAST_COUNT_RATE); }
/* * copied from httpReadReply() * * by the time this is called, the ICAP headers have already * been read. */ void icapReadReply(int fd, void *data) { IcapStateData *icap = data; StoreEntry *entry = icap->respmod.entry; const request_t *request = icap->request; int len; debug(81, 5) ("icapReadReply: FD %d: icap %p.\n", fd, data); if (icap->flags.no_content && !icap->flags.http_server_eof) { //AI return; } if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { comm_close(fd); return; } errno = 0; statCounter.syscalls.sock.reads++; len = memBufRead(fd, &icap->chunk_buf); debug(81, 5) ("icapReadReply: FD %d: len %d.\n", fd, len); if (len > 0) { fd_bytes(fd, len, FD_READ); kb_incr(&statCounter.icap.all.kbytes_in, len); commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap); if (icap->chunk_buf.size < icap->chunk_buf.capacity) { *(icap->chunk_buf.buf + icap->chunk_buf.size) = '\0'; debug(81, 9) ("{%s}\n", icap->chunk_buf.buf); } } if (len <= 0) { debug(81, 2) ("icapReadReply: FD %d: read failure: %s.\n", fd, xstrerror()); if (ignoreErrno(errno)) { debug(81, 2) ("icapReadReply: FD %d: ignored errno\n", fd); commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0); } else if (entry->mem_obj->inmem_hi == 0) { ErrorState *err; debug(81, 2) ("icapReadReply: FD %d: generating error page\n", fd); err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->request = requestLink((request_t *) request); err->xerrno = errno; errorAppendEntry(entry, err); comm_close(fd); } else { debug(81, 2) ("icapReadReply: FD %d: just calling comm_close()\n", fd); comm_close(fd); } return; } if (icapReadReply2(icap) < 0) comm_close(fd); }
static inline void modify_request(clientHttpRequest * http) { debug(97, 3)("modify_request: start, uri=[%s]\n", http->uri); request_t* old_request = http->request; request_t* new_request = urlParse(old_request->method, http->uri); safe_free(http->uri); if (new_request) { safe_free(http->uri); http->uri = xstrdup(urlCanonical(new_request)); if(!http->log_uri) http->log_uri = xstrdup(urlCanonicalClean(old_request)); new_request->http_ver = old_request->http_ver; httpHeaderAppend(&new_request->header, &old_request->header); new_request->client_addr = old_request->client_addr; new_request->client_port = old_request->client_port; #if FOLLOW_X_FORWARDED_FOR new_request->indirect_client_addr = old_request->indirect_client_addr; #endif /* FOLLOW_X_FORWARDED_FOR */ new_request->my_addr = old_request->my_addr; new_request->my_port = old_request->my_port; new_request->flags = old_request->flags; new_request->flags.redirected = 1; if (old_request->auth_user_request) { new_request->auth_user_request = old_request->auth_user_request; authenticateAuthUserRequestLock(new_request->auth_user_request); } if (old_request->body_reader) { new_request->body_reader = old_request->body_reader; new_request->body_reader_data = old_request->body_reader_data; old_request->body_reader = NULL; old_request->body_reader_data = NULL; } new_request->content_length = old_request->content_length; if (strBuf(old_request->extacl_log)) new_request->extacl_log = stringDup(&old_request->extacl_log); if (old_request->extacl_user) new_request->extacl_user = xstrdup(old_request->extacl_user); if (old_request->extacl_passwd) new_request->extacl_passwd = xstrdup(old_request->extacl_passwd); if(old_request->cc_request_private_data) { new_request->cc_request_private_data = old_request->cc_request_private_data; old_request->cc_request_private_data = NULL; } requestUnlink(old_request); http->request = requestLink(new_request); } }
/* * Function: errorCon * * Abstract: This function creates a ErrorState object. */ ErrorState * errorCon(err_type type, http_status status, request_t * request) { ErrorState *err; err = cbdataAlloc(ErrorState); err->page_id = type; /* has to be reset manually if needed */ err->type = type; err->http_status = status; if (request != NULL) { err->request = requestLink(request); err->src_addr = request->client_addr; } return err; }
static void sslConnectDone(int fdnotused, int status, void *data) { SslStateData *sslState = data; request_t *request = sslState->request; ErrorState *err = NULL; if (status == COMM_ERR_DNS) { debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host); err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND); err->request = requestLink(request); err->dnsserver_msg = xstrdup(dns_error_message); err->callback = sslErrorComplete; err->callback_data = sslState; errorSend(sslState->client.fd, err); } else if (status != COMM_OK) { err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); err->xerrno = errno; err->host = xstrdup(sslState->host); err->port = sslState->port; err->request = requestLink(request); err->callback = sslErrorComplete; err->callback_data = sslState; errorSend(sslState->client.fd, err); } else { if (sslState->servers->peer) sslProxyConnected(sslState->server.fd, sslState); else sslConnected(sslState->server.fd, sslState); commSetTimeout(sslState->server.fd, Config.Timeout.read, sslTimeout, sslState); #if DELAY_POOLS commSetDefer(sslState->server.fd, sslDeferServerRead, sslState); #endif } }
static void sslPeerSelectComplete(FwdServer * fs, void *data) { SslStateData *sslState = data; request_t *request = sslState->request; peer *g = NULL; if (fs == NULL) { ErrorState *err; err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); err->request = requestLink(sslState->request); err->callback = sslErrorComplete; err->callback_data = sslState; errorSend(sslState->client.fd, err); return; } sslState->servers = fs; sslState->host = fs->peer ? fs->peer->host : request->host; if (fs->peer == NULL) { sslState->port = request->port; } else if (fs->peer->http_port != 0) { sslState->port = fs->peer->http_port; } else if ((g = peerFindByName(fs->peer->host))) { sslState->port = g->http_port; } else { sslState->port = CACHE_HTTP_PORT; } if (fs->peer) { sslState->request->peer_login = fs->peer->login; sslState->request->flags.proxying = 1; } else { sslState->request->flags.proxying = 0; } #if DELAY_POOLS /* no point using the delayIsNoDelay stuff since ssl is nice and simple */ if (g && g->options.no_delay && sslState->delay_id) { delayUnregisterDelayIdPtr(&sslState->delay_id); sslState->delay_id = 0; } #endif hierarchyNote(&sslState->request->hier, fs->peer ? fs->code : DIRECT, sslState->host); commConnectStart(sslState->server.fd, sslState->host, sslState->port, sslConnectDone, sslState); }
static request_t * modifyRequestUrlstoreUrl(const char *url) { request_t *new_request = NULL; new_request = urlParse(METHOD_GET, (char*)url); char *new_storeurl = xstrdup((const char *)url); char* str = strchr(new_storeurl, '?'); if (str) { debug(207, 3)("modify_request_url_storeurl rid_question: storeurl=[%s] have question\n", new_storeurl); *str = '\0'; } new_request->store_url = xstrdup((const char *)new_storeurl); debug(207, 3)("after modifyRequestUrlstoreUrl url=%s,storeurl=%s,uri=%s\n",urlCanonical(new_request),new_request->store_url,strBuf(new_request->urlpath)); return requestLink(new_request); }
void icapConnectOver(int fd, int status, void *data) { ErrorState *err; IcapStateData *icap = data; debug(81, 3) ("icapConnectOver: FD %d, status=%d\n", fd, status); icap->flags.connect_pending = 0; if (status < 0) { err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; err->request = requestLink(icap->request); errorAppendEntry(icap->respmod.entry, err); comm_close(fd); debug(81, 3) ("icapConnectOver: status < 0, unreachable=1\n"); icapOptSetUnreachable(icap->current_service); return; } commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0); }
static void peerMonitorRequest(void *data) { PeerMonitor *pm = data; char *url; request_t *req; if (!cbdataValid(pm->peer)) { cbdataFree(pm); return; } url = pm->peer->monitor.url; if (!url) { cbdataFree(pm); return; } req = urlParse(METHOD_GET, url); if (!req) { debug(DBG, 1) ("peerMonitorRequest: Failed to parse URL '%s' for cache_peer %s\n", url, pm->peer->name); cbdataFree(pm); return; } pm->last_probe = squid_curtime; pm->running.timeout_set = 1; eventAdd(pm->name, peerMonitorTimeout, pm, (double) (pm->peer->monitor.timeout ? pm->peer->monitor.timeout : pm->peer->monitor.interval), 0); httpHeaderPutStr(&req->header, HDR_ACCEPT, "*/*"); httpHeaderPutStr(&req->header, HDR_USER_AGENT, full_appname_string); if (pm->peer->login) xstrncpy(req->login, pm->peer->login, MAX_LOGIN_SZ); pm->running.req = requestLink(req); pm->running.e = storeCreateEntry(url, req->flags, req->method); pm->running.sc = storeClientRegister(pm->running.e, pm); pm->running.buf = memAllocate(MEM_4K_BUF); fwdStartPeer(pm->peer, pm->running.e, pm->running.req); storeClientCopy(pm->running.sc, pm->running.e, 0, 0, 4096, pm->running.buf, peerMonitorFetchReplyHeaders, pm); return; }
static void authenticateNegotiateAuthenticateUser(auth_user_request_t * auth_user_request, request_t * request, ConnStateData * conn, http_hdr_type type) { const char *proxy_auth, *blob; auth_user_t *auth_user; negotiate_request_t *negotiate_request; auth_user = auth_user_request->auth_user; assert(auth_user); assert(auth_user->auth_type == AUTH_NEGOTIATE); assert(auth_user->scheme_data != NULL); assert(auth_user_request->scheme_data != NULL); negotiate_request = auth_user_request->scheme_data; /* Check that we are in the client side, where we can generate * auth challenges */ if (!conn) { negotiate_request->auth_state = AUTHENTICATE_STATE_FAILED; debug(29, 1) ("authenticateNegotiateAuthenticateUser: attempt to perform authentication without a connection!\n"); return; } if (negotiate_request->waiting) { debug(29, 1) ("authenticateNegotiateAuthenticateUser: waiting for helper reply!\n"); return; } if (negotiate_request->server_blob) { debug(29, 2) ("authenticateNegotiateAuthenticateUser: need to challenge client '%s'!\n", negotiate_request->server_blob); return; } /* get header */ proxy_auth = httpHeaderGetStr(&request->header, type); blob = proxy_auth; while (xisspace(*blob) && *blob) blob++; while (!xisspace(*blob) && *blob) blob++; while (xisspace(*blob) && *blob) blob++; switch (negotiate_request->auth_state) { case AUTHENTICATE_STATE_NONE: /* we've received a negotiate request. pass to a helper */ debug(29, 9) ("authenticateNegotiateAuthenticateUser: auth state negotiate none. %s\n", proxy_auth); negotiate_request->auth_state = AUTHENTICATE_STATE_INITIAL; safe_free(negotiate_request->client_blob); negotiate_request->client_blob = xstrdup(blob); conn->auth_type = AUTH_NEGOTIATE; conn->auth_user_request = auth_user_request; negotiate_request->conn = conn; /* and lock for the connection duration */ debug(29, 9) ("authenticateNegotiateAuthenticateUser: Locking auth_user from the connection.\n"); authenticateAuthUserRequestLock(auth_user_request); negotiate_request->request = requestLink(request); return; break; case AUTHENTICATE_STATE_INITIAL: debug(29, 1) ("authenticateNegotiateAuthenticateUser: need to ask helper!\n"); return; break; case AUTHENTICATE_STATE_NEGOTIATE: /* we should have received a blob from the clien. pass it to the same * helper process */ debug(29, 9) ("authenticateNegotiateAuthenticateUser: auth state challenge with header %s.\n", proxy_auth); /* do a cache lookup here. If it matches it's a successful negotiate * challenge - release the helper and use the existing auth_user * details. */ safe_free(negotiate_request->client_blob); negotiate_request->client_blob = xstrdup(blob); if (negotiate_request->request) requestUnlink(negotiate_request->request); negotiate_request->request = requestLink(request); return; break; case AUTHENTICATE_STATE_DONE: fatal("authenticateNegotiateAuthenticateUser: unexpect auth state DONE! Report a bug to the squid developers.\n"); break; case AUTHENTICATE_STATE_FAILED: /* we've failed somewhere in authentication */ debug(29, 9) ("authenticateNegotiateAuthenticateUser: auth state negotiate failed. %s\n", proxy_auth); return; } return; }
/* ask store for a digest */ static void peerDigestRequest(PeerDigest * pd) { peer *p = pd->peer; StoreEntry *e, *old_e; char *url; const cache_key *key; request_t *req; DigestFetchState *fetch = NULL; pd->req_result = NULL; pd->flags.requested = 1; /* compute future request components */ if (p->digest_url) url = xstrdup(p->digest_url); else url = internalRemoteUri(p->host, p->http_port, "/squid-internal-periodic/", StoreDigestFileName); key = storeKeyPublic(url, METHOD_GET); debug(72, 2) ("peerDigestRequest: %s key: %s\n", url, storeKeyText(key)); req = urlParse(METHOD_GET, url); assert(req); /* add custom headers */ assert(!req->header.len); httpHeaderPutStr(&req->header, HDR_ACCEPT, StoreDigestMimeStr); httpHeaderPutStr(&req->header, HDR_ACCEPT, "text/html"); if (p->login) xstrncpy(req->login, p->login, MAX_LOGIN_SZ); /* create fetch state structure */ fetch = memAllocate(MEM_DIGEST_FETCH_STATE); cbdataAdd(fetch, memFree, MEM_DIGEST_FETCH_STATE); fetch->request = requestLink(req); fetch->pd = pd; fetch->offset = 0; /* update timestamps */ fetch->start_time = squid_curtime; pd->times.requested = squid_curtime; pd_last_req_time = squid_curtime; req->flags.cachable = 1; /* the rest is based on clientProcessExpired() */ req->flags.refresh = 1; old_e = fetch->old_entry = storeGet(key); if (old_e) { debug(72, 5) ("peerDigestRequest: found old entry\n"); storeLockObject(old_e); storeCreateMemObject(old_e, url, url); storeClientListAdd(old_e, fetch); } e = fetch->entry = storeCreateEntry(url, url, req->flags, req->method); assert(EBIT_TEST(e->flags, KEY_PRIVATE)); storeClientListAdd(e, fetch); /* set lastmod to trigger IMS request if possible */ if (old_e) e->lastmod = old_e->lastmod; /* push towards peer cache */ debug(72, 3) ("peerDigestRequest: forwarding to fwdStart...\n"); fwdStart(-1, e, req); cbdataLock(fetch); cbdataLock(fetch->pd); storeClientCopy(e, 0, 0, 4096, memAllocate(MEM_4K_BUF), peerDigestFetchReply, fetch); }
void sslStart(int fd, const char *url, request_t * request, size_t * size_ptr) { /* Create state structure. */ SslStateData *sslState = NULL; int sock; ErrorState *err = NULL; debug(26, 3) ("sslStart: '%s %s'\n", RequestMethodStr[request->method], url); Counter.server.all.requests++; Counter.server.other.requests++; /* Create socket. */ sock = comm_open(SOCK_STREAM, 0, Config.Addrs.tcp_outgoing, 0, COMM_NONBLOCKING, url); if (sock == COMM_ERROR) { debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; err->request = requestLink(request); errorSend(fd, err); return; } sslState = xcalloc(1, sizeof(SslStateData)); cbdataAdd(sslState, cbdataXfree, 0); #if DELAY_POOLS sslState->delay_id = delayClient(request); delayRegisterDelayIdPtr(&sslState->delay_id); #endif sslState->url = xstrdup(url); sslState->request = requestLink(request); sslState->size_ptr = size_ptr; sslState->client.fd = fd; sslState->server.fd = sock; sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF); sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF); comm_add_close_handler(sslState->server.fd, sslServerClosed, sslState); comm_add_close_handler(sslState->client.fd, sslClientClosed, sslState); commSetTimeout(sslState->client.fd, Config.Timeout.lifetime, sslTimeout, sslState); commSetTimeout(sslState->server.fd, Config.Timeout.connect, sslTimeout, sslState); peerSelect(request, NULL, sslPeerSelectComplete, sslState); /* * Disable the client read handler until peer selection is complete * Take control away from client_side.c. */ commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0); }
static void icapRespModReadReply(int fd, void *data) { IcapStateData *icap = data; int version_major, version_minor; const char *str_status; int x; int status = 0; int isIcap = 0; int directResponse = 0; ErrorState *err; const char *start; const char *end; debug(81, 5) ("icapRespModReadReply: FD %d data = %p\n", fd, data); statCounter.syscalls.sock.reads++; x = icapReadHeader(fd, icap, &isIcap); if (x < 0) { /* Did not find a proper ICAP response */ debug(81, 3) ("ICAP : Error path!\n"); err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->request = requestLink(icap->request); err->xerrno = errno; errorAppendEntry(icap->respmod.entry, err); comm_close(fd); return; } if (x == 0) { /* * Waiting for more headers. Schedule new read hander, but * don't reset timeout. */ commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0); return; } /* * Parse the ICAP header */ assert(icap->icap_hdr.size); debug(81, 3) ("Parse icap header : <%s>\n", icap->icap_hdr.buf); if ((status = icapParseStatusLine(icap->icap_hdr.buf, icap->icap_hdr.size, &version_major, &version_minor, &str_status)) < 0) { debug(81, 1) ("BAD ICAP status line <%s>\n", icap->icap_hdr.buf); /* is this correct in case of ICAP protocol error? */ err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->request = requestLink(icap->request); err->xerrno = errno; errorAppendEntry(icap->respmod.entry, err); comm_close(fd); return; }; /* OK here we have responce. Lets stop filling the * icap->respmod.resp_copy buffer .... */ icap->flags.copy_response = 0; icapSetKeepAlive(icap, icap->icap_hdr.buf); #if ICAP_PREVIEW if (icap->flags.wait_for_preview_reply) { if (100 == status) { debug(81, 5) ("icapRespModReadReply: 100 Continue received\n"); icap->flags.wait_for_preview_reply = 0; /* if http_server_eof * call again icapSendRespMod to handle data that * was received while waiting for this ICAP response * else let http to call icapSendRespMod when new data arrived */ if (icap->flags.http_server_eof) icapSendRespMod(icap, NULL, 0, 0); /* * reset the header to send the rest of the preview */ if (!memBufIsNull(&icap->icap_hdr)) memBufReset(&icap->icap_hdr); /*We do n't need it any more .......*/ if (!memBufIsNull(&icap->respmod.resp_copy)) memBufClean(&icap->respmod.resp_copy); return; } if (204 == status) { debug(81, 5) ("icapRespModReadReply: 204 No modification received\n"); icap->flags.wait_for_preview_reply = 0; } } #endif /*ICAP_PREVIEW */ #if SUPPORT_ICAP_204 || ICAP_PREVIEW if (204 == status) { debug(81, 3) ("got 204 status from ICAP server\n"); debug(81, 3) ("setting icap->flags.no_content\n"); icap->flags.no_content = 1; /* * copy the response already written to the ICAP server */ debug(81, 3) ("copying %d bytes from resp_copy to chunk_buf\n", icap->respmod.resp_copy.size); memBufAppend(&icap->chunk_buf, icap->respmod.resp_copy.buf, icap->respmod.resp_copy.size); icap->respmod.resp_copy.size = 0; if (icapReadReply2(icap) < 0) comm_close(fd); /* * XXX ideally want to clean icap->respmod.resp_copy here * XXX ideally want to "close" ICAP server connection here * OK do it.... */ if (!memBufIsNull(&icap->respmod.resp_copy)) memBufClean(&icap->respmod.resp_copy); return; } #endif if (200 != status) { debug(81, 1) ("Unsupported status '%d' from ICAP server\n", status); /* Did not find a proper ICAP response */ err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->request = requestLink(icap->request); err->xerrno = errno; errorAppendEntry(icap->respmod.entry, err); comm_close(fd); return; } if (icapFindHeader(icap->icap_hdr.buf, "Encapsulated:", &start, &end)) { icapParseEncapsulated(icap, start, end); } else { debug(81, 1) ("WARNING: icapRespModReadReply() did not find 'Encapsulated' header\n"); } if (icap->enc.res_hdr > -1) directResponse = 1; else if (icap->enc.res_body > -1) directResponse = 1; else directResponse = 0; /* * "directResponse" is the normal case here. If we don't have * a response header or body, it is an error. */ if (!directResponse) { /* Did not find a proper ICAP response */ debug(81, 3) ("ICAP : Error path!\n"); err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->request = requestLink(icap->request); err->xerrno = errno; errorAppendEntry(icap->respmod.entry, err); comm_close(fd); return; } /* got the reply, no need to come here again */ icap->flags.wait_for_reply = 0; icap->flags.got_reply = 1; /* Next, gobble any data before the HTTP response starts */ if (icap->enc.res_hdr > -1) icap->bytes_to_gobble = icap->enc.res_hdr; commSetSelect(fd, COMM_SELECT_READ, icapRespModGobble, icap, 0); }
static void icapSendRespModDone(int fd, char *bufnotused, size_t size, int errflag, void *data) { IcapStateData *icap = data; ErrorState *err; icap->flags.write_pending = 0; debug(81, 5) ("icapSendRespModDone: FD %d: size %d: errflag %d.\n", fd, size, errflag); if (size > 0) { fd_bytes(fd, size, FD_WRITE); kb_incr(&statCounter.icap.all.kbytes_out, size); } if (errflag == COMM_ERR_CLOSING) return; if (errflag) { err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; if (cbdataValid(icap)) err->request = requestLink(icap->request); storeEntryReset(icap->respmod.entry); errorAppendEntry(icap->respmod.entry, err); comm_close(fd); return; } if (EBIT_TEST(icap->respmod.entry->flags, ENTRY_ABORTED)) { debug(81, 3) ("icapSendRespModDone: Entry Aborded\n"); comm_close(fd); return; } if (icap->flags.send_zero_chunk) { debug(81, 3) ("icapSendRespModDone: I'm supposed to send zero chunk now\n"); icap->flags.send_zero_chunk = 0; icapSendRespMod(icap, NULL, 0, 1); return; } if (icap->flags.wait_for_preview_reply || icap->flags.wait_for_reply) { /* Schedule reading the ICAP response */ debug(81, 3) ("icapSendRespModDone: FD %d: commSetSelect on read icapRespModReadReply.\n", fd); commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0); #if 1 commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap); #else if (icap->flags.wait_for_preview_reply || icap->flags.http_server_eof) { /* * Set the read timeout only after all data has been sent * or we are waiting for a preview response * If the ICAP server does not return any data till all data * has been sent, we are likely to hit the timeout for large * HTTP bodies */ commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap); } #endif } }
/* wait for full http headers to be received then parse them */ static void peerDigestFetchReply(void *data, char *buf, ssize_t size) { DigestFetchState *fetch = data; PeerDigest *pd = fetch->pd; size_t hdr_size; assert(pd && buf); assert(!fetch->offset); if (peerDigestFetchedEnough(fetch, buf, size, "peerDigestFetchReply")) return; if ((hdr_size = headersEnd(buf, size))) { http_status status; HttpReply *reply = fetch->entry->mem_obj->reply; assert(reply); httpReplyParse(reply, buf, hdr_size); status = reply->sline.status; debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %d (%+d)\n", strBuf(pd->host), status, reply->expires, reply->expires - squid_curtime); /* this "if" is based on clientHandleIMSReply() */ if (status == HTTP_NOT_MODIFIED) { request_t *r = NULL; /* our old entry is fine */ assert(fetch->old_entry); if (!fetch->old_entry->mem_obj->request) fetch->old_entry->mem_obj->request = r = requestLink(fetch->entry->mem_obj->request); assert(fetch->old_entry->mem_obj->request); httpReplyUpdateOnNotModified(fetch->old_entry->mem_obj->reply, reply); storeTimestampsSet(fetch->old_entry); /* get rid of 304 reply */ storeUnregister(fetch->entry, fetch); storeUnlockObject(fetch->entry); fetch->entry = fetch->old_entry; fetch->old_entry = NULL; /* preserve request -- we need its size to update counters */ /* requestUnlink(r); */ /* fetch->entry->mem_obj->request = NULL; */ } else if (status == HTTP_OK) { /* get rid of old entry if any */ if (fetch->old_entry) { debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n"); storeUnregister(fetch->old_entry, fetch); storeReleaseRequest(fetch->old_entry); storeUnlockObject(fetch->old_entry); fetch->old_entry = NULL; } } else { /* some kind of a bug */ peerDigestFetchAbort(fetch, buf, httpStatusLineReason(&reply->sline)); return; } /* must have a ready-to-use store entry if we got here */ /* can we stay with the old in-memory digest? */ if (status == HTTP_NOT_MODIFIED && fetch->pd->cd) peerDigestFetchStop(fetch, buf, "Not modified"); else storeClientCopy(fetch->entry, /* have to swap in */ 0, 0, SM_PAGE_SIZE, buf, peerDigestSwapInHeaders, fetch); } else { /* need more data, do we have space? */ if (size >= SM_PAGE_SIZE) peerDigestFetchAbort(fetch, buf, "reply header too big"); else storeClientCopy(fetch->entry, size, 0, SM_PAGE_SIZE, buf, peerDigestFetchReply, fetch); } }
static int icapReadReply2(IcapStateData * icap) { StoreEntry *entry = icap->respmod.entry; const request_t *request = icap->request; debug(81, 3) ("icapReadReply2\n"); if (icap->chunk_buf.size == 0 && entry->mem_obj->inmem_hi == 0) { ErrorState *err; err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE); err->xerrno = errno; err->request = requestLink((request_t *) request); errorAppendEntry(entry, err); icap->flags.http_server_eof = 1; return -1; } if (icap->chunk_buf.size == 0) { /* Retrieval done. */ if (icapHttpReplyHdrState(icap) < 2) icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf, icap->chunk_buf.size); icap->flags.http_server_eof = 1; icapReadReply3(icap); return 0; } if (icapHttpReplyHdrState(icap) == 0) { int expect = icapExpectedHttpReplyHdrSize(icap); int so_far = icap->http_header_bytes_read_so_far; int needed = expect - so_far; debug(81, 3) ("expect=%d\n", expect); debug(81, 3) ("so_far=%d\n", so_far); debug(81, 3) ("needed=%d\n", needed); assert(needed < 0 || needed >= 0); if (0 > expect) { icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf, icap->chunk_buf.size); } else if (0 == expect) { /* * this icap reply doesn't give us new HTTP headers * so we must copy them from our copy */ debug(81, 1) ("WARNING: untested code at %s:%d\n", __FILE__, __LINE__); if(icap->respmod.req_hdr_copy.size){/*For HTTP 0.9 we do not have headers*/ storeAppend(entry, icap->respmod.req_hdr_copy.buf, icap->respmod.req_hdr_copy.size); } icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf, icap->chunk_buf.size); assert(icapHttpReplyHdrState(icap) == 2); icap->chunk_size = 0;/*we are ready to read chunks of data now....*/ } else if (needed) { icapProcessHttpReplyHeader(icap, icap->chunk_buf.buf, icap->chunk_buf.size); if (icap->chunk_buf.size >= needed) { storeAppend(entry, icap->chunk_buf.buf, needed); so_far += needed; xmemmove(icap->chunk_buf.buf, icap->chunk_buf.buf + needed, icap->chunk_buf.size - needed); icap->chunk_buf.size -= needed; assert(icapHttpReplyHdrState(icap) == 2); icap->chunk_size = 0; } else { /* * We don't have the full HTTP reply headers yet, so keep * the partial reply buffered in 'chunk_buf' and wait * for more. */ debug(81,3)("We don't have full Http headers.Schedule a new read\n"); commSetSelect(icap->icap_fd, COMM_SELECT_READ, icapReadReply, icap, 0); } } icap->http_header_bytes_read_so_far = so_far; } debug(81, 3) ("%s:%d: icap->chunk_buf.size=%d\n", __FILE__, __LINE__, (int) icap->chunk_buf.size); debug(81, 3) ("%s:%d: flags.no_content=%d\n", __FILE__, __LINE__, icap->flags.no_content); if (icap->flags.no_content) { /* data from http.c is not chunked */ if (!EBIT_TEST(entry->flags, ENTRY_ABORTED)) { debug(81, 3) ("copying %d bytes from chunk_buf to entry\n", icap->chunk_buf.size); storeAppend(entry, icap->chunk_buf.buf, icap->chunk_buf.size); icap->chunk_buf.size = 0; } } else if (2 == icapHttpReplyHdrState(icap)) { if (icap->chunk_buf.size) icapParseChunkedBody(icap, (STRCB *) storeAppend, entry); } icapReadReply3(icap); return 0; }
static void urnHandleReply(void *data, char *buf, ssize_t size) { UrnState *urnState = data; StoreEntry *e = urnState->entry; StoreEntry *urlres_e = urnState->urlres_e; char *s = NULL; size_t k; HttpReply *rep; url_entry *urls; url_entry *u; url_entry *min_u; MemBuf mb; ErrorState *err; int i; int urlcnt = 0; http_version_t version; debug(52, 3) ("urnHandleReply: Called with size=%d.\n", (int) size); if (EBIT_TEST(urlres_e->flags, ENTRY_ABORTED)) { memFree(buf, MEM_4K_BUF); return; } if (size == 0) { memFree(buf, MEM_4K_BUF); return; } else if (size < 0) { memFree(buf, MEM_4K_BUF); return; } if (urlres_e->store_status == STORE_PENDING && size < SM_PAGE_SIZE) { storeClientCopy(urnState->sc, urlres_e, size, 0, SM_PAGE_SIZE, buf, urnHandleReply, urnState); return; } /* we know its STORE_OK */ k = headersEnd(buf, size); if (0 == k) { debug(52, 1) ("urnHandleReply: didn't find end-of-headers for %s\n", storeUrl(e)); return; } s = buf + k; assert(urlres_e->mem_obj->reply); httpReplyParse(urlres_e->mem_obj->reply, buf, k); debug(52, 3) ("mem->reply exists, code=%d.\n", urlres_e->mem_obj->reply->sline.status); if (urlres_e->mem_obj->reply->sline.status != HTTP_OK) { debug(52, 3) ("urnHandleReply: failed.\n"); err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND); err->request = requestLink(urnState->request); err->url = xstrdup(storeUrl(e)); errorAppendEntry(e, err); return; } while (xisspace(*s)) s++; urls = urnParseReply(s, urnState->request->method); for (i = 0; NULL != urls[i].url; i++) urlcnt++; debug(53, 3) ("urnFindMinRtt: Counted %d URLs\n", i); if (urls == NULL) { /* unkown URN error */ debug(52, 3) ("urnTranslateDone: unknown URN %s\n", storeUrl(e)); err = errorCon(ERR_URN_RESOLVE, HTTP_NOT_FOUND); err->request = requestLink(urnState->request); err->url = xstrdup(storeUrl(e)); errorAppendEntry(e, err); return; } min_u = urnFindMinRtt(urls, urnState->request->method, NULL); qsort(urls, urlcnt, sizeof(*urls), url_entry_sort); storeBuffer(e); memBufDefInit(&mb); memBufPrintf(&mb, "<TITLE>Select URL for %s</TITLE>\n" "<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n" "<H2>Select URL for %s</H2>\n" "<TABLE BORDER=\"0\" WIDTH=\"100%%\">\n", storeUrl(e), storeUrl(e)); for (i = 0; i < urlcnt; i++) { u = &urls[i]; debug(52, 3) ("URL {%s}\n", u->url); memBufPrintf(&mb, "<TR><TD><A HREF=\"%s\">%s</A></TD>", u->url, u->url); if (urls[i].rtt > 0) memBufPrintf(&mb, "<TD align=\"right\">%4d <it>ms</it></TD>", u->rtt); else memBufPrintf(&mb, "<TD align=\"right\">Unknown</TD>"); memBufPrintf(&mb, "<TD>%s</TD></TR>\n", u->flags.cached ? " [cached]" : " "); } memBufPrintf(&mb, "</TABLE>" "<HR noshade size=\"1px\">\n" "<ADDRESS>\n" "Generated by %s@%s\n" "</ADDRESS>\n", full_appname_string, getMyHostname()); rep = e->mem_obj->reply; httpReplyReset(rep); httpBuildVersion(&version, 1, 0); httpReplySetHeaders(rep, version, HTTP_MOVED_TEMPORARILY, NULL, "text/html", mb.size, 0, squid_curtime); if (urnState->flags.force_menu) { debug(51, 3) ("urnHandleReply: forcing menu\n"); } else if (min_u) { httpHeaderPutStr(&rep->header, HDR_LOCATION, min_u->url); } httpBodySet(&rep->body, &mb); httpReplySwapOut(rep, e); storeComplete(e); memFree(buf, MEM_4K_BUF); for (i = 0; i < urlcnt; i++) { safe_free(urls[i].url); safe_free(urls[i].host); } safe_free(urls); /* mb was absorbed in httpBodySet call, so we must not clean it */ storeUnregister(urnState->sc, urlres_e, urnState); storeUnlockObject(urlres_e); storeUnlockObject(urnState->entry); requestUnlink(urnState->request); requestUnlink(urnState->urlres_r); cbdataFree(urnState); }
void storeUpdate(StoreEntry * entry, request_t * request) { StoreUpdateState *state; request_flags flags = null_request_flags; const char *vary; if (!request) request = entry->mem_obj->request; if (EBIT_TEST(entry->flags, KEY_PRIVATE)) return; /* Nothing to do here... */ if (!Config.onoff.update_headers) return; /* Disabled */ CBDATA_INIT_TYPE_FREECB(StoreUpdateState, free_StoreUpdateState); if (entry->mem_obj) entry->mem_obj->refresh_timestamp = 0; state = cbdataAlloc(StoreUpdateState); state->oldentry = entry; storeLockObject(state->oldentry); flags.cachable = 1; state->newentry = storeCreateEntry(storeUrl(entry), flags, entry->mem_obj->method); storeRegisterAbort(state->newentry, storeUpdateAbort, state); state->sc = storeClientRegister(state->oldentry, state); state->offset = entry->mem_obj->reply->hdr_sz; storeBuffer(state->newentry); httpReplySwapOut(httpReplyClone(entry->mem_obj->reply), state->newentry); state->newentry->timestamp = entry->timestamp; state->newentry->lastref = entry->lastref; state->newentry->expires = entry->expires; state->newentry->lastmod = entry->lastmod; state->newentry->refcount = entry->refcount; if (request) { state->newentry->mem_obj->request = requestLink(request); vary = httpMakeVaryMark(request, state->newentry->mem_obj->reply); if (vary) { state->newentry->mem_obj->vary_headers = xstrdup(vary); if (strBuf(request->vary_encoding)) state->newentry->mem_obj->vary_encoding = xstrdup(strBuf(request->vary_encoding)); } } else { if (entry->mem_obj->vary_headers) state->newentry->mem_obj->vary_headers = xstrdup(entry->mem_obj->vary_headers); if (entry->mem_obj->vary_encoding) state->newentry->mem_obj->vary_encoding = xstrdup(entry->mem_obj->vary_encoding); } storeSetPublicKey(state->newentry); storeBufferFlush(state->newentry); if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { /* * the above storeBufferFlush() call could ABORT this entry, * in that case, there's nothing for us to do. */ debug(20, 1) ("storeUpdate: Aborted on write\n"); return; } storeClientCopy(state->sc, state->oldentry, state->offset, state->offset, sizeof(state->buf), state->buf, storeUpdateCopy, state); return; }
IcapStateData * icapRespModStart(icap_service_t type, request_t * request, StoreEntry * entry, http_state_flags http_flags) { IcapStateData *icap = NULL; CNCB *theCallback = NULL; icap_service *service = NULL; debug(81, 3) ("icapRespModStart: type=%d\n", (int) type); assert(type >= 0 && type < ICAP_SERVICE_MAX); service = icapService(type, request); if (!service) { debug(81, 3) ("icapRespModStart: no service found\n"); return NULL; /* no service found */ } if (service->unreachable) { if (service->bypass) { debug(81, 5) ("icapRespModStart: BYPASS because service unreachable: %s\n", service->uri); return NULL; } else { debug(81, 5) ("icapRespModStart: ERROR because service unreachable: %s\n", service->uri); return (IcapStateData *) - 1; } } switch (type) { /* TODO: When we support more than ICAP_SERVICE_RESPMOD_PRECACHE, we needs to change * this switch, because callbacks isn't keep */ case ICAP_SERVICE_RESPMOD_PRECACHE: theCallback = icapConnectOver; break; default: fatalf("icapRespModStart: unsupported service type '%s'\n", icap_service_type_str[type]); break; } icap = icapAllocate(); if (!icap) { debug(81, 3) ("icapRespModStart: icapAllocate() failed\n"); return NULL; } icap->request = requestLink(request); icap->respmod.entry = entry; if (entry) storeLockObject(entry); icap->http_flags = http_flags; memBufDefInit(&icap->respmod.buffer); memBufDefInit(&icap->chunk_buf); icap->current_service = service; icap->preview_size = service->preview; /* * Don't create socket to the icap server now, but only for the first * packet receive from the http server. This will resolve all timeout * between the web server and icap server. */ debug(81, 3) ("icapRespModStart: setting connect_requested to 0\n"); icap->flags.connect_requested = 0; /* * make a copy the HTTP response that we send to the ICAP server in * case it turns out to be a 204 */ #ifdef SUPPORT_ICAP_204 icap->flags.copy_response = 1; #elif ICAP_PREVIEW if(preview_size < 0 || !Config.icapcfg.preview_enable) icap->flags.copy_response = 0; else icap->flags.copy_response = 1; #else icap->flags.copy_response = 0; #endif statCounter.icap.all.requests++; debug(81, 3) ("icapRespModStart: returning %p\n", icap); return icap; }
/* wait for full http headers to be received */ static void peerDigestFetchReply(void *data, mem_node_ref nr, ssize_t size) { const char *buf = nr.node->data + nr.offset; DigestFetchState *fetch = data; PeerDigest *pd = fetch->pd; http_status status; HttpReply *reply; assert(pd && buf); assert(!fetch->offset); assert(size <= nr.node->len - nr.offset); if (peerDigestFetchedEnough(fetch, size, "peerDigestFetchReply")) goto finish; reply = fetch->entry->mem_obj->reply; assert(reply); status = reply->sline.status; debug(72, 3) ("peerDigestFetchReply: %s status: %d, expires: %ld (%+d)\n", strBuf(pd->host), status, (long int) reply->expires, (int) (reply->expires - squid_curtime)); /* this "if" is based on clientHandleIMSReply() */ if (status == HTTP_NOT_MODIFIED) { request_t *r = NULL; /* our old entry is fine */ assert(fetch->old_entry); if (!fetch->old_entry->mem_obj->request) fetch->old_entry->mem_obj->request = r = requestLink(fetch->entry->mem_obj->request); assert(fetch->old_entry->mem_obj->request); httpReplyUpdateOnNotModified(fetch->old_entry->mem_obj->reply, reply); storeTimestampsSet(fetch->old_entry); /* get rid of 304 reply */ storeClientUnregister(fetch->sc, fetch->entry, fetch); storeUnlockObject(fetch->entry); /* And prepare to swap in old entry if needed */ fetch->entry = fetch->old_entry; fetch->old_entry = NULL; fetch->sc = fetch->old_sc; fetch->old_sc = NULL; /* preserve request -- we need its size to update counters */ /* requestUnlink(r); */ /* fetch->entry->mem_obj->request = NULL; */ } else if (status == HTTP_OK) { /* get rid of old entry if any */ if (fetch->old_entry) { debug(72, 3) ("peerDigestFetchReply: got new digest, releasing old one\n"); storeClientUnregister(fetch->old_sc, fetch->old_entry, fetch); storeReleaseRequest(fetch->old_entry); storeUnlockObject(fetch->old_entry); fetch->old_entry = NULL; } } else { /* some kind of a bug */ peerDigestFetchAbort(fetch, httpStatusLineReason(&reply->sline)); goto finish; } /* must have a ready-to-use store entry if we got here */ /* can we stay with the old in-memory digest? */ if (status == HTTP_NOT_MODIFIED && fetch->pd->cd) peerDigestFetchStop(fetch, "Not modified"); else storeClientRef(fetch->sc, fetch->entry, /* have to swap in */ 0, 0, SM_PAGE_SIZE, peerDigestSwapInHeaders, fetch); finish: stmemNodeUnref(&nr); }