/* create MIME Header for Gopher Data */ static void gopherMimeCreate(GopherStateData * gopherState) { StoreEntry *e = gopherState->entry; HttpReply *reply = e->mem_obj->reply; http_version_t version; const char *mime_type = NULL; const char *mime_enc = NULL; switch (gopherState->type_id) { case GOPHER_DIRECTORY: case GOPHER_INDEX: case GOPHER_HTML: case GOPHER_WWW: case GOPHER_CSO: mime_type = "text/html"; break; case GOPHER_GIF: case GOPHER_IMAGE: case GOPHER_PLUS_IMAGE: mime_type = "image/gif"; break; case GOPHER_SOUND: case GOPHER_PLUS_SOUND: mime_type = "audio/basic"; break; case GOPHER_PLUS_MOVIE: mime_type = "video/mpeg"; break; case GOPHER_MACBINHEX: mime_type = "application/macbinary"; break; case GOPHER_DOSBIN: case GOPHER_UUENCODED: case GOPHER_BIN: case GOPHER_FILE: default: /* Rightnow We have no idea what it is. */ mime_type = mimeGetContentType(gopherState->request); mime_enc = mimeGetContentEncoding(gopherState->request); break; } storeBuffer(e); httpReplyReset(reply); EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT); httpBuildVersion(&version, 1, 0); httpReplySetHeaders(reply, version, HTTP_OK, "Gatewaying", mime_type, -1, -1, -1); if (mime_enc) httpHeaderPutStr(&reply->header, HDR_CONTENT_ENCODING, mime_enc); httpReplySwapOut(reply, e); reply->hdr_sz = e->mem_obj->inmem_hi; storeTimestampsSet(e); if (EBIT_TEST(e->flags, ENTRY_CACHABLE)) { storeSetPublicKey(e); } else { storeRelease(e); } }
/* create MIME Header for Gopher Data */ static void gopherMimeCreate(GopherStateData * gopherState) { MemBuf mb; memBufDefInit(&mb); memBufPrintf(&mb, "HTTP/1.0 200 OK Gatewaying\r\n" "Server: Squid/%s\r\n" "Date: %s\r\n" "MIME-version: 1.0\r\n", version_string, mkrfc1123(squid_curtime)); switch (gopherState->type_id) { case GOPHER_DIRECTORY: case GOPHER_INDEX: case GOPHER_HTML: case GOPHER_WWW: case GOPHER_CSO: memBufPrintf(&mb, "Content-Type: text/html\r\n"); break; case GOPHER_GIF: case GOPHER_IMAGE: case GOPHER_PLUS_IMAGE: memBufPrintf(&mb, "Content-Type: image/gif\r\n"); break; case GOPHER_SOUND: case GOPHER_PLUS_SOUND: memBufPrintf(&mb, "Content-Type: audio/basic\r\n"); break; case GOPHER_PLUS_MOVIE: memBufPrintf(&mb, "Content-Type: video/mpeg\r\n"); break; case GOPHER_MACBINHEX: case GOPHER_DOSBIN: case GOPHER_UUENCODED: case GOPHER_BIN: /* Rightnow We have no idea what it is. */ gopher_mime_content(&mb, gopherState->request, def_gopher_bin); break; case GOPHER_FILE: default: gopher_mime_content(&mb, gopherState->request, def_gopher_text); break; } memBufPrintf(&mb, "\r\n"); EBIT_CLR(gopherState->entry->flags, ENTRY_FWD_HDR_WAIT); storeAppend(gopherState->entry, mb.buf, mb.size); memBufClean(&mb); }
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); }
/* * Function: errorAppendEntry * * Arguments: err - This object is destroyed after use in this function. * * Abstract: This function generates a error page from the info contained * by 'err' and then stores the text in the specified store * entry. This function should only be called by ``server * side routines'' which need to communicate errors to the * client side. It should also be called from client_side.c * because we now support persistent connections, and * cannot assume that we can immediately write to the socket * for an error. */ void errorAppendEntry(StoreEntry * entry, ErrorState * err) { HttpReply *rep; MemObject *mem = entry->mem_obj; assert(mem != NULL); assert(mem->inmem_hi == 0); if (entry->store_status != STORE_PENDING) { /* * If the entry is not STORE_PENDING, then no clients * care about it, and we don't need to generate an * error message */ assert(EBIT_TEST(entry->flags, ENTRY_ABORTED)); assert(mem->nclients == 0); errorStateFree(err); return; } if (err->page_id == TCP_RESET) { if (err->request) { debug(4, 2) ("RSTing this reply\n"); err->request->flags.reset_tcp = 1; } } storeLockObject(entry); storeBuffer(entry); rep = errorBuildReply(err); /* Add authentication header */ /* TODO: alter errorstate to be accel on|off aware. The 0 on the next line * depends on authenticate behaviour: all schemes to date send no extra data * on 407/401 responses, and do not check the accel state on 401/407 responses */ authenticateFixHeader(rep, err->auth_user_request, err->request, 0, 1); httpReplySwapOut(rep, entry); httpReplyAbsorb(mem->reply, rep); EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); storeBufferFlush(entry); storeComplete(entry); storeNegativeCache(entry); storeReleaseRequest(entry); storeUnlockObject(entry); errorStateFree(err); }
/* Select on all sockets; call handlers for those that are ready. */ int comm_select(int msec) { fd_set readfds; fd_set pendingfds; fd_set writefds; #if DELAY_POOLS BIT_ARRAY slowfds; #endif PF *hdl = NULL; int fd; int maxfd; int num; int pending; int callicp = 0, callhttp = 0; int calldns = 0; int maxindex; int k; int j; #if DEBUG_FDBITS int i; #endif fd_mask *fdsp; fd_mask *pfdsp; fd_mask tmask; static time_t last_timeout = 0; struct timeval poll_time; double timeout = current_dtime + (msec / 1000.0); fde *F; #if DELAY_POOLS BA_INIT(slowfds,SQUID_NUMFD); #endif do { #if !ALARM_UPDATES_TIME double start; getCurrentTime(); start = current_dtime; #endif #if DELAY_POOLS BA_ZERO(slowfds); #endif /* Handle any fs callbacks that need doing */ storeDirCallback(); if (commCheckICPIncoming) comm_select_icp_incoming(); if (commCheckDNSIncoming) comm_select_dns_incoming(); if (commCheckHTTPIncoming) comm_select_http_incoming(); callicp = calldns = callhttp = 0; maxfd = Biggest_FD + 1; xmemcpy(&readfds, &global_readfds, howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES); xmemcpy(&writefds, &global_writefds, howmany(maxfd, FD_MASK_BITS) * FD_MASK_BYTES); /* remove stalled FDs, and deal with pending descriptors */ pending = 0; FD_ZERO(&pendingfds); maxindex = howmany(maxfd, FD_MASK_BITS); fdsp = (fd_mask *) & readfds; for (j = 0; j < maxindex; j++) { if ((tmask = fdsp[j]) == 0) continue; /* no bits here */ for (k = 0; k < FD_MASK_BITS; k++) { if (!EBIT_TEST(tmask, k)) continue; /* Found a set bit */ fd = (j * FD_MASK_BITS) + k; switch (commDeferRead(fd)) { case 0: break; case 1: FD_CLR(fd, &readfds); break; #if DELAY_POOLS case -1: BA_SET(fd, slowfds); break; #endif default: fatalf("bad return value from commDeferRead(FD %d)\n", fd); } if (FD_ISSET(fd, &readfds) && fd_table[fd].flags.read_pending) { FD_SET(fd, &pendingfds); pending++; } } } #if DEBUG_FDBITS for (i = 0; i < maxfd; i++) { /* Check each open socket for a handler. */ #if DELAY_POOLS if (fd_table[i].read_handler && commDeferRead(i) != 1) { #else if (fd_table[i].read_handler && !commDeferRead(i)) { #endif assert(FD_ISSET(i, &readfds)); } if (fd_table[i].write_handler) { assert(FD_ISSET(i, &writefds)); } } #endif if (nreadfds + nwritefds == 0) { assert(shutting_down); #if DELAY_POOLS BA_FREE(slowfds); #endif return COMM_SHUTDOWN; } if (msec > MAX_POLL_TIME) msec = MAX_POLL_TIME; if (pending) msec = 0; for (;;) { poll_time.tv_sec = msec / 1000; poll_time.tv_usec = (msec % 1000) * 1000; statCounter.syscalls.selects++; num = select(maxfd, &readfds, &writefds, NULL, &poll_time); statCounter.select_loops++; if (num >= 0 || pending > 0) break; if (ignoreErrno(errno)) break; debug(50, 0) ("comm_select: select failure: %s\n", xstrerror()); examine_select(&readfds, &writefds); #if DELAY_POOLS BA_FREE(slowfds); #endif return COMM_ERROR; /* NOTREACHED */ } if (num < 0 && !pending) continue; debug(5, num ? 5 : 8) ("comm_select: %d+%d FDs ready at %d\n", num, pending, (int) squid_curtime); statHistCount(&statCounter.select_fds_hist, num); /* Check lifetime and timeout handlers ONCE each second. * Replaces brain-dead check every time through the loop! */ if (squid_curtime > last_timeout) { last_timeout = squid_curtime; checkTimeouts(); } if (num == 0 && pending == 0) continue; /* Scan return fd masks for ready descriptors */ fdsp = (fd_mask *) & readfds; pfdsp = (fd_mask *) & pendingfds; maxindex = howmany(maxfd, FD_MASK_BITS); for (j = 0; j < maxindex; j++) { if ((tmask = (fdsp[j] | pfdsp[j])) == 0) continue; /* no bits here */ for (k = 0; k < FD_MASK_BITS; k++) { if (tmask == 0) break; /* no more bits left */ if (!EBIT_TEST(tmask, k)) continue; /* Found a set bit */ fd = (j * FD_MASK_BITS) + k; EBIT_CLR(tmask, k); /* this will be done */ #if DEBUG_FDBITS debug(5, 9) ("FD %d bit set for reading\n", fd); assert(FD_ISSET(fd, &readfds)); #endif if (fdIsIcp(fd)) { callicp = 1; continue; } if (fdIsDns(fd)) { calldns = 1; continue; } if (fdIsHttp(fd)) { callhttp = 1; continue; } F = &fd_table[fd]; debug(5, 6) ("comm_select: FD %d ready for reading\n", fd); if (NULL == (hdl = F->read_handler)) (void) 0; #if DELAY_POOLS else if (BA_ISSET(fd, slowfds)) commAddSlowFd(fd); #endif else { F->read_handler = NULL; commUpdateReadBits(fd, NULL); hdl(fd, F->read_data); statCounter.select_fds++; if (commCheckICPIncoming) comm_select_icp_incoming(); if (commCheckDNSIncoming) comm_select_dns_incoming(); if (commCheckHTTPIncoming) comm_select_http_incoming(); } } } fdsp = (fd_mask *) & writefds; for (j = 0; j < maxindex; j++) { if ((tmask = fdsp[j]) == 0) continue; /* no bits here */ for (k = 0; k < FD_MASK_BITS; k++) { if (tmask == 0) break; /* no more bits left */ if (!EBIT_TEST(tmask, k)) continue; /* Found a set bit */ fd = (j * FD_MASK_BITS) + k; EBIT_CLR(tmask, k); /* this will be done */ #if DEBUG_FDBITS debug(5, 9) ("FD %d bit set for writing\n", fd); assert(FD_ISSET(fd, &writefds)); #endif if (fdIsIcp(fd)) { callicp = 1; continue; } if (fdIsDns(fd)) { calldns = 1; continue; } if (fdIsHttp(fd)) { callhttp = 1; continue; } F = &fd_table[fd]; debug(5, 5) ("comm_select: FD %d ready for writing\n", fd); if ((hdl = F->write_handler)) { F->write_handler = NULL; commUpdateWriteBits(fd, NULL); hdl(fd, F->write_data); statCounter.select_fds++; if (commCheckICPIncoming) comm_select_icp_incoming(); if (commCheckDNSIncoming) comm_select_dns_incoming(); if (commCheckHTTPIncoming) comm_select_http_incoming(); } } } if (callicp) comm_select_icp_incoming(); if (calldns) comm_select_dns_incoming(); if (callhttp) comm_select_http_incoming(); #if DELAY_POOLS while ((fd = commGetSlowFd()) != -1) { F = &fd_table[fd]; debug(5, 6) ("comm_select: slow FD %d selected for reading\n", fd); if ((hdl = F->read_handler)) { F->read_handler = NULL; commUpdateReadBits(fd, NULL); hdl(fd, F->read_data); statCounter.select_fds++; if (commCheckICPIncoming) comm_select_icp_incoming(); if (commCheckDNSIncoming) comm_select_dns_incoming(); if (commCheckHTTPIncoming) comm_select_http_incoming(); } } #endif #if !ALARM_UPDATES_TIME getCurrentTime(); statCounter.select_time += (current_dtime - start); #endif #if DELAY_POOLS BA_FREE(slowfds); #endif return COMM_OK; } while (timeout > current_dtime); debug(5, 8) ("comm_select: time out: %d\n", (int) squid_curtime); #if DELAY_POOLS BA_FREE(slowfds); #endif return COMM_TIMEOUT; } #endif static void #if HAVE_POLL comm_poll_dns_incoming(void) #else comm_select_dns_incoming(void) #endif { int nfds = 0; int fds[2]; int nevents; dns_io_events = 0; if (DnsSocket < 0) return; fds[nfds++] = DnsSocket; #if HAVE_POLL nevents = comm_check_incoming_poll_handlers(nfds, fds); #else nevents = comm_check_incoming_select_handlers(nfds, fds); #endif if (nevents < 0) return; incoming_dns_interval += Config.comm_incoming.dns_average - nevents; if (incoming_dns_interval < Config.comm_incoming.dns_min_poll) incoming_dns_interval = Config.comm_incoming.dns_min_poll; if (incoming_dns_interval > MAX_INCOMING_INTERVAL) incoming_dns_interval = MAX_INCOMING_INTERVAL; if (nevents > INCOMING_DNS_MAX) nevents = INCOMING_DNS_MAX; statHistCount(&statCounter.comm_dns_incoming, nevents); }