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 }