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; }
/* return a list of entries with the same id separated by ',' and ws */ String httpHeaderGetList(const HttpHeader * hdr, http_hdr_type id) { String s = StringNull; HttpHeaderEntry *e; HttpHeaderPos pos = HttpHeaderInitPos; debug(55, 6) ("%p: joining for id %d\n", hdr, id); /* only fields from ListHeaders array can be "listed" */ assert(CBIT_TEST(ListHeadersMask, id)); if (!CBIT_TEST(hdr->mask, id)) return s; while ((e = httpHeaderGetEntry(hdr, &pos))) { if (e->id == id) strListAdd(&s, strBuf(e->value), ','); } /* * note: we might get an empty (len==0) string if there was an "empty" * header; we must not get a NULL string though. */ assert(strBuf(s)); /* temporary warning: remove it! @?@ @?@ @?@ */ if (!strLen(s)) debug(55, 3) ("empty list header: %s (%d)\n", strBuf(Headers[id].name), id); debug(55, 6) ("%p: joined for id %d: %s\n", hdr, id, strBuf(s)); return s; }
/* use fresh entries to replace old ones */ void httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask) { const HttpHeaderEntry *e; HttpHeaderPos pos = HttpHeaderInitPos; assert(old && fresh); assert(old != fresh); debug(55, 7) ("updating hdr: %p <- %p\n", old, fresh); while ((e = httpHeaderGetEntry(fresh, &pos))) { /* deny bad guys (ok to check for HDR_OTHER) here */ if (denied_mask && CBIT_TEST(*denied_mask, e->id)) continue; if (e->id != HDR_OTHER) httpHeaderDelById(old, e->id); else httpHeaderDelByName(old, strBuf(e->name)); } pos = HttpHeaderInitPos; while ((e = httpHeaderGetEntry(fresh, &pos))) { /* deny bad guys (ok to check for HDR_OTHER) here */ if (denied_mask && CBIT_TEST(*denied_mask, e->id)) continue; httpHeaderAddClone(old, e); } /* And now, repack the array to "fill in the holes" */ httpHeaderRepack(old); }
/* returns true if the key belongs to the digest */ int cacheDigestTest(const CacheDigest * cd, const cache_key * key) { assert(cd && key); /* hash */ cacheDigestHashKey(cd, key); /* test corresponding bits */ return CBIT_TEST(cd->mask, hashed_keys[0]) && CBIT_TEST(cd->mask, hashed_keys[1]) && CBIT_TEST(cd->mask, hashed_keys[2]) && CBIT_TEST(cd->mask, hashed_keys[3]); }
/* *?µIJ??ҷ?ʽ??һЩsquid??????????header?IJ??? */ static HttpHeaderEntry* httpHeaderFindEntry2(const HttpHeader * hdr, http_hdr_type id) { //zhb:let it be faster HttpHeaderPos pos = HttpHeaderInitPos + HDR_ENUM_END; HttpHeaderEntry *e; assert(hdr); //assert_eid(id); /* check mask first */ if (!CBIT_TEST(hdr->mask, id)) return NULL; if(id != HDR_OTHER) { return hdr->entries.items[hdr->pSearch[id]]; } /* looks like we must have it, do linear search */ while ((e = httpHeaderGetEntryPlus(hdr, &pos))) { if (e->id == id) return e; } /* hm.. we thought it was there, but it was not found */ assert(0); return NULL; /* not reached */ }
/* returns mask utilization parameters */ static void cacheDigestStats(const CacheDigest * cd, CacheDigestStats * stats) { int on_count = 0; int pos = cd->mask_size * 8; int seq_len_sum = 0; int seq_count = 0; int cur_seq_len = 0; int cur_seq_type = 1; assert(stats); memset(stats, 0, sizeof(*stats)); while (pos-- > 0) { const int is_on = CBIT_TEST(cd->mask, pos); if (is_on) on_count++; if (is_on != cur_seq_type || !pos) { seq_len_sum += cur_seq_len; seq_count++; cur_seq_type = is_on; cur_seq_len = 0; } cur_seq_len++; } stats->bit_count = cd->mask_size * 8; stats->bit_on_count = on_count; stats->bseq_len_sum = seq_len_sum; stats->bseq_count = seq_count; }
/* returns true if header is allowed to be passed on */ int httpRequestHdrAllowedByName(http_hdr_type id) { /* check with anonymizer tables */ if (CBIT_TEST(Config.anonymize_headers, id)) return 0; return 1; }
/* test if a field is present */ int httpHeaderHas(const HttpHeader * hdr, http_hdr_type id) { assert(hdr); assert_eid(id); assert(id != HDR_OTHER); debug(55, 7) ("%p lookup for %d\n", hdr, id); return CBIT_TEST(hdr->mask, id); }
/* returns true if header is allowed to be passed on */ int httpRequestHdrAllowed(const HttpHeaderEntry * e, String * strConn) { assert(e); /* check with anonymizer tables */ if (CBIT_TEST(Config.anonymize_headers, e->id)) return 0; /* check connection header */ if (strConn && strListIsMember(strConn, strBuf(e->name), ',')) return 0; return 1; }
/* * same as httpHeaderFindEntry */ static HttpHeaderEntry * httpHeaderFindLastEntry(const HttpHeader * hdr, http_hdr_type id) { HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; HttpHeaderEntry *result = NULL; assert(hdr); assert_eid(id); assert(!CBIT_TEST(ListHeadersMask, id)); /* check mask first */ if (!CBIT_TEST(hdr->mask, id)) return NULL; /* looks like we must have it, do linear search */ while ((e = httpHeaderGetEntry(hdr, &pos))) { if (e->id == id) result = e; } assert(result); /* must be there! */ return result; }
/* calculates a bit mask of a given array; does not reset mask! */ void httpHeaderCalcMask(HttpHeaderMask * mask, const int *enums, int count) { int i; assert(mask && enums); assert(count < sizeof(*mask) * 8); /* check for overflow */ for (i = 0; i < count; ++i) { assert(!CBIT_TEST(*mask, enums[i])); /* check for duplicates */ CBIT_SET(*mask, enums[i]); } }
/* * returns a pointer to a specified entry if any * note that we return one entry so it does not make much sense to ask for * "list" headers */ HttpHeaderEntry * httpHeaderFindEntry(const HttpHeader * hdr, http_hdr_type id) { HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; assert(hdr); assert_eid(id); assert(!CBIT_TEST(ListHeadersMask, id)); /* check mask first */ if (!CBIT_TEST(hdr->mask, id)) return NULL; /* looks like we must have it, do linear search */ while ((e = httpHeaderGetEntry(hdr, &pos))) { if (e->id == id) return e; } /* hm.. we thought it was there, but it was not found */ assert(0); return NULL; /* not reached */ }
void cacheDigestAdd(CacheDigest * cd, const cache_key * key) { assert(cd && key); /* hash */ cacheDigestHashKey(cd, key); /* turn on corresponding bits */ #if CD_FAST_ADD CBIT_SET(cd->mask, hashed_keys[0]); CBIT_SET(cd->mask, hashed_keys[1]); CBIT_SET(cd->mask, hashed_keys[2]); CBIT_SET(cd->mask, hashed_keys[3]); #else { int on_xition_cnt = 0; if (!CBIT_TEST(cd->mask, hashed_keys[0])) { CBIT_SET(cd->mask, hashed_keys[0]); on_xition_cnt++; } if (!CBIT_TEST(cd->mask, hashed_keys[1])) { CBIT_SET(cd->mask, hashed_keys[1]); on_xition_cnt++; } if (!CBIT_TEST(cd->mask, hashed_keys[2])) { CBIT_SET(cd->mask, hashed_keys[2]); on_xition_cnt++; } if (!CBIT_TEST(cd->mask, hashed_keys[3])) { CBIT_SET(cd->mask, hashed_keys[3]); on_xition_cnt++; } statHistCount(&statCounter.cd.on_xition_count, on_xition_cnt); } #endif cd->count++; }
static void httpHeaderFieldStatDumper(StoreEntry * sentry, int idx, double val, double size, int count) { const int id = (int) val; const int valid_id = id >= 0 && id < HDR_ENUM_END; const char *name = valid_id ? strBuf(Headers[id].name) : "INVALID"; int visible = count > 0; /* for entries with zero count, list only those that belong to current type of message */ if (!visible && valid_id && dump_stat->owner_mask) visible = CBIT_TEST(*dump_stat->owner_mask, id); if (visible) storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", id, name, count, xdiv(count, dump_stat->busyDestroyedCount)); }
/* return a string or list of entries with the same id separated by ',' and ws */ String httpHeaderGetStrOrList(const HttpHeader * hdr, http_hdr_type id) { HttpHeaderEntry *e; if (CBIT_TEST(ListHeadersMask, id)) return httpHeaderGetList(hdr, id); if ((e = httpHeaderFindEntry(hdr, id))) { String s; stringInit(&s, strBuf(e->value)); return s; } return StringNull; }
HttpHdrCc * httpHeaderGetCc(const HttpHeader * hdr) { HttpHdrCc *cc; String s; if (!CBIT_TEST(hdr->mask, HDR_CACHE_CONTROL)) return NULL; s = httpHeaderGetList(hdr, HDR_CACHE_CONTROL); cc = httpHdrCcParseCreate(&s); HttpHeaderStats[hdr->owner].ccParsedCount++; if (cc) httpHdrCcUpdateStats(cc, &HttpHeaderStats[hdr->owner].ccTypeDistr); httpHeaderNoteParsedEntry(HDR_CACHE_CONTROL, s, !cc); stringClean(&s); return cc; }
/* appends an entry; * does not call httpHeaderEntryClone() so one should not reuse "*e" */ void httpHeaderAddEntry(HttpHeader * hdr, HttpHeaderEntry * e) { assert(hdr && e); assert_eid(e->id); debug(55, 7) ("%p adding entry: %d at %d\n", hdr, e->id, hdr->entries.count); if (CBIT_TEST(hdr->mask, e->id)) Headers[e->id].stat.repCount++; else CBIT_SET(hdr->mask, e->id); arrayAppend(&hdr->entries, e); /* increment header length, allow for ": " and crlf */ hdr->len += strLen(e->name) + 2 + strLen(e->value) + 2; }
/* use fresh entries to replace old ones */ void httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask) { const HttpHeaderEntry *e; HttpHeaderPos pos = HttpHeaderInitPos; assert(old && fresh); assert(old != fresh); debug(55, 7) ("updating hdr: %p <- %p\n", old, fresh); while ((e = httpHeaderGetEntry(fresh, &pos))) { /* deny bad guys (ok to check for HDR_OTHER) here */ if (denied_mask && CBIT_TEST(*denied_mask, e->id)) continue; httpHeaderDelByName(old, strBuf(e->name)); httpHeaderAddEntry(old, httpHeaderEntryClone(e)); } }
/* deletes all entries with a given id, returns the #entries deleted */ int httpHeaderDelById(HttpHeader * hdr, http_hdr_type id) { int count = 0; HttpHeaderPos pos = HttpHeaderInitPos; HttpHeaderEntry *e; debug(55, 8) ("%p del-by-id %d\n", hdr, id); assert(hdr); assert_eid(id); assert(id != HDR_OTHER); /* does not make sense */ if (!CBIT_TEST(hdr->mask, id)) return 0; while ((e = httpHeaderGetEntry(hdr, &pos))) { if (e->id == id) { httpHeaderDelAt(hdr, pos); count++; } } CBIT_CLR(hdr->mask, id); assert(count); return count; }