3
A brief file description
5
@section license License
7
Licensed to the Apache Software Foundation (ASF) under one
8
or more contributor license agreements. See the NOTICE file
9
distributed with this work for additional information
10
regarding copyright ownership. The ASF licenses this file
11
to you under the Apache License, Version 2.0 (the
12
"License"); you may not use this file except in compliance
13
with the License. You may obtain a copy of the License at
15
http://www.apache.org/licenses/LICENSE-2.0
17
Unless required by applicable law or agreed to in writing, software
18
distributed under the License is distributed on an "AS IS" BASIS,
19
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
See the License for the specific language governing permissions and
21
limitations under the License.
33
/***********************************************************************
35
* C O M P I L E O P T I O N S *
37
***********************************************************************/
39
#define ENABLE_PARSER_FAST_PATHS 1
41
/***********************************************************************
45
***********************************************************************/
47
// TODO: We should enable the creation and use of these WKS. XXXX
49
static const char *cache_control_values[SIZEOF(cache_control_names)];
52
const char *HTTP_METHOD_CONNECT;
53
const char *HTTP_METHOD_DELETE;
54
const char *HTTP_METHOD_GET;
55
const char *HTTP_METHOD_HEAD;
56
const char *HTTP_METHOD_ICP_QUERY;
57
const char *HTTP_METHOD_OPTIONS;
58
const char *HTTP_METHOD_POST;
59
const char *HTTP_METHOD_PURGE;
60
const char *HTTP_METHOD_PUT;
61
const char *HTTP_METHOD_TRACE;
62
const char *HTTP_METHOD_PUSH;
64
int HTTP_WKSIDX_CONNECT;
65
int HTTP_WKSIDX_DELETE;
68
int HTTP_WKSIDX_ICP_QUERY;
69
int HTTP_WKSIDX_OPTIONS;
71
int HTTP_WKSIDX_PURGE;
73
int HTTP_WKSIDX_TRACE;
75
int HTTP_WKSIDX_METHODS_CNT = 0;
81
int HTTP_LEN_ICP_QUERY;
89
const char *HTTP_VALUE_BYTES;
90
const char *HTTP_VALUE_CHUNKED;
91
const char *HTTP_VALUE_CLOSE;
92
const char *HTTP_VALUE_COMPRESS;
93
const char *HTTP_VALUE_DEFLATE;
94
const char *HTTP_VALUE_GZIP;
95
const char *HTTP_VALUE_IDENTITY;
96
const char *HTTP_VALUE_KEEP_ALIVE;
97
const char *HTTP_VALUE_MAX_AGE;
98
const char *HTTP_VALUE_MAX_STALE;
99
const char *HTTP_VALUE_MIN_FRESH;
100
const char *HTTP_VALUE_MUST_REVALIDATE;
101
const char *HTTP_VALUE_NONE;
102
const char *HTTP_VALUE_NO_CACHE;
103
const char *HTTP_VALUE_NO_STORE;
104
const char *HTTP_VALUE_NO_TRANSFORM;
105
const char *HTTP_VALUE_ONLY_IF_CACHED;
106
const char *HTTP_VALUE_PRIVATE;
107
const char *HTTP_VALUE_PROXY_REVALIDATE;
108
const char *HTTP_VALUE_PUBLIC;
109
const char *HTTP_VALUE_S_MAXAGE;
110
const char *HTTP_VALUE_NEED_REVALIDATE_ONCE;
111
// Cache-control: extension "need-revalidate-once" is used internally by T.S.
112
// to invalidate a document, and it is not returned/forwarded.
113
// If a cached document has this extension set (ie, is invalidated),
114
// then the T.S. needs to revalidate the document once before returning it.
115
// After a successful revalidation, the extension will be removed by T.S.
116
// To set or unset this directive should be done via the following two
118
// set_cooked_cc_need_revalidate_once()
119
// unset_cooked_cc_need_revalidate_once()
120
// To test, use regular Cache-control testing functions, eg,
121
// is_cache_control_set(HTTP_VALUE_NEED_REVALIDATE_ONCE)
124
int HTTP_LEN_CHUNKED;
126
int HTTP_LEN_COMPRESS;
127
int HTTP_LEN_DEFLATE;
129
int HTTP_LEN_IDENTITY;
130
int HTTP_LEN_KEEP_ALIVE;
131
int HTTP_LEN_MAX_AGE;
132
int HTTP_LEN_MAX_STALE;
133
int HTTP_LEN_MIN_FRESH;
134
int HTTP_LEN_MUST_REVALIDATE;
136
int HTTP_LEN_NO_CACHE;
137
int HTTP_LEN_NO_STORE;
138
int HTTP_LEN_NO_TRANSFORM;
139
int HTTP_LEN_ONLY_IF_CACHED;
140
int HTTP_LEN_PRIVATE;
141
int HTTP_LEN_PROXY_REVALIDATE;
143
int HTTP_LEN_S_MAXAGE;
144
int HTTP_LEN_NEED_REVALIDATE_ONCE;
146
/***********************************************************************
148
* U T I L I T Y R O U T I N E S *
150
***********************************************************************/
155
return ((c <= '9') && (c >= '0'));
158
/***********************************************************************
162
***********************************************************************/
165
http_hdr_adjust(HTTPHdrImpl * hdrp, int32_t offset, int32_t length, int32_t delta)
168
NOWARN_UNUSED(offset);
169
NOWARN_UNUSED(length);
170
NOWARN_UNUSED(delta);
171
ink_release_assert(!"http_hdr_adjust not implemented");
174
/*-------------------------------------------------------------------------
175
-------------------------------------------------------------------------*/
178
http_init(const char *path)
188
HTTP_METHOD_CONNECT = hdrtoken_string_to_wks("CONNECT");
189
HTTP_METHOD_DELETE = hdrtoken_string_to_wks("DELETE");
190
HTTP_METHOD_GET = hdrtoken_string_to_wks("GET");
191
HTTP_METHOD_HEAD = hdrtoken_string_to_wks("HEAD");
192
HTTP_METHOD_ICP_QUERY = hdrtoken_string_to_wks("ICP_QUERY");
193
HTTP_METHOD_OPTIONS = hdrtoken_string_to_wks("OPTIONS");
194
HTTP_METHOD_POST = hdrtoken_string_to_wks("POST");
195
HTTP_METHOD_PURGE = hdrtoken_string_to_wks("PURGE");
196
HTTP_METHOD_PUT = hdrtoken_string_to_wks("PUT");
197
HTTP_METHOD_TRACE = hdrtoken_string_to_wks("TRACE");
198
HTTP_METHOD_PUSH = hdrtoken_string_to_wks("PUSH");
200
// HTTP methods index calculation. Don't forget to count them!
201
// Don't change the order of calculation! Each index has related bitmask (see http quick filter)
202
HTTP_WKSIDX_CONNECT = hdrtoken_wks_to_index(HTTP_METHOD_CONNECT);
203
HTTP_WKSIDX_METHODS_CNT++;
204
HTTP_WKSIDX_DELETE = hdrtoken_wks_to_index(HTTP_METHOD_DELETE);
205
HTTP_WKSIDX_METHODS_CNT++;
206
HTTP_WKSIDX_GET = hdrtoken_wks_to_index(HTTP_METHOD_GET);
207
HTTP_WKSIDX_METHODS_CNT++;
208
HTTP_WKSIDX_HEAD = hdrtoken_wks_to_index(HTTP_METHOD_HEAD);
209
HTTP_WKSIDX_METHODS_CNT++;
210
HTTP_WKSIDX_ICP_QUERY = hdrtoken_wks_to_index(HTTP_METHOD_ICP_QUERY);
211
HTTP_WKSIDX_METHODS_CNT++;
212
HTTP_WKSIDX_OPTIONS = hdrtoken_wks_to_index(HTTP_METHOD_OPTIONS);
213
HTTP_WKSIDX_METHODS_CNT++;
214
HTTP_WKSIDX_POST = hdrtoken_wks_to_index(HTTP_METHOD_POST);
215
HTTP_WKSIDX_METHODS_CNT++;
216
HTTP_WKSIDX_PURGE = hdrtoken_wks_to_index(HTTP_METHOD_PURGE);
217
HTTP_WKSIDX_METHODS_CNT++;
218
HTTP_WKSIDX_PUT = hdrtoken_wks_to_index(HTTP_METHOD_PUT);
219
HTTP_WKSIDX_METHODS_CNT++;
220
HTTP_WKSIDX_TRACE = hdrtoken_wks_to_index(HTTP_METHOD_TRACE);
221
HTTP_WKSIDX_METHODS_CNT++;
222
HTTP_WKSIDX_PUSH = hdrtoken_wks_to_index(HTTP_METHOD_PUSH);
223
HTTP_WKSIDX_METHODS_CNT++;
226
HTTP_LEN_CONNECT = hdrtoken_wks_to_length(HTTP_METHOD_CONNECT);
227
HTTP_LEN_DELETE = hdrtoken_wks_to_length(HTTP_METHOD_DELETE);
228
HTTP_LEN_GET = hdrtoken_wks_to_length(HTTP_METHOD_GET);
229
HTTP_LEN_HEAD = hdrtoken_wks_to_length(HTTP_METHOD_HEAD);
230
HTTP_LEN_ICP_QUERY = hdrtoken_wks_to_length(HTTP_METHOD_ICP_QUERY);
231
HTTP_LEN_OPTIONS = hdrtoken_wks_to_length(HTTP_METHOD_OPTIONS);
232
HTTP_LEN_POST = hdrtoken_wks_to_length(HTTP_METHOD_POST);
233
HTTP_LEN_PURGE = hdrtoken_wks_to_length(HTTP_METHOD_PURGE);
234
HTTP_LEN_PUT = hdrtoken_wks_to_length(HTTP_METHOD_PUT);
235
HTTP_LEN_TRACE = hdrtoken_wks_to_length(HTTP_METHOD_TRACE);
236
HTTP_LEN_PUSH = hdrtoken_wks_to_length(HTTP_METHOD_PUSH);
238
HTTP_VALUE_BYTES = hdrtoken_string_to_wks("bytes");
239
HTTP_VALUE_CHUNKED = hdrtoken_string_to_wks("chunked");
240
HTTP_VALUE_CLOSE = hdrtoken_string_to_wks("close");
241
HTTP_VALUE_COMPRESS = hdrtoken_string_to_wks("compress");
242
HTTP_VALUE_DEFLATE = hdrtoken_string_to_wks("deflate");
243
HTTP_VALUE_GZIP = hdrtoken_string_to_wks("gzip");
244
HTTP_VALUE_IDENTITY = hdrtoken_string_to_wks("identity");
245
HTTP_VALUE_KEEP_ALIVE = hdrtoken_string_to_wks("keep-alive");
246
HTTP_VALUE_MAX_AGE = hdrtoken_string_to_wks("max-age");
247
HTTP_VALUE_MAX_STALE = hdrtoken_string_to_wks("max-stale");
248
HTTP_VALUE_MIN_FRESH = hdrtoken_string_to_wks("min-fresh");
249
HTTP_VALUE_MUST_REVALIDATE = hdrtoken_string_to_wks("must-revalidate");
250
HTTP_VALUE_NONE = hdrtoken_string_to_wks("none");
251
HTTP_VALUE_NO_CACHE = hdrtoken_string_to_wks("no-cache");
252
HTTP_VALUE_NO_STORE = hdrtoken_string_to_wks("no-store");
253
HTTP_VALUE_NO_TRANSFORM = hdrtoken_string_to_wks("no-transform");
254
HTTP_VALUE_ONLY_IF_CACHED = hdrtoken_string_to_wks("only-if-cached");
255
HTTP_VALUE_PRIVATE = hdrtoken_string_to_wks("private");
256
HTTP_VALUE_PROXY_REVALIDATE = hdrtoken_string_to_wks("proxy-revalidate");
257
HTTP_VALUE_PUBLIC = hdrtoken_string_to_wks("public");
258
HTTP_VALUE_S_MAXAGE = hdrtoken_string_to_wks("s-maxage");
259
HTTP_VALUE_NEED_REVALIDATE_ONCE = hdrtoken_string_to_wks("need-revalidate-once");
261
HTTP_LEN_BYTES = hdrtoken_wks_to_length(HTTP_VALUE_BYTES);
262
HTTP_LEN_CHUNKED = hdrtoken_wks_to_length(HTTP_VALUE_CHUNKED);
263
HTTP_LEN_CLOSE = hdrtoken_wks_to_length(HTTP_VALUE_CLOSE);
264
HTTP_LEN_COMPRESS = hdrtoken_wks_to_length(HTTP_VALUE_COMPRESS);
265
HTTP_LEN_DEFLATE = hdrtoken_wks_to_length(HTTP_VALUE_DEFLATE);
266
HTTP_LEN_GZIP = hdrtoken_wks_to_length(HTTP_VALUE_GZIP);
267
HTTP_LEN_IDENTITY = hdrtoken_wks_to_length(HTTP_VALUE_IDENTITY);
268
HTTP_LEN_KEEP_ALIVE = hdrtoken_wks_to_length(HTTP_VALUE_KEEP_ALIVE);
269
HTTP_LEN_MAX_AGE = hdrtoken_wks_to_length(HTTP_VALUE_MAX_AGE);
270
HTTP_LEN_MAX_STALE = hdrtoken_wks_to_length(HTTP_VALUE_MAX_STALE);
271
HTTP_LEN_MIN_FRESH = hdrtoken_wks_to_length(HTTP_VALUE_MIN_FRESH);
272
HTTP_LEN_MUST_REVALIDATE = hdrtoken_wks_to_length(HTTP_VALUE_MUST_REVALIDATE);
273
HTTP_LEN_NONE = hdrtoken_wks_to_length(HTTP_VALUE_NONE);
274
HTTP_LEN_NO_CACHE = hdrtoken_wks_to_length(HTTP_VALUE_NO_CACHE);
275
HTTP_LEN_NO_STORE = hdrtoken_wks_to_length(HTTP_VALUE_NO_STORE);
276
HTTP_LEN_NO_TRANSFORM = hdrtoken_wks_to_length(HTTP_VALUE_NO_TRANSFORM);
277
HTTP_LEN_ONLY_IF_CACHED = hdrtoken_wks_to_length(HTTP_VALUE_ONLY_IF_CACHED);
278
HTTP_LEN_PRIVATE = hdrtoken_wks_to_length(HTTP_VALUE_PRIVATE);
279
HTTP_LEN_PROXY_REVALIDATE = hdrtoken_wks_to_length(HTTP_VALUE_PROXY_REVALIDATE);
280
HTTP_LEN_PUBLIC = hdrtoken_wks_to_length(HTTP_VALUE_PUBLIC);
281
HTTP_LEN_S_MAXAGE = hdrtoken_wks_to_length(HTTP_VALUE_S_MAXAGE);
282
HTTP_LEN_NEED_REVALIDATE_ONCE = hdrtoken_wks_to_length(HTTP_VALUE_NEED_REVALIDATE_ONCE);
284
// TODO: We need to look into enable these CC values as WKS XXX
286
for (int i = 0; i < (int) SIZEOF(cache_control_values); i++) {
287
cache_control_values[i] = hdrtoken_string_to_wks(cache_control_names[i]);
293
/*-------------------------------------------------------------------------
294
-------------------------------------------------------------------------*/
297
http_hdr_create(HdrHeap * heap, HTTPType polarity)
301
hh = (HTTPHdrImpl *) heap->allocate_obj(sizeof(HTTPHdrImpl), HDR_HEAP_OBJ_HTTP_HEADER);
302
http_hdr_init(heap, hh, polarity);
306
/*-------------------------------------------------------------------------
307
-------------------------------------------------------------------------*/
310
http_hdr_init(HdrHeap * heap, HTTPHdrImpl * hh, HTTPType polarity)
312
memset(&(hh->u), 0, sizeof(hh->u));
313
hh->m_polarity = polarity;
314
hh->m_version = HTTP_VERSION(0, 9);
315
hh->m_fields_impl = mime_hdr_create(heap);
316
if (polarity == HTTP_TYPE_REQUEST) {
317
hh->u.req.m_url_impl = url_create(heap);
318
hh->u.req.m_method_wks_idx = -1;
322
/*-------------------------------------------------------------------------
323
-------------------------------------------------------------------------*/
326
http_hdr_copy_onto(HTTPHdrImpl * s_hh, HdrHeap * s_heap, HTTPHdrImpl * d_hh, HdrHeap * d_heap, bool inherit_strs)
328
MIMEHdrImpl *s_mh, *d_mh;
329
URLImpl *s_url, *d_url;
332
s_mh = s_hh->m_fields_impl;
333
s_url = s_hh->u.req.m_url_impl;
334
d_mh = d_hh->m_fields_impl;
335
d_url = d_hh->u.req.m_url_impl;
336
d_polarity = d_hh->m_polarity;
338
ink_assert(s_hh->m_polarity != HTTP_TYPE_UNKNOWN);
339
ink_assert(s_mh != NULL);
340
ink_assert(d_mh != NULL);
342
memcpy(d_hh, s_hh, sizeof(HTTPHdrImpl));
343
d_hh->m_fields_impl = d_mh; // restore pre-memcpy mime impl
345
if (s_hh->m_polarity == HTTP_TYPE_REQUEST) {
346
if (d_polarity == HTTP_TYPE_REQUEST) {
347
d_hh->u.req.m_url_impl = d_url; // restore pre-memcpy url impl
349
d_url = d_hh->u.req.m_url_impl = url_create(d_heap); // create url
351
url_copy_onto(s_url, s_heap, d_url, d_heap, false);
352
} else if (d_polarity == HTTP_TYPE_REQUEST) {
353
// gender bender. Need to kill off old url
357
mime_hdr_copy_onto(s_mh, s_heap, d_mh, d_heap, false);
359
d_heap->inherit_string_heaps(s_heap);
362
/*-------------------------------------------------------------------------
363
-------------------------------------------------------------------------*/
366
http_hdr_clone(HTTPHdrImpl * s_hh, HdrHeap * s_heap, HdrHeap * d_heap)
370
// FIX: A future optimization is to copy contiguous objects with
371
// one single memcpy. For this first optimization, we just
372
// copy each object separately.
374
d_hh = http_hdr_create(d_heap, s_hh->m_polarity);
375
http_hdr_copy_onto(s_hh, s_heap, d_hh, d_heap, ((s_heap != d_heap) ? true : false));
379
/*-------------------------------------------------------------------------
380
-------------------------------------------------------------------------*/
383
http_hdr_version_to_string(int32_t version, char *buf9)
385
ink_debug_assert(HTTP_MAJOR(version) < 10);
386
ink_debug_assert(HTTP_MINOR(version) < 10);
393
buf9[5] = '0' + HTTP_MAJOR(version);
395
buf9[7] = '0' + HTTP_MINOR(version);
401
/*-------------------------------------------------------------------------
402
-------------------------------------------------------------------------*/
405
http_version_print(int32_t version, char *buf, int bufsize, int *bufindex, int *dumpoffset)
407
#define TRY(x) if (!x) return 0
410
http_hdr_version_to_string(version, tmpbuf);
411
TRY(mime_mem_print(tmpbuf, 8, buf, bufsize, bufindex, dumpoffset));
417
/*-------------------------------------------------------------------------
418
-------------------------------------------------------------------------*/
421
http_hdr_print(HdrHeap * heap, HTTPHdrImpl * hdr, char *buf, int bufsize, int *bufindex, int *dumpoffset)
423
#define TRY(x) if (!x) return 0
429
ink_debug_assert((hdr->m_polarity == HTTP_TYPE_REQUEST) || (hdr->m_polarity == HTTP_TYPE_RESPONSE));
431
if (hdr->m_polarity == HTTP_TYPE_REQUEST) {
433
if (hdr->u.req.m_ptr_method == NULL)
436
if ((buf != NULL) && (*dumpoffset == 0) && (bufsize - *bufindex >= hdr->u.req.m_len_method + 1)) { // fastpath
439
memcpy(p, hdr->u.req.m_ptr_method, hdr->u.req.m_len_method);
440
p += hdr->u.req.m_len_method;
442
*bufindex += hdr->u.req.m_len_method + 1;
444
if (hdr->u.req.m_url_impl) {
445
TRY(url_print(hdr->u.req.m_url_impl, buf, bufsize, bufindex, dumpoffset));
446
if (bufsize - *bufindex >= 1) {
455
if (bufsize - *bufindex >= 9) {
456
http_hdr_version_to_string(hdr->m_version, p);
457
*bufindex += 9 - 1; // overwrite '\0';
459
TRY(http_version_print(hdr->m_version, buf, bufsize, bufindex, dumpoffset));
462
if (bufsize - *bufindex >= 2) {
468
TRY(mime_mem_print("\r\n", 2, buf, bufsize, bufindex, dumpoffset));
471
TRY(mime_hdr_print(heap, hdr->m_fields_impl, buf, bufsize, bufindex, dumpoffset));
475
TRY(mime_mem_print(hdr->u.req.m_ptr_method, hdr->u.req.m_len_method, buf, bufsize, bufindex, dumpoffset));
477
TRY(mime_mem_print(" ", 1, buf, bufsize, bufindex, dumpoffset));
479
if (hdr->u.req.m_url_impl) {
480
TRY(url_print(hdr->u.req.m_url_impl, buf, bufsize, bufindex, dumpoffset));
481
TRY(mime_mem_print(" ", 1, buf, bufsize, bufindex, dumpoffset));
484
TRY(http_version_print(hdr->m_version, buf, bufsize, bufindex, dumpoffset));
486
TRY(mime_mem_print("\r\n", 2, buf, bufsize, bufindex, dumpoffset));
488
TRY(mime_hdr_print(heap, hdr->m_fields_impl, buf, bufsize, bufindex, dumpoffset));
491
} else { // hdr->m_polarity == HTTP_TYPE_RESPONSE
493
if ((buf != NULL) && (*dumpoffset == 0) && (bufsize - *bufindex >= 9 + 6 + 1)) { // fastpath
496
http_hdr_version_to_string(hdr->m_version, p);
497
p += 8; // overwrite '\0' with space
501
hdrstat = http_hdr_status_get(hdr);
502
if (hdrstat == 200) {
508
tmplen = mime_format_int(p, hdrstat, (bufsize - (p - buf)));
509
ink_debug_assert(tmplen <= 6);
513
*bufindex += tmplen + 1;
515
if (hdr->u.resp.m_ptr_reason) {
516
TRY(mime_mem_print(hdr->u.resp.m_ptr_reason, hdr->u.resp.m_len_reason, buf, bufsize, bufindex, dumpoffset));
519
if (bufsize - *bufindex >= 2) {
525
TRY(mime_mem_print("\r\n", 2, buf, bufsize, bufindex, dumpoffset));
528
TRY(mime_hdr_print(heap, hdr->m_fields_impl, buf, bufsize, bufindex, dumpoffset));
532
TRY(http_version_print(hdr->m_version, buf, bufsize, bufindex, dumpoffset));
534
TRY(mime_mem_print(" ", 1, buf, bufsize, bufindex, dumpoffset));
536
tmplen = mime_format_int(tmpbuf, http_hdr_status_get(hdr), sizeof(tmpbuf));
538
TRY(mime_mem_print(tmpbuf, tmplen, buf, bufsize, bufindex, dumpoffset));
540
TRY(mime_mem_print(" ", 1, buf, bufsize, bufindex, dumpoffset));
542
if (hdr->u.resp.m_ptr_reason) {
543
TRY(mime_mem_print(hdr->u.resp.m_ptr_reason, hdr->u.resp.m_len_reason, buf, bufsize, bufindex, dumpoffset));
546
TRY(mime_mem_print("\r\n", 2, buf, bufsize, bufindex, dumpoffset));
548
TRY(mime_hdr_print(heap, hdr->m_fields_impl, buf, bufsize, bufindex, dumpoffset));
558
/*-------------------------------------------------------------------------
559
-------------------------------------------------------------------------*/
562
http_hdr_describe(HdrHeapObjImpl * raw, bool recurse)
564
HTTPHdrImpl *obj = (HTTPHdrImpl *) raw;
566
if (obj->m_polarity == HTTP_TYPE_REQUEST) {
567
Debug("http", "[TYPE: REQ, V: %04X, URL: 0x%04X, METHOD: \"%.*s\", METHOD_LEN: %d, FIELDS: 0x%04X]\n",
568
obj->m_version, obj->u.req.m_url_impl,
569
obj->u.req.m_len_method, (obj->u.req.m_ptr_method ? obj->u.req.m_ptr_method : "NULL"),
570
obj->u.req.m_len_method, obj->m_fields_impl);
572
if (obj->u.req.m_url_impl)
573
obj_describe(obj->u.req.m_url_impl, recurse);
574
if (obj->m_fields_impl)
575
obj_describe(obj->m_fields_impl, recurse);
578
Debug("http", "[TYPE: RSP, V: %04X, STATUS: %d, REASON: \"%.*s\", REASON_LEN: %d, FIELDS: 0x%04X]\n",
579
obj->m_version, obj->u.resp.m_status,
580
obj->u.resp.m_len_reason, (obj->u.resp.m_ptr_reason ? obj->u.resp.m_ptr_reason : "NULL"),
581
obj->u.resp.m_len_reason, obj->m_fields_impl);
583
if (obj->m_fields_impl)
584
obj_describe(obj->m_fields_impl, recurse);
589
/*-------------------------------------------------------------------------
590
-------------------------------------------------------------------------*/
593
http_hdr_length_get(HTTPHdrImpl * hdr)
597
if (hdr->m_polarity == HTTP_TYPE_REQUEST) {
598
if (hdr->u.req.m_ptr_method) {
599
length = hdr->u.req.m_len_method;
606
if (hdr->u.req.m_url_impl) {
607
length += url_length_get(hdr->u.req.m_url_impl);
612
length += 8; // HTTP/%d.%d
614
length += 2; // "\r\n"
615
} else if (hdr->m_polarity == HTTP_TYPE_RESPONSE) {
616
if (hdr->u.resp.m_ptr_reason) {
617
length = hdr->u.resp.m_len_reason;
623
length += 8; // HTTP/%d.%d
627
length += 3; // status
631
length += 2; // "\r\n"
634
length += mime_hdr_length_get(hdr->m_fields_impl);
640
/*-------------------------------------------------------------------------
641
-------------------------------------------------------------------------*/
644
http_hdr_type_set(HTTPHdrImpl * hh, HTTPType type)
646
hh->m_polarity = type;
649
/*-------------------------------------------------------------------------
650
-------------------------------------------------------------------------*/
653
http_hdr_version_set(HTTPHdrImpl * hh, int32_t ver)
658
/*-------------------------------------------------------------------------
659
-------------------------------------------------------------------------*/
662
http_hdr_method_get(HTTPHdrImpl * hh, int *length)
666
ink_debug_assert(hh->m_polarity == HTTP_TYPE_REQUEST);
668
if (hh->u.req.m_method_wks_idx >= 0) {
669
str = hdrtoken_index_to_wks(hh->u.req.m_method_wks_idx);
670
*length = hdrtoken_index_to_length(hh->u.req.m_method_wks_idx);
672
str = hh->u.req.m_ptr_method;
673
*length = hh->u.req.m_len_method;
679
/*-------------------------------------------------------------------------
680
-------------------------------------------------------------------------*/
683
http_hdr_method_set(HdrHeap * heap,
684
HTTPHdrImpl * hh, const char *method, int16_t method_wks_idx, int method_length, bool must_copy)
686
ink_debug_assert(hh->m_polarity == HTTP_TYPE_REQUEST);
688
hh->u.req.m_method_wks_idx = method_wks_idx;
689
mime_str_u16_set(heap, method, method_length, &(hh->u.req.m_ptr_method), &(hh->u.req.m_len_method), must_copy);
692
/*-------------------------------------------------------------------------
693
-------------------------------------------------------------------------*/
696
http_hdr_url_set(HdrHeap * heap, HTTPHdrImpl * hh, URLImpl * url)
698
ink_debug_assert(hh->m_polarity == HTTP_TYPE_REQUEST);
699
if (hh->u.req.m_url_impl != url) {
700
if (hh->u.req.m_url_impl != NULL) {
701
heap->deallocate_obj(hh->u.req.m_url_impl);
703
hh->u.req.m_url_impl = url;
708
/*-------------------------------------------------------------------------
709
-------------------------------------------------------------------------*/
712
http_hdr_status_set(HTTPHdrImpl * hh, HTTPStatus status)
714
ink_debug_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
715
hh->u.resp.m_status = status;
718
/*-------------------------------------------------------------------------
719
-------------------------------------------------------------------------*/
722
http_hdr_reason_get(HTTPHdrImpl * hh, int *length)
724
ink_debug_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
725
*length = hh->u.resp.m_len_reason;
726
return (hh->u.resp.m_ptr_reason);
729
/*-------------------------------------------------------------------------
730
-------------------------------------------------------------------------*/
733
http_hdr_reason_set(HdrHeap * heap, HTTPHdrImpl * hh, const char *value, int length, bool must_copy)
735
ink_debug_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
736
mime_str_u16_set(heap, value, length, &(hh->u.resp.m_ptr_reason), &(hh->u.resp.m_len_reason), must_copy);
739
/*-------------------------------------------------------------------------
740
-------------------------------------------------------------------------*/
743
http_hdr_reason_lookup(HTTPStatus status)
746
case HTTP_STATUS_NONE:
748
case HTTP_STATUS_CONTINUE:
750
case HTTP_STATUS_SWITCHING_PROTOCOL:
751
return "Switching Protocol";
754
case HTTP_STATUS_CREATED:
756
case HTTP_STATUS_ACCEPTED:
758
case HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION:
759
return "Non Authoritative Information";
760
case HTTP_STATUS_NO_CONTENT:
762
case HTTP_STATUS_RESET_CONTENT:
763
return "Reset Content";
764
case HTTP_STATUS_PARTIAL_CONTENT:
765
return "Partial Content";
766
case HTTP_STATUS_MULTIPLE_CHOICES:
767
return "Multiple Choices";
768
case HTTP_STATUS_MOVED_PERMANENTLY:
769
return "Moved Permanently";
770
case HTTP_STATUS_MOVED_TEMPORARILY:
771
return "Moved Temporarily";
772
case HTTP_STATUS_SEE_OTHER:
774
case HTTP_STATUS_NOT_MODIFIED:
775
return "Not Modified";
776
case HTTP_STATUS_USE_PROXY:
778
case HTTP_STATUS_TEMPORARY_REDIRECT:
779
return "Temporary Redirect";
780
case HTTP_STATUS_BAD_REQUEST:
781
return "Bad Request";
782
case HTTP_STATUS_UNAUTHORIZED:
783
return "Unauthorized";
784
case HTTP_STATUS_PAYMENT_REQUIRED:
785
return "Payment Required";
786
case HTTP_STATUS_FORBIDDEN:
788
case HTTP_STATUS_NOT_FOUND:
790
case HTTP_STATUS_METHOD_NOT_ALLOWED:
791
return "Method Not Allowed";
792
case HTTP_STATUS_NOT_ACCEPTABLE:
793
return "Not Acceptable";
794
case HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED:
795
return "Proxy Authentication Required";
796
case HTTP_STATUS_REQUEST_TIMEOUT:
797
return "Request Timeout";
798
case HTTP_STATUS_CONFLICT:
800
case HTTP_STATUS_GONE:
802
case HTTP_STATUS_LENGTH_REQUIRED:
803
return "Length Required";
804
case HTTP_STATUS_PRECONDITION_FAILED:
805
return "Precondition Failed";
806
case HTTP_STATUS_RANGE_NOT_SATISFIABLE:
807
return "Requested Range Not Satisfiable";
808
case HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE:
809
return "Request Entity Too Large";
810
case HTTP_STATUS_REQUEST_URI_TOO_LONG:
811
return "Request URI Too Long";
812
case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:
813
return "Unsupported Media Type";
814
case HTTP_STATUS_INTERNAL_SERVER_ERROR:
815
return "Internal Server Error";
816
case HTTP_STATUS_NOT_IMPLEMENTED:
817
return "Not Implemented";
818
case HTTP_STATUS_BAD_GATEWAY:
819
return "Bad Gateway";
820
case HTTP_STATUS_SERVICE_UNAVAILABLE:
821
return "Service Unavailable";
822
case HTTP_STATUS_GATEWAY_TIMEOUT:
823
return "Gateway Timeout";
824
case HTTP_STATUS_HTTPVER_NOT_SUPPORTED:
825
return "HTTP Version Not Supported";
831
/*-------------------------------------------------------------------------
832
-------------------------------------------------------------------------*/
835
_http_parser_init(HTTPParser * parser)
837
parser->m_parsing_http = true;
840
//////////////////////////////////////////////////////
841
// init first time structure setup //
842
// clear resets an already-initialized structure //
843
//////////////////////////////////////////////////////
846
http_parser_init(HTTPParser * parser)
848
_http_parser_init(parser);
849
mime_parser_init(&parser->m_mime_parser);
853
http_parser_clear(HTTPParser * parser)
855
_http_parser_init(parser);
856
mime_parser_clear(&parser->m_mime_parser);
859
/*-------------------------------------------------------------------------
860
-------------------------------------------------------------------------*/
862
#define GETNEXT(label) { \
869
#define GETPREV(label) { \
871
if (cur < line_start) { \
876
// NOTE: end is ONE CHARACTER PAST end of string!
879
http_parser_parse_req(HTTPParser * parser,
881
HTTPHdrImpl * hh, const char **start, const char *end, bool must_copy_strings, bool eof)
883
if (parser->m_parsing_http) {
884
MIMEScanner *scanner = &parser->m_mime_parser.m_scanner;
890
const char *line_start;
891
const char *real_end;
892
const char *method_start;
893
const char *method_end;
894
const char *url_start;
896
const char *version_start;
897
const char *version_end;
902
hh->m_polarity = HTTP_TYPE_REQUEST;
904
err = mime_scanner_get(scanner, start, real_end, &line_start, &end, &line_is_real, eof, MIME_SCANNER_TYPE_LINE);
907
// We have to get a request line. If we get parse done here,
908
// that meas we got an empty request
909
if (err == PARSE_DONE)
911
if (err == PARSE_CONT)
915
must_copy_strings = (must_copy_strings || (!line_is_real));
917
#if (ENABLE_PARSER_FAST_PATHS)
918
// first try fast path
919
if (end - cur >= 16) {
920
if (((cur[0] ^ 'G') | (cur[1] ^ 'E') | (cur[2] ^ 'T')) != 0)
922
if (((end[-10] ^ 'H') | (end[-9] ^ 'T') | (end[-8] ^ 'T') | (end[-7] ^ 'P') |
923
(end[-6] ^ '/') | (end[-4] ^ '.') | (end[-2] ^ '\r') | (end[-1] ^ '\n')) != 0)
925
if (!(is_digit(end[-5]) && is_digit(end[-3])))
927
if (!(ParseRules::is_space(cur[3]) && (!ParseRules::is_space(cur[4])) &&
928
(!ParseRules::is_space(end[-12])) && ParseRules::is_space(end[-11])))
930
if (&(cur[4]) >= &(end[-11]))
933
int32_t version = HTTP_VERSION(end[-5] - '0', end[-3] - '0');
935
http_hdr_method_set(heap, hh, &(cur[0]), hdrtoken_wks_to_index(HTTP_METHOD_GET), 3, must_copy_strings);
936
ink_debug_assert(hh->u.req.m_url_impl != NULL);
937
url = hh->u.req.m_url_impl;
938
url_start = &(cur[4]);
939
err =::url_parse(heap, url, &url_start, &(end[-11]), must_copy_strings);
942
http_hdr_version_set(hh, version);
945
parser->m_parsing_http = false;
946
if (version == HTTP_VERSION(0, 9))
949
return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
959
version_start = NULL;
963
if (ParseRules::is_cr(*cur))
965
if (ParseRules::is_lf(*cur))
969
if (ParseRules::is_ws(*cur)) {
976
if (ParseRules::is_ws(*cur)) {
985
if (ParseRules::is_lf(*cur) && (cur >= line_start)) {
988
if (ParseRules::is_cr(*cur) && (cur >= line_start)) {
991
// A client may add extra white spaces after the HTTP version.
992
// So, skip white spaces.
993
while (ParseRules::is_ws(*cur) && (cur >= line_start)) {
996
version_end = cur + 1;
998
if (ParseRules::is_digit(*cur)) {
1000
goto parse_version2;
1004
goto parse_version3;
1008
if (ParseRules::is_digit(*cur)) {
1010
goto parse_version3;
1014
goto parse_version4;
1018
if ((*cur != 'P') && (*cur != 'p')) {
1022
if ((*cur != 'T') && (*cur != 't')) {
1026
if ((*cur != 'T') && (*cur != 't')) {
1030
if ((*cur != 'H') && (*cur != 'h')) {
1033
version_start = cur;
1036
url_start = method_end + 1;
1037
if (version_start) {
1038
url_end = version_start - 1;
1042
while ((url_start < end) && ParseRules::is_ws(*url_start)) {
1045
while ((url_end >= line_start) && ParseRules::is_wslfcr(*url_end)) {
1051
if (!method_start || !method_end)
1054
int method_wks_idx = hdrtoken_tokenize(method_start,
1055
(int) (method_end - method_start));
1056
http_hdr_method_set(heap, hh, method_start, method_wks_idx, (int) (method_end - method_start), must_copy_strings);
1058
if (!url_start || !url_end)
1061
ink_debug_assert(hh->u.req.m_url_impl != NULL);
1063
url = hh->u.req.m_url_impl;
1064
err =::url_parse(heap, url, &url_start, url_end, must_copy_strings);
1070
if (version_start && version_end) {
1071
version = http_parse_version(version_start, version_end);
1073
version = HTTP_VERSION(0, 9);
1074
http_hdr_version_set(hh, version);
1077
parser->m_parsing_http = false;
1078
if (version == HTTP_VERSION(0, 9))
1082
return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
1085
/*-------------------------------------------------------------------------
1086
-------------------------------------------------------------------------*/
1089
http_parser_parse_resp(HTTPParser * parser,
1091
HTTPHdrImpl * hh, const char **start, const char *end, bool must_copy_strings, bool eof)
1093
if (parser->m_parsing_http) {
1094
MIMEScanner *scanner = &parser->m_mime_parser.m_scanner;
1096
MIMEParseResult err;
1099
const char *line_start;
1100
const char *real_end;
1101
const char *version_start;
1102
const char *version_end;
1103
const char *status_start;
1104
const char *status_end;
1105
const char *reason_start;
1106
const char *reason_end;
1107
const char *old_start;
1112
hh->m_polarity = HTTP_TYPE_RESPONSE;
1114
err = mime_scanner_get(scanner, start, real_end, &line_start, &end, &line_is_real, eof, MIME_SCANNER_TYPE_LINE);
1117
if ((err == PARSE_DONE) || (err == PARSE_CONT))
1121
must_copy_strings = (must_copy_strings || (!line_is_real));
1123
#if (ENABLE_PARSER_FAST_PATHS)
1124
// first try fast path
1125
if (end - cur >= 16) {
1126
int http_match = ((cur[0] ^ 'H') | (cur[1] ^ 'T') | (cur[2] ^ 'T') | (cur[3] ^ 'P') |
1127
(cur[4] ^ '/') | (cur[6] ^ '.') | (cur[8] ^ ' '));
1128
if ((http_match != 0) ||
1129
(!(is_digit(cur[5]) && is_digit(cur[7]) &&
1130
is_digit(cur[9]) && is_digit(cur[10]) && is_digit(cur[11]) && (!ParseRules::is_space(cur[13]))))) {
1134
reason_start = &(cur[13]);
1135
reason_end = end - 1;
1136
while ((reason_end > reason_start + 1) && (ParseRules::is_space(reason_end[-1])))
1139
int32_t version = HTTP_VERSION(cur[5] - '0', cur[7] - '0');
1140
HTTPStatus status = (HTTPStatus) ((cur[9] - '0') * 100 + (cur[10] - '0') * 10 + (cur[11] - '0'));
1142
http_hdr_version_set(hh, version);
1143
http_hdr_status_set(hh, status);
1144
http_hdr_reason_set(heap, hh, reason_start, (int) (reason_end - reason_start), must_copy_strings);
1147
parser->m_parsing_http = false;
1148
return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
1153
version_start = NULL;
1155
status_start = NULL;
1157
reason_start = NULL;
1160
version_start = cur = line_start;
1161
if ((*cur != 'H') && (*cur != 'h')) {
1165
if ((*cur != 'T') && (*cur != 't')) {
1169
if ((*cur != 'T') && (*cur != 't')) {
1173
if ((*cur != 'P') && (*cur != 'p')) {
1182
if (ParseRules::is_digit(*cur)) {
1184
goto parse_version2;
1188
goto parse_version3;
1192
if (ParseRules::is_digit(*cur)) {
1194
goto parse_version3;
1196
if (ParseRules::is_ws(*cur)) {
1204
if (ParseRules::is_ws(*cur)) {
1211
if (ParseRules::is_digit(*cur)) {
1215
if (ParseRules::is_ws(*cur)) {
1222
if (ParseRules::is_ws(*cur)) {
1227
reason_end = end - 1;
1228
while ((reason_end >= line_start) && (ParseRules::is_cr(*reason_end) || ParseRules::is_lf(*reason_end))) {
1239
if (!version_start || !version_end) {
1243
http_hdr_version_set(hh, http_parse_version(version_start, version_end));
1245
if (status_start && status_end)
1246
http_hdr_status_set(hh, http_parse_status(status_start, status_end));
1248
if (reason_start && reason_end) {
1249
http_hdr_reason_set(heap, hh, reason_start, (int) (reason_end - reason_start), must_copy_strings);
1253
parser->m_parsing_http = false;
1256
return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
1259
/*-------------------------------------------------------------------------
1260
-------------------------------------------------------------------------*/
1263
http_parse_status(const char *start, const char *end)
1267
while ((start != end) && ParseRules::is_space(*start)) {
1271
while ((start != end) && ParseRules::is_digit(*start)) {
1272
status = (status * 10) + (*start++ - '0');
1275
return (HTTPStatus) status;
1278
/*-------------------------------------------------------------------------
1279
-------------------------------------------------------------------------*/
1282
http_parse_version(const char *start, const char *end)
1287
if ((end - start) < 8) {
1288
return HTTP_VERSION(0, 9);
1291
if (((start[0] == 'H') || (start[0] == 'h')) &&
1292
((start[1] == 'T') || (start[1] == 't')) &&
1293
((start[2] == 'T') || (start[2] == 't')) && ((start[3] == 'P') || (start[3] == 'p')) && (start[4] == '/')) {
1299
while ((start != end) && ParseRules::is_digit(*start)) {
1300
maj = (maj * 10) + (*start - '0');
1304
if (*start == '.') {
1308
while ((start != end) && ParseRules::is_digit(*start)) {
1309
min = (min * 10) + (*start - '0');
1313
return HTTP_VERSION(maj, min);
1316
return HTTP_VERSION(0, 9);
1319
/*-------------------------------------------------------------------------
1320
-------------------------------------------------------------------------*/
1323
http_str_store(Arena * arena, const char *str, int length)
1326
int idx = hdrtoken_tokenize(str, length, &wks);
1328
return arena->str_store(str, length);
1330
return (char *) wks;
1334
/*-------------------------------------------------------------------------
1335
-------------------------------------------------------------------------*/
1338
http_skip_ws(const char *&buf, int &len)
1340
while (len > 0 && *buf && ParseRules::is_ws(*buf)) {
1346
/*-------------------------------------------------------------------------
1347
-------------------------------------------------------------------------*/
1350
http_parse_qvalue(const char *&buf, int &len)
1361
while (len > 0 && *buf) {
1362
http_skip_ws(buf, len);
1367
http_skip_ws(buf, len);
1375
http_skip_ws(buf, len);
1378
while (len > 0 && *buf && ParseRules::is_digit(*buf)) {
1379
n = (n * 10) + (*buf++ - '0');
1388
while (len > 0 && *buf && ParseRules::is_digit(*buf)) {
1389
n += (*buf++ - '0') / (double) f;
1398
// The current parameter is not a q-value, so go to the next param.
1399
while (len > 0 && *buf) {
1404
// Move to the character after the semicolon.
1416
/*-------------------------------------------------------------------------
1417
-------------------------------------------------------------------------*/
1420
/*-------------------------------------------------------------------------
1421
TE = "TE" ":" #( t-codings )
1422
t-codings = "trailers" | ( transfer-extension [ accept-params ] )
1423
-------------------------------------------------------------------------*/
1426
http_parse_te(const char *buf, int len, Arena * arena)
1431
http_skip_ws(buf, len);
1435
while (len > 0 && *buf && (*buf != ';')) {
1440
val = (HTTPValTE *) arena->alloc(sizeof(HTTPValTE));
1441
val->encoding = http_str_store(arena, s, (int) (buf - s));
1442
val->qvalue = http_parse_qvalue(buf, len);
1448
HTTPHdr::_fill_target_cache() const
1450
URL* url = this->url_get();
1451
m_target_in_url = false;
1452
m_port_in_header = false;
1453
// Check in the URL first, then the HOST field.
1454
if (0 != (m_host = url->host_get(&m_host_length))) {
1455
m_target_in_url = true;
1456
m_port = url->port_get();
1457
m_port_in_header = 0 != url->port_get_raw();
1458
} else if (0 != (m_host = const_cast<HTTPHdr*>(this)->value_get(MIME_FIELD_HOST, MIME_LEN_HOST, &m_host_length))) {
1459
// Check for port in the host.
1460
char const* colon = static_cast<char const*>(memchr(m_host, ':', m_host_length));
1463
m_host_length = colon - m_host; // Length of just the host in the value.
1465
for ( ++colon ; is_digit(*colon) ; ++colon )
1466
m_port = m_port * 10 + *colon - '0';
1467
m_port_in_header = 0 != m_port;
1469
m_port = url_canonicalize_port(url->m_url_impl->m_url_type, m_port);
1471
m_host_length = 0; // reset in case any earlier check corrupted it
1473
m_target_cached = true;
1477
HTTPHdr::set_url_target_from_host_field(URL* url) {
1478
this->_test_and_fill_target_cache();
1481
// Use local cached URL and don't copy if the target
1482
// is already there.
1483
if (!m_target_in_url && m_host_length) {
1484
m_url_cached.host_set(m_host, m_host_length);
1485
if (m_port_in_header) m_url_cached.port_set(m_port);
1486
m_target_in_url = true; // it's there now.
1489
url->host_set(m_host, m_host_length);
1490
if (m_port_in_header) url->port_set(m_port);
1494
// Very ugly, but a proper implementation will require
1495
// rewriting the URL class and all of its clients so that
1496
// clients access the URL through the HTTP header instance
1497
// unless they really need low level access. The header would
1498
// need to either keep two versions of the URL (pristine
1499
// and effective) or URl would have to provide access to
1502
HTTPHdr::url_string_get(Arena* arena, int* length) {
1505
if (length) *length = 0;
1506
this->_test_and_fill_target_cache();
1507
if (m_url_cached.valid()) {
1508
URLImpl* ui = m_url_cached.m_url_impl;
1509
bool should_reset_host = false;
1510
bool should_reset_port = false;
1513
/* Get dirty. We reach in to the URL implementation to
1514
set the host and port if
1515
1) They are not already set and
1516
2) The values were in a HTTP header field.
1519
if (!m_target_in_url && m_host_length) {
1520
assert(0 == ui->m_ptr_host); // shouldn't be non-zero if not in URL.
1521
ui->m_ptr_host = m_host;
1522
ui->m_len_host = m_host_length;
1523
should_reset_host = true;
1526
if (0 == m_url_cached.port_get_raw() && m_port_in_header) {
1527
assert(0 == ui->m_ptr_port); // shouldn't be set if not in URL.
1528
ui->m_ptr_port = port_buff;
1529
ui->m_len_port = sprintf(port_buff, "%.5d", m_port);
1530
should_reset_port = true;
1533
zret = m_url_cached.string_get(arena, length);
1534
if (should_reset_host) { ui->m_ptr_host = 0; ui->m_len_host = 0; }
1535
if (should_reset_port) { ui->m_ptr_port = 0; ui->m_len_port = 0; }
1541
/***********************************************************************
1543
* M A R S H A L I N G *
1545
***********************************************************************/
1548
HTTPHdr::unmarshal(char *buf, int len, RefCountObj * block_ref)
1550
m_heap = (HdrHeap *) buf;
1552
int res = m_heap->unmarshal(len,
1553
HDR_HEAP_OBJ_HTTP_HEADER,
1554
(HdrHeapObjImpl **) & m_http,
1558
m_mime = m_http->m_fields_impl;
1567
HTTPHdrImpl::marshal(MarshalXlate * ptr_xlate, int num_ptr, MarshalXlate * str_xlate, int num_str)
1570
if (m_polarity == HTTP_TYPE_REQUEST) {
1571
HDR_MARSHAL_STR(u.req.m_ptr_method, str_xlate, num_str);
1572
HDR_MARSHAL_PTR(u.req.m_url_impl, URLImpl, ptr_xlate, num_ptr);
1573
} else if (m_polarity == HTTP_TYPE_RESPONSE) {
1574
HDR_MARSHAL_STR(u.resp.m_ptr_reason, str_xlate, num_str);
1576
ink_release_assert(!"unknown m_polarity");
1579
HDR_MARSHAL_PTR(m_fields_impl, MIMEHdrImpl, ptr_xlate, num_ptr);
1586
HTTPHdrImpl::unmarshal(intptr_t offset)
1589
if (m_polarity == HTTP_TYPE_REQUEST) {
1590
HDR_UNMARSHAL_STR(u.req.m_ptr_method, offset);
1591
HDR_UNMARSHAL_PTR(u.req.m_url_impl, URLImpl, offset);
1592
} else if (m_polarity == HTTP_TYPE_RESPONSE) {
1593
HDR_UNMARSHAL_STR(u.resp.m_ptr_reason, offset);
1595
ink_release_assert(!"unknown m_polarity");
1598
HDR_UNMARSHAL_PTR(m_fields_impl, MIMEHdrImpl, offset);
1603
HTTPHdrImpl::move_strings(HdrStrHeap * new_heap)
1605
if (m_polarity == HTTP_TYPE_REQUEST) {
1606
HDR_MOVE_STR(u.req.m_ptr_method, u.req.m_len_method);
1607
} else if (m_polarity == HTTP_TYPE_RESPONSE) {
1608
HDR_MOVE_STR(u.resp.m_ptr_reason, u.resp.m_len_reason);
1610
ink_release_assert(!"unknown m_polarity");
1615
HTTPHdrImpl::check_strings(HeapCheck * heaps, int num_heaps)
1618
if (m_polarity == HTTP_TYPE_REQUEST) {
1619
CHECK_STR(u.req.m_ptr_method, u.req.m_len_method, heaps, num_heaps);
1620
} else if (m_polarity == HTTP_TYPE_RESPONSE) {
1621
CHECK_STR(u.resp.m_ptr_reason, u.resp.m_len_reason, heaps, num_heaps);
1623
ink_release_assert(!"unknown m_polarity");
1627
ClassAllocator<HTTPCacheAlt> httpCacheAltAllocator("httpCacheAltAllocator");
1629
/*-------------------------------------------------------------------------
1630
-------------------------------------------------------------------------*/
1631
HTTPCacheAlt::HTTPCacheAlt():
1632
m_magic(CACHE_ALT_MAGIC_ALIVE), m_writeable(1),
1633
m_unmarshal_len(-1),
1634
m_id(-1), m_rid(-1), m_request_hdr(),
1635
m_response_hdr(), m_request_sent_time(0), m_response_received_time(0), m_ext_buffer(NULL)
1638
m_object_key[0] = 0;
1639
m_object_key[1] = 0;
1640
m_object_key[2] = 0;
1641
m_object_key[3] = 0;
1642
m_object_size[0] = 0;
1643
m_object_size[1] = 0;
1647
HTTPCacheAlt::destroy()
1649
ink_assert(m_magic == CACHE_ALT_MAGIC_ALIVE);
1650
ink_assert(m_writeable);
1651
m_magic = CACHE_ALT_MAGIC_DEAD;
1653
m_request_hdr.destroy();
1654
m_response_hdr.destroy();
1655
httpCacheAltAllocator.free(this);
1659
HTTPCacheAlt::copy(HTTPCacheAlt * to_copy)
1662
m_magic = to_copy->m_magic;
1663
// m_writeable = to_copy->m_writeable;
1664
m_unmarshal_len = to_copy->m_unmarshal_len;
1665
m_id = to_copy->m_id;
1666
m_rid = to_copy->m_rid;
1667
m_object_key[0] = to_copy->m_object_key[0];
1668
m_object_key[1] = to_copy->m_object_key[1];
1669
m_object_key[2] = to_copy->m_object_key[2];
1670
m_object_key[3] = to_copy->m_object_key[3];
1671
m_object_size[0] = to_copy->m_object_size[0];
1672
m_object_size[1] = to_copy->m_object_size[1];
1674
if (to_copy->m_request_hdr.valid()) {
1675
m_request_hdr.copy(&to_copy->m_request_hdr);
1678
if (to_copy->m_response_hdr.valid()) {
1679
m_response_hdr.copy(&to_copy->m_response_hdr);
1682
m_request_sent_time = to_copy->m_request_sent_time;
1683
m_response_received_time = to_copy->m_response_received_time;
1686
const int HTTP_ALT_MARSHAL_SIZE = ROUND(sizeof(HTTPCacheAlt), HDR_PTR_SIZE);
1691
m_alt = httpCacheAltAllocator.alloc();
1695
HTTPInfo::copy(HTTPInfo * hi)
1698
if (m_alt && m_alt->m_writeable) {
1703
m_alt->copy(hi->m_alt);
1708
HTTPInfo::marshal_length()
1710
int len = HTTP_ALT_MARSHAL_SIZE;
1712
if (m_alt->m_request_hdr.valid()) {
1713
len += m_alt->m_request_hdr.m_heap->marshal_length();
1716
if (m_alt->m_response_hdr.valid()) {
1717
len += m_alt->m_response_hdr.m_heap->marshal_length();
1724
HTTPInfo::marshal(char *buf, int len)
1728
HTTPCacheAlt *marshal_alt = (HTTPCacheAlt *) buf;
1730
ink_debug_assert(m_alt->m_magic == CACHE_ALT_MAGIC_ALIVE);
1732
// Make sure the buffer is aligned
1733
// ink_debug_assert(((intptr_t)buf) & 0x3 == 0);
1735
// Memcpy the whole object so that we can use it
1736
// live later. This involves copying a few
1737
// extra bytes now but will save copying any
1738
// bytes on the way out of the cache
1739
memcpy(buf, m_alt, sizeof(HTTPCacheAlt));
1740
marshal_alt->m_magic = CACHE_ALT_MAGIC_MARSHALED;
1741
marshal_alt->m_writeable = 0;
1742
marshal_alt->m_unmarshal_len = -1;
1743
marshal_alt->m_ext_buffer = NULL;
1744
buf += HTTP_ALT_MARSHAL_SIZE;
1745
used += HTTP_ALT_MARSHAL_SIZE;
1747
// The m_{request,response}_hdr->m_heap pointers are converted
1748
// to zero based offsets from the start of the buffer we're
1749
// marshalling in to
1750
if (m_alt->m_request_hdr.valid()) {
1751
tmp = m_alt->m_request_hdr.m_heap->marshal(buf, len - used);
1752
marshal_alt->m_request_hdr.m_heap = (HdrHeap *)(intptr_t)used;
1753
ink_assert(((intptr_t) marshal_alt->m_request_hdr.m_heap) < len);
1757
marshal_alt->m_request_hdr.m_heap = NULL;
1761
if (m_alt->m_response_hdr.valid()) {
1762
tmp = m_alt->m_response_hdr.m_heap->marshal(buf, len - used);
1763
marshal_alt->m_response_hdr.m_heap = (HdrHeap *)(intptr_t)used;
1764
ink_assert(((intptr_t) marshal_alt->m_response_hdr.m_heap) < len);
1767
marshal_alt->m_response_hdr.m_heap = NULL;
1770
// The prior system failed the marshal if there wasn't
1771
// enough space by measuring the space for every
1772
// component. Seems much faster to check once to
1773
// see if we spammed memory
1774
ink_release_assert(used <= len);
1780
HTTPInfo::unmarshal(char *buf, int len, RefCountObj * block_ref)
1782
HTTPCacheAlt *alt = (HTTPCacheAlt *) buf;
1785
if (alt->m_magic == CACHE_ALT_MAGIC_ALIVE) {
1786
// Already unmarshaled, must be a ram cache
1788
ink_assert(alt->m_unmarshal_len > 0);
1789
ink_assert(alt->m_unmarshal_len <= len);
1790
return alt->m_unmarshal_len;
1791
} else if (alt->m_magic != CACHE_ALT_MAGIC_MARSHALED) {
1792
ink_assert(!"HTTPInfo::unmarshal bad magic");
1796
ink_assert(alt->m_unmarshal_len < 0);
1797
alt->m_magic = CACHE_ALT_MAGIC_ALIVE;
1798
ink_assert(alt->m_writeable == 0);
1799
len -= HTTP_ALT_MARSHAL_SIZE;
1801
HdrHeap *heap = (HdrHeap *) (alt->m_request_hdr.m_heap ? (buf + (intptr_t) alt->m_request_hdr.m_heap) : 0);
1802
HTTPHdrImpl *hh = NULL;
1806
tmp = heap->unmarshal(len, HDR_HEAP_OBJ_HTTP_HEADER, (HdrHeapObjImpl **) & hh, block_ref);
1807
if (hh == NULL || tmp < 0) {
1808
ink_assert(!"HTTPInfo::request unmarshal failed");
1812
alt->m_request_hdr.m_heap = heap;
1813
alt->m_request_hdr.m_http = hh;
1814
alt->m_request_hdr.m_mime = hh->m_fields_impl;
1815
alt->m_request_hdr.m_url_cached.m_heap = heap;
1818
heap = (HdrHeap *) (alt->m_response_hdr.m_heap ? (buf + (intptr_t) alt->m_response_hdr.m_heap) : 0);
1820
tmp = heap->unmarshal(len, HDR_HEAP_OBJ_HTTP_HEADER, (HdrHeapObjImpl **) & hh, block_ref);
1821
if (hh == NULL || tmp < 0) {
1822
ink_assert(!"HTTPInfo::response unmarshal failed");
1827
alt->m_response_hdr.m_heap = heap;
1828
alt->m_response_hdr.m_http = hh;
1829
alt->m_response_hdr.m_mime = hh->m_fields_impl;
1832
alt->m_unmarshal_len = orig_len - len;
1834
return alt->m_unmarshal_len;
1837
// bool HTTPInfo::check_marshalled(char* buf, int len)
1838
// Checks a marhshalled HTTPInfo buffer to make
1839
// sure it's sane. Returns true if sane, false otherwise
1842
HTTPInfo::check_marshalled(char *buf, int len)
1844
HTTPCacheAlt *alt = (HTTPCacheAlt *) buf;
1846
if (alt->m_magic != CACHE_ALT_MAGIC_MARSHALED) {
1850
if (alt->m_writeable != false) {
1854
if (len < HTTP_ALT_MARSHAL_SIZE) {
1858
if (alt->m_request_hdr.m_heap == NULL) {
1862
if ((intptr_t) alt->m_request_hdr.m_heap > len) {
1866
HdrHeap *heap = (HdrHeap *) (buf + (intptr_t) alt->m_request_hdr.m_heap);
1867
if (heap->check_marshalled(len) == false) {
1871
if (alt->m_response_hdr.m_heap == NULL) {
1875
if ((intptr_t) alt->m_response_hdr.m_heap > len) {
1879
heap = (HdrHeap *) (buf + (intptr_t) alt->m_response_hdr.m_heap);
1880
if (heap->check_marshalled(len) == false) {
1888
// void HTTPInfo::set_buffer_reference(RefCountObj* block_ref)
1890
// Setting a buffer reference for the alt is separate from
1891
// the unmarshalling operation because the clustering
1892
// utilizes the system differently than cache does
1893
// The cache maintains external refcounting of the buffer that
1894
// the alt is in & doesn't always destroy the alt when its
1895
// done with it because it figures it doesn't need to since
1896
// it is managing the buffer
1897
// The receiver of ClusterRPC system has the alt manage the
1898
// buffer itself and therefore needs to call this function
1899
// to set up the reference
1902
HTTPInfo::set_buffer_reference(RefCountObj * block_ref)
1904
ink_assert(m_alt->m_magic == CACHE_ALT_MAGIC_ALIVE);
1906
// Free existing reference
1907
if (m_alt->m_ext_buffer != NULL) {
1908
if (m_alt->m_ext_buffer->refcount_dec() == 0) {
1909
m_alt->m_ext_buffer->free();
1912
// Set up the ref count for the external buffer
1915
block_ref->refcount_inc();
1918
m_alt->m_ext_buffer = block_ref;
1922
HTTPInfo::get_handle(char *buf, int len)
1925
// All the offsets have already swizzled to pointers. All we
1926
// need to do is set m_alt and make sure things are sane
1927
HTTPCacheAlt *a = (HTTPCacheAlt *) buf;
1929
if (a->m_magic == CACHE_ALT_MAGIC_ALIVE) {
1931
ink_assert(m_alt->m_unmarshal_len > 0);
1932
ink_assert(m_alt->m_unmarshal_len <= len);
1933
return m_alt->m_unmarshal_len;