/*
- * $Id: HttpHdrCc.cc,v 1.4 1998/03/07 23:42:56 rousskov Exp $
+ * $Id: HttpHdrCc.cc,v 1.5 1998/03/08 21:02:07 rousskov Exp $
*
* DEBUG: section 65 HTTP Cache Control Header
* AUTHOR: Alex Rousskov
}
void
-httpHdrCcPackValueInto(const HttpHdrCc * cc, Packer * p)
+httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p)
{
http_hdr_cc_type flag;
int pcount = 0;
/*
- * $Id: HttpHdrExtField.cc,v 1.1 1998/03/08 18:59:11 rousskov Exp $
+ * $Id: HttpHdrExtField.cc,v 1.2 1998/03/08 21:02:07 rousskov Exp $
*
- * DEBUG: section 6? HTTP Header: Extension Field
+ * DEBUG: section 69 HTTP Header: Extension Field
* AUTHOR: Alex Rousskov
*
* SQUID Internet Object Cache http://squid.nlanr.net/Squid/
/*
- * $Id: HttpHdrRange.cc,v 1.2 1998/03/07 23:42:57 rousskov Exp $
+ * $Id: HttpHdrRange.cc,v 1.3 1998/03/08 21:02:08 rousskov Exp $
*
- * DEBUG: section 64 HTTP Content-Range Header
+ * DEBUG: section 64 HTTP Range Header
* AUTHOR: Alex Rousskov
*
* SQUID Internet Object Cache http://squid.nlanr.net/Squid/
#define size_diff(a,b) ((a) >= (b) ? ((a)-(b)) : 0)
static HttpHdrRangeSpec *httpHdrRangeSpecDup(const HttpHdrRangeSpec *spec);
static int httpHdrRangeSpecCanonize(HttpHdrRangeSpec *spec, size_t clen);
+static void httpHdrRangeSpecPackInto(const HttpHdrRangeSpec *spec, Packer *p);
/* globals */
static int RangeParsedCount = 0;
* Range-Spec
*/
-
static HttpHdrRangeSpec *
httpHdrRangeSpecCreate()
{
return dup;
}
+static void
+httpHdrRangeSpecPackInto(const HttpHdrRangeSpec *spec, Packer *p)
+{
+ if (!known_spec(spec->offset)) /* suffix */
+ packerPrintf(p, "-%d", spec->length);
+ else
+ if (!known_spec(spec->length)) /* trailer */
+ packerPrintf(p, "%d-", spec->offset);
+ else /* range */
+ packerPrintf(p, "%d-%d",
+ spec->offset, spec->offset+spec->length-1);
+}
+
/* fills "absent" positions in range specification based on response body size
returns true if the range is still valid
range is valid if its intersection with [0,length-1] is not empty
}
void
-httpHdrRangePackValueInto(const HttpHdrRange * range, Packer * p)
+httpHdrRangePackInto(const HttpHdrRange * range, Packer * p)
{
HttpHdrRangePos pos = HttpHdrRangeInitPos;
HttpHdrRangeSpec spec;
assert(range);
while (httpHdrRangeGetSpec(range, &spec, &pos)) {
- packerPrintf(p, (pos == HttpHdrRangeInitPos) ? "%d-%d" : ",%d-%d",
- spec.offset, spec.offset+spec.length-1);
+ if (pos != HttpHdrRangeInitPos)
+ packerAppend(p, ",", 1);
+ httpHdrRangeSpecPackInto(&spec, p);
}
}
/*
- * $Id: HttpHeader.cc,v 1.20 1998/03/08 18:58:40 rousskov Exp $
+ * $Id: HttpHeader.cc,v 1.21 1998/03/08 21:02:09 rousskov Exp $
*
* DEBUG: section 55 HTTP Header
* AUTHOR: Alex Rousskov
*/
/*
- * HttpHeader entry
- * ( the concrete type of entry.field is Headers[id].type )
+ * HttpHeader entry (type of entry.field is Headers[id].type)
*/
struct _HttpHeaderEntry {
field_store field;
{"Content-Encoding", HDR_CONTENT_ENCODING, ftStr},
{"Content-Length", HDR_CONTENT_LENGTH, ftInt},
{"Content-MD5", HDR_CONTENT_MD5, ftStr}, /* for now */
+ {"Content-Range", HDR_CONTENT_RANGE, ftPContRange},
{"Content-Type", HDR_CONTENT_TYPE, ftStr},
{"Date", HDR_DATE, ftDate_1123},
{"Etag", HDR_ETAG, ftStr}, /* for now */
/* HDR_ALLOW, */
HDR_CACHE_CONTROL, HDR_CONNECTION,
HDR_CONTENT_ENCODING,
- /* HDR_CONTENT_LANGUAGE, HDR_IF_MATCH, HDR_IF_NONE_MATCH,
- * HDR_PRAGMA, HDR_TRANSFER_ENCODING, */
+ /* HDR_CONTENT_LANGUAGE, */
+ /* HDR_IF_MATCH, HDR_IF_NONE_MATCH, HDR_PRAGMA, */
+ HDR_RANGE,
+ /* HDR_TRANSFER_ENCODING, */
HDR_UPGRADE, /* HDR_VARY, */
/* HDR_VIA, HDR_WARNING, */
HDR_WWW_AUTHENTICATE,
static int RequestHeadersMask = 0; /* set run-time using RequestHeaders */
static http_hdr_type RequestHeaders[] =
{
- HDR_OTHER
+ HDR_CONTENT_RANGE, HDR_OTHER
};
/* when first field is added, this is how much entries we allocate */
return httpHeaderGet(hdr, HDR_RANGE).v_prange;
}
+HttpHdrContRange *
+httpHeaderGetContRange(const HttpHeader * hdr)
+{
+ return httpHeaderGet(hdr, HDR_CONTENT_RANGE).v_pcont_range;
+}
+
/* updates header masks */
static void
httpHeaderSyncMasks(HttpHeader * hdr, const HttpHeaderEntry * e, int add)
if (e->field.v_prange)
httpHdrRangeDestroy(e->field.v_prange);
break;
+ case ftPContRange:
+ if (e->field.v_pcont_range)
+ httpHdrContRangeDestroy(e->field.v_pcont_range);
+ break;
case ftPExtField:
if (e->field.v_pefield)
httpHdrExtFieldDestroy(e->field.v_pefield);
static int
httpHeaderEntryParseByTypeInit(HttpHeaderEntry * e, int id, const HttpHdrExtField * f)
{
+ const char *err_entry_descr = NULL;
int type;
field_store field;
assert(e && f);
httpHeaderFieldInit(&field);
switch (type) {
case ftInt:
- if (!httpHeaderParseInt(strBuf(f->value), &field.v_int)) {
- Headers[id].stat.errCount++;
- return 0;
- }
+ if (!httpHeaderParseInt(strBuf(f->value), &field.v_int))
+ err_entry_descr = "integer field";
break;
-
case ftStr:
field.v_str = stringDup(&f->value);
break;
-
case ftDate_1123:
field.v_time = parse_rfc1123(strBuf(f->value));
if (field.v_time <= 0)
Headers[id].stat.errCount++;
/*
* if parse_rfc1123 fails we fall through anyway so upper levels
- * will notice invalid date
+ * will notice invalid date rather than unparsible header
*/
break;
-
case ftPCc:
field.v_pcc = httpHdrCcParseCreate(strBuf(f->value));
- if (!field.v_pcc) {
- debug(55, 2) ("failed to parse cc hdr: id: %d, field: '%s: %s'\n",
- id, strBuf(f->name), strBuf(f->value));
- Headers[id].stat.errCount++;
- return 0;
- }
+ if (!field.v_pcc)
+ err_entry_descr = "cache control hdr";
break;
-
case ftPRange:
field.v_prange = httpHdrRangeParseCreate(strBuf(f->value));
- if (!field.v_prange) {
- debug(55, 2) ("failed to parse range hdr: id: %d, field: '%s: %s'\n",
- id, strBuf(f->name), strBuf(f->value));
- Headers[id].stat.errCount++;
- return 0;
- }
+ if (!field.v_prange)
+ err_entry_descr = "range hdr";
+ break;
+ case ftPContRange:
+ field.v_pcont_range = httpHdrContRangeParseCreate(strBuf(f->value));
+ if (!field.v_pcont_range)
+ err_entry_descr = "content range hdr";
break;
-
default:
debug(55, 2) ("something went wrong with hdr field type analysis: id: %d, type: %d, field: '%s: %s'\n",
id, type, strBuf(f->name), strBuf(f->value));
assert(0);
}
+ /* failure ? */
+ if (err_entry_descr) {
+ debug(55, 2) ("failed to parse %s: id: %d, field: '%s: %s'\n",
+ err_entry_descr, id, strBuf(f->name), strBuf(f->value));
+ Headers[id].stat.errCount++;
+ return 0;
+ }
/* success, do actual init */
httpHeaderEntryInit(e, id, field);
return 1;
}
-
static HttpHeaderEntry
httpHeaderEntryClone(const HttpHeaderEntry * e)
{
packerPrintf(p, "%s", mkrfc1123(e->field.v_time));
break;
case ftPCc:
- httpHdrCcPackValueInto(e->field.v_pcc, p);
+ httpHdrCcPackInto(e->field.v_pcc, p);
break;
case ftPRange:
- httpHdrRangePackValueInto(e->field.v_prange, p);
+ httpHdrRangePackInto(e->field.v_prange, p);
+ break;
+ case ftPContRange:
+ httpHdrContRangePackInto(e->field.v_pcont_range, p);
break;
case ftPExtField:
packerPrintf(p, "%s", e->field.v_pefield->value);
return e->field.v_pcc != NULL;
case ftPRange:
return e->field.v_prange != NULL;
+ case ftPContRange:
+ return e->field.v_pcont_range != NULL;
case ftPExtField:
return e->field.v_pefield != NULL;
default:
return ptrField(httpHdrCcDup(value.v_pcc));
case ftPRange:
return ptrField(httpHdrRangeDup(value.v_prange));
+ case ftPContRange:
+ return ptrField(httpHdrContRangeDup(value.v_pcont_range));
case ftPExtField:
return ptrField(httpHdrExtFieldDup(value.v_pefield));
default:
return strField(StringNull);
case ftPCc:
case ftPRange:
+ case ftPContRange:
case ftPExtField:
return ptrField(NULL);
case ftInvalid:
#
# Makefile for the Squid Object Cache server
#
-# $Id: Makefile.in,v 1.131 1998/03/08 18:58:41 rousskov Exp $
+# $Id: Makefile.in,v 1.132 1998/03/08 21:02:09 rousskov Exp $
#
# Uncomment and customize the following to suit your needs:
#
HttpHdrExtField.o \
HttpHdrCc.o \
HttpHdrRange.o \
+ HttpHdrContRange.o \
HttpHeader.o \
HttpHeaderTools.o \
HttpBody.o \
HDR_CONTENT_ENCODING,
HDR_CONTENT_LENGTH,
HDR_CONTENT_MD5,
+ HDR_CONTENT_RANGE,
HDR_CONTENT_TYPE,
HDR_DATE,
HDR_ETAG,
typedef enum {
ftInvalid = HDR_ENUM_END, /* to catch nasty errors with hdr_id<->fld_type clashes */
ftInt,
-#if OLD_CODE
- ftPChar,
-#else
ftStr,
-#endif
ftDate_1123,
ftPCc,
ftPRange,
+ ftPContRange,
ftPExtField
} field_type;
MEM_HTTP_HDR_CC,
MEM_HTTP_HDR_RANGE_SPEC,
MEM_HTTP_HDR_RANGE,
+ MEM_HTTP_HDR_CONTENT_RANGE,
MEM_HTTPSTATEDATA,
MEM_ICPUDPDATA,
MEM_CLIENTHTTPREQUEST,
/*
- * $Id: mem.cc,v 1.15 1998/03/07 20:46:18 rousskov Exp $
+ * $Id: mem.cc,v 1.16 1998/03/08 21:02:10 rousskov Exp $
*
* DEBUG: section 13 High Level Memory Pool Management
* AUTHOR: Harvest Derived
memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0);
memDataInit(MEM_HTTP_HDR_RANGE_SPEC, "HttpHdrRangeSpec", sizeof(HttpHdrRangeSpec), 0);
memDataInit(MEM_HTTP_HDR_RANGE, "HttpHdrRange", sizeof(HttpHdrRange), 0);
+ memDataInit(MEM_HTTP_HDR_CONTENT_RANGE, "HttpHdrContRange", sizeof(HttpHdrContRange), 0);
memDataInit(MEM_ICPUDPDATA, "icpUdpData", sizeof(icpUdpData), 0);
memDataInit(MEM_ICP_COMMON_T, "icp_common_t", sizeof(icp_common_t), 0);
memDataInit(MEM_ICP_PING_DATA, "icp_ping_data", sizeof(icp_ping_data), 0);
extern HttpHdrCc *httpHdrCcParseCreate(const char *str);
extern void httpHdrCcDestroy(HttpHdrCc * cc);
extern HttpHdrCc *httpHdrCcDup(const HttpHdrCc * cc);
-extern void httpHdrCcPackValueInto(const HttpHdrCc * cc, Packer * p);
+extern void httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p);
extern void httpHdrCcJoinWith(HttpHdrCc * cc, const HttpHdrCc * new_cc);
extern void httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist);
extern void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count);
extern int httpHdrRangeParseInit(HttpHdrRange *range, const char *range_spec);
extern void httpHdrRangeDestroy(HttpHdrRange *range);
extern HttpHdrRange *httpHdrRangeDup(const HttpHdrRange * range);
-extern void httpHdrRangePackValueInto(const HttpHdrRange * range, Packer * p);
+extern void httpHdrRangePackInto(const HttpHdrRange * range, Packer * p);
extern void httpHdrRangeJoinWith(HttpHdrRange * range, const HttpHdrRange * new_range);
/* iterate through specs */
extern int httpHdrRangeGetSpec(const HttpHdrRange *range, HttpHdrRangeSpec *spec, int *pos);
+/* Http Content Range Header Field */
+extern HttpHdrContRange *httpHdrContRangeParseCreate(const char *crange_spec);
+/* returns true if range is valid; inits HttpHdrContRange */
+extern int httpHdrContRangeParseInit(HttpHdrContRange *crange, const char *crange_spec);
+extern void httpHdrContRangeDestroy(HttpHdrContRange *crange);
+extern HttpHdrContRange *httpHdrContRangeDup(const HttpHdrContRange * crange);
+extern void httpHdrContRangePackInto(const HttpHdrContRange * crange, Packer * p);
/* Http Header Tools */
extern int httpHeaderIdByName(const char *name, int name_len, const field_attrs_t * attrs, int end, int mask);
extern time_t httpHeaderGetTime(const HttpHeader * hdr, http_hdr_type id);
extern HttpHdrCc *httpHeaderGetCc(const HttpHeader * hdr);
extern HttpHdrRange *httpHeaderGetRange(const HttpHeader * hdr);
+extern HttpHdrContRange *httpHeaderGetContRange(const HttpHeader * hdr);
extern const char *httpHeaderGetStr(const HttpHeader * hdr, http_hdr_type id);
int httpHeaderDelFields(HttpHeader * hdr, const char *name);
/* store report about current header usage and other stats */
Stack specs;
};
+/* http content-range header field */
+struct _HttpHdrContRange {
+ HttpHdrRangeSpec spec;
+ size_t elength; /* entity length, not content length */
+};
+
+
/* a storage for an entry of one of possible types (for lower level routines) */
union _field_store {
int v_int;
String v_str;
HttpHdrCc *v_pcc;
HttpHdrRange *v_prange;
+ HttpHdrContRange *v_pcont_range;
HttpHdrExtField *v_pefield;
};
typedef struct _HttpHdrCc HttpHdrCc;
typedef struct _HttpHdrRangeSpec HttpHdrRangeSpec;
typedef struct _HttpHdrRange HttpHdrRange;
+typedef struct _HttpHdrContRange HttpHdrContRange;
typedef struct _HttpHdrExtField HttpHdrExtField;
typedef struct _HttpHeaderEntry HttpHeaderEntry;
typedef struct _HttpHeaderFieldStat HttpHeaderFieldStat;