static void peerSelectCallback(ps_state * psstate) { StoreEntry *entry = psstate->entry; FwdServer *fs = psstate->servers; void *data = psstate->callback_data; if (entry) { debug(44, 3) ("peerSelectCallback: %s\n", storeUrl(entry)); if (entry->ping_status == PING_WAITING) eventDelete(peerPingTimeout, psstate); entry->ping_status = PING_DONE; } if (fs == NULL) { debug(44, 1) ("Failed to select source for '%s'\n", storeUrl(entry)); debug(44, 1) (" always_direct = %d\n", psstate->always_direct); debug(44, 1) (" never_direct = %d\n", psstate->never_direct); debug(44, 1) (" timedout = %d\n", psstate->ping.timedout); } psstate->ping.stop = current_time; psstate->request->hier.ping = psstate->ping; if (cbdataValid(data)) { psstate->servers = NULL; psstate->callback(fs, data); } cbdataUnlock(data); peerSelectStateFree(psstate); }
static int swdaeSwapDirRoundRobin(cache_select_t *cache, const StoreEntry * e) { static int dirn = 0; int i; int load; SwapDir *sd; squid_off_t objsize = objectLen(e); for (i = 0; i < cache->dir.count; i++) { cache->dirn = cache->dirn % cache->dir.count; dirn = (int)cache->dir.items[cache->dirn]; cache->dirn++; if (0 > dirn || dirn >= Config.cacheSwap.n_configured) continue; sd = &Config.cacheSwap.swapDirs[dirn]; if (sd->flags.read_only) { debug(172, 5)("%s %s: %s read_only\n", PMOD_NAME, __func__, sd->path); continue; } if (sd->cur_size > sd->max_size) { debug(172, 5)("%s %s: %scur_size > sd->max_size\n", PMOD_NAME, __func__, sd->path); continue; } if (!swdaeSwapDirSwapDirSize(dirn, objsize)) { debug(172,5)("%s %s objsize isn't Suitable %s %s\n",PMOD_NAME, __func__, sd->path, storeUrl(e)); continue; } if (sd->checkobj(sd, e) == 0) { debug(172,5)("%s %s checkobj(sd,e) == 0\n", PMOD_NAME, sd->path); continue; } load = sd->checkload(sd, ST_OP_CREATE); if (load < 0 || load > 2000) { debug(172, 5)("%s %s Load too high %s\n", PMOD_NAME, sd->path, storeUrl(e)); continue; } debug(172,3)("%s %s select [%s] store %s\n", PMOD_NAME, __func__, sd->path, storeUrl(e)); return dirn; } debug(172, 7)("%s %s nomatch %s\n", PMOD_NAME, __func__, storeUrl(e)); return -1; }
/* * Build a TLV list for a StoreEntry */ tlv * storeSwapMetaBuild(StoreEntry * e) { tlv *TLV = NULL; /* we'll return this */ tlv **T = &TLV; const char *url; const char *vary; const squid_off_t objsize = objectLen(e); assert(e->mem_obj != NULL); assert(e->swap_status == SWAPOUT_WRITING); url = storeUrl(e); debug(20, 3) ("storeSwapMetaBuild: %s\n", url); T = storeSwapTLVAdd(STORE_META_KEY, e->hash.key, SQUID_MD5_DIGEST_LENGTH, T); #if SIZEOF_SQUID_FILE_SZ == SIZEOF_SIZE_T T = storeSwapTLVAdd(STORE_META_STD, &e->timestamp, STORE_HDR_METASIZE, T); #else T = storeSwapTLVAdd(STORE_META_STD_LFS, &e->timestamp, STORE_HDR_METASIZE, T); #endif T = storeSwapTLVAdd(STORE_META_URL, url, strlen(url) + 1, T); if (objsize > -1) { T = storeSwapTLVAdd(STORE_META_OBJSIZE, &objsize, sizeof(objsize), T); } vary = e->mem_obj->vary_headers; if (vary) T = storeSwapTLVAdd(STORE_META_VARY_HEADERS, vary, strlen(vary) + 1, T); if (e->mem_obj->store_url) T = storeSwapTLVAdd(STORE_META_STOREURL, e->mem_obj->store_url, strlen(e->mem_obj->store_url) + 1, T); if (e->dirkey) T = storeSwapTLVAdd(STORE_META_KEY_URL, e->dirkey, SQUID_MD5_DIGEST_LENGTH, T); return TLV; }
static void whoisTimeout(int fd, void *data) { WhoisState *p = data; debug(75, 1) ("whoisTimeout: %s\n", storeUrl(p->entry)); whoisClose(fd, p); }
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); }
static int swdaeSwapDirAclNBCheck(aclCheck_t *ch, const StoreEntry *e) { int pos = 0; int dirn = -1; int answer = 0; acl_access *A = mod->acl_rules; cc_mod_param *mod_param = NULL; cache_select_t *cache = NULL; while (0 > dirn && A && pos < mod->mod_params.count) { if ((mod_param = mod->mod_params.items[pos]) && (cache = mod_param->param)) { answer = aclMatchAclList(A->acl_list, ch); if (answer > 0 && A->allow == ACCESS_ALLOWED) { dirn = swdaeSwapDirSelectDiskStart(g_SelectDiskMethod, cache, e); } } pos++; A = A->next; } debug(172, 8)("%s %s reply_check %d %s\n", PMOD_NAME,__func__, dirn, storeUrl(e)); return dirn < 0 ? -1: dirn; }
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 asStateFree(void *data) { ASState *asState = data; debug(53, 3) ("asStateFree: %s\n", storeUrl(asState->entry)); storeClientUnregister(asState->sc, asState->entry, asState); storeUnlockObject(asState->entry); requestUnlink(asState->request); cbdataFree(asState); }
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); }
static void netdbExchangeDone(void *data) { netdbExchangeState *ex = data; debug(38, 3) ("netdbExchangeDone: %s\n", storeUrl(ex->e)); requestUnlink(ex->r); storeClientUnregister(ex->sc, ex->e, ex); storeUnlockObject(ex->e); cbdataUnlock(ex->p); cbdataFree(ex); }
/* 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); }
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 int hookSwdaeSwapRegiestMemPd(HttpStateData *hs, char *buf, ssize_t len) { StoreEntry *e = hs ? hs->entry : NULL; if (0 == g_CheckReply_Flags && e->mem_obj && e && EBIT_TEST(e->flags, ENTRY_CACHABLE)) { SD_MemPd_t *ssPd = cc_get_mod_private_data(MEMOBJECT_PRIVATE_DATA, e->mem_obj , mod); if (NULL == ssPd) ssPd = p_Mod_AllocMemPd(); ssPd->fd = hs->fd; cc_register_mod_private_data(MEMOBJECT_PRIVATE_DATA, e->mem_obj, ssPd, p_Mod_FreeMemPd, mod); debug(172,5)("%s %s %s %s\n", PMOD_NAME,__func__, ssPd ? "cache":"no-cache", storeUrl(e)); } return 0; }
static int peerSelectIcpPing(request_t * request, int direct, StoreEntry * entry) { int n; assert(entry); assert(entry->ping_status == PING_NONE); assert(direct != DIRECT_YES); debug(44, 3) ("peerSelectIcpPing: %s\n", storeUrl(entry)); if (!request->flags.hierarchical && direct != DIRECT_NO) return 0; if (EBIT_TEST(entry->flags, KEY_PRIVATE) && !neighbors_do_private_keys) if (direct != DIRECT_NO) return 0; n = neighborsCount(request); debug(44, 3) ("peerSelectIcpPing: counted %d neighbors\n", n); return n; }
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); }
/***********************************Moudle Hook Start****************************************/ static int hookSwdaeSwapDirAclCheck(const StoreEntry *e, char **forbid, int *ret) { int dirn = *ret; if (forbid) *forbid = g_CacheDirForbidDisk; if(NULL ==e || NULL == e->mem_obj) { return dirn; } if(0 == mod->flags.param || 0 == mod->mod_params.count) { return dirn; } if (dirn >= 0 && dirn < Config.cacheSwap.n_configured) { debug(172, 5)("%s %s areadly selected %d %s\n", PMOD_NAME,__func__, dirn, storeUrl(e)); return dirn; } SD_MemPd_t *ssPd = cc_get_mod_private_data(MEMOBJECT_PRIVATE_DATA, e->mem_obj , mod); if (ssPd && ssPd->fd >= 0 && fd_table[ssPd->fd].cc_run_state) { cache_select_t *cache = cc_get_mod_param(ssPd->fd, mod); dirn = swdaeSwapDirSelectDiskStart(g_SelectDiskMethod, cache, e); ssPd = dirn >= 0 ? ssPd : NULL; } if (NULL == ssPd && g_CheckReply_Flags) { aclCheck_t ch; memset(&ch, 0, sizeof(ch)); ch.request = e->mem_obj->request; ch.reply = storeEntryReply((StoreEntry *)e); aclChecklistCacheInit(&ch); dirn = swdaeSwapDirAclNBCheck(&ch, e); aclCheckCleanup(&ch); } *ret = dirn; return 0; }
/* * Build a TLV list for a StoreEntry */ tlv * storeSwapMetaBuild(StoreEntry * e) { tlv *TLV = NULL; /* we'll return this */ tlv **T = &TLV; const char *url; const char *vary; assert(e->mem_obj != NULL); assert(e->swap_status == SWAPOUT_WRITING); url = storeUrl(e); debug(20, 3) ("storeSwapMetaBuild: %s\n", url); T = storeSwapTLVAdd(STORE_META_KEY, e->hash.key, MD5_DIGEST_CHARS, T); #if SIZEOF_SQUID_FILE_SZ == SIZEOF_SIZE_T T = storeSwapTLVAdd(STORE_META_STD, &e->timestamp, STORE_HDR_METASIZE, T); #else T = storeSwapTLVAdd(STORE_META_STD_LFS, &e->timestamp, STORE_HDR_METASIZE, T); #endif T = storeSwapTLVAdd(STORE_META_URL, url, strlen(url) + 1, T); vary = e->mem_obj->vary_headers; if (vary) T = storeSwapTLVAdd(STORE_META_VARY_HEADERS, vary, strlen(vary) + 1, T); return TLV; }
void storeDigestDel(const StoreEntry * entry) { #if USE_CACHE_DIGESTS if (!Config.onoff.digest_generation) { return; } assert(entry && store_digest); debug(71, 6) ("storeDigestDel: checking entry, key: %s\n", storeKeyText(entry->hash.key)); if (!EBIT_TEST(entry->flags, KEY_PRIVATE)) { if (!cacheDigestTest(store_digest, entry->hash.key)) { sd_stats.del_lost_count++; debug(71, 6) ("storeDigestDel: lost entry, key: %s url: %s\n", storeKeyText(entry->hash.key), storeUrl(entry)); } else { sd_stats.del_count++; cacheDigestDel(store_digest, entry->hash.key); debug(71, 6) ("storeDigestDel: deled entry, key: %s\n", storeKeyText(entry->hash.key)); } } #endif }
/* Borrow part of code from libwww2 came with Mosaic distribution */ static void gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) { char *pos = inbuf; char *lpos = NULL; char *tline = NULL; LOCAL_ARRAY(char, line, TEMP_BUF_SIZE); LOCAL_ARRAY(char, tmpbuf, TEMP_BUF_SIZE); LOCAL_ARRAY(char, outbuf, TEMP_BUF_SIZE << 4); char *name = NULL; char *selector = NULL; char *host = NULL; char *port = NULL; char *escaped_selector = NULL; const char *icon_url = NULL; char gtype; StoreEntry *entry = NULL; memset(outbuf, '\0', TEMP_BUF_SIZE << 4); memset(tmpbuf, '\0', TEMP_BUF_SIZE); memset(line, '\0', TEMP_BUF_SIZE); entry = gopherState->entry; if (gopherState->conversion == HTML_INDEX_PAGE) { storeAppendPrintf(entry, "<HTML><HEAD><TITLE>Gopher Index %s</TITLE></HEAD>\n" "<BODY><H1>%s<BR>Gopher Search</H1>\n" "<p>This is a searchable Gopher index. Use the search\n" "function of your browser to enter search terms.\n" "<ISINDEX></BODY></HTML>\n", storeUrl(entry), storeUrl(entry)); /* now let start sending stuff to client */ storeBufferFlush(entry); gopherState->data_in = 1; return; } if (gopherState->conversion == HTML_CSO_PAGE) { storeAppendPrintf(entry, "<HTML><HEAD><TITLE>CSO Search of %s</TITLE></HEAD>\n" "<BODY><H1>%s<BR>CSO Search</H1>\n" "<P>A CSO database usually contains a phonebook or\n" "directory. Use the search function of your browser to enter\n" "search terms.</P><ISINDEX></BODY></HTML>\n", storeUrl(entry), storeUrl(entry)); /* now let start sending stuff to client */ storeBufferFlush(entry); gopherState->data_in = 1; return; } inbuf[len] = '\0'; if (!gopherState->HTML_header_added) { if (gopherState->conversion == HTML_CSO_RESULT) strcat(outbuf, "<HTML><HEAD><TITLE>CSO Searchs Result</TITLE></HEAD>\n" "<BODY><H1>CSO Searchs Result</H1>\n<PRE>\n"); else strcat(outbuf, "<HTML><HEAD><TITLE>Gopher Menu</TITLE></HEAD>\n" "<BODY><H1>Gopher Menu</H1>\n<PRE>\n"); gopherState->HTML_header_added = 1; } while ((pos != NULL) && (pos < inbuf + len)) { if (gopherState->len != 0) { /* there is something left from last tx. */ xstrncpy(line, gopherState->buf, gopherState->len); lpos = (char *) memccpy(line + gopherState->len, inbuf, '\n', len); if (lpos) *lpos = '\0'; else { /* there is no complete line in inbuf */ /* copy it to temp buffer */ if (gopherState->len + len > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE - gopherState->len; } xmemcpy(gopherState->buf + gopherState->len, inbuf, len); gopherState->len += len; return; } /* skip one line */ pos = (char *) memchr(pos, '\n', len); if (pos) pos++; /* we're done with the remain from last tx. */ gopherState->len = 0; *(gopherState->buf) = '\0'; } else { lpos = (char *) memccpy(line, pos, '\n', len - (pos - inbuf)); if (lpos) *lpos = '\0'; else { /* there is no complete line in inbuf */ /* copy it to temp buffer */ if ((len - (pos - inbuf)) > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE; } if (len > (pos - inbuf)) { xmemcpy(gopherState->buf, pos, len - (pos - inbuf)); gopherState->len = len - (pos - inbuf); } break; } /* skip one line */ pos = (char *) memchr(pos, '\n', len); if (pos) pos++; } /* at this point. We should have one line in buffer to process */ if (*line == '.') { /* skip it */ memset(line, '\0', TEMP_BUF_SIZE); continue; } switch (gopherState->conversion) { case HTML_INDEX_RESULT: case HTML_DIR:{ tline = line; gtype = *tline++; name = tline; selector = strchr(tline, TAB); if (selector) { *selector++ = '\0'; host = strchr(selector, TAB); if (host) { *host++ = '\0'; port = strchr(host, TAB); if (port) { char *junk; port[0] = ':'; junk = strchr(host, TAB); if (junk) *junk++ = 0; /* Chop port */ else { junk = strchr(host, '\r'); if (junk) *junk++ = 0; /* Chop port */ else { junk = strchr(host, '\n'); if (junk) *junk++ = 0; /* Chop port */ } } if ((port[1] == '0') && (!port[2])) port[0] = 0; /* 0 means none */ } /* escape a selector here */ escaped_selector = xstrdup(rfc1738_escape_part(selector)); switch (gtype) { case GOPHER_DIRECTORY: icon_url = mimeGetIconURL("internal-menu"); break; case GOPHER_FILE: icon_url = mimeGetIconURL("internal-text"); break; case GOPHER_INDEX: case GOPHER_CSO: icon_url = mimeGetIconURL("internal-index"); break; case GOPHER_IMAGE: case GOPHER_GIF: case GOPHER_PLUS_IMAGE: icon_url = mimeGetIconURL("internal-image"); break; case GOPHER_SOUND: case GOPHER_PLUS_SOUND: icon_url = mimeGetIconURL("internal-sound"); break; case GOPHER_PLUS_MOVIE: icon_url = mimeGetIconURL("internal-movie"); break; case GOPHER_TELNET: case GOPHER_3270: icon_url = mimeGetIconURL("internal-telnet"); break; case GOPHER_BIN: case GOPHER_MACBINHEX: case GOPHER_DOSBIN: case GOPHER_UUENCODED: icon_url = mimeGetIconURL("internal-binary"); break; default: icon_url = mimeGetIconURL("internal-unknown"); break; } memset(tmpbuf, '\0', TEMP_BUF_SIZE); if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) { if (strlen(escaped_selector) != 0) snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG BORDER=0 SRC=\"%s\"> <A HREF=\"telnet://%s@%s/\">%s</A>\n", icon_url, escaped_selector, host, name); else snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG BORDER=0 SRC=\"%s\"> <A HREF=\"telnet://%s/\">%s</A>\n", icon_url, host, name); } else { snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG BORDER=0 SRC=\"%s\"> <A HREF=\"gopher://%s/%c%s\">%s</A>\n", icon_url, host, gtype, escaped_selector, name); } safe_free(escaped_selector); strcat(outbuf, tmpbuf); gopherState->data_in = 1; } else { memset(line, '\0', TEMP_BUF_SIZE); continue; } } else { memset(line, '\0', TEMP_BUF_SIZE); continue; } break; } /* HTML_DIR, HTML_INDEX_RESULT */ case HTML_CSO_RESULT:{ int t; int code; int recno; LOCAL_ARRAY(char, result, MAX_CSO_RESULT); tline = line; if (tline[0] == '-') { t = sscanf(tline, "-%d:%d:%[^\n]", &code, &recno, result); if (t < 3) break; if (code != 200) break; if (gopherState->cso_recno != recno) { snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR><H2>Record# %d<br><i>%s</i></H2>\n<PRE>", recno, result); gopherState->cso_recno = recno; } else { snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", result); } strcat(outbuf, tmpbuf); gopherState->data_in = 1; break; } else { /* handle some error codes */ t = sscanf(tline, "%d:%[^\n]", &code, result); if (t < 2) break; switch (code) { case 200:{ /* OK */ /* Do nothing here */ break; } case 102: /* Number of matches */ case 501: /* No Match */ case 502: /* Too Many Matches */ { /* Print the message the server returns */ snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR><H2>%s</H2>\n<PRE>", result); strcat(outbuf, tmpbuf); gopherState->data_in = 1; break; } } } } /* HTML_CSO_RESULT */ default: break; /* do nothing */ } /* switch */ } /* while loop */ if ((int) strlen(outbuf) > 0) { storeAppend(entry, outbuf, strlen(outbuf)); /* now let start sending stuff to client */ storeBufferFlush(entry); } return; }
static int getHttpResponseParam(HttpStateData *httpState,char *buf, ssize_t len) { HttpReply *reply = httpState->entry->mem_obj->reply; request_t *request = httpState->request; assert(reply); if (reply->sline.status != HTTP_OK) { debug(207, 1) ("mod_m3u8_prefetch httpState entry url: %s, reply status = %d is not 200\n",storeUrl(httpState->entry),reply->sline.status); return 0; } request_param *r= cc_get_mod_private_data(REQUEST_T_PRIVATE_DATA, request, mod); if (!r) { r = request_param_pool_alloc(); r->m3u8_fd = -1; r->content_length = -1; r->remain_clen = -1; strncpy(r->default_prefix, request->canonical, strlen(request->canonical)); char *end= strstr(r->default_prefix, ".m3u8"); *end ='\0'; debug(207, 3) ("Debug input_buf1=[%s]\n",r->default_prefix); end = strrchr(r->default_prefix,'/'); *(end+1) = '\0'; debug(207, 3)("Debug input_buf=[%s]\n",r->default_prefix); cc_register_mod_private_data(REQUEST_T_PRIVATE_DATA, request,r, free_request_param,mod); } long content_length = getContentLength(httpState); if (content_length > 0) { r->content_length = content_length; r->remain_clen = content_length; } debug(207, 1) ("mod_m3u8_prefetch getHttpResponseParam url=%s,content_length=%ld,remain_clen=%ld\n",storeUrl(httpState->entry),r->content_length, r->remain_clen); return 0; }
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; }
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 int asyncGetTsFromM3u8(HttpStateData * httpState, char *buf, ssize_t len, char* comp_buf, ssize_t comp_buf_len, size_t *comp_size, int buffer_filled) { HttpReply *reply = httpState->entry->mem_obj->reply; assert(reply); if (reply->sline.status != HTTP_OK) { debug(207, 1) ("mod_m3u8_prefetch asyncGetTsFromM3u8 entry url: %s, reply status = %d is not 200 return\n",storeUrl(httpState->entry),reply->sline.status); return 0; } memset(comp_buf, 0, comp_buf_len); xmemcpy(comp_buf, buf, len); *comp_size = len; mod_config *cfg = cc_get_mod_param(httpState->fd, mod); assert(cfg); request_param *r= cc_get_mod_private_data(REQUEST_T_PRIVATE_DATA, httpState->request, mod); assert(r); parseM3u8(buf, len, r,cfg); return 0; }
static int swdaeSwapDirLeastLoad(cache_select_t *cache, const StoreEntry *e) { squid_off_t objsize; int most_free = 0, cur_free; squid_off_t least_objsize = -1; int least_load = INT_MAX; int load; int dirn = 0; int dirn_no = -1; int i; SwapDir *sd; /* Calculate the object size */ objsize = objectLen(e); if (objsize != -1) objsize += e->mem_obj->swap_hdr_sz; for (i = 0; i < cache->dir.count; i++) { cache->dirn = cache->dirn % cache->dir.count; dirn = (int)cache->dir.items[cache->dirn]; cache->dirn++; if (0 > dirn || dirn >= Config.cacheSwap.n_configured) continue; sd = &Config.cacheSwap.swapDirs[dirn]; sd->flags.selected = 0; if (sd->flags.read_only) { debug(172, 5)("%s %s %s read_only\n", PMOD_NAME, __func__,sd->path); continue; } if (sd->cur_size > sd->max_size) { debug(172, 5)("%s %s %s cur_size > sd->max_size\n", PMOD_NAME, __func__, sd->path); continue; } if (!swdaeSwapDirSwapDirSize(dirn, objsize)) { debug(172,5)("%s %s objsize isn't Suitable %s %s\n", PMOD_NAME, __func__, sd->path, storeUrl(e)); continue; } if (sd->checkobj(sd, e) == 0) { debug(172,5)("%s %s %s checkobj(sd,e) == 0\n",PMOD_NAME, __func__, sd->path); continue; } load = sd->checkload(sd, ST_OP_CREATE); if (load < 0 || load > 2000) { debug(172, 5)("%s %s %s Load too high %s\n", PMOD_NAME, __func__, sd->path, storeUrl(e)); continue; } if (load > least_load) continue; cur_free = sd->max_size - sd->cur_size; /* If the load is equal, then look in more details */ if (load == least_load) { /* closest max_objsize fit */ if (least_objsize != -1) if (sd->max_objsize > least_objsize || sd->max_objsize == -1) continue; /* most free */ if (cur_free < most_free) continue; } least_load = load; least_objsize = sd->max_objsize; most_free = cur_free; dirn_no = dirn; } if (dirn_no >= 0) { sd = &Config.cacheSwap.swapDirs[dirn_no]; debug(172,5)("%s %s Select [%s] store %s\n", PMOD_NAME, __func__, sd->path, storeUrl(e)); Config.cacheSwap.swapDirs[dirn_no].flags.selected = 1; }else { debug(172,5)("%s %s Select Null store %s\n",PMOD_NAME, __func__, storeUrl(e)); } return dirn_no; }
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); }
static void asHandleReply(void *data, mem_node_ref nr, ssize_t size) { ASState *asState = data; StoreEntry *e = asState->entry; char *s; char *t; LOCAL_ARRAY(char, buf, SM_PAGE_SIZE); debug(53, 3) ("asHandleReply: Called with size=%ld\n", (long int) size); if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { stmemNodeUnref(&nr); asStateFree(asState); return; } if (size == 0 && e->mem_obj->inmem_hi > 0) { asStateFree(asState); stmemNodeUnref(&nr); return; } else if (size < 0) { debug(53, 1) ("asHandleReply: Called with size=%ld\n", (long int) size); asStateFree(asState); stmemNodeUnref(&nr); return; } else if (HTTP_OK != e->mem_obj->reply->sline.status) { debug(53, 1) ("WARNING: AS %d whois request failed\n", asState->as_number); stmemNodeUnref(&nr); asStateFree(asState); return; } assert((nr.offset + size) < SM_PAGE_SIZE); memcpy(buf, nr.node->data + nr.offset, size); stmemNodeUnref(&nr); s = buf; while (s - buf < size && *s != '\0') { while (*s && xisspace(*s)) s++; for (t = s; *t; t++) { if (xisspace(*t)) break; } if (*t == '\0') { /* oof, word should continue on next block */ break; } *t = '\0'; debug(53, 3) ("asHandleReply: AS# %s (%d)\n", s, asState->as_number); asnAddNet(s, asState->as_number); s = t + 1; } asState->seen = asState->offset + size; asState->offset += (s - buf); debug(53, 3) ("asState->seen = %ld, asState->offset = %ld\n", (long int) asState->seen, (long int) asState->offset); if (e->store_status == STORE_PENDING) { debug(53, 3) ("asHandleReply: store_status == STORE_PENDING: %s\n", storeUrl(e)); storeClientRef(asState->sc, e, asState->seen, asState->offset, SM_PAGE_SIZE, asHandleReply, asState); } else if (asState->seen < e->mem_obj->inmem_hi) { debug(53, 3) ("asHandleReply: asState->seen < e->mem_obj->inmem_hi %s\n", storeUrl(e)); storeClientRef(asState->sc, e, asState->seen, asState->offset, SM_PAGE_SIZE, asHandleReply, asState); } else { debug(53, 3) ("asHandleReply: Done: %s\n", storeUrl(e)); asStateFree(asState); } }
int neighborsUdpPing(request_t * request, StoreEntry * entry, IRCB * callback, void *callback_data, int *exprep, int *timeout) { const char *url = storeUrl(entry); MemObject *mem = entry->mem_obj; peer *p = NULL; int i; int reqnum = 0; int flags; icp_common_t *query; int queries_sent = 0; int peers_pinged = 0; int parent_timeout = 0, parent_exprep = 0; int sibling_timeout = 0, sibling_exprep = 0; int mcast_timeout = 0, mcast_exprep = 0; if (Config.peers == NULL) return 0; if (theOutIcpConnection < 0) fatal("neighborsUdpPing: There is no ICP socket!"); assert(entry->swap_status == SWAPOUT_NONE); mem->start_ping = current_time; mem->ping_reply_callback = callback; mem->ircb_data = callback_data; reqnum = icpSetCacheKey(entry->hash.key); for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) { if (p == NULL) p = Config.peers; debug(15, 5) ("neighborsUdpPing: Peer %s\n", p->name); if (!peerWouldBePinged(p, request)) continue; /* next peer */ peers_pinged++; debug(15, 4) ("neighborsUdpPing: pinging peer %s for '%s'\n", p->name, url); if (p->type == PEER_MULTICAST) mcastSetTtl(theOutIcpConnection, p->mcast.ttl); debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->hash.key)); debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum); #if USE_HTCP if (p->options.htcp && !p->options.htcp_only_clr) { debug(15, 3) ("neighborsUdpPing: sending HTCP query\n"); htcpQuery(entry, request, p); } else #endif if (p->icp.port == echo_port) { debug(15, 4) ("neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n"); echo_hdr.reqnum = reqnum; query = icpCreateMessage(ICP_DECHO, 0, url, reqnum, 0); icpUdpSend(theOutIcpConnection, &p->in_addr, query, LOG_ICP_QUERY, 0); } else { flags = 0; if (Config.onoff.query_icmp) if (p->icp.version == ICP_VERSION_2) flags |= ICP_FLAG_SRC_RTT; query = icpCreateMessage(ICP_QUERY, flags, url, reqnum, 0); icpUdpSend(theOutIcpConnection, &p->in_addr, query, LOG_ICP_QUERY, 0); } queries_sent++; p->stats.pings_sent++; if (p->type == PEER_MULTICAST) { mcast_exprep += p->mcast.n_replies_expected; mcast_timeout += (p->stats.rtt * p->mcast.n_replies_expected); } else if (neighborUp(p)) { /* its alive, expect a reply from it */ if (neighborType(p, request) == PEER_PARENT) { parent_exprep++; parent_timeout += p->stats.rtt; } else { sibling_exprep++; sibling_timeout += p->stats.rtt; } } else { /* Neighbor is dead; ping it anyway, but don't expect a reply */ /* log it once at the threshold */ if (p->stats.logged_state == PEER_ALIVE) { debug(15, 1) ("Detected DEAD %s: %s\n", neighborTypeStr(p), p->name); p->stats.logged_state = PEER_DEAD; } } p->stats.last_query = squid_curtime; /* * keep probe_start == 0 for a multicast peer, * so neighborUp() never says this peer is dead. */ if ((p->type != PEER_MULTICAST) && (p->stats.probe_start == 0)) p->stats.probe_start = squid_curtime; } if ((first_ping = first_ping->next) == NULL) first_ping = Config.peers; #if ALLOW_SOURCE_PING /* only do source_ping if we have neighbors */ if (Config.npeers) { const ipcache_addrs *ia = NULL; struct sockaddr_in to_addr; char *host = request->host; if (!Config.onoff.source_ping) { debug(15, 6) ("neighborsUdpPing: Source Ping is disabled.\n"); } else if ((ia = ipcache_gethostbyname(host, 0))) { debug(15, 6) ("neighborsUdpPing: Source Ping: to %s for '%s'\n", host, url); echo_hdr.reqnum = reqnum; if (icmp_sock != -1) { icmpSourcePing(ia->in_addrs[ia->cur], &echo_hdr, url); } else { to_addr.sin_family = AF_INET; to_addr.sin_addr = ia->in_addrs[ia->cur]; to_addr.sin_port = htons(echo_port); query = icpCreateMessage(ICP_SECHO, 0, url, reqnum, 0); icpUdpSend(theOutIcpConnection, &to_addr, query, LOG_ICP_QUERY, 0); } } else { debug(15, 6) ("neighborsUdpPing: Source Ping: unknown host: %s\n", host); } } #endif /* * How many replies to expect? */ *exprep = parent_exprep + sibling_exprep + mcast_exprep; /* * If there is a configured timeout, use it */ if (Config.Timeout.icp_query) *timeout = Config.Timeout.icp_query; else { if (*exprep > 0) { if (parent_exprep) *timeout = 2 * parent_timeout / parent_exprep; else if (mcast_exprep) *timeout = 2 * mcast_timeout / mcast_exprep; else *timeout = 2 * sibling_timeout / sibling_exprep; } else *timeout = 2000; /* 2 seconds */ if (Config.Timeout.icp_query_max) if (*timeout > Config.Timeout.icp_query_max) *timeout = Config.Timeout.icp_query_max; if (*timeout < Config.Timeout.icp_query_min) *timeout = Config.Timeout.icp_query_min; } return peers_pinged; }
/* Borrow part of code from libwww2 came with Mosaic distribution */ static void gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) { char *pos = inbuf; char *lpos = NULL; char *tline = NULL; LOCAL_ARRAY(char, line, TEMP_BUF_SIZE); LOCAL_ARRAY(char, tmpbuf, TEMP_BUF_SIZE); String outbuf = StringNull; char *name = NULL; char *selector = NULL; char *host = NULL; char *port = NULL; char *escaped_selector = NULL; const char *icon_url = NULL; char gtype; StoreEntry *entry = NULL; memset(tmpbuf, '\0', TEMP_BUF_SIZE); memset(line, '\0', TEMP_BUF_SIZE); entry = gopherState->entry; if (gopherState->conversion == HTML_INDEX_PAGE) { char *html_url = html_quote(storeUrl(entry)); gopherHTMLHeader(entry, "Gopher Index %s", html_url); storeAppendPrintf(entry, "<p>This is a searchable Gopher index. Use the search\n" "function of your browser to enter search terms.\n" "<ISINDEX>\n"); gopherHTMLFooter(entry); /* now let start sending stuff to client */ storeBufferFlush(entry); gopherState->HTML_header_added = 1; return; } if (gopherState->conversion == HTML_CSO_PAGE) { char *html_url = html_quote(storeUrl(entry)); gopherHTMLHeader(entry, "CSO Search of %s", html_url); storeAppendPrintf(entry, "<P>A CSO database usually contains a phonebook or\n" "directory. Use the search function of your browser to enter\n" "search terms.</P><ISINDEX>\n"); gopherHTMLFooter(entry); /* now let start sending stuff to client */ storeBufferFlush(entry); gopherState->HTML_header_added = 1; return; } inbuf[len] = '\0'; if (!gopherState->HTML_header_added) { if (gopherState->conversion == HTML_CSO_RESULT) gopherHTMLHeader(entry, "CSO Search Result", NULL); else gopherHTMLHeader(entry, "Gopher Menu", NULL); strCat(outbuf, "<PRE>"); gopherState->HTML_header_added = 1; gopherState->HTML_pre = 1; } while ((pos != NULL) && (pos < inbuf + len)) { if (gopherState->len != 0) { /* there is something left from last tx. */ xstrncpy(line, gopherState->buf, gopherState->len + 1); if (gopherState->len + len > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE - gopherState->len; } lpos = (char *) memccpy(line + gopherState->len, inbuf, '\n', len); if (lpos) *lpos = '\0'; else { /* there is no complete line in inbuf */ /* copy it to temp buffer */ if (gopherState->len + len > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE - gopherState->len; } xmemcpy(gopherState->buf + gopherState->len, inbuf, len); gopherState->len += len; return; } /* skip one line */ pos = (char *) memchr(pos, '\n', len); if (pos) pos++; /* we're done with the remain from last tx. */ gopherState->len = 0; *(gopherState->buf) = '\0'; } else { lpos = (char *) memccpy(line, pos, '\n', len - (pos - inbuf)); if (lpos) *lpos = '\0'; else { /* there is no complete line in inbuf */ /* copy it to temp buffer */ if ((len - (pos - inbuf)) > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE; } if (len > (pos - inbuf)) { xmemcpy(gopherState->buf, pos, len - (pos - inbuf)); gopherState->len = len - (pos - inbuf); } break; } /* skip one line */ pos = (char *) memchr(pos, '\n', len); if (pos) pos++; } /* at this point. We should have one line in buffer to process */ if (*line == '.') { /* skip it */ memset(line, '\0', TEMP_BUF_SIZE); continue; } switch (gopherState->conversion) { case HTML_INDEX_RESULT: case HTML_DIR:{ tline = line; gtype = *tline++; name = tline; selector = strchr(tline, TAB); if (selector) { *selector++ = '\0'; host = strchr(selector, TAB); if (host) { *host++ = '\0'; port = strchr(host, TAB); if (port) { char *junk; port[0] = ':'; junk = strchr(host, TAB); if (junk) *junk++ = 0; /* Chop port */ else { junk = strchr(host, '\r'); if (junk) *junk++ = 0; /* Chop port */ else { junk = strchr(host, '\n'); if (junk) *junk++ = 0; /* Chop port */ } } if ((port[1] == '0') && (!port[2])) port[0] = 0; /* 0 means none */ } /* escape a selector here */ escaped_selector = xstrdup(rfc1738_escape_part(selector)); switch (gtype) { case GOPHER_DIRECTORY: icon_url = mimeGetIconURL("internal-menu"); break; case GOPHER_HTML: case GOPHER_FILE: icon_url = mimeGetIconURL("internal-text"); break; case GOPHER_INDEX: case GOPHER_CSO: icon_url = mimeGetIconURL("internal-index"); break; case GOPHER_IMAGE: case GOPHER_GIF: case GOPHER_PLUS_IMAGE: icon_url = mimeGetIconURL("internal-image"); break; case GOPHER_SOUND: case GOPHER_PLUS_SOUND: icon_url = mimeGetIconURL("internal-sound"); break; case GOPHER_PLUS_MOVIE: icon_url = mimeGetIconURL("internal-movie"); break; case GOPHER_TELNET: case GOPHER_3270: icon_url = mimeGetIconURL("internal-telnet"); break; case GOPHER_BIN: case GOPHER_MACBINHEX: case GOPHER_DOSBIN: case GOPHER_UUENCODED: icon_url = mimeGetIconURL("internal-binary"); break; case GOPHER_INFO: icon_url = NULL; break; default: icon_url = mimeGetIconURL("internal-unknown"); break; } memset(tmpbuf, '\0', TEMP_BUF_SIZE); if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) { if (strlen(escaped_selector) != 0) snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"telnet://%s@%s%s%s/\">%s</A>\n", icon_url, escaped_selector, rfc1738_escape_part(host), *port ? ":" : "", port, html_quote(name)); else snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"telnet://%s%s%s/\">%s</A>\n", icon_url, rfc1738_escape_part(host), *port ? ":" : "", port, html_quote(name)); } else if (gtype == GOPHER_INFO) { snprintf(tmpbuf, TEMP_BUF_SIZE, "\t%s\n", html_quote(name)); } else { if (strncmp(selector, "GET /", 5) == 0) { /* WWW link */ snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"http://%s/%s\">%s</A>\n", icon_url, host, rfc1738_escape_unescaped(selector + 5), html_quote(name)); } else { /* Standard link */ snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"gopher://%s/%c%s\">%s</A>\n", icon_url, host, gtype, escaped_selector, html_quote(name)); } } safe_free(escaped_selector); strCat(outbuf, tmpbuf); } else { memset(line, '\0', TEMP_BUF_SIZE); continue; } } else { memset(line, '\0', TEMP_BUF_SIZE); continue; } break; } /* HTML_DIR, HTML_INDEX_RESULT */ case HTML_CSO_RESULT:{ if (line[0] == '-') { int code, recno; char *s_code, *s_recno, *result; s_code = strtok(line + 1, ":\n"); s_recno = strtok(NULL, ":\n"); result = strtok(NULL, "\n"); if (!result) break; code = atoi(s_code); recno = atoi(s_recno); if (code != 200) break; if (gopherState->cso_recno != recno) { snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR noshade size=\"1px\"><H2>Record# %d<br><i>%s</i></H2>\n<PRE>", recno, html_quote(result)); gopherState->cso_recno = recno; } else { snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", html_quote(result)); } strCat(outbuf, tmpbuf); break; } else { int code; char *s_code, *result; s_code = strtok(line, ":"); result = strtok(NULL, "\n"); if (!result) break; code = atoi(s_code); switch (code) { case 200:{ /* OK */ /* Do nothing here */ break; } case 102: /* Number of matches */ case 501: /* No Match */ case 502: /* Too Many Matches */ { /* Print the message the server returns */ snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR noshade size=\"1px\"><H2>%s</H2>\n<PRE>", html_quote(result)); strCat(outbuf, tmpbuf); break; } } } } /* HTML_CSO_RESULT */ default: break; /* do nothing */ } /* switch */ } /* while loop */ if (strLen(outbuf) > 0) { storeAppend(entry, strBuf(outbuf), strLen(outbuf)); /* now let start sending stuff to client */ storeBufferFlush(entry); } stringClean(&outbuf); return; }