• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

LogAccessHttp.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /***************************************************************************
00025  LogAccessHttp.cc
00026 
00027  This file defines the Http implementation of a LogAccess object, and
00028  implements the accessor functions using information about an Http state
00029  machine.
00030 
00031 
00032  ***************************************************************************/
00033 #include "libts.h"
00034 #include "Error.h"
00035 #include "LogAccessHttp.h"
00036 #include "http/HttpSM.h"
00037 #include "MIME.h"
00038 #include "HTTP.h"
00039 #include "LogUtils.h"
00040 #include "LogObject.h"
00041 #include "LogConfig.h"
00042 #include "Log.h"
00043 
00044 /*-------------------------------------------------------------------------
00045   LogAccessHttp
00046 
00047   Initialize the private data members and assert that we got a valid state
00048   machine pointer.
00049   -------------------------------------------------------------------------*/
00050 
00051 LogAccessHttp::LogAccessHttp(HttpSM * sm)
00052   : m_http_sm(sm), m_arena(), m_client_request(NULL), m_proxy_response(NULL), m_proxy_request(NULL),
00053     m_server_response(NULL), m_cache_response(NULL), m_client_req_url_str(NULL), m_client_req_url_len(0),
00054     m_client_req_url_canon_str(NULL), m_client_req_url_canon_len(0), m_client_req_unmapped_url_canon_str(NULL),
00055     m_client_req_unmapped_url_canon_len(-1), m_client_req_unmapped_url_path_str(NULL),
00056     m_client_req_unmapped_url_path_len(-1), m_client_req_unmapped_url_host_str(NULL),
00057     m_client_req_unmapped_url_host_len(-1), m_client_req_url_path_str(NULL), m_client_req_url_path_len(0),
00058     m_proxy_resp_content_type_str(NULL), m_proxy_resp_content_type_len(0)
00059 {
00060   ink_assert(m_http_sm != NULL);
00061 }
00062 
00063 /*-------------------------------------------------------------------------
00064   LogAccessHttp::~LogAccessHttp
00065 
00066   Deallocate space for any strings allocated in the init routine.
00067   -------------------------------------------------------------------------*/
00068 
00069 LogAccessHttp::~LogAccessHttp()
00070 {
00071 }
00072 
00073 /*-------------------------------------------------------------------------
00074   LogAccessHttp::init
00075 
00076   Build some strings that will come in handy for processing later, such as
00077   URL.  This saves us from having to build the strings twice: once to
00078   compute their length and a second time to actually marshal them.  We also
00079   initialize local pointers to each of the 4 http headers.  However, there
00080   is no guarantee that these headers will all be valid, so we must always
00081   check the validity of these pointers before using them.
00082   -------------------------------------------------------------------------*/
00083 
00084 #define HIDDEN_CONTENT_TYPE "@Content-Type"
00085 #define HIDDEN_CONTENT_TYPE_LEN 13
00086 
00087 void
00088 LogAccessHttp::init()
00089 {
00090   HttpTransact::HeaderInfo * hdr = &(m_http_sm->t_state.hdr_info);
00091 
00092   if (hdr->client_request.valid()) {
00093     m_client_request = &(hdr->client_request);
00094 
00095     // make a copy of the incoming url into the arena
00096     const char *url_string_ref = m_client_request->url_string_get_ref(&m_client_req_url_len);
00097     m_client_req_url_str = m_arena.str_alloc(m_client_req_url_len + 1);
00098     memcpy(m_client_req_url_str, url_string_ref, m_client_req_url_len);
00099     m_client_req_url_str[m_client_req_url_len] = '\0';
00100 
00101     m_client_req_url_canon_str = LogUtils::escapify_url(&m_arena, m_client_req_url_str, m_client_req_url_len,
00102                                                         &m_client_req_url_canon_len);
00103     m_client_req_url_path_str = m_client_request->path_get(&m_client_req_url_path_len);
00104   }
00105 
00106   if (hdr->client_response.valid()) {
00107     m_proxy_response = &(hdr->client_response);
00108     MIMEField *field = m_proxy_response->field_find(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE);
00109     if (field) {
00110       m_proxy_resp_content_type_str = (char *) field->value_get(&m_proxy_resp_content_type_len);
00111       //
00112       // here is the assert
00113       //
00114       //assert (m_proxy_resp_content_type_str[0] >= 'A' && m_proxy_resp_content_type_str[0] <= 'z');
00115       LogUtils::remove_content_type_attributes(m_proxy_resp_content_type_str, &m_proxy_resp_content_type_len);
00116     } else {
00117       // If Content-Type field is missing, check for @Content-Type
00118       field = m_proxy_response->field_find(HIDDEN_CONTENT_TYPE, HIDDEN_CONTENT_TYPE_LEN);
00119       if (field) {
00120         m_proxy_resp_content_type_str = (char *) field->value_get(&m_proxy_resp_content_type_len);
00121         LogUtils::remove_content_type_attributes(m_proxy_resp_content_type_str, &m_proxy_resp_content_type_len);
00122       }
00123     }
00124   }
00125   if (hdr->server_request.valid()) {
00126     m_proxy_request = &(hdr->server_request);
00127   }
00128   if (hdr->server_response.valid()) {
00129     m_server_response = &(hdr->server_response);
00130   }
00131   if (hdr->cache_response.valid()) {
00132     m_cache_response = &(hdr->cache_response);
00133   }
00134 }
00135 
00136 /*-------------------------------------------------------------------------
00137   The set routines ...
00138 
00139   These routines are used by the WIPE_FIELD_VALUE filter to replace the original req url
00140   strings with the WIPED req strings.
00141   -------------------------------------------------------------------------*/
00142 
00143 void
00144 LogAccessHttp::set_client_req_url(char *buf, int len)
00145 {
00146   if (buf) {
00147     m_client_req_url_len = len;
00148     ink_strlcpy(m_client_req_url_str, buf, m_client_req_url_len + 1);
00149   }
00150 }
00151 
00152 void
00153 LogAccessHttp::set_client_req_url_canon(char *buf, int len)
00154 {
00155   if (buf) {
00156     m_client_req_url_canon_len = len;
00157     ink_strlcpy(m_client_req_url_canon_str, buf, m_client_req_url_canon_len + 1);
00158   }
00159 }
00160 
00161 void
00162 LogAccessHttp::set_client_req_unmapped_url_canon(char *buf, int len)
00163 {
00164   if (buf) {
00165     m_client_req_unmapped_url_canon_len = len;
00166     ink_strlcpy(m_client_req_unmapped_url_canon_str, buf, m_client_req_unmapped_url_canon_len + 1);
00167   }
00168 }
00169 
00170 void
00171 LogAccessHttp::set_client_req_unmapped_url_path(char *buf, int len)
00172 {
00173   if (buf) {
00174     m_client_req_unmapped_url_path_len = len;
00175     ink_strlcpy(m_client_req_unmapped_url_path_str, buf, m_client_req_unmapped_url_path_len + 1);
00176   }
00177 }
00178 
00179 void
00180 LogAccessHttp::set_client_req_unmapped_url_host(char *buf, int len)
00181 {
00182   if (buf) {
00183     m_client_req_unmapped_url_host_len = len;
00184     ink_strlcpy(m_client_req_unmapped_url_host_str, buf, m_client_req_unmapped_url_host_len + 1);
00185   }
00186 }
00187 
00188 void
00189 LogAccessHttp::set_client_req_url_path(char *buf, int len)
00190 {
00191   //?? use m_client_req_unmapped_url_path_str for now..may need to enhance later..
00192   if (buf) {
00193     m_client_req_url_path_len = len;
00194     ink_strlcpy(m_client_req_unmapped_url_path_str, buf, m_client_req_url_path_len + 1);
00195   }
00196 }
00197 
00198 
00199 /*-------------------------------------------------------------------------
00200   The marshalling routines ...
00201 
00202   We know that m_http_sm is a valid pointer (we assert so in the ctor), but
00203   we still need to check the other header pointers before using them in the
00204   routines.
00205   -------------------------------------------------------------------------*/
00206 
00207 /*-------------------------------------------------------------------------
00208   -------------------------------------------------------------------------*/
00209 int
00210 LogAccessHttp::marshal_plugin_identity_id(char *buf)
00211 {
00212   if (buf) marshal_int(buf, m_http_sm->plugin_id);
00213   return INK_MIN_ALIGN;
00214 }
00215 
00216 int
00217 LogAccessHttp::marshal_plugin_identity_tag(char *buf)
00218 {
00219   int len = INK_MIN_ALIGN;
00220   char const* tag = m_http_sm->plugin_tag;
00221 
00222   if (!tag) tag = "*";
00223   else len = LogAccess::strlen(tag);
00224 
00225   if (buf) marshal_str(buf, tag, len);
00226 
00227   return len;
00228 }
00229 
00230 int
00231 LogAccessHttp::marshal_client_host_ip(char *buf)
00232 {
00233   return marshal_ip(buf, &m_http_sm->t_state.client_info.addr.sa);
00234 }
00235 
00236 /*-------------------------------------------------------------------------
00237   -------------------------------------------------------------------------*/
00238 
00239 int
00240 LogAccessHttp::marshal_client_host_port(char *buf)
00241 {
00242   if (buf) {
00243     uint16_t port = ntohs(m_http_sm->t_state.client_info.addr.port());
00244     marshal_int(buf, port);
00245   }
00246   return INK_MIN_ALIGN;
00247 }
00248 
00249 /*-------------------------------------------------------------------------
00250   user authenticated to the proxy (RFC931)
00251   -------------------------------------------------------------------------*/
00252 
00253 int
00254 LogAccessHttp::marshal_client_auth_user_name(char *buf)
00255 {
00256   char *str = NULL;
00257   int len = INK_MIN_ALIGN;
00258 
00259   // Jira TS-40:
00260   // NOTE: Authentication related code and modules were removed/disabled.
00261   //       Uncomment code path below when re-added/enabled.
00262   /*if (m_http_sm->t_state.auth_params.user_name) {
00263     str = m_http_sm->t_state.auth_params.user_name;
00264     len = LogAccess::strlen(str);
00265     } */
00266   if (buf) {
00267     marshal_str(buf, str, len);
00268   }
00269   return len;
00270 }
00271 
00272 
00273 /*-------------------------------------------------------------------------
00274   Private utility function to validate m_client_req_unmapped_url_canon_str &
00275   m_client_req_unmapped_url_canon_len fields.
00276   -------------------------------------------------------------------------*/
00277 
00278 void
00279 LogAccessHttp::validate_unmapped_url(void)
00280 {
00281   if (m_client_req_unmapped_url_canon_len < 0) {
00282     if (m_http_sm->t_state.pristine_url.valid()) {
00283       int unmapped_url_len;
00284       char *unmapped_url = m_http_sm->t_state.pristine_url.string_get_ref(&unmapped_url_len);
00285 
00286       if (unmapped_url && unmapped_url[0] != 0) {
00287         m_client_req_unmapped_url_canon_str =
00288         LogUtils::escapify_url(&m_arena, unmapped_url, unmapped_url_len, &m_client_req_unmapped_url_canon_len);
00289       }
00290     } else {
00291       m_client_req_unmapped_url_canon_len = 0;
00292     }
00293   }
00294 }
00295 
00296 /*-------------------------------------------------------------------------
00297   Private utility function to validate m_client_req_unmapped_url_path_str &
00298   m_client_req_unmapped_url_path_len fields.
00299   -------------------------------------------------------------------------*/
00300 
00301 void
00302 LogAccessHttp::validate_unmapped_url_path(void)
00303 {
00304   int len;
00305   char *c;
00306 
00307   if (m_client_req_unmapped_url_path_len < 0 && m_client_req_unmapped_url_host_len < 0) {
00308     // Use unmapped canonical URL as default
00309     m_client_req_unmapped_url_path_str = m_client_req_unmapped_url_canon_str;
00310     m_client_req_unmapped_url_path_len = m_client_req_unmapped_url_canon_len;
00311 
00312     if (m_client_req_unmapped_url_path_len >= 6) {      // xxx:// - minimum schema size
00313       c = (char *) memchr((void *) m_client_req_unmapped_url_path_str, ':', m_client_req_unmapped_url_path_len - 1);
00314       if (c && (len = (int) (c - m_client_req_unmapped_url_path_str)) <= 5) {   // 5 - max schema size
00315         if (len + 2 <= m_client_req_unmapped_url_canon_len && c[1] == '/' && c[2] == '/') {
00316           len += 3;             // Skip "://"
00317           m_client_req_unmapped_url_host_str = &m_client_req_unmapped_url_canon_str[len];
00318           m_client_req_unmapped_url_host_len = m_client_req_unmapped_url_path_len - len;
00319           // Attempt to find first '/' in the path
00320           if (m_client_req_unmapped_url_host_len > 0 &&
00321               (c =
00322                (char *) memchr((void *) m_client_req_unmapped_url_host_str, '/',
00323                                m_client_req_unmapped_url_path_len)) != 0) {
00324             m_client_req_unmapped_url_host_len = (int) (c - m_client_req_unmapped_url_host_str);
00325             m_client_req_unmapped_url_path_str = &m_client_req_unmapped_url_host_str[m_client_req_unmapped_url_host_len];
00326             m_client_req_unmapped_url_path_len = m_client_req_unmapped_url_path_len - len - m_client_req_unmapped_url_host_len;
00327           }
00328         }
00329       }
00330     }
00331   }
00332 }
00333 
00334 
00335 /*-------------------------------------------------------------------------
00336   This is the method, url, and version all rolled into one.  Use the
00337   respective marshalling routines to do the job.
00338   -------------------------------------------------------------------------*/
00339 
00340 int
00341 LogAccessHttp::marshal_client_req_text(char *buf)
00342 {
00343   int len = marshal_client_req_http_method(NULL) + marshal_client_req_url(NULL) + marshal_client_req_http_version(NULL);
00344 
00345   if (buf) {
00346     int offset = 0;
00347     offset += marshal_client_req_http_method(&buf[offset]);
00348     offset += marshal_client_req_url(&buf[offset]);
00349     offset += marshal_client_req_http_version(&buf[offset]);
00350     len = offset;
00351   }
00352   return len;
00353 }
00354 
00355 /*-------------------------------------------------------------------------
00356   -------------------------------------------------------------------------*/
00357 
00358 int
00359 LogAccessHttp::marshal_client_req_http_method(char *buf)
00360 {
00361   char *str = NULL;
00362   int alen = 0;
00363   int plen = INK_MIN_ALIGN;
00364 
00365   if (m_client_request) {
00366     str = (char *) m_client_request->method_get(&alen);
00367 
00368     // calculate the the padded length only if the actual length
00369     // is not zero. We don't want the padded length to be zero
00370     // because marshal_mem should write the DEFAULT_STR to the
00371     // buffer if str is nil, and we need room for this.
00372     //
00373     if (alen) {
00374       plen = round_strlen(alen + 1);    // +1 for trailing 0
00375     }
00376   }
00377 
00378   if (buf)
00379     marshal_mem(buf, str, alen, plen);
00380   return plen;
00381 }
00382 
00383 /*-------------------------------------------------------------------------
00384   -------------------------------------------------------------------------*/
00385 
00386 int
00387 LogAccessHttp::marshal_client_req_url(char *buf)
00388 {
00389   int len = round_strlen(m_client_req_url_len + 1);     // +1 for trailing 0
00390 
00391   if (buf) {
00392     marshal_mem(buf, m_client_req_url_str, m_client_req_url_len, len);
00393   }
00394   return len;
00395 }
00396 
00397 /*-------------------------------------------------------------------------
00398   -------------------------------------------------------------------------*/
00399 
00400 int
00401 LogAccessHttp::marshal_client_req_url_canon(char *buf)
00402 {
00403   int len = round_strlen(m_client_req_url_canon_len + 1);
00404 
00405   if (buf) {
00406     marshal_mem(buf, m_client_req_url_canon_str, m_client_req_url_canon_len, len);
00407   }
00408   return len;
00409 }
00410 
00411 
00412 /*-------------------------------------------------------------------------
00413   -------------------------------------------------------------------------*/
00414 
00415 int
00416 LogAccessHttp::marshal_client_req_unmapped_url_canon(char *buf)
00417 {
00418   int len = INK_MIN_ALIGN;
00419 
00420   validate_unmapped_url();
00421   if (0 == m_client_req_unmapped_url_canon_len) {
00422     // If the unmapped URL isn't populated, we'll fall back to the original
00423     // client URL. This helps for example server intercepts to continue to
00424     // log the requests, even when there is no remap rule for it.
00425     len = marshal_client_req_url_canon(buf);
00426   } else {
00427     len = round_strlen(m_client_req_unmapped_url_canon_len + 1);      // +1 for eos
00428     if (buf) {
00429       marshal_mem(buf, m_client_req_unmapped_url_canon_str, m_client_req_unmapped_url_canon_len, len);
00430     }
00431   }
00432 
00433   return len;
00434 }
00435 
00436 /*-------------------------------------------------------------------------
00437   -------------------------------------------------------------------------*/
00438 
00439 int
00440 LogAccessHttp::marshal_client_req_unmapped_url_path(char *buf)
00441 {
00442   int len = INK_MIN_ALIGN;
00443 
00444   validate_unmapped_url();
00445   validate_unmapped_url_path();
00446 
00447   if (0 == m_client_req_unmapped_url_path_len) {
00448     len = marshal_client_req_url_path(buf);
00449   } else {
00450     len = round_strlen(m_client_req_unmapped_url_path_len + 1);   // +1 for eos
00451     if (buf) {
00452       marshal_mem(buf, m_client_req_unmapped_url_path_str, m_client_req_unmapped_url_path_len, len);
00453     }
00454   }
00455   return len;
00456 }
00457 
00458 /*-------------------------------------------------------------------------
00459   -------------------------------------------------------------------------*/
00460 
00461 int
00462 LogAccessHttp::marshal_client_req_unmapped_url_host(char *buf)
00463 {
00464   int len = INK_MIN_ALIGN;
00465 
00466   validate_unmapped_url();
00467   validate_unmapped_url_path();
00468 
00469   len = round_strlen(m_client_req_unmapped_url_host_len + 1);      // +1 for eos
00470   if (buf) {
00471     marshal_mem(buf, m_client_req_unmapped_url_host_str, m_client_req_unmapped_url_host_len, len);
00472   }
00473   return len;
00474 }
00475 
00476 int
00477 LogAccessHttp::marshal_client_req_url_path(char *buf)
00478 {
00479   int len = round_strlen(m_client_req_url_path_len + 1);
00480   if (buf) {
00481     marshal_mem(buf, m_client_req_url_path_str, m_client_req_url_path_len, len);
00482   }
00483   return len;
00484 }
00485 
00486 int
00487 LogAccessHttp::marshal_client_req_url_scheme(char *buf)
00488 {
00489   char *str = NULL;
00490   int alen = 0;
00491   int plen = INK_MIN_ALIGN;
00492 
00493   str = (char *) m_client_request->scheme_get(&alen);
00494 
00495   // calculate the the padded length only if the actual length
00496   // is not zero. We don't want the padded length to be zero
00497   // because marshal_mem should write the DEFAULT_STR to the
00498   // buffer if str is nil, and we need room for this.
00499   //
00500   if (alen) {
00501     plen = round_strlen(alen + 1);    // +1 for trailing 0
00502   }
00503 
00504   if (buf) {
00505     marshal_mem(buf, str, alen, plen);
00506   }
00507 
00508   return plen;
00509 }
00510 
00511 /*-------------------------------------------------------------------------
00512   For this one we're going to marshal two INTs, one the first representing
00513   the major number and the second representing the minor.
00514   -------------------------------------------------------------------------*/
00515 
00516 int
00517 LogAccessHttp::marshal_client_req_http_version(char *buf)
00518 {
00519   if (buf) {
00520     int64_t major = 0;
00521     int64_t minor = 0;
00522     if (m_client_request) {
00523       HTTPVersion versionObject = m_client_request->version_get();
00524       major = HTTP_MAJOR(versionObject.m_version);
00525       minor = HTTP_MINOR(versionObject.m_version);
00526     }
00527     marshal_int(buf, major);
00528     marshal_int((buf + INK_MIN_ALIGN), minor);
00529   }
00530   return (2 * INK_MIN_ALIGN);
00531 }
00532 
00533 /*-------------------------------------------------------------------------
00534   -------------------------------------------------------------------------*/
00535 
00536 int
00537 LogAccessHttp::marshal_client_req_header_len(char *buf)
00538 {
00539   if (buf) {
00540     int64_t len = 0;
00541     if (m_client_request) {
00542       len = m_client_request->length_get();
00543     }
00544     marshal_int(buf, len);
00545   }
00546   return INK_MIN_ALIGN;
00547 }
00548 
00549 /*-------------------------------------------------------------------------
00550   -------------------------------------------------------------------------*/
00551 
00552 int
00553 LogAccessHttp::marshal_client_req_body_len(char *buf)
00554 {
00555   if (buf) {
00556     int64_t len = 0;
00557     if (m_client_request) {
00558       len = m_http_sm->client_request_body_bytes;
00559     }
00560     marshal_int(buf, len);
00561   }
00562   return INK_MIN_ALIGN;
00563 }
00564 
00565 int
00566 LogAccessHttp::marshal_client_finish_status_code(char *buf)
00567 {
00568   if (buf) {
00569     int code = LOG_FINISH_FIN;
00570     HttpTransact::AbortState_t cl_abort_state = m_http_sm->t_state.client_info.abort;
00571     if (cl_abort_state == HttpTransact::ABORTED) {
00572 
00573       // Check to see if the abort is due to a timeout
00574       if (m_http_sm->t_state.client_info.state == HttpTransact::ACTIVE_TIMEOUT ||
00575           m_http_sm->t_state.client_info.state == HttpTransact::INACTIVE_TIMEOUT) {
00576         code = LOG_FINISH_TIMEOUT;
00577       } else {
00578         code = LOG_FINISH_INTR;
00579       }
00580     }
00581     marshal_int(buf, code);
00582   }
00583   return INK_MIN_ALIGN;
00584 }
00585 
00586 /*-------------------------------------------------------------------------
00587   -------------------------------------------------------------------------*/
00588 
00589 int
00590 LogAccessHttp::marshal_proxy_resp_content_type(char *buf)
00591 {
00592   int len = round_strlen(m_proxy_resp_content_type_len + 1);
00593   if (buf) {
00594     marshal_mem(buf, m_proxy_resp_content_type_str, m_proxy_resp_content_type_len, len);
00595   }
00596   return len;
00597 }
00598 
00599 /*-------------------------------------------------------------------------
00600   Squid returns the content-length + header length as the total length.
00601   -------------------------------------------------------------------------*/
00602 
00603 int
00604 LogAccessHttp::marshal_proxy_resp_squid_len(char *buf)
00605 {
00606   if (buf) {
00607     int64_t val = m_http_sm->client_response_hdr_bytes + m_http_sm->client_response_body_bytes;
00608     marshal_int(buf, val);
00609   }
00610   return INK_MIN_ALIGN;
00611 }
00612 
00613 /*-------------------------------------------------------------------------
00614   -------------------------------------------------------------------------*/
00615 
00616 int
00617 LogAccessHttp::marshal_proxy_resp_content_len(char *buf)
00618 {
00619   if (buf) {
00620     int64_t val = m_http_sm->client_response_body_bytes;
00621     marshal_int(buf, val);
00622   }
00623   return INK_MIN_ALIGN;
00624 }
00625 
00626 /*-------------------------------------------------------------------------
00627   -------------------------------------------------------------------------*/
00628 
00629 int
00630 LogAccessHttp::marshal_proxy_resp_status_code(char *buf)
00631 {
00632   if (buf) {
00633     HTTPStatus status;
00634     if (m_proxy_response && m_client_request) {
00635       if (m_client_request->version_get() >= HTTPVersion(1, 0)) {
00636         status = m_proxy_response->status_get();
00637       }
00638       // INKqa10788
00639       // For bad/incomplete request, the request version may be 0.9.
00640       // However, we can still log the status code if there is one.
00641       else if (m_proxy_response->valid()) {
00642         status = m_proxy_response->status_get();
00643       } else {
00644         status = HTTP_STATUS_OK;
00645       }
00646     } else {
00647       status = HTTP_STATUS_NONE;
00648     }
00649     marshal_int(buf, (int64_t) status);
00650   }
00651   return INK_MIN_ALIGN;
00652 }
00653 
00654 /*-------------------------------------------------------------------------
00655   -------------------------------------------------------------------------*/
00656 
00657 int
00658 LogAccessHttp::marshal_proxy_resp_header_len(char *buf)
00659 {
00660   if (buf) {
00661     int64_t val = m_http_sm->client_response_hdr_bytes;
00662     marshal_int(buf, val);
00663   }
00664   return INK_MIN_ALIGN;
00665 }
00666 
00667 int
00668 LogAccessHttp::marshal_proxy_finish_status_code(char *buf)
00669 {
00670   /* FIXME: Should there be no server transaction code if
00671      the result comes out of the cache.  Right now we default
00672      to FIN */
00673   if (buf) {
00674     int code = LOG_FINISH_FIN;
00675     if (m_http_sm->t_state.current.server) {
00676       switch (m_http_sm->t_state.current.server->state) {
00677       case HttpTransact::ACTIVE_TIMEOUT:
00678       case HttpTransact::INACTIVE_TIMEOUT:
00679         code = LOG_FINISH_TIMEOUT;
00680         break;
00681       case HttpTransact::CONNECTION_ERROR:
00682         code = LOG_FINISH_INTR;
00683         break;
00684       default:
00685         if (m_http_sm->t_state.current.server->abort == HttpTransact::ABORTED) {
00686           code = LOG_FINISH_INTR;
00687         }
00688         break;
00689       }
00690     }
00691 
00692     marshal_int(buf, code);
00693   }
00694 
00695   return INK_MIN_ALIGN;
00696 }
00697 
00698 /*-------------------------------------------------------------------------
00699   -------------------------------------------------------------------------*/
00700 
00701 int
00702 LogAccessHttp::marshal_cache_result_code(char *buf)
00703 {
00704   if (buf) {
00705     SquidLogCode code = m_http_sm->t_state.squid_codes.log_code;
00706     marshal_int(buf, (int64_t) code);
00707   }
00708   return INK_MIN_ALIGN;
00709 }
00710 
00711 /*-------------------------------------------------------------------------
00712   -------------------------------------------------------------------------*/
00713 
00714 int
00715 LogAccessHttp::marshal_proxy_req_header_len(char *buf)
00716 {
00717   if (buf) {
00718     int64_t val = 0;
00719     if (m_proxy_request) {
00720       val = m_proxy_request->length_get();
00721     }
00722     marshal_int(buf, val);
00723   }
00724   return INK_MIN_ALIGN;
00725 }
00726 
00727 /*-------------------------------------------------------------------------
00728   -------------------------------------------------------------------------*/
00729 
00730 int
00731 LogAccessHttp::marshal_proxy_req_body_len(char *buf)
00732 {
00733   if (buf) {
00734     int64_t val = 0;
00735     if (m_proxy_request) {
00736       val = m_http_sm->server_request_body_bytes;
00737     }
00738     marshal_int(buf, val);
00739   }
00740   return INK_MIN_ALIGN;
00741 }
00742 
00743 int
00744 LogAccessHttp::marshal_proxy_req_server_name(char *buf)
00745 {
00746   char *str = NULL;
00747   int len = INK_MIN_ALIGN;
00748 
00749   if (m_http_sm->t_state.current.server) {
00750     str = m_http_sm->t_state.current.server->name;
00751     len = LogAccess::strlen(str);
00752   }
00753 
00754   if (buf) {
00755     marshal_str(buf, str, len);
00756   }
00757   return len;
00758 }
00759 
00760 // TODO: Change marshalling code to support both IPv4 and IPv6 addresses.
00761 int
00762 LogAccessHttp::marshal_proxy_req_server_ip(char *buf)
00763 {
00764   return marshal_ip(buf, m_http_sm->t_state.current.server != NULL ? &m_http_sm->t_state.current.server->addr.sa : 0);
00765 }
00766 
00767 /*-------------------------------------------------------------------------
00768   -------------------------------------------------------------------------*/
00769 
00770 int
00771 LogAccessHttp::marshal_proxy_hierarchy_route(char *buf)
00772 {
00773   if (buf) {
00774     SquidHierarchyCode code = m_http_sm->t_state.squid_codes.hier_code;
00775     marshal_int(buf, (int64_t) code);
00776   }
00777   return INK_MIN_ALIGN;
00778 }
00779 
00780 /*-------------------------------------------------------------------------
00781   -------------------------------------------------------------------------*/
00782 
00783 // TODO: Change marshalling code to support both IPv4 and IPv6 addresses.
00784 int
00785 LogAccessHttp::marshal_server_host_ip(char *buf)
00786 {
00787   sockaddr const* ip = 0;
00788   ip = &m_http_sm->t_state.server_info.addr.sa;
00789   if (! ats_is_ip(ip)) {
00790     if (m_http_sm->t_state.current.server) {
00791       ip = &m_http_sm->t_state.current.server->addr.sa;
00792       if (! ats_is_ip(ip)) ip = 0;
00793     } else {
00794       ip = 0;
00795     }
00796   }
00797   return marshal_ip(buf, ip);
00798 }
00799 
00800 
00801 /*-------------------------------------------------------------------------
00802   -------------------------------------------------------------------------*/
00803 
00804 int
00805 LogAccessHttp::marshal_server_host_name(char *buf)
00806 {
00807   char const* str = NULL;
00808   int padded_len = INK_MIN_ALIGN;
00809   int actual_len = 0;
00810 
00811   if (m_client_request) {
00812     str = m_client_request->host_get(&actual_len);
00813 
00814     if (str)
00815       padded_len = round_strlen(actual_len + 1);        // +1 for trailing 0
00816   }
00817   if (buf) {
00818     marshal_mem(buf, str, actual_len, padded_len);
00819   }
00820   return padded_len;
00821 }
00822 
00823 
00824 /*-------------------------------------------------------------------------
00825   -------------------------------------------------------------------------*/
00826 
00827 int
00828 LogAccessHttp::marshal_server_resp_status_code(char *buf)
00829 {
00830   if (buf) {
00831     HTTPStatus status;
00832     if (m_server_response) {
00833       status = m_server_response->status_get();
00834     } else {
00835       status = HTTP_STATUS_NONE;
00836     }
00837     marshal_int(buf, (int64_t) status);
00838   }
00839   return INK_MIN_ALIGN;
00840 }
00841 
00842 /*-------------------------------------------------------------------------
00843   -------------------------------------------------------------------------*/
00844 
00845 int
00846 LogAccessHttp::marshal_server_resp_content_len(char *buf)
00847 {
00848   if (buf) {
00849     int64_t val = 0;
00850     if (m_server_response) {
00851       val = m_http_sm->server_response_body_bytes;
00852     }
00853     marshal_int(buf, val);
00854   }
00855   return INK_MIN_ALIGN;
00856 }
00857 
00858 /*-------------------------------------------------------------------------
00859   -------------------------------------------------------------------------*/
00860 
00861 int
00862 LogAccessHttp::marshal_server_resp_header_len(char *buf)
00863 {
00864   if (buf) {
00865     int64_t val = 0;
00866     if (m_server_response) {
00867       val = m_server_response->length_get();
00868     }
00869     marshal_int(buf, val);
00870   }
00871   return INK_MIN_ALIGN;
00872 }
00873 
00874 int
00875 LogAccessHttp::marshal_server_resp_http_version(char *buf)
00876 {
00877   if (buf) {
00878     int64_t major = 0;
00879     int64_t minor = 0;
00880     if (m_server_response) {
00881       major = HTTP_MAJOR(m_server_response->version_get().m_version);
00882       minor = HTTP_MINOR(m_server_response->version_get().m_version);
00883     }
00884     marshal_int(buf, major);
00885     marshal_int((buf + INK_MIN_ALIGN), minor);
00886   }
00887   return (2 * INK_MIN_ALIGN);
00888 }
00889 
00890 /*-------------------------------------------------------------------------
00891   -------------------------------------------------------------------------*/
00892 
00893 int
00894 LogAccessHttp::marshal_cache_resp_status_code(char *buf)
00895 {
00896   if (buf) {
00897     HTTPStatus status;
00898     if (m_cache_response) {
00899       status = m_cache_response->status_get();
00900     } else {
00901       status = HTTP_STATUS_NONE;
00902     }
00903     marshal_int(buf, (int64_t) status);
00904   }
00905   return INK_MIN_ALIGN;
00906 }
00907 
00908 /*-------------------------------------------------------------------------
00909   -------------------------------------------------------------------------*/
00910 
00911 int
00912 LogAccessHttp::marshal_cache_resp_content_len(char *buf)
00913 {
00914   if (buf) {
00915     int64_t val = 0;
00916     if (m_cache_response) {
00917       val = m_http_sm->cache_response_body_bytes;
00918     }
00919     marshal_int(buf, val);
00920   }
00921   return INK_MIN_ALIGN;
00922 }
00923 
00924 /*-------------------------------------------------------------------------
00925   -------------------------------------------------------------------------*/
00926 
00927 int
00928 LogAccessHttp::marshal_cache_resp_header_len(char *buf)
00929 {
00930   if (buf) {
00931     int64_t val = 0;
00932     if (m_cache_response) {
00933       val = m_http_sm->cache_response_hdr_bytes;
00934     }
00935     marshal_int(buf, val);
00936   }
00937   return INK_MIN_ALIGN;
00938 }
00939 
00940 int
00941 LogAccessHttp::marshal_cache_resp_http_version(char *buf)
00942 {
00943   if (buf) {
00944     int64_t major = 0;
00945     int64_t minor = 0;
00946     if (m_cache_response) {
00947       major = HTTP_MAJOR(m_cache_response->version_get().m_version);
00948       minor = HTTP_MINOR(m_cache_response->version_get().m_version);
00949     }
00950     marshal_int(buf, major);
00951     marshal_int((buf + INK_MIN_ALIGN), minor);
00952   }
00953   return (2 * INK_MIN_ALIGN);
00954 }
00955 
00956 
00957 int
00958 LogAccessHttp::marshal_client_retry_after_time(char *buf)
00959 {
00960   if (buf) {
00961     int64_t crat = m_http_sm->t_state.congestion_control_crat;
00962     marshal_int(buf, crat);
00963   }
00964   return INK_MIN_ALIGN;
00965 }
00966 
00967 static LogCacheWriteCodeType
00968 convert_cache_write_code(HttpTransact::CacheWriteStatus_t t)
00969 {
00970 
00971   LogCacheWriteCodeType code;
00972   switch (t) {
00973   case HttpTransact::NO_CACHE_WRITE:
00974     code = LOG_CACHE_WRITE_NONE;
00975     break;
00976   case HttpTransact::CACHE_WRITE_LOCK_MISS:
00977     code = LOG_CACHE_WRITE_LOCK_MISSED;
00978     break;
00979   case HttpTransact::CACHE_WRITE_IN_PROGRESS:
00980     // Hack - the HttpSM doesn't record
00981     //   cache write aborts currently so
00982     //   if it's not complete declare it
00983     //   aborted
00984     code = LOG_CACHE_WRITE_LOCK_ABORTED;
00985     break;
00986   case HttpTransact::CACHE_WRITE_ERROR:
00987     code = LOG_CACHE_WRITE_ERROR;
00988     break;
00989   case HttpTransact::CACHE_WRITE_COMPLETE:
00990     code = LOG_CACHE_WRITE_COMPLETE;
00991     break;
00992   default:
00993     ink_assert(!"bad cache write code");
00994     code = LOG_CACHE_WRITE_NONE;
00995     break;
00996   }
00997 
00998   return code;
00999 }
01000 
01001 
01002 int
01003 LogAccessHttp::marshal_cache_write_code(char *buf)
01004 {
01005 
01006   if (buf) {
01007     int code = convert_cache_write_code(m_http_sm->t_state.cache_info.write_status);
01008     marshal_int(buf, code);
01009   }
01010 
01011   return INK_MIN_ALIGN;
01012 }
01013 
01014 int
01015 LogAccessHttp::marshal_cache_write_transform_code(char *buf)
01016 {
01017 
01018   if (buf) {
01019     int code = convert_cache_write_code(m_http_sm->t_state.cache_info.transform_write_status);
01020     marshal_int(buf, code);
01021   }
01022 
01023   return INK_MIN_ALIGN;
01024 }
01025 
01026 
01027 /*-------------------------------------------------------------------------
01028   -------------------------------------------------------------------------*/
01029 
01030 int
01031 LogAccessHttp::marshal_transfer_time_ms(char *buf)
01032 {
01033   if (buf) {
01034     ink_hrtime elapsed = m_http_sm->milestones.sm_finish - m_http_sm->milestones.sm_start;
01035     elapsed /= HRTIME_MSECOND;
01036     int64_t val = (int64_t) elapsed;
01037     marshal_int(buf, val);
01038   }
01039   return INK_MIN_ALIGN;
01040 }
01041 
01042 int
01043 LogAccessHttp::marshal_transfer_time_s(char *buf)
01044 {
01045   if (buf) {
01046     ink_hrtime elapsed = m_http_sm->milestones.sm_finish - m_http_sm->milestones.sm_start;
01047     elapsed /= HRTIME_SECOND;
01048     int64_t val = (int64_t) elapsed;
01049     marshal_int(buf, val);
01050   }
01051   return INK_MIN_ALIGN;
01052 }
01053 
01054 /*-------------------------------------------------------------------------
01055   Figure out the size of the object *on origin*. This is somewhat tricky
01056   since there are many variations on how this can be calculated.
01057   -------------------------------------------------------------------------*/
01058 int
01059 LogAccessHttp::marshal_file_size(char *buf)
01060 {
01061   if (buf) {
01062     MIMEField *fld;
01063     HTTPHdr *hdr = m_server_response ? m_server_response : m_cache_response;
01064 
01065     if (hdr && (fld = hdr->field_find(MIME_FIELD_CONTENT_RANGE, MIME_LEN_CONTENT_RANGE))) {
01066       int len;
01067       char *str = (char*)fld->value_get(&len);
01068       char *pos = (char*)memchr(str, '/', len); // Find the /
01069 
01070       // If the size is not /* (which means unknown) use it as the file_size.
01071       if (pos && !memchr(pos+1, '*', len - (pos + 1 - str))) {
01072         marshal_int(buf, ink_atoi64(pos+1, len - (pos + 1 - str)));
01073       }
01074     } else {
01075       // This is semi-broken when we serveq zero length objects. See TS-2213
01076       if (m_http_sm->server_response_body_bytes > 0)
01077         marshal_int(buf, m_http_sm->server_response_body_bytes);
01078       else if (m_http_sm->cache_response_body_bytes > 0)
01079         marshal_int(buf, m_http_sm->cache_response_body_bytes);
01080     }
01081   }
01082   // Else, we don't set the value at all (so, -)
01083 
01084   return INK_MIN_ALIGN;
01085 }
01086 
01087 /*-------------------------------------------------------------------------
01088   -------------------------------------------------------------------------*/
01089 
01090 int
01091 LogAccessHttp::marshal_http_header_field(LogField::Container container, char *field, char *buf)
01092 {
01093   char *str = NULL;
01094   int padded_len = INK_MIN_ALIGN;
01095   int actual_len = 0;
01096   bool valid_field = false;
01097   HTTPHdr *header;
01098 
01099   switch (container) {
01100   case LogField::CQH:
01101     header = m_client_request;
01102     break;
01103 
01104   case LogField::PSH:
01105     header = m_proxy_response;
01106     break;
01107 
01108   case LogField::PQH:
01109     header = m_proxy_request;
01110     break;
01111 
01112   case LogField::SSH:
01113     header = m_server_response;
01114     break;
01115 
01116   case LogField::CSSH:
01117     header = m_cache_response;
01118     break;
01119 
01120   default:
01121     header = NULL;
01122     break;
01123   }
01124 
01125   if (header) {
01126     MIMEField *fld = header->field_find(field, (int)::strlen(field));
01127     if (fld) {
01128       valid_field = true;
01129 
01130       // Loop over dups, marshalling each one into the buffer and
01131       // summing up their length
01132       //
01133       int running_len = 0;
01134       while (fld) {
01135         str = (char *) fld->value_get(&actual_len);
01136         if (buf) {
01137           memcpy(buf, str, actual_len);
01138           buf += actual_len;
01139         }
01140         running_len += actual_len;
01141         fld = fld->m_next_dup;
01142 
01143         // Dups need to be comma separated.  So if there's another
01144         // dup, then add a comma and a space ...
01145         //
01146         if (fld != NULL) {
01147           if (buf) {
01148             memcpy(buf, ", ", 2);
01149             buf += 2;
01150           }
01151           running_len += 2;
01152         }
01153       }
01154 
01155       // Done with all dups.  Ensure that the string is terminated
01156       // and that the running_len is padded.
01157       //
01158       if (buf) {
01159         *buf = '\0';
01160         buf++;
01161       }
01162       running_len += 1;
01163       padded_len = round_strlen(running_len);
01164 
01165       // Note: marshal_string fills the padding to
01166       //  prevent purify UMRs so we do it here too
01167       //  since we always pass the unpadded length on
01168       //  our calls to marshal string
01169 #ifdef DEBUG
01170       if (buf) {
01171         int pad_len = padded_len - running_len;
01172         for (int i = 0; i < pad_len; i++) {
01173           *buf = '$';
01174           buf++;
01175         }
01176       }
01177 #endif
01178     }
01179   }
01180 
01181   if (valid_field == false) {
01182     padded_len = INK_MIN_ALIGN;
01183     if (buf) {
01184       marshal_str(buf, NULL, padded_len);
01185     }
01186   }
01187 
01188   return (padded_len);
01189 }
01190 
01191 int
01192 LogAccessHttp::marshal_http_header_field_escapify(LogField::Container container, char *field, char *buf)
01193 {
01194   char *str = NULL, *new_str = NULL;
01195   int padded_len = INK_MIN_ALIGN;
01196   int actual_len = 0, new_len = 0;
01197   bool valid_field = false;
01198   HTTPHdr *header;
01199 
01200   switch (container) {
01201   case LogField::ECQH:
01202     header = m_client_request;
01203     break;
01204 
01205   case LogField::EPSH:
01206     header = m_proxy_response;
01207     break;
01208 
01209   case LogField::EPQH:
01210     header = m_proxy_request;
01211     break;
01212 
01213   case LogField::ESSH:
01214     header = m_server_response;
01215     break;
01216 
01217   case LogField::ECSSH:
01218     header = m_cache_response;
01219     break;
01220 
01221   default:
01222     header = NULL;
01223     break;
01224   }
01225 
01226   if (header) {
01227     MIMEField *fld = header->field_find(field, (int)::strlen(field));
01228     if (fld) {
01229       valid_field = true;
01230 
01231       // Loop over dups, marshalling each one into the buffer and
01232       // summing up their length
01233       //
01234       int running_len = 0;
01235       while (fld) {
01236         str = (char *) fld->value_get(&actual_len);
01237         new_str = LogUtils::escapify_url(&m_arena, str, actual_len, &new_len);
01238         if (buf) {
01239           memcpy(buf, new_str, new_len);
01240           buf += new_len;
01241         }
01242         running_len += new_len;
01243         fld = fld->m_next_dup;
01244 
01245         // Dups need to be comma separated.  So if there's another
01246         // dup, then add a comma and a space ...
01247         //
01248         if (fld != NULL) {
01249           if (buf) {
01250             memcpy(buf, ", ", 2);
01251             buf += 2;
01252           }
01253           running_len += 2;
01254         }
01255       }
01256 
01257       // Done with all dups.  Ensure that the string is terminated
01258       // and that the running_len is padded.
01259       //
01260       if (buf) {
01261         *buf = '\0';
01262         buf++;
01263       }
01264       running_len += 1;
01265       padded_len = round_strlen(running_len);
01266 
01267       // Note: marshal_string fills the padding to
01268       //  prevent purify UMRs so we do it here too
01269       //  since we always pass the unpadded length on
01270       //  our calls to marshal string
01271 #ifdef DEBUG
01272       if (buf) {
01273         int pad_len = padded_len - running_len;
01274         for (int i = 0; i < pad_len; i++) {
01275           *buf = '$';
01276           buf++;
01277         }
01278       }
01279 #endif
01280     }
01281   }
01282 
01283   if (valid_field == false) {
01284     padded_len = INK_MIN_ALIGN;
01285     if (buf) {
01286       marshal_str(buf, NULL, padded_len);
01287     }
01288   }
01289 
01290   return (padded_len);
01291 }

Generated by  doxygen 1.7.1