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 gopherTimeout(int fd, void *data) { GopherStateData *gopherState = data; StoreEntry *entry = gopherState->entry; debug(10, 4) ("gopherTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); fwdFail(gopherState->fwdState, errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT)); comm_close(fd); }
/* This will be called when socket lifetime is expired. */ static void waisTimeout(int fd, void *data) { WaisStateData *waisState = data; StoreEntry *entry = waisState->entry; debug(24, 4) ("waisTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); if (entry->store_status == STORE_PENDING) { fwdFail(waisState->fwd, errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT, waisState->fwd->request)); } comm_close(fd); }
/* * 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 void whoisReadReply(int fd, void *data) { WhoisState *p = data; StoreEntry *entry = p->entry; char *buf = memAllocate(MEM_4K_BUF); MemObject *mem = entry->mem_obj; int len; statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, 4095); buf[len] = '\0'; debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, len); debug(75, 5) ("{%s}\n", buf); if (len > 0) { if (0 == mem->inmem_hi) { http_reply *reply = mem->reply; http_version_t version; storeBuffer(entry); httpBuildVersion(&version, 1, 0); httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", "text/plain", -1, -1, -2); httpReplySwapOut(reply, entry); } fd_bytes(fd, len, FD_READ); kb_incr(&statCounter.server.all.kbytes_in, len); kb_incr(&statCounter.server.http.kbytes_in, len); storeAppend(entry, buf, len); storeBufferFlush(entry); commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read); } else if (len < 0) { debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n", fd, xstrerror()); if (ignoreErrno(errno)) { commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read); } else { ErrorState *err; err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, p->fwd->request); err->xerrno = errno; fwdFail(p->fwd, err); comm_close(fd); } } else { storeTimestampsSet(entry); storeBufferFlush(entry); if (!EBIT_TEST(entry->flags, RELEASE_REQUEST)) storeSetPublicKey(entry); fwdComplete(p->fwd); debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry)); comm_close(fd); } memFree(buf, MEM_4K_BUF); }
static void gopherTimeout(int fd, void *data) { GopherStateData *gopherState = data; StoreEntry *entry = gopherState->entry; debug(10, 4) ("gopherTimeout: FD %d: '%s'\n", fd, storeUrl(entry)); if (entry->store_status == STORE_PENDING) { if (entry->mem_obj->inmem_hi == 0) { fwdFail(gopherState->fwdState, errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT)); } } comm_close(fd); }
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); }
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 whoisReadReply(int fd, void *data) { WhoisState *p = data; StoreEntry *entry = p->entry; char *buf = memAllocate(MEM_4K_BUF); MemObject *mem = entry->mem_obj; int len; statCounter.syscalls.sock.reads++; len = FD_READ_METHOD(fd, buf, 4095); buf[len] = '\0'; debug(75, 3) ("whoisReadReply: FD %d read %d bytes\n", fd, len); debug(75, 5) ("{%s}\n", buf); if (len > 0) { if (0 == mem->inmem_hi) mem->reply->sline.status = HTTP_OK; fd_bytes(fd, len, FD_READ); kb_incr(&statCounter.server.all.kbytes_in, len); kb_incr(&statCounter.server.http.kbytes_in, len); storeAppend(entry, buf, len); commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read); } else if (len < 0) { debug(50, 2) ("whoisReadReply: FD %d: read failure: %s.\n", fd, xstrerror()); if (ignoreErrno(errno)) { commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, Config.Timeout.read); } else if (mem->inmem_hi == 0) { ErrorState *err; err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; fwdFail(p->fwd, err); comm_close(fd); } else { comm_close(fd); } } else { fwdComplete(p->fwd); debug(75, 3) ("whoisReadReply: Done: %s\n", storeUrl(entry)); comm_close(fd); } memFree(buf, MEM_4K_BUF); }
/*handle errorEntry here*/ static int repl_send_start(clientHttpRequest *http, int *ret) { debug(115, 4)("mod_customized_server_side_error_page repl_send_start\n"); int fd= http->conn->fd; mod_config* cfg = cc_get_mod_param(fd,mod); //mod_config *cfg = ((mod_config*)(param->param)); if(fd_table[fd].cc_run_state[mod->slot]>0) { error_page_private_data* pd = (error_page_private_data*) cc_get_mod_private_data(REQUEST_PRIVATE_DATA,http,mod); if(pd->OfflineTimeToLive > 0&& pd->recusive_time<2 && pd->recusive_time > 0 && cfg->customized_error_text.buf != NULL/* && pd->ResponseStatus <400 */) { debug(115,4)("customized_server_side_error_page: repl_send_start the recusive_time is: %d\n",pd->recusive_time); ErrorState *err; err_type page_id; int status = pd->ResponseStatus; switch(status) { case HTTP_BAD_REQUEST: case HTTP_LENGTH_REQUIRED: case HTTP_EXPECTATION_FAILED: page_id = ERR_INVALID_REQ; break; case HTTP_UNAUTHORIZED: case HTTP_FORBIDDEN: case HTTP_METHOD_NOT_ALLOWED: case HTTP_NOT_ACCEPTABLE: case HTTP_PROXY_AUTHENTICATION_REQUIRED: case HTTP_REQUEST_TIMEOUT: case HTTP_CONFLICT: case HTTP_GONE: case HTTP_PRECONDITION_FAILED: case HTTP_UNSUPPORTED_MEDIA_TYPE: case HTTP_UNPROCESSABLE_ENTITY: case HTTP_LOCKED: case HTTP_FAILED_DEPENDENCY: page_id = ERR_ACCESS_DENIED; break; case HTTP_NOT_FOUND : page_id = ERR_FTP_NOT_FOUND; break; case HTTP_REQUEST_ENTITY_TOO_LARGE: case HTTP_REQUEST_URI_TOO_LONG: page_id = ERR_TOO_BIG; break; case HTTP_INTERNAL_SERVER_ERROR: page_id= ERR_SOCKET_FAILURE; break; case HTTP_NOT_IMPLEMENTED: page_id = ERR_UNSUP_REQ; break; case HTTP_BAD_GATEWAY: case HTTP_GATEWAY_TIMEOUT: page_id = ERR_CONNECT_FAIL; break; case HTTP_SERVICE_UNAVAILABLE: page_id = ERR_FTP_UNAVAILABLE; break; default: page_id = ERR_HTTP_SPECIAL; } // err = errorCon(page_id, err = errorCon(page_id,pd->ResponseStatus,http->request); /********************may be leak here**********************************/ assert(err!=NULL); if(squid_curtime > cfg->error_page_expires) cfg->error_page_expires = squid_curtime + pd->OfflineTimeToLive; //err->request = requestLink(http->request); storeClientUnregister(http->sc,http->entry,http); http->sc = NULL; storeUnlockObject(http->entry); http->log_type = LOG_TCP_HIT; http->entry = clientCreateStoreEntry(http,http->request->method,null_request_flags); debug(115,4)("mod_customized_server_side_error_page repl_send_start: before errorAppendEntry, the err->page_id is: %d, the err->http_status is: %d , the err->type is: %d \n",err->page_id, err->http_status,err->type); errorAppendEntry(http->entry,err); /********************may be leak here**********************************/ *ret = 1; } // add by xueye.zhao // 2013-4-18 else if (pd->OfflineTimeToLive > 0&& pd->recusive_time<2 && pd->recusive_time > 0) { if(squid_curtime > cfg->error_page_expires) cfg->error_page_expires = squid_curtime + pd->OfflineTimeToLive; HttpReply *rep = httpReplyCreate(); http->entry = clientCreateStoreEntry(http, http->request->method, http->request->flags); http->log_type = LOG_TCP_MISS; storeReleaseRequest(http->entry); httpRedirectReply(rep, cfg->ResponseStatus, cfg->location); httpReplySwapOut(rep, http->entry); storeComplete(http->entry); *ret = 1; return *ret; } // end add } return *ret; }
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 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); }
void cachemgrStart(int fd, request_t * request, StoreEntry * entry) { cachemgrStateData *mgr = NULL; ErrorState *err = NULL; action_table *a; debug(16, 3) ("cachemgrStart: '%s'\n", storeUrl(entry)); if ((mgr = cachemgrParseUrl(storeUrl(entry))) == NULL) { err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND, request); err->url = xstrdup(storeUrl(entry)); errorAppendEntry(entry, err); entry->expires = squid_curtime; return; } mgr->entry = entry; storeLockObject(entry); entry->expires = squid_curtime; debug(16, 5) ("CACHEMGR: %s requesting '%s'\n", fd_table[fd].ipaddr, mgr->action); /* get additional info from request headers */ cachemgrParseHeaders(mgr, request); /* Check password */ if (cachemgrCheckPassword(mgr) != 0) { /* build error message */ ErrorState *err; HttpReply *rep; err = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED, request); /* warn if user specified incorrect password */ if (mgr->passwd) debug(16, 1) ("CACHEMGR: %s@%s: incorrect password for '%s'\n", mgr->user_name ? mgr->user_name : "<unknown>", fd_table[fd].ipaddr, mgr->action); else debug(16, 1) ("CACHEMGR: %s@%s: password needed for '%s'\n", mgr->user_name ? mgr->user_name : "<unknown>", fd_table[fd].ipaddr, mgr->action); rep = errorBuildReply(err); errorStateFree(err); /* * add Authenticate header, use 'action' as a realm because * password depends on action */ httpHeaderPutAuth(&rep->header, "Basic", mgr->action); /* store the reply */ httpReplySwapOut(rep, entry); entry->expires = squid_curtime; storeComplete(entry); cachemgrStateFree(mgr); return; } debug(16, 1) ("CACHEMGR: %s@%s requesting '%s'\n", mgr->user_name ? mgr->user_name : "<unknown>", fd_table[fd].ipaddr, mgr->action); /* retrieve object requested */ a = cachemgrFindAction(mgr->action); assert(a != NULL); storeBuffer(entry); { HttpReply *rep = entry->mem_obj->reply; /* prove there are no previous reply headers around */ assert(0 == rep->sline.status); httpReplySetHeaders(rep, HTTP_OK, NULL, "text/plain", -1, -1, squid_curtime); httpReplySwapOut(rep, entry); } a->handler(entry); storeBufferFlush(entry); if (a->flags.atomic) storeComplete(entry); cachemgrStateFree(mgr); }
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 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 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 } }
static int process_miss_in_error_page(clientHttpRequest* http ,int *ret) { debug(115, 4)("mod_customized_server_side_error_page process_miss_in_error_page\n"); int fd = http->conn->fd; if(fd_table[fd].cc_run_state[mod->slot]>0) { mod_config* cfg = cc_get_mod_param(fd,mod); if(squid_curtime < cfg->error_page_expires ) { ErrorState* err = NULL; /**********************************/ err_type page_id; int status = cfg->ResponseStatus; // add by xueye.zhao // 2013-4-18 if (is_http_move_status(status)) { HttpReply *rep = httpReplyCreate(); http->entry = clientCreateStoreEntry(http, http->request->method, http->request->flags); http->log_type = LOG_TCP_HIT; storeReleaseRequest(http->entry); httpRedirectReply(rep, cfg->ResponseStatus, cfg->location); httpReplySwapOut(rep, http->entry); storeComplete(http->entry); *ret = 1; return *ret; } //end add switch(status) { case HTTP_BAD_REQUEST: case HTTP_LENGTH_REQUIRED: case HTTP_EXPECTATION_FAILED: page_id = ERR_INVALID_REQ; break; case HTTP_UNAUTHORIZED: case HTTP_FORBIDDEN: case HTTP_METHOD_NOT_ALLOWED: case HTTP_NOT_ACCEPTABLE: case HTTP_PROXY_AUTHENTICATION_REQUIRED: case HTTP_REQUEST_TIMEOUT: case HTTP_CONFLICT: case HTTP_GONE: case HTTP_PRECONDITION_FAILED: case HTTP_UNSUPPORTED_MEDIA_TYPE: case HTTP_UNPROCESSABLE_ENTITY: case HTTP_LOCKED: case HTTP_FAILED_DEPENDENCY: page_id = ERR_ACCESS_DENIED; break; case HTTP_NOT_FOUND : page_id = ERR_FTP_NOT_FOUND; break; case HTTP_REQUEST_ENTITY_TOO_LARGE: case HTTP_REQUEST_URI_TOO_LONG: page_id = ERR_TOO_BIG; break; case HTTP_INTERNAL_SERVER_ERROR: page_id= ERR_SOCKET_FAILURE; break; case HTTP_NOT_IMPLEMENTED: page_id = ERR_UNSUP_REQ; break; case HTTP_BAD_GATEWAY: case HTTP_GATEWAY_TIMEOUT: page_id = ERR_CONNECT_FAIL; break; case HTTP_SERVICE_UNAVAILABLE: page_id = ERR_FTP_UNAVAILABLE; break; default: page_id = ERR_HTTP_SPECIAL; } /**********************************/ debug(115, 5)("mod_customized_server_side_error_page: cc_error_page running, don't back source server\n"); http->al.http.code = HTTP_FORBIDDEN; err = errorCon(page_id, cfg->ResponseStatus,http->request); // err->request = requestLink(http->request); err->src_addr = http->conn->peer.sin_addr; http->log_type = LOG_TCP_DENIED; http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags); errorAppendEntry(http->entry, err); *ret =1; } } return *ret; }