00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "ink_defs.h"
00025 #include "libts.h"
00026 #include <assert.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include "HTTP.h"
00030 #include "HdrToken.h"
00031 #include "Diags.h"
00032
00033
00034
00035
00036
00037
00038
00039
00040 #define ENABLE_PARSER_FAST_PATHS 1
00041
00042
00043
00044
00045
00046
00047
00048
00049 #if 0
00050 static const char *cache_control_values[SIZEOF(cache_control_names)];
00051 #endif
00052
00053 const char *HTTP_METHOD_CONNECT;
00054 const char *HTTP_METHOD_DELETE;
00055 const char *HTTP_METHOD_GET;
00056 const char *HTTP_METHOD_HEAD;
00057 const char *HTTP_METHOD_ICP_QUERY;
00058 const char *HTTP_METHOD_OPTIONS;
00059 const char *HTTP_METHOD_POST;
00060 const char *HTTP_METHOD_PURGE;
00061 const char *HTTP_METHOD_PUT;
00062 const char *HTTP_METHOD_TRACE;
00063 const char *HTTP_METHOD_PUSH;
00064
00065 int HTTP_WKSIDX_CONNECT;
00066 int HTTP_WKSIDX_DELETE;
00067 int HTTP_WKSIDX_GET;
00068 int HTTP_WKSIDX_HEAD;
00069 int HTTP_WKSIDX_ICP_QUERY;
00070 int HTTP_WKSIDX_OPTIONS;
00071 int HTTP_WKSIDX_POST;
00072 int HTTP_WKSIDX_PURGE;
00073 int HTTP_WKSIDX_PUT;
00074 int HTTP_WKSIDX_TRACE;
00075 int HTTP_WKSIDX_PUSH;
00076 int HTTP_WKSIDX_METHODS_CNT = 0;
00077
00078 int HTTP_LEN_CONNECT;
00079 int HTTP_LEN_DELETE;
00080 int HTTP_LEN_GET;
00081 int HTTP_LEN_HEAD;
00082 int HTTP_LEN_ICP_QUERY;
00083 int HTTP_LEN_OPTIONS;
00084 int HTTP_LEN_POST;
00085 int HTTP_LEN_PURGE;
00086 int HTTP_LEN_PUT;
00087 int HTTP_LEN_TRACE;
00088 int HTTP_LEN_PUSH;
00089
00090 const char *HTTP_VALUE_BYTES;
00091 const char *HTTP_VALUE_CHUNKED;
00092 const char *HTTP_VALUE_CLOSE;
00093 const char *HTTP_VALUE_COMPRESS;
00094 const char *HTTP_VALUE_DEFLATE;
00095 const char *HTTP_VALUE_GZIP;
00096 const char *HTTP_VALUE_IDENTITY;
00097 const char *HTTP_VALUE_KEEP_ALIVE;
00098 const char *HTTP_VALUE_MAX_AGE;
00099 const char *HTTP_VALUE_MAX_STALE;
00100 const char *HTTP_VALUE_MIN_FRESH;
00101 const char *HTTP_VALUE_MUST_REVALIDATE;
00102 const char *HTTP_VALUE_NONE;
00103 const char *HTTP_VALUE_NO_CACHE;
00104 const char *HTTP_VALUE_NO_STORE;
00105 const char *HTTP_VALUE_NO_TRANSFORM;
00106 const char *HTTP_VALUE_ONLY_IF_CACHED;
00107 const char *HTTP_VALUE_PRIVATE;
00108 const char *HTTP_VALUE_PROXY_REVALIDATE;
00109 const char *HTTP_VALUE_PUBLIC;
00110 const char *HTTP_VALUE_S_MAXAGE;
00111 const char *HTTP_VALUE_NEED_REVALIDATE_ONCE;
00112 const char *HTTP_VALUE_100_CONTINUE;
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 int HTTP_LEN_BYTES;
00126 int HTTP_LEN_CHUNKED;
00127 int HTTP_LEN_CLOSE;
00128 int HTTP_LEN_COMPRESS;
00129 int HTTP_LEN_DEFLATE;
00130 int HTTP_LEN_GZIP;
00131 int HTTP_LEN_IDENTITY;
00132 int HTTP_LEN_KEEP_ALIVE;
00133 int HTTP_LEN_MAX_AGE;
00134 int HTTP_LEN_MAX_STALE;
00135 int HTTP_LEN_MIN_FRESH;
00136 int HTTP_LEN_MUST_REVALIDATE;
00137 int HTTP_LEN_NONE;
00138 int HTTP_LEN_NO_CACHE;
00139 int HTTP_LEN_NO_STORE;
00140 int HTTP_LEN_NO_TRANSFORM;
00141 int HTTP_LEN_ONLY_IF_CACHED;
00142 int HTTP_LEN_PRIVATE;
00143 int HTTP_LEN_PROXY_REVALIDATE;
00144 int HTTP_LEN_PUBLIC;
00145 int HTTP_LEN_S_MAXAGE;
00146 int HTTP_LEN_NEED_REVALIDATE_ONCE;
00147 int HTTP_LEN_100_CONTINUE;
00148
00149 Arena* const HTTPHdr::USE_HDR_HEAP_MAGIC = reinterpret_cast<Arena*>(1);
00150
00151
00152
00153
00154
00155
00156
00157 inline static int
00158 is_digit(char c)
00159 {
00160 return ((c <= '9') && (c >= '0'));
00161 }
00162
00163
00164
00165
00166
00167
00168
00169 void
00170 http_hdr_adjust(HTTPHdrImpl *, int32_t , int32_t ,
00171 int32_t )
00172 {
00173 ink_release_assert(!"http_hdr_adjust not implemented");
00174 }
00175
00176
00177
00178
00179 void
00180 http_init()
00181 {
00182 static int init = 1;
00183
00184 if (init) {
00185 init = 0;
00186
00187 mime_init();
00188 url_init();
00189
00190 HTTP_METHOD_CONNECT = hdrtoken_string_to_wks("CONNECT");
00191 HTTP_METHOD_DELETE = hdrtoken_string_to_wks("DELETE");
00192 HTTP_METHOD_GET = hdrtoken_string_to_wks("GET");
00193 HTTP_METHOD_HEAD = hdrtoken_string_to_wks("HEAD");
00194 HTTP_METHOD_ICP_QUERY = hdrtoken_string_to_wks("ICP_QUERY");
00195 HTTP_METHOD_OPTIONS = hdrtoken_string_to_wks("OPTIONS");
00196 HTTP_METHOD_POST = hdrtoken_string_to_wks("POST");
00197 HTTP_METHOD_PURGE = hdrtoken_string_to_wks("PURGE");
00198 HTTP_METHOD_PUT = hdrtoken_string_to_wks("PUT");
00199 HTTP_METHOD_TRACE = hdrtoken_string_to_wks("TRACE");
00200 HTTP_METHOD_PUSH = hdrtoken_string_to_wks("PUSH");
00201
00202
00203
00204 HTTP_WKSIDX_CONNECT = hdrtoken_wks_to_index(HTTP_METHOD_CONNECT);
00205 HTTP_WKSIDX_METHODS_CNT++;
00206 HTTP_WKSIDX_DELETE = hdrtoken_wks_to_index(HTTP_METHOD_DELETE);
00207 HTTP_WKSIDX_METHODS_CNT++;
00208 HTTP_WKSIDX_GET = hdrtoken_wks_to_index(HTTP_METHOD_GET);
00209 HTTP_WKSIDX_METHODS_CNT++;
00210 HTTP_WKSIDX_HEAD = hdrtoken_wks_to_index(HTTP_METHOD_HEAD);
00211 HTTP_WKSIDX_METHODS_CNT++;
00212 HTTP_WKSIDX_ICP_QUERY = hdrtoken_wks_to_index(HTTP_METHOD_ICP_QUERY);
00213 HTTP_WKSIDX_METHODS_CNT++;
00214 HTTP_WKSIDX_OPTIONS = hdrtoken_wks_to_index(HTTP_METHOD_OPTIONS);
00215 HTTP_WKSIDX_METHODS_CNT++;
00216 HTTP_WKSIDX_POST = hdrtoken_wks_to_index(HTTP_METHOD_POST);
00217 HTTP_WKSIDX_METHODS_CNT++;
00218 HTTP_WKSIDX_PURGE = hdrtoken_wks_to_index(HTTP_METHOD_PURGE);
00219 HTTP_WKSIDX_METHODS_CNT++;
00220 HTTP_WKSIDX_PUT = hdrtoken_wks_to_index(HTTP_METHOD_PUT);
00221 HTTP_WKSIDX_METHODS_CNT++;
00222 HTTP_WKSIDX_TRACE = hdrtoken_wks_to_index(HTTP_METHOD_TRACE);
00223 HTTP_WKSIDX_METHODS_CNT++;
00224 HTTP_WKSIDX_PUSH = hdrtoken_wks_to_index(HTTP_METHOD_PUSH);
00225 HTTP_WKSIDX_METHODS_CNT++;
00226
00227
00228 HTTP_LEN_CONNECT = hdrtoken_wks_to_length(HTTP_METHOD_CONNECT);
00229 HTTP_LEN_DELETE = hdrtoken_wks_to_length(HTTP_METHOD_DELETE);
00230 HTTP_LEN_GET = hdrtoken_wks_to_length(HTTP_METHOD_GET);
00231 HTTP_LEN_HEAD = hdrtoken_wks_to_length(HTTP_METHOD_HEAD);
00232 HTTP_LEN_ICP_QUERY = hdrtoken_wks_to_length(HTTP_METHOD_ICP_QUERY);
00233 HTTP_LEN_OPTIONS = hdrtoken_wks_to_length(HTTP_METHOD_OPTIONS);
00234 HTTP_LEN_POST = hdrtoken_wks_to_length(HTTP_METHOD_POST);
00235 HTTP_LEN_PURGE = hdrtoken_wks_to_length(HTTP_METHOD_PURGE);
00236 HTTP_LEN_PUT = hdrtoken_wks_to_length(HTTP_METHOD_PUT);
00237 HTTP_LEN_TRACE = hdrtoken_wks_to_length(HTTP_METHOD_TRACE);
00238 HTTP_LEN_PUSH = hdrtoken_wks_to_length(HTTP_METHOD_PUSH);
00239
00240 HTTP_VALUE_BYTES = hdrtoken_string_to_wks("bytes");
00241 HTTP_VALUE_CHUNKED = hdrtoken_string_to_wks("chunked");
00242 HTTP_VALUE_CLOSE = hdrtoken_string_to_wks("close");
00243 HTTP_VALUE_COMPRESS = hdrtoken_string_to_wks("compress");
00244 HTTP_VALUE_DEFLATE = hdrtoken_string_to_wks("deflate");
00245 HTTP_VALUE_GZIP = hdrtoken_string_to_wks("gzip");
00246 HTTP_VALUE_IDENTITY = hdrtoken_string_to_wks("identity");
00247 HTTP_VALUE_KEEP_ALIVE = hdrtoken_string_to_wks("keep-alive");
00248 HTTP_VALUE_MAX_AGE = hdrtoken_string_to_wks("max-age");
00249 HTTP_VALUE_MAX_STALE = hdrtoken_string_to_wks("max-stale");
00250 HTTP_VALUE_MIN_FRESH = hdrtoken_string_to_wks("min-fresh");
00251 HTTP_VALUE_MUST_REVALIDATE = hdrtoken_string_to_wks("must-revalidate");
00252 HTTP_VALUE_NONE = hdrtoken_string_to_wks("none");
00253 HTTP_VALUE_NO_CACHE = hdrtoken_string_to_wks("no-cache");
00254 HTTP_VALUE_NO_STORE = hdrtoken_string_to_wks("no-store");
00255 HTTP_VALUE_NO_TRANSFORM = hdrtoken_string_to_wks("no-transform");
00256 HTTP_VALUE_ONLY_IF_CACHED = hdrtoken_string_to_wks("only-if-cached");
00257 HTTP_VALUE_PRIVATE = hdrtoken_string_to_wks("private");
00258 HTTP_VALUE_PROXY_REVALIDATE = hdrtoken_string_to_wks("proxy-revalidate");
00259 HTTP_VALUE_PUBLIC = hdrtoken_string_to_wks("public");
00260 HTTP_VALUE_S_MAXAGE = hdrtoken_string_to_wks("s-maxage");
00261 HTTP_VALUE_NEED_REVALIDATE_ONCE = hdrtoken_string_to_wks("need-revalidate-once");
00262 HTTP_VALUE_100_CONTINUE = hdrtoken_string_to_wks("100-continue");
00263
00264 HTTP_LEN_BYTES = hdrtoken_wks_to_length(HTTP_VALUE_BYTES);
00265 HTTP_LEN_CHUNKED = hdrtoken_wks_to_length(HTTP_VALUE_CHUNKED);
00266 HTTP_LEN_CLOSE = hdrtoken_wks_to_length(HTTP_VALUE_CLOSE);
00267 HTTP_LEN_COMPRESS = hdrtoken_wks_to_length(HTTP_VALUE_COMPRESS);
00268 HTTP_LEN_DEFLATE = hdrtoken_wks_to_length(HTTP_VALUE_DEFLATE);
00269 HTTP_LEN_GZIP = hdrtoken_wks_to_length(HTTP_VALUE_GZIP);
00270 HTTP_LEN_IDENTITY = hdrtoken_wks_to_length(HTTP_VALUE_IDENTITY);
00271 HTTP_LEN_KEEP_ALIVE = hdrtoken_wks_to_length(HTTP_VALUE_KEEP_ALIVE);
00272 HTTP_LEN_MAX_AGE = hdrtoken_wks_to_length(HTTP_VALUE_MAX_AGE);
00273 HTTP_LEN_MAX_STALE = hdrtoken_wks_to_length(HTTP_VALUE_MAX_STALE);
00274 HTTP_LEN_MIN_FRESH = hdrtoken_wks_to_length(HTTP_VALUE_MIN_FRESH);
00275 HTTP_LEN_MUST_REVALIDATE = hdrtoken_wks_to_length(HTTP_VALUE_MUST_REVALIDATE);
00276 HTTP_LEN_NONE = hdrtoken_wks_to_length(HTTP_VALUE_NONE);
00277 HTTP_LEN_NO_CACHE = hdrtoken_wks_to_length(HTTP_VALUE_NO_CACHE);
00278 HTTP_LEN_NO_STORE = hdrtoken_wks_to_length(HTTP_VALUE_NO_STORE);
00279 HTTP_LEN_NO_TRANSFORM = hdrtoken_wks_to_length(HTTP_VALUE_NO_TRANSFORM);
00280 HTTP_LEN_ONLY_IF_CACHED = hdrtoken_wks_to_length(HTTP_VALUE_ONLY_IF_CACHED);
00281 HTTP_LEN_PRIVATE = hdrtoken_wks_to_length(HTTP_VALUE_PRIVATE);
00282 HTTP_LEN_PROXY_REVALIDATE = hdrtoken_wks_to_length(HTTP_VALUE_PROXY_REVALIDATE);
00283 HTTP_LEN_PUBLIC = hdrtoken_wks_to_length(HTTP_VALUE_PUBLIC);
00284 HTTP_LEN_S_MAXAGE = hdrtoken_wks_to_length(HTTP_VALUE_S_MAXAGE);
00285 HTTP_LEN_NEED_REVALIDATE_ONCE = hdrtoken_wks_to_length(HTTP_VALUE_NEED_REVALIDATE_ONCE);
00286 HTTP_LEN_100_CONTINUE = hdrtoken_wks_to_length(HTTP_VALUE_100_CONTINUE);
00287
00288
00289 #if 0
00290 for (int i = 0; i < (int) SIZEOF(cache_control_values); i++) {
00291 cache_control_values[i] = hdrtoken_string_to_wks(cache_control_names[i]);
00292 }
00293 #endif
00294 }
00295 }
00296
00297
00298
00299
00300 HTTPHdrImpl *
00301 http_hdr_create(HdrHeap *heap, HTTPType polarity)
00302 {
00303 HTTPHdrImpl *hh;
00304
00305 hh = (HTTPHdrImpl *) heap->allocate_obj(sizeof(HTTPHdrImpl), HDR_HEAP_OBJ_HTTP_HEADER);
00306 http_hdr_init(heap, hh, polarity);
00307 return (hh);
00308 }
00309
00310
00311
00312
00313 void
00314 http_hdr_init(HdrHeap *heap, HTTPHdrImpl *hh, HTTPType polarity)
00315 {
00316 memset(&(hh->u), 0, sizeof(hh->u));
00317 hh->m_polarity = polarity;
00318 hh->m_version = HTTP_VERSION(0, 9);
00319 hh->m_fields_impl = mime_hdr_create(heap);
00320 if (polarity == HTTP_TYPE_REQUEST) {
00321 hh->u.req.m_url_impl = url_create(heap);
00322 hh->u.req.m_method_wks_idx = -1;
00323 }
00324 }
00325
00326
00327
00328
00329 void
00330 http_hdr_copy_onto(HTTPHdrImpl *s_hh, HdrHeap *s_heap, HTTPHdrImpl *d_hh, HdrHeap *d_heap, bool inherit_strs)
00331 {
00332 MIMEHdrImpl *s_mh, *d_mh;
00333 URLImpl *s_url, *d_url;
00334 HTTPType d_polarity;
00335
00336 s_mh = s_hh->m_fields_impl;
00337 s_url = s_hh->u.req.m_url_impl;
00338 d_mh = d_hh->m_fields_impl;
00339 d_url = d_hh->u.req.m_url_impl;
00340 d_polarity = d_hh->m_polarity;
00341
00342 ink_assert(s_hh->m_polarity != HTTP_TYPE_UNKNOWN);
00343 ink_assert(s_mh != NULL);
00344 ink_assert(d_mh != NULL);
00345
00346 memcpy(d_hh, s_hh, sizeof(HTTPHdrImpl));
00347 d_hh->m_fields_impl = d_mh;
00348
00349 if (s_hh->m_polarity == HTTP_TYPE_REQUEST) {
00350 if (d_polarity == HTTP_TYPE_REQUEST) {
00351 d_hh->u.req.m_url_impl = d_url;
00352 } else {
00353 d_url = d_hh->u.req.m_url_impl = url_create(d_heap);
00354 }
00355 url_copy_onto(s_url, s_heap, d_url, d_heap, false);
00356 } else if (d_polarity == HTTP_TYPE_REQUEST) {
00357
00358 url_clear(d_url);
00359 }
00360
00361 mime_hdr_copy_onto(s_mh, s_heap, d_mh, d_heap, false);
00362 if (inherit_strs)
00363 d_heap->inherit_string_heaps(s_heap);
00364 }
00365
00366
00367
00368
00369 HTTPHdrImpl *
00370 http_hdr_clone(HTTPHdrImpl *s_hh, HdrHeap *s_heap, HdrHeap *d_heap)
00371 {
00372 HTTPHdrImpl *d_hh;
00373
00374
00375
00376
00377
00378 d_hh = http_hdr_create(d_heap, s_hh->m_polarity);
00379 http_hdr_copy_onto(s_hh, s_heap, d_hh, d_heap, ((s_heap != d_heap) ? true : false));
00380 return (d_hh);
00381 }
00382
00383
00384
00385
00386 static inline char *
00387 http_hdr_version_to_string(int32_t version, char *buf9)
00388 {
00389 ink_assert(HTTP_MAJOR(version) < 10);
00390 ink_assert(HTTP_MINOR(version) < 10);
00391
00392 buf9[0] = 'H';
00393 buf9[1] = 'T';
00394 buf9[2] = 'T';
00395 buf9[3] = 'P';
00396 buf9[4] = '/';
00397 buf9[5] = '0' + HTTP_MAJOR(version);
00398 buf9[6] = '.';
00399 buf9[7] = '0' + HTTP_MINOR(version);
00400 buf9[8] = '\0';
00401
00402 return (buf9);
00403 }
00404
00405
00406
00407
00408 int
00409 http_version_print(int32_t version, char *buf, int bufsize, int *bufindex, int *dumpoffset)
00410 {
00411 #define TRY(x) if (!x) return 0
00412
00413 char tmpbuf[16];
00414 http_hdr_version_to_string(version, tmpbuf);
00415 TRY(mime_mem_print(tmpbuf, 8, buf, bufsize, bufindex, dumpoffset));
00416 return 1;
00417
00418 #undef TRY
00419 }
00420
00421
00422
00423
00424 int
00425 http_hdr_print(HdrHeap *heap, HTTPHdrImpl *hdr, char *buf, int bufsize, int *bufindex, int *dumpoffset)
00426 {
00427 #define TRY(x) if (!x) return 0
00428
00429 int tmplen, hdrstat;
00430 char tmpbuf[32];
00431 char *p;
00432
00433 ink_assert((hdr->m_polarity == HTTP_TYPE_REQUEST) || (hdr->m_polarity == HTTP_TYPE_RESPONSE));
00434
00435 if (hdr->m_polarity == HTTP_TYPE_REQUEST) {
00436
00437 if (hdr->u.req.m_ptr_method == NULL)
00438 return 1;
00439
00440 if ((buf != NULL) && (*dumpoffset == 0) && (bufsize - *bufindex >= hdr->u.req.m_len_method + 1)) {
00441
00442 p = buf + *bufindex;
00443 memcpy(p, hdr->u.req.m_ptr_method, hdr->u.req.m_len_method);
00444 p += hdr->u.req.m_len_method;
00445 *p++ = ' ';
00446 *bufindex += hdr->u.req.m_len_method + 1;
00447
00448 if (hdr->u.req.m_url_impl) {
00449 TRY(url_print(hdr->u.req.m_url_impl, buf, bufsize, bufindex, dumpoffset));
00450 if (bufsize - *bufindex >= 1) {
00451 if (hdr->u.req.m_method_wks_idx == HTTP_WKSIDX_CONNECT) {
00452 *bufindex -= 1;
00453 }
00454 p = buf + *bufindex;
00455 *p++ = ' ';
00456 *bufindex += 1;
00457 } else {
00458 return 0;
00459 }
00460 }
00461
00462 if (bufsize - *bufindex >= 9) {
00463 http_hdr_version_to_string(hdr->m_version, p);
00464 *bufindex += 9 - 1;
00465 } else {
00466 TRY(http_version_print(hdr->m_version, buf, bufsize, bufindex, dumpoffset));
00467 }
00468
00469 if (bufsize - *bufindex >= 2) {
00470 p = buf + *bufindex;
00471 *p++ = '\r';
00472 *p++ = '\n';
00473 *bufindex += 2;
00474 } else {
00475 TRY(mime_mem_print("\r\n", 2, buf, bufsize, bufindex, dumpoffset));
00476 }
00477
00478 TRY(mime_hdr_print(heap, hdr->m_fields_impl, buf, bufsize, bufindex, dumpoffset));
00479
00480 } else {
00481
00482 TRY(mime_mem_print(hdr->u.req.m_ptr_method, hdr->u.req.m_len_method, buf, bufsize, bufindex, dumpoffset));
00483
00484 TRY(mime_mem_print(" ", 1, buf, bufsize, bufindex, dumpoffset));
00485
00486 if (hdr->u.req.m_url_impl) {
00487 TRY(url_print(hdr->u.req.m_url_impl, buf, bufsize, bufindex, dumpoffset));
00488 TRY(mime_mem_print(" ", 1, buf, bufsize, bufindex, dumpoffset));
00489 }
00490
00491 TRY(http_version_print(hdr->m_version, buf, bufsize, bufindex, dumpoffset));
00492
00493 TRY(mime_mem_print("\r\n", 2, buf, bufsize, bufindex, dumpoffset));
00494
00495 TRY(mime_hdr_print(heap, hdr->m_fields_impl, buf, bufsize, bufindex, dumpoffset));
00496 }
00497
00498 } else {
00499
00500 if ((buf != NULL) && (*dumpoffset == 0) && (bufsize - *bufindex >= 9 + 6 + 1)) {
00501
00502 p = buf + *bufindex;
00503 http_hdr_version_to_string(hdr->m_version, p);
00504 p += 8;
00505 *p++ = ' ';
00506 *bufindex += 9;
00507
00508 hdrstat = http_hdr_status_get(hdr);
00509 if (hdrstat == 200) {
00510 *p++ = '2';
00511 *p++ = '0';
00512 *p++ = '0';
00513 tmplen = 3;
00514 } else {
00515 tmplen = mime_format_int(p, hdrstat, (bufsize - (p - buf)));
00516 ink_assert(tmplen <= 6);
00517 p += tmplen;
00518 }
00519 *p++ = ' ';
00520 *bufindex += tmplen + 1;
00521
00522 if (hdr->u.resp.m_ptr_reason) {
00523 TRY(mime_mem_print(hdr->u.resp.m_ptr_reason, hdr->u.resp.m_len_reason, buf, bufsize, bufindex, dumpoffset));
00524 }
00525
00526 if (bufsize - *bufindex >= 2) {
00527 p = buf + *bufindex;
00528 *p++ = '\r';
00529 *p++ = '\n';
00530 *bufindex += 2;
00531 } else {
00532 TRY(mime_mem_print("\r\n", 2, buf, bufsize, bufindex, dumpoffset));
00533 }
00534
00535 TRY(mime_hdr_print(heap, hdr->m_fields_impl, buf, bufsize, bufindex, dumpoffset));
00536
00537 } else {
00538
00539 TRY(http_version_print(hdr->m_version, buf, bufsize, bufindex, dumpoffset));
00540
00541 TRY(mime_mem_print(" ", 1, buf, bufsize, bufindex, dumpoffset));
00542
00543 tmplen = mime_format_int(tmpbuf, http_hdr_status_get(hdr), sizeof(tmpbuf));
00544
00545 TRY(mime_mem_print(tmpbuf, tmplen, buf, bufsize, bufindex, dumpoffset));
00546
00547 TRY(mime_mem_print(" ", 1, buf, bufsize, bufindex, dumpoffset));
00548
00549 if (hdr->u.resp.m_ptr_reason) {
00550 TRY(mime_mem_print(hdr->u.resp.m_ptr_reason, hdr->u.resp.m_len_reason, buf, bufsize, bufindex, dumpoffset));
00551 }
00552
00553 TRY(mime_mem_print("\r\n", 2, buf, bufsize, bufindex, dumpoffset));
00554
00555 TRY(mime_hdr_print(heap, hdr->m_fields_impl, buf, bufsize, bufindex, dumpoffset));
00556
00557 }
00558 }
00559
00560 return 1;
00561
00562 #undef TRY
00563 }
00564
00565
00566
00567
00568 void
00569 http_hdr_describe(HdrHeapObjImpl *raw, bool recurse)
00570 {
00571 HTTPHdrImpl *obj = (HTTPHdrImpl *) raw;
00572
00573 if (obj->m_polarity == HTTP_TYPE_REQUEST) {
00574 Debug("http", "[TYPE: REQ, V: %04X, URL: %p, METHOD: \"%.*s\", METHOD_LEN: %d, FIELDS: %p]\n",
00575 obj->m_version, obj->u.req.m_url_impl,
00576 obj->u.req.m_len_method, (obj->u.req.m_ptr_method ? obj->u.req.m_ptr_method : "NULL"),
00577 obj->u.req.m_len_method, obj->m_fields_impl);
00578 if (recurse) {
00579 if (obj->u.req.m_url_impl)
00580 obj_describe(obj->u.req.m_url_impl, recurse);
00581 if (obj->m_fields_impl)
00582 obj_describe(obj->m_fields_impl, recurse);
00583 }
00584 } else {
00585 Debug("http", "[TYPE: RSP, V: %04X, STATUS: %d, REASON: \"%.*s\", REASON_LEN: %d, FIELDS: %p]\n",
00586 obj->m_version, obj->u.resp.m_status,
00587 obj->u.resp.m_len_reason, (obj->u.resp.m_ptr_reason ? obj->u.resp.m_ptr_reason : "NULL"),
00588 obj->u.resp.m_len_reason, obj->m_fields_impl);
00589 if (recurse) {
00590 if (obj->m_fields_impl)
00591 obj_describe(obj->m_fields_impl, recurse);
00592 }
00593 }
00594 }
00595
00596
00597
00598
00599 int
00600 http_hdr_length_get(HTTPHdrImpl *hdr)
00601 {
00602 int length = 0;
00603
00604 if (hdr->m_polarity == HTTP_TYPE_REQUEST) {
00605 if (hdr->u.req.m_ptr_method) {
00606 length = hdr->u.req.m_len_method;
00607 } else {
00608 length = 0;
00609 }
00610
00611 length += 1;
00612
00613 if (hdr->u.req.m_url_impl) {
00614 length += url_length_get(hdr->u.req.m_url_impl);
00615 }
00616
00617 length += 1;
00618
00619 length += 8;
00620
00621 length += 2;
00622 } else if (hdr->m_polarity == HTTP_TYPE_RESPONSE) {
00623 if (hdr->u.resp.m_ptr_reason) {
00624 length = hdr->u.resp.m_len_reason;
00625 } else {
00626 length = 0;
00627
00628 }
00629
00630 length += 8;
00631
00632 length += 1;
00633
00634 length += 3;
00635
00636 length += 1;
00637
00638 length += 2;
00639 }
00640
00641 length += mime_hdr_length_get(hdr->m_fields_impl);
00642
00643 return length;
00644 }
00645
00646
00647
00648
00649
00650 void
00651 http_hdr_type_set(HTTPHdrImpl *hh, HTTPType type)
00652 {
00653 hh->m_polarity = type;
00654 }
00655
00656
00657
00658
00659 void
00660 http_hdr_version_set(HTTPHdrImpl *hh, int32_t ver)
00661 {
00662 hh->m_version = ver;
00663 }
00664
00665
00666
00667
00668 const char *
00669 http_hdr_method_get(HTTPHdrImpl *hh, int *length)
00670 {
00671 const char *str;
00672
00673 ink_assert(hh->m_polarity == HTTP_TYPE_REQUEST);
00674
00675 if (hh->u.req.m_method_wks_idx >= 0) {
00676 str = hdrtoken_index_to_wks(hh->u.req.m_method_wks_idx);
00677 *length = hdrtoken_index_to_length(hh->u.req.m_method_wks_idx);
00678 } else {
00679 str = hh->u.req.m_ptr_method;
00680 *length = hh->u.req.m_len_method;
00681 }
00682
00683 return (str);
00684 }
00685
00686
00687
00688
00689 void
00690 http_hdr_method_set(HdrHeap *heap, HTTPHdrImpl *hh, const char *method, int16_t method_wks_idx, int method_length,
00691 bool must_copy)
00692 {
00693 ink_assert(hh->m_polarity == HTTP_TYPE_REQUEST);
00694
00695 hh->u.req.m_method_wks_idx = method_wks_idx;
00696 mime_str_u16_set(heap, method, method_length, &(hh->u.req.m_ptr_method), &(hh->u.req.m_len_method), must_copy);
00697 }
00698
00699
00700
00701
00702 void
00703 http_hdr_url_set(HdrHeap *heap, HTTPHdrImpl *hh, URLImpl *url)
00704 {
00705 ink_assert(hh->m_polarity == HTTP_TYPE_REQUEST);
00706 if (hh->u.req.m_url_impl != url) {
00707 if (hh->u.req.m_url_impl != NULL) {
00708 heap->deallocate_obj(hh->u.req.m_url_impl);
00709 }
00710 hh->u.req.m_url_impl = url;
00711 }
00712 }
00713
00714
00715
00716
00717
00718 void
00719 http_hdr_status_set(HTTPHdrImpl *hh, HTTPStatus status)
00720 {
00721 ink_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
00722 hh->u.resp.m_status = status;
00723 }
00724
00725
00726
00727
00728 const char *
00729 http_hdr_reason_get(HTTPHdrImpl *hh, int *length)
00730 {
00731 ink_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
00732 *length = hh->u.resp.m_len_reason;
00733 return (hh->u.resp.m_ptr_reason);
00734 }
00735
00736
00737
00738
00739 void
00740 http_hdr_reason_set(HdrHeap *heap, HTTPHdrImpl *hh, const char *value, int length, bool must_copy)
00741 {
00742 ink_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
00743 mime_str_u16_set(heap, value, length, &(hh->u.resp.m_ptr_reason), &(hh->u.resp.m_len_reason), must_copy);
00744 }
00745
00746
00747
00748
00749 const char *
00750 http_hdr_reason_lookup(unsigned status)
00751 {
00752 #define HTTP_STATUS_ENTRY(value, reason) \
00753 case value: return #reason
00754
00755 switch (status) {
00756 HTTP_STATUS_ENTRY(0, None);
00757 HTTP_STATUS_ENTRY(100, Continue);
00758 HTTP_STATUS_ENTRY(101, Switching Protocols);
00759 HTTP_STATUS_ENTRY(102, Processing);
00760
00761 HTTP_STATUS_ENTRY(200, OK);
00762 HTTP_STATUS_ENTRY(201, Created);
00763 HTTP_STATUS_ENTRY(202, Accepted);
00764 HTTP_STATUS_ENTRY(203, Non-Authoritative Information);
00765 HTTP_STATUS_ENTRY(204, No Content);
00766 HTTP_STATUS_ENTRY(205, Reset Content);
00767 HTTP_STATUS_ENTRY(206, Partial Content);
00768 HTTP_STATUS_ENTRY(207, Multi-Status);
00769 HTTP_STATUS_ENTRY(208, Already Reported);
00770
00771 HTTP_STATUS_ENTRY(226, IM Used);
00772
00773 HTTP_STATUS_ENTRY(300, Multiple Choices);
00774 HTTP_STATUS_ENTRY(301, Moved Permanently);
00775 HTTP_STATUS_ENTRY(302, Found);
00776 HTTP_STATUS_ENTRY(303, See Other);
00777 HTTP_STATUS_ENTRY(304, Not Modified);
00778 HTTP_STATUS_ENTRY(305, Use Proxy);
00779
00780 HTTP_STATUS_ENTRY(307, Temporary Redirect);
00781 HTTP_STATUS_ENTRY(308, Permanent Redirect);
00782
00783 HTTP_STATUS_ENTRY(400, Bad Request);
00784 HTTP_STATUS_ENTRY(401, Unauthorized);
00785 HTTP_STATUS_ENTRY(402, Payment Required);
00786 HTTP_STATUS_ENTRY(403, Forbidden);
00787 HTTP_STATUS_ENTRY(404, Not Found);
00788 HTTP_STATUS_ENTRY(405, Method Not Allowed);
00789 HTTP_STATUS_ENTRY(406, Not Acceptable);
00790 HTTP_STATUS_ENTRY(407, Proxy Authentication Required);
00791 HTTP_STATUS_ENTRY(408, Request Timeout);
00792 HTTP_STATUS_ENTRY(409, Conflict);
00793 HTTP_STATUS_ENTRY(410, Gone);
00794 HTTP_STATUS_ENTRY(411, Length Required);
00795 HTTP_STATUS_ENTRY(412, Precondition Failed);
00796 HTTP_STATUS_ENTRY(413, Request Entity Too Large);
00797 HTTP_STATUS_ENTRY(414, Request-URI Too Long);
00798 HTTP_STATUS_ENTRY(415, Unsupported Media Type);
00799 HTTP_STATUS_ENTRY(416, Requested Range Not Satisfiable);
00800 HTTP_STATUS_ENTRY(417, Expectation Failed);
00801 HTTP_STATUS_ENTRY(422, Unprocessable Entity);
00802 HTTP_STATUS_ENTRY(423, Locked);
00803 HTTP_STATUS_ENTRY(424, Failed Dependency);
00804
00805 HTTP_STATUS_ENTRY(426, Upgrade Required);
00806
00807 HTTP_STATUS_ENTRY(428, Precondition Required);
00808 HTTP_STATUS_ENTRY(429, Too Many Requests);
00809
00810 HTTP_STATUS_ENTRY(431, Request Header Fields Too Large);
00811
00812 HTTP_STATUS_ENTRY(500, Internal Server Error);
00813 HTTP_STATUS_ENTRY(501, Not Implemented);
00814 HTTP_STATUS_ENTRY(502, Bad Gateway);
00815 HTTP_STATUS_ENTRY(503, Service Unavailable);
00816 HTTP_STATUS_ENTRY(504, Gateway Timeout);
00817 HTTP_STATUS_ENTRY(505, HTTP Version Not Supported);
00818 HTTP_STATUS_ENTRY(506, Variant Also Negotiates);
00819 HTTP_STATUS_ENTRY(507, Insufficient Storage);
00820 HTTP_STATUS_ENTRY(508, Loop Detected);
00821
00822 HTTP_STATUS_ENTRY(510, Not Extended);
00823 HTTP_STATUS_ENTRY(511, Network Authentication Required);
00824
00825 }
00826
00827 #undef HTTP_STATUS_ENTRY
00828
00829 return NULL;
00830 }
00831
00832
00833
00834
00835 void
00836 _http_parser_init(HTTPParser *parser)
00837 {
00838 parser->m_parsing_http = true;
00839 }
00840
00841
00842
00843
00844
00845
00846 void
00847 http_parser_init(HTTPParser *parser)
00848 {
00849 _http_parser_init(parser);
00850 mime_parser_init(&parser->m_mime_parser);
00851 }
00852
00853 void
00854 http_parser_clear(HTTPParser *parser)
00855 {
00856 _http_parser_init(parser);
00857 mime_parser_clear(&parser->m_mime_parser);
00858 }
00859
00860
00861
00862
00863 #define GETNEXT(label) { \
00864 cur += 1; \
00865 if (cur >= end) { \
00866 goto label; \
00867 } \
00868 }
00869
00870 #define GETPREV(label) { \
00871 cur -= 1; \
00872 if (cur < line_start) { \
00873 goto label; \
00874 } \
00875 }
00876
00877
00878
00879 MIMEParseResult
00880 http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end,
00881 bool must_copy_strings, bool eof)
00882 {
00883 if (parser->m_parsing_http) {
00884 MIMEScanner *scanner = &parser->m_mime_parser.m_scanner;
00885 URLImpl *url;
00886
00887 MIMEParseResult err;
00888 bool line_is_real;
00889 const char *cur;
00890 const char *line_start;
00891 const char *real_end;
00892 const char *method_start;
00893 const char *method_end;
00894 const char *url_start;
00895 const char *url_end;
00896 const char *version_start;
00897 const char *version_end;
00898
00899 real_end = end;
00900
00901 start:
00902 hh->m_polarity = HTTP_TYPE_REQUEST;
00903
00904
00905 if (scanner->m_line_length >= UINT16_MAX)
00906 return PARSE_ERROR;
00907
00908 err = mime_scanner_get(scanner, start, real_end, &line_start, &end, &line_is_real, eof, MIME_SCANNER_TYPE_LINE);
00909 if (err < 0)
00910 return err;
00911
00912
00913 if (err == PARSE_DONE)
00914 return PARSE_ERROR;
00915 if (err == PARSE_CONT)
00916 return err;
00917
00918 cur = line_start;
00919 ink_assert((end - cur) >= 0);
00920 ink_assert((end - cur) < UINT16_MAX);
00921
00922 must_copy_strings = (must_copy_strings || (!line_is_real));
00923
00924 #if (ENABLE_PARSER_FAST_PATHS)
00925
00926 if (end - cur >= 16) {
00927 if (((cur[0] ^ 'G') | (cur[1] ^ 'E') | (cur[2] ^ 'T')) != 0)
00928 goto slow_case;
00929 if (((end[-10] ^ 'H') | (end[-9] ^ 'T') | (end[-8] ^ 'T') | (end[-7] ^ 'P') |
00930 (end[-6] ^ '/') | (end[-4] ^ '.') | (end[-2] ^ '\r') | (end[-1] ^ '\n')) != 0)
00931 goto slow_case;
00932 if (!(is_digit(end[-5]) && is_digit(end[-3])))
00933 goto slow_case;
00934 if (!(ParseRules::is_space(cur[3]) && (!ParseRules::is_space(cur[4])) &&
00935 (!ParseRules::is_space(end[-12])) && ParseRules::is_space(end[-11])))
00936 goto slow_case;
00937 if (&(cur[4]) >= &(end[-11]))
00938 goto slow_case;
00939
00940 int32_t version = HTTP_VERSION(end[-5] - '0', end[-3] - '0');
00941
00942 http_hdr_method_set(heap, hh, &(cur[0]), hdrtoken_wks_to_index(HTTP_METHOD_GET), 3, must_copy_strings);
00943 ink_assert(hh->u.req.m_url_impl != NULL);
00944 url = hh->u.req.m_url_impl;
00945 url_start = &(cur[4]);
00946 err =::url_parse(heap, url, &url_start, &(end[-11]), must_copy_strings);
00947 if (err < 0)
00948 return err;
00949 http_hdr_version_set(hh, version);
00950
00951 end = real_end;
00952 parser->m_parsing_http = false;
00953 if (version == HTTP_VERSION(0, 9))
00954 return PARSE_DONE;
00955
00956 return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
00957 }
00958 #endif
00959
00960 slow_case:
00961
00962 method_start = NULL;
00963 method_end = NULL;
00964 url_start = NULL;
00965 url_end = NULL;
00966 version_start = NULL;
00967 version_end = NULL;
00968 url = NULL;
00969
00970 if (ParseRules::is_cr(*cur))
00971 GETNEXT(done);
00972 if (ParseRules::is_lf(*cur))
00973 goto start;
00974
00975 parse_method1:
00976 if (ParseRules::is_ws(*cur)) {
00977 GETNEXT(done);
00978 goto parse_method1;
00979 }
00980 method_start = cur;
00981 GETNEXT(done);
00982 parse_method2:
00983 if (ParseRules::is_ws(*cur)) {
00984 method_end = cur;
00985 goto parse_version1;
00986 }
00987 GETNEXT(done);
00988 goto parse_method2;
00989
00990 parse_version1:
00991 cur = end - 1;
00992 if (ParseRules::is_lf(*cur) && (cur >= line_start)) {
00993 cur -= 1;
00994 }
00995 if (ParseRules::is_cr(*cur) && (cur >= line_start)) {
00996 cur -= 1;
00997 }
00998
00999
01000 while (ParseRules::is_ws(*cur) && (cur >= line_start)) {
01001 cur -= 1;
01002 }
01003 version_end = cur + 1;
01004 parse_version2:
01005 if (ParseRules::is_digit(*cur)) {
01006 GETPREV(parse_url);
01007 goto parse_version2;
01008 }
01009 if (*cur == '.') {
01010 GETPREV(parse_url);
01011 goto parse_version3;
01012 }
01013 goto parse_url;
01014 parse_version3:
01015 if (ParseRules::is_digit(*cur)) {
01016 GETPREV(parse_url);
01017 goto parse_version3;
01018 }
01019 if (*cur == '/') {
01020 GETPREV(parse_url);
01021 goto parse_version4;
01022 }
01023 goto parse_url;
01024 parse_version4:
01025 if ((*cur != 'P') && (*cur != 'p')) {
01026 goto parse_url;
01027 }
01028 GETPREV(parse_url);
01029 if ((*cur != 'T') && (*cur != 't')) {
01030 goto parse_url;
01031 }
01032 GETPREV(parse_url);
01033 if ((*cur != 'T') && (*cur != 't')) {
01034 goto parse_url;
01035 }
01036 GETPREV(parse_url);
01037 if ((*cur != 'H') && (*cur != 'h')) {
01038 goto parse_url;
01039 }
01040 version_start = cur;
01041
01042 parse_url:
01043 url_start = method_end + 1;
01044 if (version_start) {
01045 url_end = version_start - 1;
01046 } else {
01047 url_end = end - 1;
01048 }
01049 while ((url_start < end) && ParseRules::is_ws(*url_start)) {
01050 url_start += 1;
01051 }
01052 while ((url_end >= line_start) && ParseRules::is_wslfcr(*url_end)) {
01053 url_end -= 1;
01054 }
01055 url_end += 1;
01056
01057 done:
01058 if (!method_start || !method_end)
01059 return PARSE_ERROR;
01060
01061 int method_wks_idx = hdrtoken_tokenize(method_start,
01062 (int) (method_end - method_start));
01063 http_hdr_method_set(heap, hh, method_start, method_wks_idx, (int) (method_end - method_start), must_copy_strings);
01064
01065 if (!url_start || !url_end)
01066 return PARSE_ERROR;
01067
01068 ink_assert(hh->u.req.m_url_impl != NULL);
01069
01070 url = hh->u.req.m_url_impl;
01071 err =::url_parse(heap, url, &url_start, url_end, must_copy_strings);
01072
01073 if (err < 0)
01074 return err;
01075
01076 int32_t version;
01077 if (version_start && version_end) {
01078 version = http_parse_version(version_start, version_end);
01079 } else
01080 version = HTTP_VERSION(0, 9);
01081 http_hdr_version_set(hh, version);
01082
01083 end = real_end;
01084 parser->m_parsing_http = false;
01085 if (version == HTTP_VERSION(0, 9))
01086 return PARSE_DONE;
01087 }
01088
01089 return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
01090 }
01091
01092
01093
01094
01095 MIMEParseResult
01096 http_parser_parse_resp(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end,
01097 bool must_copy_strings, bool eof)
01098 {
01099 if (parser->m_parsing_http) {
01100 MIMEScanner *scanner = &parser->m_mime_parser.m_scanner;
01101
01102 MIMEParseResult err;
01103 bool line_is_real;
01104 const char *cur;
01105 const char *line_start;
01106 const char *real_end;
01107 const char *version_start;
01108 const char *version_end;
01109 const char *status_start;
01110 const char *status_end;
01111 const char *reason_start;
01112 const char *reason_end;
01113 const char *old_start;
01114
01115 real_end = end;
01116 old_start = *start;
01117
01118 hh->m_polarity = HTTP_TYPE_RESPONSE;
01119
01120
01121 if (scanner->m_line_length >= UINT16_MAX)
01122 return PARSE_ERROR;
01123
01124 err = mime_scanner_get(scanner, start, real_end, &line_start, &end, &line_is_real, eof, MIME_SCANNER_TYPE_LINE);
01125 if (err < 0)
01126 return err;
01127 if ((err == PARSE_DONE) || (err == PARSE_CONT))
01128 return err;
01129
01130 cur = line_start;
01131 ink_assert((end - cur) >= 0);
01132 ink_assert((end - cur) < UINT16_MAX);
01133
01134 must_copy_strings = (must_copy_strings || (!line_is_real));
01135
01136 #if (ENABLE_PARSER_FAST_PATHS)
01137
01138 if (end - cur >= 16) {
01139 int http_match = ((cur[0] ^ 'H') | (cur[1] ^ 'T') | (cur[2] ^ 'T') | (cur[3] ^ 'P') |
01140 (cur[4] ^ '/') | (cur[6] ^ '.') | (cur[8] ^ ' '));
01141 if ((http_match != 0) ||
01142 (!(is_digit(cur[5]) && is_digit(cur[7]) &&
01143 is_digit(cur[9]) && is_digit(cur[10]) && is_digit(cur[11]) && (!ParseRules::is_space(cur[13]))))) {
01144 goto slow_case;
01145 }
01146
01147 reason_start = &(cur[13]);
01148 reason_end = end - 1;
01149 while ((reason_end > reason_start + 1) && (ParseRules::is_space(reason_end[-1])))
01150 --reason_end;
01151
01152 int32_t version = HTTP_VERSION(cur[5] - '0', cur[7] - '0');
01153 HTTPStatus status = (HTTPStatus) ((cur[9] - '0') * 100 + (cur[10] - '0') * 10 + (cur[11] - '0'));
01154
01155 http_hdr_version_set(hh, version);
01156 http_hdr_status_set(hh, status);
01157 http_hdr_reason_set(heap, hh, reason_start, (int) (reason_end - reason_start), must_copy_strings);
01158
01159 end = real_end;
01160 parser->m_parsing_http = false;
01161 return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
01162 }
01163 #endif
01164
01165 slow_case:
01166 version_start = NULL;
01167 version_end = NULL;
01168 status_start = NULL;
01169 status_end = NULL;
01170 reason_start = NULL;
01171 reason_end = NULL;
01172
01173 version_start = cur = line_start;
01174 if ((*cur != 'H') && (*cur != 'h')) {
01175 goto eoh;
01176 }
01177 GETNEXT(eoh);
01178 if ((*cur != 'T') && (*cur != 't')) {
01179 goto eoh;
01180 }
01181 GETNEXT(eoh);
01182 if ((*cur != 'T') && (*cur != 't')) {
01183 goto eoh;
01184 }
01185 GETNEXT(eoh);
01186 if ((*cur != 'P') && (*cur != 'p')) {
01187 goto eoh;
01188 }
01189 GETNEXT(eoh);
01190 if (*cur != '/') {
01191 goto eoh;
01192 }
01193 GETNEXT(eoh);
01194 parse_version2:
01195 if (ParseRules::is_digit(*cur)) {
01196 GETNEXT(eoh);
01197 goto parse_version2;
01198 }
01199 if (*cur == '.') {
01200 GETNEXT(eoh);
01201 goto parse_version3;
01202 }
01203 goto eoh;
01204 parse_version3:
01205 if (ParseRules::is_digit(*cur)) {
01206 GETNEXT(eoh);
01207 goto parse_version3;
01208 }
01209 if (ParseRules::is_ws(*cur)) {
01210 version_end = cur;
01211 GETNEXT(eoh);
01212 goto parse_status1;
01213 }
01214 goto eoh;
01215
01216 parse_status1:
01217 if (ParseRules::is_ws(*cur)) {
01218 GETNEXT(done);
01219 goto parse_status1;
01220 }
01221 status_start = cur;
01222 parse_status2:
01223 status_end = cur;
01224 if (ParseRules::is_digit(*cur)) {
01225 GETNEXT(done);
01226 goto parse_status2;
01227 }
01228 if (ParseRules::is_ws(*cur)) {
01229 GETNEXT(done);
01230 goto parse_reason1;
01231 }
01232 goto done;
01233
01234 parse_reason1:
01235 if (ParseRules::is_ws(*cur)) {
01236 GETNEXT(done);
01237 goto parse_reason1;
01238 }
01239 reason_start = cur;
01240 reason_end = end - 1;
01241 while ((reason_end >= line_start) && (ParseRules::is_cr(*reason_end) || ParseRules::is_lf(*reason_end))) {
01242 reason_end -= 1;
01243 }
01244 reason_end += 1;
01245 goto done;
01246
01247 eoh:
01248 *start = old_start;
01249 return PARSE_DONE;
01250
01251 done:
01252 if (!version_start || !version_end) {
01253 return PARSE_DONE;
01254 }
01255
01256 http_hdr_version_set(hh, http_parse_version(version_start, version_end));
01257
01258 if (status_start && status_end)
01259 http_hdr_status_set(hh, http_parse_status(status_start, status_end));
01260
01261 if (reason_start && reason_end) {
01262 http_hdr_reason_set(heap, hh, reason_start, (int) (reason_end - reason_start), must_copy_strings);
01263 }
01264
01265 end = real_end;
01266 parser->m_parsing_http = false;
01267 }
01268
01269 return mime_parser_parse(&parser->m_mime_parser, heap, hh->m_fields_impl, start, end, must_copy_strings, eof);
01270 }
01271
01272
01273
01274
01275 HTTPStatus
01276 http_parse_status(const char *start, const char *end)
01277 {
01278 int status = 0;
01279
01280 while ((start != end) && ParseRules::is_space(*start)) {
01281 start += 1;
01282 }
01283
01284 while ((start != end) && ParseRules::is_digit(*start)) {
01285 status = (status * 10) + (*start++ - '0');
01286 }
01287
01288 return (HTTPStatus) status;
01289 }
01290
01291
01292
01293
01294 int32_t
01295 http_parse_version(const char *start, const char *end)
01296 {
01297 int maj;
01298 int min;
01299
01300 if ((end - start) < 8) {
01301 return HTTP_VERSION(0, 9);
01302 }
01303
01304 if (((start[0] == 'H') || (start[0] == 'h')) &&
01305 ((start[1] == 'T') || (start[1] == 't')) &&
01306 ((start[2] == 'T') || (start[2] == 't')) && ((start[3] == 'P') || (start[3] == 'p')) && (start[4] == '/')) {
01307 start += 5;
01308
01309 maj = 0;
01310 min = 0;
01311
01312 while ((start != end) && ParseRules::is_digit(*start)) {
01313 maj = (maj * 10) + (*start - '0');
01314 start += 1;
01315 }
01316
01317 if (*start == '.') {
01318 start += 1;
01319 }
01320
01321 while ((start != end) && ParseRules::is_digit(*start)) {
01322 min = (min * 10) + (*start - '0');
01323 start += 1;
01324 }
01325
01326 return HTTP_VERSION(maj, min);
01327 }
01328
01329 return HTTP_VERSION(0, 9);
01330 }
01331
01332
01333
01334
01335 static char *
01336 http_str_store(Arena *arena, const char *str, int length)
01337 {
01338 const char *wks;
01339 int idx = hdrtoken_tokenize(str, length, &wks);
01340 if (idx < 0) {
01341 return arena->str_store(str, length);
01342 } else {
01343 return (char *) wks;
01344 }
01345 }
01346
01347
01348
01349
01350 static void
01351 http_skip_ws(const char *&buf, int &len)
01352 {
01353 while (len > 0 && *buf && ParseRules::is_ws(*buf)) {
01354 buf += 1;
01355 len -= 1;
01356 }
01357 }
01358
01359
01360
01361
01362 static double
01363 http_parse_qvalue(const char *&buf, int &len)
01364 {
01365 double val = 1.0;
01366
01367 if (*buf != ';') {
01368 return val;
01369 }
01370
01371 buf += 1;
01372 len -= 1;
01373
01374 while (len > 0 && *buf) {
01375 http_skip_ws(buf, len);
01376
01377 if (*buf == 'q') {
01378 buf += 1;
01379 len -= 1;
01380 http_skip_ws(buf, len);
01381
01382 if (*buf == '=') {
01383 double n;
01384 int f;
01385
01386 buf += 1;
01387 len -= 1;
01388 http_skip_ws(buf, len);
01389
01390 n = 0.0;
01391 while (len > 0 && *buf && ParseRules::is_digit(*buf)) {
01392 n = (n * 10) + (*buf++ - '0');
01393 len -= 1;
01394 }
01395
01396 if (*buf == '.') {
01397 buf += 1;
01398 len -= 1;
01399
01400 f = 10;
01401 while (len > 0 && *buf && ParseRules::is_digit(*buf)) {
01402 n += (*buf++ - '0') / (double) f;
01403 f *= 10;
01404 len -= 1;
01405 }
01406 }
01407
01408 val = n;
01409 }
01410 } else {
01411
01412 while (len > 0 && *buf) {
01413 if (*buf != ';') {
01414 buf += 1;
01415 len -= 1;
01416 } else {
01417
01418 buf += 1;
01419 len -= 1;
01420 break;
01421 }
01422 }
01423 }
01424 }
01425
01426 return val;
01427 }
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438 HTTPValTE *
01439 http_parse_te(const char *buf, int len, Arena *arena)
01440 {
01441 HTTPValTE *val;
01442 const char *s;
01443
01444 http_skip_ws(buf, len);
01445
01446 s = buf;
01447
01448 while (len > 0 && *buf && (*buf != ';')) {
01449 buf += 1;
01450 len -= 1;
01451 }
01452
01453 val = (HTTPValTE *) arena->alloc(sizeof(HTTPValTE));
01454 val->encoding = http_str_store(arena, s, (int) (buf - s));
01455 val->qvalue = http_parse_qvalue(buf, len);
01456
01457 return val;
01458 }
01459
01460 void
01461 HTTPHdr::_fill_target_cache() const
01462 {
01463 URL* url = this->url_get();
01464 char const* port_ptr;
01465
01466 m_target_in_url = false;
01467 m_port_in_header = false;
01468 m_host_mime = NULL;
01469
01470 if (0 != url->host_get(&m_host_length)) {
01471 m_target_in_url = true;
01472 m_port = url->port_get();
01473 m_port_in_header = 0 != url->port_get_raw();
01474 m_host_mime = NULL;
01475 } else if (0 != (m_host_mime = const_cast<HTTPHdr*>(this)->get_host_port_values(0, &m_host_length, &port_ptr, 0))) {
01476 if (port_ptr) {
01477 m_port = 0;
01478 for ( ; is_digit(*port_ptr) ; ++port_ptr )
01479 m_port = m_port * 10 + *port_ptr - '0';
01480 m_port_in_header = (0 != m_port);
01481 }
01482 m_port = url_canonicalize_port(url->m_url_impl->m_url_type, m_port);
01483 }
01484
01485 m_target_cached = true;
01486 }
01487
01488 void
01489 HTTPHdr::set_url_target_from_host_field(URL* url) {
01490 this->_test_and_fill_target_cache();
01491
01492 if (!url) {
01493
01494
01495 if (!m_target_in_url && m_host_mime && m_host_length) {
01496 m_url_cached.host_set(m_host_mime->m_ptr_value, m_host_length);
01497 if (m_port_in_header) m_url_cached.port_set(m_port);
01498 m_target_in_url = true;
01499 }
01500 } else {
01501 int host_len = 0;
01502 char const *host = NULL;
01503 host = host_get(&host_len);
01504 url->host_set(host, host_len);
01505 if (m_port_in_header) url->port_set(m_port);
01506 }
01507 }
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519 class UrlPrintHack {
01520 friend class HTTPHdr;
01521 UrlPrintHack(HTTPHdr* hdr) {
01522 hdr->_test_and_fill_target_cache();
01523 if (hdr->m_url_cached.valid()) {
01524 URLImpl* ui = hdr->m_url_cached.m_url_impl;
01525 char port_buff[10];
01526
01527 m_hdr = hdr;
01528
01529
01530
01531
01532
01533
01534
01535 if (!hdr->m_target_in_url && hdr->m_host_length && hdr->m_host_mime) {
01536 ink_assert(0 == ui->m_ptr_host);
01537 ui->m_ptr_host = hdr->m_host_mime->m_ptr_value;
01538 ui->m_len_host = hdr->m_host_length;
01539 m_host_modified_p = true;
01540 } else {
01541 m_host_modified_p = false;
01542 }
01543
01544 if (0 == hdr->m_url_cached.port_get_raw() && hdr->m_port_in_header) {
01545 ink_assert(0 == ui->m_ptr_port);
01546 ui->m_ptr_port = port_buff;
01547 ui->m_len_port = sprintf(port_buff, "%.5d", hdr->m_port);
01548 m_port_modified_p = true;
01549 } else {
01550 m_port_modified_p = false;
01551 }
01552 } else {
01553 m_hdr = 0;
01554 }
01555 }
01556
01557
01558 ~UrlPrintHack() {
01559 if (m_hdr) {
01560 URLImpl* ui = m_hdr->m_url_cached.m_url_impl;
01561
01562
01563
01564
01565
01566
01567 if (m_port_modified_p) {
01568 ui->m_len_port = 0;
01569 ui->m_ptr_port = 0;
01570 }
01571 if (m_host_modified_p) {
01572 ui->m_len_host = 0;
01573 ui->m_ptr_host = 0;
01574 }
01575 }
01576 }
01577
01578
01579 bool is_valid() const {
01580 return 0 != m_hdr;
01581 }
01582
01583
01584
01585 bool m_host_modified_p;
01586 bool m_port_modified_p;
01587 HTTPHdr* m_hdr;
01588
01589 };
01590
01591 char*
01592 HTTPHdr::url_string_get(Arena* arena, int* length)
01593 {
01594 char* zret = 0;
01595 UrlPrintHack hack(this);
01596
01597 if (hack.is_valid()) {
01598
01599
01600
01601
01602 zret = (arena == USE_HDR_HEAP_MAGIC)
01603 ? m_url_cached.string_get_ref(length)
01604 : m_url_cached.string_get(arena, length)
01605 ;
01606 }
01607 return zret;
01608 }
01609
01610 int
01611 HTTPHdr::url_print(char* buff, int length, int* offset, int* skip)
01612 {
01613 ink_release_assert(offset);
01614 ink_release_assert(skip);
01615
01616 int zret = 0;
01617 UrlPrintHack hack(this);
01618 if (hack.is_valid()) {
01619 zret = m_url_cached.print(buff, length, offset, skip);
01620 }
01621 return zret;
01622 }
01623
01624
01625
01626
01627
01628
01629
01630 int
01631 HTTPHdr::unmarshal(char *buf, int len, RefCountObj *block_ref)
01632 {
01633 m_heap = (HdrHeap *)buf;
01634
01635 int res = m_heap->unmarshal(len, HDR_HEAP_OBJ_HTTP_HEADER, (HdrHeapObjImpl **) & m_http, block_ref);
01636
01637 if (res > 0) {
01638 m_mime = m_http->m_fields_impl;
01639 } else {
01640 clear();
01641 }
01642
01643 return res;
01644 }
01645
01646 int
01647 HTTPHdrImpl::marshal(MarshalXlate *ptr_xlate, int num_ptr, MarshalXlate *str_xlate, int num_str)
01648 {
01649
01650 if (m_polarity == HTTP_TYPE_REQUEST) {
01651 HDR_MARSHAL_STR(u.req.m_ptr_method, str_xlate, num_str);
01652 HDR_MARSHAL_PTR(u.req.m_url_impl, URLImpl, ptr_xlate, num_ptr);
01653 } else if (m_polarity == HTTP_TYPE_RESPONSE) {
01654 HDR_MARSHAL_STR(u.resp.m_ptr_reason, str_xlate, num_str);
01655 } else {
01656 ink_release_assert(!"unknown m_polarity");
01657 }
01658
01659 HDR_MARSHAL_PTR(m_fields_impl, MIMEHdrImpl, ptr_xlate, num_ptr);
01660
01661 return 0;
01662 }
01663
01664
01665 void
01666 HTTPHdrImpl::unmarshal(intptr_t offset)
01667 {
01668
01669 if (m_polarity == HTTP_TYPE_REQUEST) {
01670 HDR_UNMARSHAL_STR(u.req.m_ptr_method, offset);
01671 HDR_UNMARSHAL_PTR(u.req.m_url_impl, URLImpl, offset);
01672 } else if (m_polarity == HTTP_TYPE_RESPONSE) {
01673 HDR_UNMARSHAL_STR(u.resp.m_ptr_reason, offset);
01674 } else {
01675 ink_release_assert(!"unknown m_polarity");
01676 }
01677
01678 HDR_UNMARSHAL_PTR(m_fields_impl, MIMEHdrImpl, offset);
01679 }
01680
01681
01682 void
01683 HTTPHdrImpl::move_strings(HdrStrHeap *new_heap)
01684 {
01685 if (m_polarity == HTTP_TYPE_REQUEST) {
01686 HDR_MOVE_STR(u.req.m_ptr_method, u.req.m_len_method);
01687 } else if (m_polarity == HTTP_TYPE_RESPONSE) {
01688 HDR_MOVE_STR(u.resp.m_ptr_reason, u.resp.m_len_reason);
01689 } else {
01690 ink_release_assert(!"unknown m_polarity");
01691 }
01692 }
01693
01694 size_t
01695 HTTPHdrImpl::strings_length()
01696 {
01697 size_t ret = 0;
01698
01699 if (m_polarity == HTTP_TYPE_REQUEST) {
01700 ret += u.req.m_len_method;
01701 } else if (m_polarity == HTTP_TYPE_RESPONSE) {
01702 ret += u.resp.m_len_reason;
01703 }
01704 return ret;
01705 }
01706
01707 void
01708 HTTPHdrImpl::check_strings(HeapCheck *heaps, int num_heaps)
01709 {
01710
01711 if (m_polarity == HTTP_TYPE_REQUEST) {
01712 CHECK_STR(u.req.m_ptr_method, u.req.m_len_method, heaps, num_heaps);
01713 } else if (m_polarity == HTTP_TYPE_RESPONSE) {
01714 CHECK_STR(u.resp.m_ptr_reason, u.resp.m_len_reason, heaps, num_heaps);
01715 } else {
01716 ink_release_assert(!"unknown m_polarity");
01717 }
01718 }
01719
01720 ClassAllocator<HTTPCacheAlt> httpCacheAltAllocator("httpCacheAltAllocator");
01721
01722
01723
01724 HTTPCacheAlt::HTTPCacheAlt():
01725 m_magic(CACHE_ALT_MAGIC_ALIVE), m_writeable(1),
01726 m_unmarshal_len(-1),
01727 m_id(-1), m_rid(-1), m_request_hdr(),
01728 m_response_hdr(), m_request_sent_time(0), m_response_received_time(0),
01729 m_frag_offset_count(0), m_frag_offsets(0),
01730 m_ext_buffer(NULL)
01731 {
01732
01733 m_object_key[0] = 0;
01734 m_object_key[1] = 0;
01735 m_object_key[2] = 0;
01736 m_object_key[3] = 0;
01737 m_object_size[0] = 0;
01738 m_object_size[1] = 0;
01739 }
01740
01741 void
01742 HTTPCacheAlt::destroy()
01743 {
01744 ink_assert(m_magic == CACHE_ALT_MAGIC_ALIVE);
01745 ink_assert(m_writeable);
01746 m_magic = CACHE_ALT_MAGIC_DEAD;
01747 m_writeable = 0;
01748 m_request_hdr.destroy();
01749 m_response_hdr.destroy();
01750 m_frag_offset_count = 0;
01751 if (m_frag_offsets && m_frag_offsets != m_integral_frag_offsets) {
01752 ats_free(m_frag_offsets);
01753 m_frag_offsets = 0;
01754 }
01755 httpCacheAltAllocator.free(this);
01756 }
01757
01758 void
01759 HTTPCacheAlt::copy(HTTPCacheAlt *to_copy)
01760 {
01761
01762 m_magic = to_copy->m_magic;
01763
01764 m_unmarshal_len = to_copy->m_unmarshal_len;
01765 m_id = to_copy->m_id;
01766 m_rid = to_copy->m_rid;
01767 m_object_key[0] = to_copy->m_object_key[0];
01768 m_object_key[1] = to_copy->m_object_key[1];
01769 m_object_key[2] = to_copy->m_object_key[2];
01770 m_object_key[3] = to_copy->m_object_key[3];
01771 m_object_size[0] = to_copy->m_object_size[0];
01772 m_object_size[1] = to_copy->m_object_size[1];
01773
01774 if (to_copy->m_request_hdr.valid()) {
01775 m_request_hdr.copy(&to_copy->m_request_hdr);
01776 }
01777
01778 if (to_copy->m_response_hdr.valid()) {
01779 m_response_hdr.copy(&to_copy->m_response_hdr);
01780 }
01781
01782 m_request_sent_time = to_copy->m_request_sent_time;
01783 m_response_received_time = to_copy->m_response_received_time;
01784 this->copy_frag_offsets_from(to_copy);
01785 }
01786
01787 void
01788 HTTPCacheAlt::copy_frag_offsets_from(HTTPCacheAlt *src)
01789 {
01790 m_frag_offset_count = src->m_frag_offset_count;
01791 if (m_frag_offset_count > 0) {
01792 if (m_frag_offset_count > N_INTEGRAL_FRAG_OFFSETS) {
01793
01794
01795
01796
01797
01798 int bcount = HTTPCacheAlt::N_INTEGRAL_FRAG_OFFSETS * 2;
01799 while (bcount < m_frag_offset_count) bcount *= 2;
01800 m_frag_offsets = static_cast<FragOffset*>(ats_malloc(sizeof(FragOffset) * bcount));
01801 } else {
01802 m_frag_offsets = m_integral_frag_offsets;
01803 }
01804 memcpy(m_frag_offsets, src->m_frag_offsets, sizeof(FragOffset) * m_frag_offset_count);
01805 }
01806 }
01807
01808 const int HTTP_ALT_MARSHAL_SIZE = ROUND(sizeof(HTTPCacheAlt), HDR_PTR_SIZE);
01809
01810 void
01811 HTTPInfo::create()
01812 {
01813 m_alt = httpCacheAltAllocator.alloc();
01814 }
01815
01816 void
01817 HTTPInfo::copy(HTTPInfo *hi)
01818 {
01819
01820 if (m_alt && m_alt->m_writeable) {
01821 destroy();
01822 }
01823
01824 create();
01825 m_alt->copy(hi->m_alt);
01826 }
01827
01828 void
01829 HTTPInfo::copy_frag_offsets_from(HTTPInfo* src) {
01830 if (m_alt && src->m_alt)
01831 m_alt->copy_frag_offsets_from(src->m_alt);
01832 }
01833
01834
01835 int
01836 HTTPInfo::marshal_length()
01837 {
01838 int len = HTTP_ALT_MARSHAL_SIZE;
01839
01840 if (m_alt->m_request_hdr.valid()) {
01841 len += m_alt->m_request_hdr.m_heap->marshal_length();
01842 }
01843
01844 if (m_alt->m_response_hdr.valid()) {
01845 len += m_alt->m_response_hdr.m_heap->marshal_length();
01846 }
01847
01848 if (m_alt->m_frag_offset_count > HTTPCacheAlt::N_INTEGRAL_FRAG_OFFSETS) {
01849 len -= sizeof(m_alt->m_integral_frag_offsets);
01850 len += sizeof(FragOffset) * m_alt->m_frag_offset_count;
01851 }
01852
01853 return len;
01854 }
01855
01856 int
01857 HTTPInfo::marshal(char *buf, int len)
01858 {
01859 int tmp;
01860 int used = 0;
01861 HTTPCacheAlt *marshal_alt = (HTTPCacheAlt *) buf;
01862
01863
01864 int frag_len = (0 == m_alt->m_frag_offset_count || m_alt->m_frag_offsets == m_alt->m_integral_frag_offsets) ? 0 : sizeof(HTTPCacheAlt::FragOffset) * m_alt->m_frag_offset_count;
01865
01866 ink_assert(m_alt->m_magic == CACHE_ALT_MAGIC_ALIVE);
01867
01868
01869
01870
01871
01872
01873 if (frag_len) {
01874 memcpy(m_alt->m_integral_frag_offsets, m_alt->m_frag_offsets, sizeof(m_alt->m_integral_frag_offsets));
01875 frag_len -= sizeof(m_alt->m_integral_frag_offsets);
01876
01877
01878 }
01879
01880
01881
01882
01883 memcpy(buf, m_alt, sizeof(HTTPCacheAlt));
01884 marshal_alt->m_magic = CACHE_ALT_MAGIC_MARSHALED;
01885 marshal_alt->m_writeable = 0;
01886 marshal_alt->m_unmarshal_len = -1;
01887 marshal_alt->m_ext_buffer = NULL;
01888 buf += HTTP_ALT_MARSHAL_SIZE;
01889 used += HTTP_ALT_MARSHAL_SIZE;
01890
01891 if (frag_len > 0) {
01892 marshal_alt->m_frag_offsets = static_cast<FragOffset*>(reinterpret_cast<void*>(used));
01893 memcpy(buf, m_alt->m_frag_offsets + HTTPCacheAlt::N_INTEGRAL_FRAG_OFFSETS, frag_len);
01894 buf += frag_len;
01895 used += frag_len;
01896 } else {
01897 marshal_alt->m_frag_offsets = 0;
01898 }
01899
01900
01901
01902
01903 if (m_alt->m_request_hdr.valid()) {
01904 tmp = m_alt->m_request_hdr.m_heap->marshal(buf, len - used);
01905 marshal_alt->m_request_hdr.m_heap = (HdrHeap *)(intptr_t)used;
01906 ink_assert(((intptr_t) marshal_alt->m_request_hdr.m_heap) < len);
01907 buf += tmp;
01908 used += tmp;
01909 } else {
01910 marshal_alt->m_request_hdr.m_heap = NULL;
01911 }
01912
01913 if (m_alt->m_response_hdr.valid()) {
01914 tmp = m_alt->m_response_hdr.m_heap->marshal(buf, len - used);
01915 marshal_alt->m_response_hdr.m_heap = (HdrHeap *)(intptr_t)used;
01916 ink_assert(((intptr_t) marshal_alt->m_response_hdr.m_heap) < len);
01917 used += tmp;
01918 } else {
01919 marshal_alt->m_response_hdr.m_heap = NULL;
01920 }
01921
01922
01923
01924
01925
01926 ink_release_assert(used <= len);
01927
01928 return used;
01929 }
01930
01931 int
01932 HTTPInfo::unmarshal(char *buf, int len, RefCountObj *block_ref)
01933 {
01934 HTTPCacheAlt *alt = (HTTPCacheAlt *) buf;
01935 int orig_len = len;
01936
01937 if (alt->m_magic == CACHE_ALT_MAGIC_ALIVE) {
01938
01939
01940 ink_assert(alt->m_unmarshal_len > 0);
01941 ink_assert(alt->m_unmarshal_len <= len);
01942 return alt->m_unmarshal_len;
01943 } else if (alt->m_magic != CACHE_ALT_MAGIC_MARSHALED) {
01944 ink_assert(!"HTTPInfo::unmarshal bad magic");
01945 return -1;
01946 }
01947
01948 ink_assert(alt->m_unmarshal_len < 0);
01949 alt->m_magic = CACHE_ALT_MAGIC_ALIVE;
01950 ink_assert(alt->m_writeable == 0);
01951 len -= HTTP_ALT_MARSHAL_SIZE;
01952
01953 if (alt->m_frag_offset_count > HTTPCacheAlt::N_INTEGRAL_FRAG_OFFSETS) {
01954
01955 int extra = sizeof(FragOffset) * alt->m_frag_offset_count - sizeof(alt->m_integral_frag_offsets);
01956 char* extra_src = buf + reinterpret_cast<intptr_t>(alt->m_frag_offsets);
01957
01958
01959
01960
01961 int bcount = HTTPCacheAlt::N_INTEGRAL_FRAG_OFFSETS * 2;
01962
01963 while (bcount < alt->m_frag_offset_count) bcount *= 2;
01964 alt->m_frag_offsets = static_cast<FragOffset*>(ats_malloc(bcount * sizeof(FragOffset)));
01965 memcpy(alt->m_frag_offsets, alt->m_integral_frag_offsets, sizeof(alt->m_integral_frag_offsets));
01966 memcpy(alt->m_frag_offsets + HTTPCacheAlt::N_INTEGRAL_FRAG_OFFSETS, extra_src, extra);
01967 len -= extra;
01968 } else if (alt->m_frag_offset_count > 0) {
01969 alt->m_frag_offsets = alt->m_integral_frag_offsets;
01970 } else {
01971 alt->m_frag_offsets = 0;
01972 }
01973
01974 HdrHeap *heap = (HdrHeap *) (alt->m_request_hdr.m_heap ? (buf + (intptr_t) alt->m_request_hdr.m_heap) : 0);
01975 HTTPHdrImpl *hh = NULL;
01976 int tmp;
01977 if (heap != NULL) {
01978
01979 tmp = heap->unmarshal(len, HDR_HEAP_OBJ_HTTP_HEADER, (HdrHeapObjImpl **) & hh, block_ref);
01980 if (hh == NULL || tmp < 0) {
01981 ink_assert(!"HTTPInfo::request unmarshal failed");
01982 return -1;
01983 }
01984 len -= tmp;
01985 alt->m_request_hdr.m_heap = heap;
01986 alt->m_request_hdr.m_http = hh;
01987 alt->m_request_hdr.m_mime = hh->m_fields_impl;
01988 alt->m_request_hdr.m_url_cached.m_heap = heap;
01989 }
01990
01991 heap = (HdrHeap *) (alt->m_response_hdr.m_heap ? (buf + (intptr_t) alt->m_response_hdr.m_heap) : 0);
01992 if (heap != NULL) {
01993 tmp = heap->unmarshal(len, HDR_HEAP_OBJ_HTTP_HEADER, (HdrHeapObjImpl **) & hh, block_ref);
01994 if (hh == NULL || tmp < 0) {
01995 ink_assert(!"HTTPInfo::response unmarshal failed");
01996 return -1;
01997 }
01998 len -= tmp;
01999
02000 alt->m_response_hdr.m_heap = heap;
02001 alt->m_response_hdr.m_http = hh;
02002 alt->m_response_hdr.m_mime = hh->m_fields_impl;
02003 }
02004
02005 alt->m_unmarshal_len = orig_len - len;
02006
02007 return alt->m_unmarshal_len;
02008 }
02009
02010
02011
02012
02013
02014 bool
02015 HTTPInfo::check_marshalled(char *buf, int len)
02016 {
02017 HTTPCacheAlt *alt = (HTTPCacheAlt *) buf;
02018
02019 if (alt->m_magic != CACHE_ALT_MAGIC_MARSHALED) {
02020 return false;
02021 }
02022
02023 if (alt->m_writeable != false) {
02024 return false;
02025 }
02026
02027 if (len < HTTP_ALT_MARSHAL_SIZE) {
02028 return false;
02029 }
02030
02031 if (alt->m_request_hdr.m_heap == NULL) {
02032 return false;
02033 }
02034
02035 if ((intptr_t) alt->m_request_hdr.m_heap > len) {
02036 return false;
02037 }
02038
02039 HdrHeap *heap = (HdrHeap *) (buf + (intptr_t) alt->m_request_hdr.m_heap);
02040 if (heap->check_marshalled(len) == false) {
02041 return false;
02042 }
02043
02044 if (alt->m_response_hdr.m_heap == NULL) {
02045 return false;
02046 }
02047
02048 if ((intptr_t) alt->m_response_hdr.m_heap > len) {
02049 return false;
02050 }
02051
02052 heap = (HdrHeap *) (buf + (intptr_t) alt->m_response_hdr.m_heap);
02053 if (heap->check_marshalled(len) == false) {
02054 return false;
02055 }
02056
02057 return true;
02058 }
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074 void
02075 HTTPInfo::set_buffer_reference(RefCountObj *block_ref)
02076 {
02077 ink_assert(m_alt->m_magic == CACHE_ALT_MAGIC_ALIVE);
02078
02079
02080 if (m_alt->m_ext_buffer != NULL) {
02081 if (m_alt->m_ext_buffer->refcount_dec() == 0) {
02082 m_alt->m_ext_buffer->free();
02083 }
02084 }
02085
02086
02087 if (block_ref) {
02088 block_ref->refcount_inc();
02089 }
02090
02091 m_alt->m_ext_buffer = block_ref;
02092 }
02093
02094 int
02095 HTTPInfo::get_handle(char *buf, int len)
02096 {
02097
02098
02099
02100 HTTPCacheAlt *a = (HTTPCacheAlt *) buf;
02101
02102 if (a->m_magic == CACHE_ALT_MAGIC_ALIVE) {
02103 m_alt = a;
02104 ink_assert(m_alt->m_unmarshal_len > 0);
02105 ink_assert(m_alt->m_unmarshal_len <= len);
02106 return m_alt->m_unmarshal_len;
02107 }
02108
02109 clear();
02110 return -1;
02111 }
02112
02113 void
02114 HTTPInfo::push_frag_offset(FragOffset offset) {
02115 ink_assert(m_alt);
02116 if (0 == m_alt->m_frag_offsets) {
02117 m_alt->m_frag_offsets = m_alt->m_integral_frag_offsets;
02118 } else if (m_alt->m_frag_offset_count >= HTTPCacheAlt::N_INTEGRAL_FRAG_OFFSETS && 0 == (m_alt->m_frag_offset_count & (m_alt->m_frag_offset_count-1))) {
02119
02120
02121 FragOffset* nf = static_cast<FragOffset*>(ats_malloc(sizeof(FragOffset) * (m_alt->m_frag_offset_count * 2)));
02122 memcpy(nf, m_alt->m_frag_offsets, sizeof(FragOffset) * m_alt->m_frag_offset_count);
02123 if (m_alt->m_frag_offsets != m_alt->m_integral_frag_offsets)
02124 ats_free(m_alt->m_frag_offsets);
02125 m_alt->m_frag_offsets = nf;
02126 }
02127
02128 m_alt->m_frag_offsets[m_alt->m_frag_offset_count++] = offset;
02129 }