~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to proxy/http/HttpSM.cc

  • Committer: Package Import Robot
  • Author(s): Aron Xu
  • Date: 2013-05-09 01:00:04 UTC
  • mto: (1.1.11) (5.3.3 experimental)
  • mto: This revision was merged to the branch mainline in revision 15.
  • Revision ID: package-import@ubuntu.com-20130509010004-9fqq9n0adseg3f8w
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
316
316
    plugin_tunnel(NULL), reentrancy_count(0),
317
317
    history_pos(0), tunnel(), ua_entry(NULL),
318
318
    ua_session(NULL), background_fill(BACKGROUND_FILL_NONE),
 
319
    ua_raw_buffer_reader(NULL),
319
320
    server_entry(NULL), server_session(NULL), shared_session_retries(0),
320
321
    server_buffer_reader(NULL),
321
322
    transform_info(), post_transform_info(), second_cache_sm(NULL),
417
418
  t_state.cache_info.config.cache_vary_default_other = t_state.http_config_param->cache_vary_default_other;
418
419
 
419
420
  t_state.init();
 
421
  t_state.srv_lookup = HttpConfig::m_master.srv_enabled;
420
422
  // Added to skip dns if the document is in cache. DNS will be forced if there is a ip based ACL in
421
423
  // cache control or parent.config or if the doc_in_cache_skip_dns is disabled or if http caching is disabled
422
424
  // TODO: This probably doesn't honor this as a per-transaction overridable config.
621
623
  t_state.hdr_info.client_request.create(HTTP_TYPE_REQUEST);
622
624
  http_parser_init(&http_parser);
623
625
 
 
626
  // Prepare raw reader which will live until we are sure this is HTTP indeed
 
627
  if (is_transparent_passthrough_allowed()) {
 
628
      ua_raw_buffer_reader = buffer_reader->clone();
 
629
  }
 
630
 
624
631
  // We first need to run the transaction start hook.  Since
625
632
  //  this hook maybe asyncronous, we need to disable IO on
626
633
  //  client but set the continuation to be the state machine
689
696
  case VC_EVENT_ACTIVE_TIMEOUT:
690
697
    // The user agent is hosed.  Close it &
691
698
    //   bail on the state machine
692
 
    if (t_state.http_config_param->log_spider_codes) {
693
 
      t_state.squid_codes.wuts_proxy_status_code = WUTS_PROXY_STATUS_SPIDER_TIMEOUT_WHILE_DRAINING;
694
 
      t_state.squid_codes.log_code = SQUID_LOG_ERR_SPIDER_TIMEOUT_WHILE_DRAINING;
695
 
      t_state.squid_codes.hier_code = SQUID_HIER_TIMEOUT_DIRECT;
696
 
    }
697
699
    vc_table.cleanup_entry(ua_entry);
698
700
    ua_entry = NULL;
699
701
    t_state.client_info.abort = HttpTransact::ABORTED;
712
714
  // tokenize header //
713
715
  /////////////////////
714
716
 
715
 
  int state = t_state.hdr_info.client_request.parse_req(&http_parser,
 
717
  MIMEParseResult state = t_state.hdr_info.client_request.parse_req(&http_parser,
716
718
                                                        ua_buffer_reader,
717
719
                                                        &bytes_used,
718
720
                                                        ua_entry->eos);
724
726
    DebugSM("http", "client header bytes were over max header size; treating as a bad request");
725
727
    state = PARSE_ERROR;
726
728
  }
 
729
 
 
730
  if (event == VC_EVENT_READ_READY &&
 
731
      state == PARSE_ERROR &&
 
732
      is_transparent_passthrough_allowed() &&
 
733
      ua_raw_buffer_reader != NULL) {
 
734
 
 
735
      DebugSM("http", "[%" PRId64 "] first request on connection failed parsing, switching to passthrough.", sm_id);
 
736
 
 
737
      t_state.transparent_passthrough = true;
 
738
      http_parser_clear(&http_parser);
 
739
 
 
740
      /* establish blind tunnel */
 
741
      setup_blind_tunnel_port();
 
742
      return 0;
 
743
  }
 
744
 
727
745
  // Check to see if we are done parsing the header
728
746
  if (state != PARSE_CONT || ua_entry->eos) {
 
747
    if (ua_raw_buffer_reader != NULL) {
 
748
        ua_raw_buffer_reader->dealloc();
 
749
        ua_raw_buffer_reader = NULL;
 
750
    }
729
751
    http_parser_clear(&http_parser);
730
752
    ua_entry->vc_handler = &HttpSM::state_watch_for_client_abort;
731
753
    milestones.ua_read_header_done = ink_get_hrtime();
752
774
      call_transact_and_set_next_state(HttpTransact::BadRequest);
753
775
      break;
754
776
    } else {
 
777
      if (is_transparent_passthrough_allowed() &&
 
778
          ua_raw_buffer_reader != NULL &&
 
779
          ua_raw_buffer_reader->get_current_block()->write_avail() <= 0) {
 
780
        //Disable passthrough regardless of eventual parsing failure or success -- otherwise
 
781
        //we either have to consume some data or risk blocking the writer.
 
782
        ua_raw_buffer_reader->dealloc();
 
783
        ua_raw_buffer_reader = NULL;
 
784
      }
755
785
      ua_entry->read_vio->reenable();
756
786
      return VC_EVENT_CONT;
757
787
    }
762
792
      ua_session->m_active = true;
763
793
      HTTP_INCREMENT_DYN_STAT(http_current_active_client_connections_stat);
764
794
    }
765
 
    if (t_state.hdr_info.client_request.method_get_wksidx() == HTTP_WKSIDX_GET) {
 
795
    if (t_state.hdr_info.client_request.method_get_wksidx() == HTTP_WKSIDX_TRACE ||
 
796
         (t_state.hdr_info.request_content_length == 0 &&
 
797
          t_state.client_info.transfer_encoding != HttpTransact::CHUNKED_ENCODING)) {
 
798
 
766
799
      // Enable further IO to watch for client aborts
767
800
      ua_entry->read_vio->reenable();
768
801
    } else {
1867
1900
    server_entry->write_buffer = NULL;
1868
1901
    method = t_state.hdr_info.server_request.method_get_wksidx();
1869
1902
    if (!t_state.api_server_request_body_set &&
1870
 
        (method != HTTP_WKSIDX_GET) &&
1871
 
        (method == HTTP_WKSIDX_POST || method == HTTP_WKSIDX_PUT ||
1872
 
         (t_state.hdr_info.extension_method && t_state.hdr_info.request_content_length > 0))) {
 
1903
         method != HTTP_WKSIDX_TRACE &&
 
1904
         (t_state.hdr_info.request_content_length > 0 || t_state.client_info.transfer_encoding == HttpTransact::CHUNKED_ENCODING)) {
 
1905
 
1873
1906
      if (post_transform_info.vc) {
1874
1907
        setup_transform_to_server_transfer();
1875
1908
      } else {
1943
1976
{
1944
1977
  DebugSM("dns_srv", "beginning process_srv_info");
1945
1978
 
1946
 
  SRVHosts s(r);                /* handled by conversion constructor */
1947
 
  char new_host[MAXDNAME];
1948
 
 
1949
1979
  /* we didnt get any SRV records, continue w normal lookup */
1950
 
  if (!r->srv_count) {
 
1980
  if (!r || !r->is_srv || !r->round_robin) {
 
1981
    t_state.dns_info.srv_hostname[0] = '\0';
 
1982
    t_state.dns_info.srv_lookup_success = false;
 
1983
    t_state.srv_lookup = false;
1951
1984
    DebugSM("dns_srv", "No SRV records were available, continuing to lookup %s", t_state.dns_info.lookup_name);
1952
 
    ink_strlcpy(new_host, t_state.dns_info.lookup_name, sizeof(new_host));
1953
 
    goto lookup;
1954
 
  }
1955
 
 
1956
 
  s.getWeightedHost(&new_host[0]);
1957
 
 
1958
 
  if (*new_host == '\0') {
1959
 
    DebugSM("dns_srv", "Weighted host returned was NULL or blank!, using %s as origin", t_state.dns_info.lookup_name);
1960
 
    ink_strlcpy(new_host, t_state.dns_info.lookup_name, sizeof(new_host));
1961
 
  } else {
1962
 
    DebugSM("dns_srv", "Weighted host now: %s", new_host);
1963
 
  }
1964
 
 
1965
 
  DebugSM("dns_srv", "ending process_srv_info SRV stuff; moving on to lookup origin host");
1966
 
 
1967
 
lookup:
1968
 
  DebugSM("http_seq", "[HttpStateMachineGet::process_srv_info] Doing DNS Lookup based on SRV %s", new_host);
1969
 
 
1970
 
  int server_port = t_state.current.server ? t_state.current.server->port : t_state.server_info.port;
1971
 
 
1972
 
  HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_hostdb_lookup);
1973
 
 
1974
 
  if (t_state.api_txn_dns_timeout_value != -1) {
1975
 
    DebugSM("http_timeout", "beginning DNS lookup. allowing %d mseconds for DNS", t_state.api_txn_dns_timeout_value);
1976
 
  }
1977
 
 
1978
 
  Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this,
1979
 
                                                                   (process_hostdb_info_pfn) & HttpSM::
1980
 
                                                                   process_hostdb_info,
1981
 
                                                                   &new_host[0], 0,
1982
 
                                                                   server_port,
1983
 
                                                                   ((t_state.cache_info.directives.
1984
 
                                                                     does_client_permit_dns_storing) ? HostDBProcessor::
1985
 
                                                                    HOSTDB_DO_NOT_FORCE_DNS : HostDBProcessor::
1986
 
                                                                    HOSTDB_FORCE_DNS_RELOAD),
1987
 
                                                                   (t_state.api_txn_dns_timeout_value != -1) ? t_state.
1988
 
                                                                   api_txn_dns_timeout_value : 0);
1989
 
 
1990
 
 
1991
 
  if (dns_lookup_action_handle != ACTION_RESULT_DONE) {
1992
 
    ink_assert(!pending_action);
1993
 
    pending_action = dns_lookup_action_handle;
1994
 
    historical_action = pending_action;
1995
 
  } else {
1996
 
    call_transact_and_set_next_state(NULL);
 
1985
  } else {
 
1986
    HostDBRoundRobin *rr = r->rr();
 
1987
    HostDBInfo *srv = NULL;
 
1988
    if (rr) {
 
1989
      srv = rr->select_best_srv(t_state.dns_info.srv_hostname, &mutex.m_ptr->thread_holding->generator,
 
1990
          ink_cluster_time(), (int) t_state.txn_conf->down_server_timeout);
 
1991
    }
 
1992
    if (!srv) {
 
1993
      t_state.dns_info.srv_lookup_success = false;
 
1994
      t_state.dns_info.srv_hostname[0] = '\0';
 
1995
      t_state.srv_lookup = false;
 
1996
      DebugSM("dns_srv", "SRV records empty for %s", t_state.dns_info.lookup_name);
 
1997
    } else {
 
1998
      ink_debug_assert(r->md5_high == srv->md5_high && r->md5_low == srv->md5_low &&
 
1999
          r->md5_low_low == srv->md5_low_low);
 
2000
      t_state.dns_info.srv_lookup_success = true;
 
2001
      t_state.dns_info.srv_port = srv->data.srv.srv_port;
 
2002
      t_state.dns_info.srv_app = srv->app;
 
2003
      //t_state.dns_info.single_srv = (rr->good == 1);
 
2004
      ink_debug_assert(srv->data.srv.key == makeHostHash(t_state.dns_info.srv_hostname));
 
2005
      DebugSM("dns_srv", "select SRV records %s", t_state.dns_info.srv_hostname);
 
2006
    }
1997
2007
  }
1998
2008
  return;
1999
2009
}
2001
2011
void
2002
2012
HttpSM::process_hostdb_info(HostDBInfo * r)
2003
2013
{
2004
 
  if (r) {
2005
 
    HostDBInfo *rr = NULL;
 
2014
  if (r && !r->failed()) {
 
2015
    ink_time_t now = ink_cluster_time();
 
2016
    HostDBInfo *ret = NULL;
2006
2017
    t_state.dns_info.lookup_success = true;
2007
 
 
2008
2018
    if (r->round_robin) {
2009
2019
      // Since the time elapsed between current time and client_request_time
2010
2020
      // may be very large, we cannot use client_request_time to approximate
2011
2021
      // current time when calling select_best_http().
2012
 
      rr = r->rr()->select_best_http(&t_state.client_info.addr.sa, ink_cluster_time(), (int) t_state.txn_conf->down_server_timeout);
 
2022
      HostDBRoundRobin *rr = r->rr();
 
2023
      ret = rr->select_best_http(&t_state.client_info.addr.sa, now, (int) t_state.txn_conf->down_server_timeout);
2013
2024
      t_state.dns_info.round_robin = true;
 
2025
 
 
2026
      // set the srv target`s last_failure
 
2027
      if (t_state.dns_info.srv_lookup_success) {
 
2028
        uint32_t last_failure = 0xFFFFFFFF;
 
2029
        for (int i = 0; i < rr->n && last_failure != 0; ++i) {
 
2030
          if (last_failure > rr->info[i].app.http_data.last_failure)
 
2031
            last_failure = rr->info[i].app.http_data.last_failure;
 
2032
        }
 
2033
 
 
2034
        if (last_failure != 0 && (uint32_t) (now - t_state.txn_conf->down_server_timeout) < last_failure) {
 
2035
          HostDBApplicationInfo app;
 
2036
          app.allotment.application1 = 0;
 
2037
          app.allotment.application2 = 0;
 
2038
          app.http_data.last_failure = last_failure;
 
2039
          hostDBProcessor.setby_srv(t_state.dns_info.lookup_name, 0, t_state.dns_info.srv_hostname, &app);
 
2040
        }
 
2041
      }
2014
2042
    } else {
2015
 
      rr = r;
 
2043
      ret = r;
2016
2044
      t_state.dns_info.round_robin = false;
2017
2045
    }
2018
 
    if (rr) {
2019
 
//                  m_s.host_db_info = m_updated_host_db_info = *rr;
2020
 
      t_state.host_db_info = *rr;
 
2046
    if (ret) {
 
2047
      t_state.host_db_info = *ret;
2021
2048
      ink_release_assert(!t_state.host_db_info.reverse_dns);
2022
2049
      ink_release_assert(ats_is_ip(t_state.host_db_info.ip()));
2023
2050
    }
2062
2089
    process_hostdb_info((HostDBInfo *) data);
2063
2090
    call_transact_and_set_next_state(NULL);
2064
2091
    break;
 
2092
    case EVENT_SRV_LOOKUP:
 
2093
    {
 
2094
      pending_action = NULL;
 
2095
      process_srv_info((HostDBInfo *) data);
 
2096
 
 
2097
      char *host_name = t_state.dns_info.srv_lookup_success ? t_state.dns_info.srv_hostname : t_state.dns_info.lookup_name;
 
2098
      HostDBProcessor::Options opt;
 
2099
      opt.port = t_state.dns_info.srv_lookup_success ? t_state.dns_info.srv_port : t_state.server_info.port;
 
2100
      opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing)
 
2101
            ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS
 
2102
            : HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD
 
2103
          ;
 
2104
      opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
 
2105
      opt.host_res_style = ua_session->host_res_style;
 
2106
 
 
2107
      Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this,
 
2108
                                                                 (process_hostdb_info_pfn) & HttpSM::
 
2109
                                                                 process_hostdb_info,
 
2110
                                                                 host_name, 0,
 
2111
                                                                 opt);
 
2112
      if (dns_lookup_action_handle != ACTION_RESULT_DONE) {
 
2113
        ink_assert(!pending_action);
 
2114
        pending_action = dns_lookup_action_handle;
 
2115
        historical_action = pending_action;
 
2116
      } else {
 
2117
        call_transact_and_set_next_state(NULL);
 
2118
      }
 
2119
    }
 
2120
    break;
2065
2121
  case EVENT_HOST_DB_IP_REMOVED:
2066
2122
    ink_assert(!"Unexpected event from HostDB");
2067
2123
    break;
2715
2771
  milestones.server_close = ink_get_hrtime();
2716
2772
 
2717
2773
  bool close_connection = false;
2718
 
  bool log_spider_codes = t_state.http_config_param->log_spider_codes != 0;
2719
2774
 
2720
2775
  switch (event) {
2721
2776
  case VC_EVENT_INACTIVITY_TIMEOUT:
2722
2777
  case VC_EVENT_ACTIVE_TIMEOUT:
2723
2778
  case VC_EVENT_ERROR:
2724
 
    t_state.squid_codes.wuts_proxy_status_code =
2725
 
      log_spider_codes ? WUTS_PROXY_STATUS_SPIDER_TIMEOUT_WHILE_PASSING : WUTS_PROXY_STATUS_READ_TIMEOUT;
2726
 
    t_state.squid_codes.log_code =
2727
 
      log_spider_codes ? SQUID_LOG_ERR_SPIDER_TIMEOUT_WHILE_PASSING : SQUID_LOG_ERR_READ_TIMEOUT;
 
2779
    t_state.squid_codes.log_code = SQUID_LOG_ERR_READ_TIMEOUT;
2728
2780
    t_state.squid_codes.hier_code = SQUID_HIER_TIMEOUT_DIRECT;
2729
2781
 
2730
2782
    switch (event) {
2756
2808
      t_state.current.server->abort = HttpTransact::ABORTED;
2757
2809
      t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
2758
2810
      t_state.current.server->keep_alive = HTTP_NO_KEEPALIVE;
2759
 
      if (t_state.http_config_param->log_spider_codes) {
2760
 
        t_state.squid_codes.wuts_proxy_status_code = WUTS_PROXY_STATUS_SPIDER_TIMEOUT_WHILE_DRAINING;
2761
 
        t_state.squid_codes.log_code = SQUID_LOG_ERR_SPIDER_TIMEOUT_WHILE_DRAINING;
2762
 
        t_state.squid_codes.hier_code = SQUID_HIER_TIMEOUT_DIRECT;
2763
 
      }
2764
2811
    } else {
2765
2812
      p->read_success = true;
2766
2813
      t_state.current.server->abort = HttpTransact::DIDNOT_ABORT;
2847
2894
  if (close_connection) {
2848
2895
    p->vc->do_io_close();
2849
2896
    p->read_vio = NULL;
 
2897
    /* TS-1424: if we're outbound transparent and using the client
 
2898
       source port for the outbound connection we must effectively
 
2899
       propagate server closes back to the client.
 
2900
    */
 
2901
    if (ua_session && ua_session->f_outbound_transparent && t_state.http_config_param->use_client_source_port)
 
2902
      t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
2850
2903
  } else {
2851
2904
    server_session->attach_hostname(t_state.current.server->name);
2852
2905
    server_session->server_trans_stat--;
3082
3135
  case VC_EVENT_ERROR:
3083
3136
  case VC_EVENT_EOS:
3084
3137
    // Transfer terminated.  Bail on the cache write.
3085
 
    if (t_state.http_config_param->log_spider_codes) {
3086
 
      t_state.squid_codes.wuts_proxy_status_code = WUTS_PROXY_STATUS_SPIDER_TIMEOUT_WHILE_DRAINING;
3087
 
      t_state.squid_codes.log_code = SQUID_LOG_ERR_SPIDER_TIMEOUT_WHILE_DRAINING;
3088
 
      t_state.squid_codes.hier_code = SQUID_HIER_TIMEOUT_DIRECT;
3089
 
    }
3090
3138
    t_state.client_info.abort = HttpTransact::ABORTED;
3091
3139
    p->vc->do_io_close(EHTTP_ERROR);
3092
3140
    p->read_vio = NULL;
3125
3173
    if (t_state.cache_info.object_read->object_size_get() != INT64_MAX || event == VC_EVENT_ERROR) {
3126
3174
      // Abnormal termination
3127
3175
      t_state.squid_codes.log_code = SQUID_LOG_TCP_SWAPFAIL;
3128
 
      t_state.squid_codes.wuts_proxy_status_code =
3129
 
        t_state.http_config_param->
3130
 
        log_spider_codes ? WUTS_PROXY_STATUS_SPIDER_GENERAL_TIMEOUT : WUTS_PROXY_STATUS_READ_TIMEOUT;
3131
3176
      p->vc->do_io_close(EHTTP_ERROR);
3132
3177
      p->read_vio = NULL;
3133
3178
      tunnel.chain_abort_all(p);
3482
3527
    c->write_success = true;
3483
3528
    if (c->self_producer->alive == true) {
3484
3529
      c->vc->do_io_shutdown(IO_SHUTDOWN_WRITE);
 
3530
      if (!c->producer->alive) {
 
3531
        tunnel.close_vc(c);
 
3532
        tunnel.local_finish_all(c->self_producer);
 
3533
        break;
 
3534
      }
3485
3535
    } else {
3486
3536
      c->vc->do_io_close();
3487
3537
    }
3747
3797
  ink_assert(pending_action == NULL);
3748
3798
 
3749
3799
  milestones.dns_lookup_begin = ink_get_hrtime();
3750
 
  bool use_srv_records = HttpConfig::m_master.srv_enabled;
 
3800
  bool use_srv_records = t_state.srv_lookup;
3751
3801
 
3752
3802
  if (use_srv_records) {
3753
 
    char* d = t_state.dns_info.srv_hostname;
 
3803
    char d[MAXDNAME];
3754
3804
 
3755
3805
    memcpy(d, "_http._tcp.", 11); // don't copy '\0'
3756
3806
    ink_strlcpy(d + 11, t_state.server_info.name, sizeof(d) - 11 ); // all in the name of performance!
3757
3807
 
3758
3808
    DebugSM("dns_srv", "Beginning lookup of SRV records for origin %s", d);
3759
 
    HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_srv_lookup);
3760
3809
 
 
3810
    HostDBProcessor::Options opt;
 
3811
    if (t_state.api_txn_dns_timeout_value != -1)
 
3812
      opt.timeout = t_state.api_txn_dns_timeout_value;
3761
3813
    Action *srv_lookup_action_handle =
3762
 
      hostDBProcessor.getSRVbyname_imm(this, (process_srv_info_pfn) & HttpSM::process_srv_info, d,
3763
 
                                       (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0);
 
3814
      hostDBProcessor.getSRVbyname_imm(this, (process_srv_info_pfn) & HttpSM::process_srv_info, d, 0, opt);
3764
3815
 
3765
3816
    if (srv_lookup_action_handle != ACTION_RESULT_DONE) {
3766
3817
      ink_assert(!pending_action);
3767
3818
      pending_action = srv_lookup_action_handle;
3768
3819
      historical_action = pending_action;
 
3820
    } else {
 
3821
      char *host_name = t_state.dns_info.srv_lookup_success ? t_state.dns_info.srv_hostname : t_state.dns_info.lookup_name;
 
3822
      opt.port = t_state.dns_info.srv_lookup_success ? t_state.dns_info.srv_port : t_state.server_info.port;
 
3823
      opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing)
 
3824
            ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS
 
3825
            : HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD
 
3826
          ;
 
3827
      opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
 
3828
      opt.host_res_style = ua_session->host_res_style;
 
3829
 
 
3830
      Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this,
 
3831
                                                                 (process_hostdb_info_pfn) & HttpSM::
 
3832
                                                                 process_hostdb_info,
 
3833
                                                                 host_name, 0,
 
3834
                                                                 opt);
 
3835
      if (dns_lookup_action_handle != ACTION_RESULT_DONE) {
 
3836
        ink_assert(!pending_action);
 
3837
        pending_action = dns_lookup_action_handle;
 
3838
        historical_action = pending_action;
 
3839
      } else {
 
3840
        call_transact_and_set_next_state(NULL);
 
3841
      }
3769
3842
    }
3770
3843
    return;
3771
3844
  } else {                      /* we arent using SRV stuff... */
3772
 
    DebugSM("http_seq", "[HttpStateMachineGet::do_hostdb_lookup] Doing DNS Lookup");
 
3845
    DebugSM("http_seq", "[HttpSM::do_hostdb_lookup] Doing DNS Lookup");
3773
3846
 
3774
3847
    // If there is not a current server, we must be looking up the origin
3775
3848
    //  server at the beginning of the transaction
3780
3853
            t_state.api_txn_dns_timeout_value);
3781
3854
    }
3782
3855
 
3783
 
    Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this,
3784
 
                                                                     (process_hostdb_info_pfn) & HttpSM::
3785
 
                                                                     process_hostdb_info,
3786
 
                                                                     t_state.dns_info.lookup_name, 0,
3787
 
                                                                     server_port,
3788
 
                                                                     ((t_state.cache_info.directives.
3789
 
                                                                       does_client_permit_dns_storing) ?
3790
 
                                                                      HostDBProcessor::
3791
 
                                                                      HOSTDB_DO_NOT_FORCE_DNS : HostDBProcessor::
3792
 
                                                                      HOSTDB_FORCE_DNS_RELOAD),
3793
 
                                                                     (t_state.api_txn_dns_timeout_value != -1) ? t_state.
3794
 
                                                                     api_txn_dns_timeout_value : 0);
 
3856
    HostDBProcessor::Options opt;
 
3857
    opt.port = server_port;
 
3858
    opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing)
 
3859
      ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS
 
3860
      : HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD
 
3861
    ;
 
3862
    opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
 
3863
    opt.host_res_style = ua_session->host_res_style;
 
3864
 
 
3865
    Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this, (process_hostdb_info_pfn) & HttpSM::process_hostdb_info, t_state.dns_info.lookup_name, 0, opt);
3795
3866
 
3796
3867
    if (dns_lookup_action_handle != ACTION_RESULT_DONE) {
3797
3868
      ink_assert(!pending_action);
3871
3942
            sm_id,
3872
3943
            ats_ip_nptop(&t_state.current.server->addr.sa, addrbuf, sizeof(addrbuf)));
3873
3944
    }
 
3945
 
 
3946
    if (t_state.dns_info.srv_lookup_success && t_state.dns_info.srv_app.http_data.last_failure != 0) {
 
3947
      t_state.dns_info.srv_app.http_data.last_failure = 0;
 
3948
      hostDBProcessor.setby_srv(t_state.dns_info.lookup_name, 0, t_state.dns_info.srv_hostname, &t_state.dns_info.srv_app);
 
3949
      DebugSM("http", "[%" PRId64 "] hostdb update marking SRV: %s as up",
 
3950
                  sm_id,
 
3951
                  t_state.dns_info.srv_hostname);
 
3952
    }
3874
3953
  }
3875
3954
 
3876
3955
  if (issue_update) {
3886
3965
  return;
3887
3966
}
3888
3967
 
 
3968
/*
 
3969
 * range entry vaild [a,b] (a >= 0 and b >= 0 and a <= b)
 
3970
 * HttpTransact::RANGE_NONE if the content length of cached copy is zero or
 
3971
 * no range entry
 
3972
 * HttpTransact::RANGE_NOT_SATISFIABLE iff all range entrys are valid but
 
3973
 * none overlap the current extent of the cached copy
 
3974
 * HttpTransact::RANGE_NOT_HANDLED if out-of-order Range entrys or
 
3975
 * the cached copy`s content_length is INT64_MAX (e.g. read_from_writer and trunked)
 
3976
 * HttpTransact::RANGE_REQUESTED if all sub range entrys are valid and
 
3977
 * in order (remove the entrys that not overlap the extent of cache copy)
 
3978
 */
3889
3979
void
3890
3980
HttpSM::parse_range_and_compare(MIMEField *field, int64_t content_length)
3891
3981
{
3892
 
  // note: unsatisfiable_range is initialized to true in constructor
3893
3982
  int prev_good_range = -1;
3894
3983
  const char *value;
3895
3984
  int value_len;
3896
3985
  int n_values;
3897
3986
  int nr = 0; // number of valid ranges, also index to range array.
 
3987
  int not_satisfy = 0;
3898
3988
  HdrCsvIter csv;
3899
 
  const char *s, *e;
 
3989
  const char *s, *e, *tmp;
 
3990
  RangeRecord *ranges = NULL;
 
3991
  int64_t start, end;
 
3992
 
 
3993
  ink_debug_assert(field != NULL && t_state.range_setup == HttpTransact::RANGE_NONE && t_state.ranges == NULL);
3900
3994
 
3901
3995
  if (content_length <= 0)
3902
3996
    return;
3903
 
 
3904
 
  ink_assert(field != NULL);
 
3997
  if (content_length == INT64_MAX) {
 
3998
    t_state.range_setup = HttpTransact::RANGE_NOT_HANDLED;
 
3999
    return;
 
4000
  }
3905
4001
 
3906
4002
  n_values = 0;
3907
4003
  value = csv.get_first(field, &value_len);
3910
4006
    value = csv.get_next(&value_len);
3911
4007
  }
3912
4008
 
3913
 
  if (n_values <= 0)
 
4009
  value = csv.get_first(field, &value_len);
 
4010
  if (n_values <= 0 || ptr_len_ncmp(value, value_len, "bytes=", 6))
3914
4011
    return;
3915
4012
 
3916
 
  value = csv.get_first(field, &value_len);
3917
 
 
3918
 
  // Currently HTTP/1.1 only defines bytes Range
3919
 
  if (ptr_len_ncmp(value, value_len, "bytes=", 6) == 0) {
3920
 
    t_state.ranges = NEW(new RangeRecord[n_values]);
3921
 
    value += 6; // skip leading 'bytes='
3922
 
    value_len -= 6;
3923
 
 
3924
 
    while (value) {
3925
 
      bool valid = true; // found valid range.
3926
 
      // If delimiter '-' is missing
3927
 
      if (!(e = (const char *) memchr(value, '-', value_len))) {
3928
 
        t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
3929
 
        t_state.num_range_fields = -1;
3930
 
        return;
3931
 
      }
3932
 
 
3933
 
      /* [amc] We should do a much better job of checking the values
3934
 
         from mime_parse_int64 to detect invalid range values (e.g.
3935
 
         non-numeric). Those need to be handled differently than
3936
 
         missing values. My reading of the spec is that ATS should go to
3937
 
         RANGE_NONE in such a case.
3938
 
      */
3939
 
      s = value;
3940
 
      t_state.ranges[nr]._start = ((s==e)?-1:mime_parse_int64(s, e));
3941
 
 
3942
 
      ++e;
3943
 
      s = e;
3944
 
      e = value + value_len;
3945
 
      if ( e && *(e-1) == '-') { //open-ended Range: bytes=10-\r\n\r\n should be supported
3946
 
        t_state.ranges[nr]._end = -1;
3947
 
      }
3948
 
      else {
3949
 
        t_state.ranges[nr]._end = mime_parse_int64(s, e);
3950
 
      }
3951
 
 
3952
 
      // check and change if necessary whether this is a right entry
3953
 
      if (t_state.ranges[nr]._start >= content_length) {
3954
 
          valid = false;
3955
 
      } 
3956
 
      // open start
3957
 
      else if (t_state.ranges[nr]._start == -1 && t_state.ranges[nr]._end > 0) {
3958
 
        if (t_state.ranges[nr]._end > content_length)
3959
 
          t_state.ranges[nr]._end = content_length;
3960
 
 
3961
 
        t_state.ranges[nr]._start = content_length - t_state.ranges[nr]._end;
3962
 
        t_state.ranges[nr]._end = content_length - 1;
3963
 
      }
3964
 
      // open end
3965
 
      else if (t_state.ranges[nr]._start >= 0 && t_state.ranges[nr]._end == -1) {
3966
 
          t_state.ranges[nr]._end = content_length - 1;
3967
 
      }
3968
 
      // "normal" Range - could be wrong if _end<_start
3969
 
      else if (t_state.ranges[nr]._start >= 0 && t_state.ranges[nr]._end >= 0) {
3970
 
        if (t_state.ranges[nr]._start > t_state.ranges[nr]._end)
3971
 
          // [amc] My reading of the spec is that this should cause a change
3972
 
          // to RANGE_NONE because it is syntatically invalid.
3973
 
          valid = false;
3974
 
        else if (t_state.ranges[nr]._end >= content_length)
3975
 
          t_state.ranges[nr]._end = content_length - 1;
3976
 
      }
3977
 
      // Syntactically invalid range, fail.
3978
 
      else {
3979
 
        // [amc] My reading of the spec is that this should cause a change
3980
 
        // to RANGE_NONE because it is syntatically invalid.
3981
 
        t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
3982
 
        t_state.num_range_fields = -1;
3983
 
        return;
3984
 
      }
3985
 
 
3986
 
      // this is a good Range entry
3987
 
      if (valid) {
3988
 
        if (t_state.unsatisfiable_range) {
3989
 
          t_state.unsatisfiable_range = false;
3990
 
          // initialize t_state.current_range to the first good Range
3991
 
          t_state.current_range = nr;
3992
 
        }
3993
 
        // currently we don't handle out-of-order Range entry
3994
 
        else if (prev_good_range >= 0 && t_state.ranges[nr]._start <= t_state.ranges[prev_good_range]._end) {
3995
 
          t_state.not_handle_range = true;
3996
 
          break;
3997
 
        }
3998
 
 
3999
 
        prev_good_range = nr;
4000
 
        ++nr;
4001
 
      }
4002
 
      value = csv.get_next(&value_len);
4003
 
    }
 
4013
  ranges = NEW(new RangeRecord[n_values]);
 
4014
  value += 6; // skip leading 'bytes='
 
4015
  value_len -= 6;
 
4016
 
 
4017
  for (; value; value = csv.get_next(&value_len)) {
 
4018
    if (!(tmp = (const char *) memchr(value, '-', value_len))) {
 
4019
      t_state.range_setup = HttpTransact::RANGE_NONE;
 
4020
      goto Lfaild;
 
4021
    }
 
4022
 
 
4023
    // process start value
 
4024
    s = value;
 
4025
    e = tmp;
 
4026
    // skip leading white spaces
 
4027
    for (; s < e && ParseRules::is_ws(*s); ++s) ;
 
4028
 
 
4029
    if (s >= e)
 
4030
      start = -1;
 
4031
    else {
 
4032
      for (start = 0; s < e && *s >= '0' && *s <= '9'; ++s)
 
4033
        start = start * 10 + (*s - '0');
 
4034
      // skip last white spaces
 
4035
      for (; s < e && ParseRules::is_ws(*s); ++s) ;
 
4036
 
 
4037
      if (s < e || start < 0) {
 
4038
        t_state.range_setup = HttpTransact::RANGE_NONE;
 
4039
        goto Lfaild;
 
4040
      }
 
4041
    }
 
4042
 
 
4043
    // process end value
 
4044
    s = tmp + 1;
 
4045
    e = value + value_len;
 
4046
    // skip leading white spaces
 
4047
    for (; s < e && ParseRules::is_ws(*s); ++s) ;
 
4048
 
 
4049
    if (s >= e) {
 
4050
      if (start < 0) {
 
4051
        t_state.range_setup = HttpTransact::RANGE_NONE;
 
4052
        goto Lfaild;
 
4053
      } else if (start >= content_length) {
 
4054
        not_satisfy++;
 
4055
        continue;
 
4056
      }
 
4057
      end = content_length - 1;
 
4058
    } else {
 
4059
      for (end = 0; s < e && *s >= '0' && *s <= '9'; ++s)
 
4060
        end = end * 10 + (*s - '0');
 
4061
      // skip last white spaces
 
4062
      for (; s < e && ParseRules::is_ws(*s); ++s) ;
 
4063
 
 
4064
      if (s < e || end < 0) {
 
4065
        t_state.range_setup = HttpTransact::RANGE_NONE;
 
4066
        goto Lfaild;
 
4067
      }
 
4068
 
 
4069
      if (start < 0) {
 
4070
        if (end >= content_length)
 
4071
          end = content_length;
 
4072
        start = content_length - end;
 
4073
        end = content_length - 1;
 
4074
      } else if (start >= content_length && start <= end) {
 
4075
        not_satisfy++;
 
4076
        continue;
 
4077
      }
 
4078
 
 
4079
      if (end >= content_length)
 
4080
        end = content_length - 1;
 
4081
    }
 
4082
 
 
4083
    if (start > end) {
 
4084
      t_state.range_setup = HttpTransact::RANGE_NONE;
 
4085
      goto Lfaild;
 
4086
    }
 
4087
 
 
4088
    if (prev_good_range >= 0 && start <= ranges[prev_good_range]._end) {
 
4089
      t_state.range_setup = HttpTransact::RANGE_NOT_HANDLED;
 
4090
      goto Lfaild;
 
4091
    }
 
4092
 
 
4093
    ink_debug_assert(start >= 0 && end >= 0 && start < content_length && end < content_length);
 
4094
 
 
4095
    prev_good_range = nr;
 
4096
    ranges[nr]._start = start;
 
4097
    ranges[nr]._end = end;
 
4098
    ++nr;
4004
4099
  }
4005
 
  // Fail if we didn't find any valid ranges.
4006
 
  if (nr < 1) {
4007
 
    t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
4008
 
    t_state.num_range_fields = -1;
4009
 
  } else {
 
4100
 
 
4101
  if (nr > 0) {
 
4102
    t_state.range_setup = HttpTransact::RANGE_REQUESTED;
 
4103
    t_state.ranges = ranges;
4010
4104
    t_state.num_range_fields = nr;
 
4105
    return;
4011
4106
  }
 
4107
 
 
4108
  if (not_satisfy)
 
4109
    t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
 
4110
 
 
4111
Lfaild:
 
4112
  t_state.num_range_fields = -1;
 
4113
  delete []ranges;
 
4114
  return;
4012
4115
}
4013
4116
 
4014
4117
void
4016
4119
{
4017
4120
  int i;
4018
4121
 
4019
 
  if (t_state.unsatisfiable_range)
 
4122
  if (t_state.range_setup != HttpTransact::RANGE_REQUESTED &&
 
4123
      t_state.range_setup != HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED)
4020
4124
    return;
4021
4125
 
 
4126
  ink_debug_assert(t_state.ranges);
 
4127
 
4022
4128
  if (t_state.num_range_fields == 1) {
4023
4129
    t_state.range_output_cl = t_state.ranges[0]._end - t_state.ranges[0]._start + 1;
4024
4130
  }
4051
4157
  
4052
4158
  parse_range_and_compare(range_field, content_length);
4053
4159
  calculate_output_cl(content_length, num_chars_for_cl);
4054
 
  
4055
 
  if (t_state.unsatisfiable_range) {
4056
 
    t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
4057
 
    return;
4058
 
  }
4059
 
 
4060
 
  if (t_state.not_handle_range) {
4061
 
    t_state.range_setup = HttpTransact::RANGE_NOT_HANDLED;
4062
 
    return;
4063
 
  }
4064
 
 
4065
 
  t_state.range_setup = HttpTransact::RANGE_REQUESTED;
4066
4160
}
4067
4161
 
4068
4162
// this function looks for any Range: headers, parses them and either
4082
4176
  ink_assert(field != NULL);
4083
4177
  
4084
4178
  t_state.range_setup = HttpTransact::RANGE_NONE;
 
4179
 
4085
4180
  if (t_state.method == HTTP_WKSIDX_GET && t_state.hdr_info.client_request.version_get() == HTTPVersion(1, 1)) {
4086
4181
    do_range_parse(field);
4087
 
    
 
4182
 
 
4183
    // if only one range entry and pread is capable, no need transform range
 
4184
    if (t_state.range_setup == HttpTransact::RANGE_REQUESTED &&
 
4185
        t_state.num_range_fields == 1 &&
 
4186
        cache_sm.cache_read_vc->is_pread_capable())
 
4187
      t_state.range_setup = HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED;
 
4188
 
4088
4189
    if (t_state.range_setup == HttpTransact::RANGE_REQUESTED && 
4089
 
        (t_state.num_range_fields > 1 || !cache_sm.cache_read_vc->is_pread_capable()) &&
4090
 
        api_hooks.get(TS_HTTP_RESPONSE_TRANSFORM_HOOK) == NULL
4091
 
       ) 
4092
 
    {
4093
 
          Debug("http_trans", "Unable to accelerate range request, fallback to transform");
4094
 
          content_type = t_state.cache_info.object_read->response_get()->value_get(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE, &field_content_type_len);
4095
 
          //create a Range: transform processor for requests of type Range: bytes=1-2,4-5,10-100 (eg. multiple ranges)
4096
 
          range_trans = transformProcessor.range_transform(mutex, 
4097
 
                  t_state.ranges,
4098
 
                  t_state.unsatisfiable_range, 
4099
 
                  t_state.num_range_fields, 
4100
 
                  &t_state.hdr_info.transform_response,
4101
 
                  content_type,
4102
 
                  field_content_type_len,
4103
 
                  t_state.cache_info.object_read->object_size_get()
4104
 
                  );
4105
 
          if (range_trans != NULL) {
4106
 
            api_hooks.append(TS_HTTP_RESPONSE_TRANSFORM_HOOK, range_trans);
4107
 
            t_state.range_setup = HttpTransact::RANGE_REQUESTED;
4108
 
          }
4109
 
          else { //we couldnt append the transform to our API hooks so bailing
4110
 
            t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
4111
 
          } 
4112
 
    }
4113
 
    else if (t_state.range_setup == HttpTransact::RANGE_REQUESTED && t_state.num_range_fields == 1) {
4114
 
      Debug("http_trans", "Handling single Range: request");
4115
 
      //no op, we will handle this later in the HttpTunnel
4116
 
    }
4117
 
    else {
4118
 
      t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
 
4190
        api_hooks.get(TS_HTTP_RESPONSE_TRANSFORM_HOOK) == NULL) {
 
4191
      Debug("http_trans", "Unable to accelerate range request, fallback to transform");
 
4192
      content_type = t_state.cache_info.object_read->response_get()->value_get(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE, &field_content_type_len);
 
4193
      //create a Range: transform processor for requests of type Range: bytes=1-2,4-5,10-100 (eg. multiple ranges)
 
4194
      range_trans = transformProcessor.range_transform(mutex,
 
4195
          t_state.ranges,
 
4196
          t_state.num_range_fields,
 
4197
          &t_state.hdr_info.transform_response,
 
4198
          content_type,
 
4199
          field_content_type_len,
 
4200
          t_state.cache_info.object_read->object_size_get()
 
4201
          );
 
4202
      api_hooks.append(TS_HTTP_RESPONSE_TRANSFORM_HOOK, range_trans);
4119
4203
    }
4120
4204
  }
4121
4205
}
4170
4254
  // Do not delete a non-existant object.
4171
4255
  ink_assert(t_state.cache_info.object_read);
4172
4256
 
4173
 
#ifdef DEBUG
4174
 
  INK_MD5 md5a;
4175
 
  INK_MD5 md5b;
4176
 
  t_state.hdr_info.client_request.url_get()->MD5_get(&md5a);
4177
 
  t_state.cache_info.lookup_url->MD5_get(&md5b);
4178
 
  ink_assert(md5a == md5b || t_state.txn_conf->maintain_pristine_host_hdr);
4179
 
#endif
4180
 
 
4181
4257
  DebugSM("http_seq", "[HttpSM::do_cache_delete_all_alts] Issuing cache delete for %s",
4182
 
        t_state.cache_info.lookup_url->string_get_ref());
 
4258
          t_state.cache_info.lookup_url->string_get_ref());
4183
4259
 
4184
4260
  Action *cache_action_handle = NULL;
4185
4261
 
4296
4372
 
4297
4373
//////////////////////////////////////////////////////////////////////////
4298
4374
//
4299
 
//  HttpStateMachineGet::do_http_server_open()
 
4375
//  HttpSM::do_http_server_open()
4300
4376
//
4301
4377
//////////////////////////////////////////////////////////////////////////
4302
4378
void
4303
4379
HttpSM::do_http_server_open(bool raw)
4304
4380
{
4305
 
  DebugSM("http_track", "entered inside do_http_server_open");
4306
4381
  int ip_family = t_state.current.server->addr.sa.sa_family;
 
4382
  DebugSM("http_track", "entered inside do_http_server_open ][%s]", ats_ip_family_name(ip_family));
4307
4383
 
4308
4384
  ink_assert(server_entry == NULL);
4309
4385
 
4316
4392
 
4317
4393
  ink_assert(pending_action == NULL);
4318
4394
 
4319
 
  HSMresult_t shared_result;
4320
 
 
4321
4395
  if (false == t_state.api_server_addr_set) {
4322
4396
    ink_assert(t_state.current.server->port > 0);
4323
4397
    t_state.current.server->addr.port() = htons(t_state.current.server->port);
4376
4450
  if (raw == false && t_state.txn_conf->share_server_sessions &&
4377
4451
      (t_state.txn_conf->keep_alive_post_out == 1 || t_state.hdr_info.request_content_length == 0) &&
4378
4452
       !is_private() && ua_session != NULL) {
 
4453
    HSMresult_t shared_result;
4379
4454
    shared_result = httpSessionManager.acquire_session(this,    // state machine
4380
4455
                                                       &t_state.current.server->addr.sa,    // ip + port
4381
4456
                                                       t_state.current.server->name,    // hostname
4382
4457
                                                       ua_session,      // has ptr to bound ua sessions
4383
4458
                                                       this     // sm
4384
 
      );
 
4459
    );
4385
4460
 
4386
4461
    switch (shared_result) {
4387
4462
    case HSM_DONE:
4407
4482
 
4408
4483
    if (existing_ss) {
4409
4484
      // [amc] Is this OK? Should we compare ports? (not done by ats_ip_addr_cmp)
4410
 
      if (ats_ip_addr_cmp(&existing_ss->server_ip.sa, &t_state.current.server->addr.sa) == 0) {
 
4485
      if (ats_ip_addr_eq(&existing_ss->server_ip.sa, &t_state.current.server->addr.sa)) {
4411
4486
        ua_session->attach_server_session(NULL);
4412
4487
        existing_ss->state = HSS_ACTIVE;
4413
4488
        this->attach_server_session(existing_ss);
4605
4680
    break;
4606
4681
  case HttpTransact::HTTP_API_SEND_REPONSE_HDR:
4607
4682
    cur_hook_id = TS_HTTP_SEND_RESPONSE_HDR_HOOK;
 
4683
    milestones.ua_begin_write = ink_get_hrtime();
4608
4684
    break;
4609
4685
  case HttpTransact::HTTP_API_SM_SHUTDOWN:
4610
4686
    if (callout_state == HTTP_API_IN_CALLOUT || callout_state == HTTP_API_DEFERED_SERVER_ERROR) {
4701
4777
void
4702
4778
HttpSM::set_ua_abort(HttpTransact::AbortState_t ua_abort, int event)
4703
4779
{
4704
 
  bool log_spider_codes = t_state.http_config_param->log_spider_codes != 0;
4705
 
 
4706
4780
  t_state.client_info.abort = ua_abort;
4707
4781
 
4708
4782
  switch (ua_abort) {
4709
4783
  case HttpTransact::ABORTED:
4710
4784
  case HttpTransact::MAYBE_ABORTED:
4711
 
    t_state.squid_codes.wuts_proxy_status_code =
4712
 
      log_spider_codes ? WUTS_PROXY_STATUS_SPIDER_MEMBER_ABORTED : WUTS_PROXY_STATUS_CLIENT_ABORT;
4713
 
    t_state.squid_codes.log_code = log_spider_codes ? SQUID_LOG_ERR_SPIDER_MEMBER_ABORTED : SQUID_LOG_ERR_CLIENT_ABORT;
 
4785
    t_state.squid_codes.log_code = SQUID_LOG_ERR_CLIENT_ABORT;
4714
4786
    break;
4715
4787
  default:
4716
4788
    // Handled here:
4890
4962
  }
4891
4963
 
4892
4964
  int method = t_state.hdr_info.server_request.method_get_wksidx();
4893
 
  if ((method == HTTP_WKSIDX_POST || method == HTTP_WKSIDX_PUT) && do_post_transform_open()) {
 
4965
  if (method != HTTP_WKSIDX_TRACE &&
 
4966
      (t_state.hdr_info.request_content_length > 0 || t_state.client_info.transfer_encoding == HttpTransact::CHUNKED_ENCODING) &&
 
4967
       do_post_transform_open()) {
4894
4968
    do_setup_post_tunnel(HTTP_TRANSFORM_VC);
4895
4969
  } else {
4896
4970
    setup_server_send_request_api();
6153
6227
    client_response_hdr_bytes = 0;
6154
6228
  }
6155
6229
 
 
6230
  client_request_body_bytes = 0;
 
6231
  if (ua_raw_buffer_reader != NULL) {
 
6232
    client_request_body_bytes += from_ua_buf->write(ua_raw_buffer_reader, client_request_hdr_bytes);
 
6233
    ua_raw_buffer_reader->dealloc();
 
6234
    ua_raw_buffer_reader = NULL;
 
6235
  }
 
6236
 
6156
6237
  // Next order of business if copy the remaining data from the
6157
6238
  //  header buffer into new buffer
6158
 
  client_request_body_bytes = from_ua_buf->write(ua_buffer_reader);
 
6239
  client_request_body_bytes += from_ua_buf->write(ua_buffer_reader);
6159
6240
 
6160
6241
  HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler);
6161
6242
 
6335
6416
  //////////////
6336
6417
  // Log Data //
6337
6418
  //////////////
6338
 
  DebugSM("http_seq", "[HttpStateMachineGet::update_stats] Logging transaction");
 
6419
  DebugSM("http_seq", "[HttpSM::update_stats] Logging transaction");
6339
6420
  if (Log::transaction_logging_enabled() && t_state.api_info.logging_enabled) {
6340
6421
    LogAccessHttp accessor(this);
6341
6422
 
6576
6657
 *****************************************************************************/
6577
6658
//////////////////////////////////////////////////////////////////////////
6578
6659
//
6579
 
//      HttpStateMachineGet::call_transact_and_set_next_state(f)
 
6660
//      HttpSM::call_transact_and_set_next_state(f)
6580
6661
//
6581
6662
//      This routine takes an HttpTransact function <f>, calls the function
6582
6663
//      to perform some actions on the current HttpTransact::State, and
6615
6696
 
6616
6697
//////////////////////////////////////////////////////////////////////////////
6617
6698
//
6618
 
//  HttpStateMachineGet::set_next_state()
 
6699
//  HttpSM::set_next_state()
6619
6700
//
6620
6701
//  call_transact_and_set_next_state() was broken into two parts, one
6621
6702
//  which calls the HttpTransact method and the second which sets the
6691
6772
        && !t_state.url_remap_success
6692
6773
        && t_state.parent_result.r != PARENT_SPECIFIED
6693
6774
        && t_state.client_info.is_transparent
 
6775
        && t_state.dns_info.os_addr_style == HttpTransact::DNSLookupInfo::OS_ADDR_TRY_DEFAULT
6694
6776
        && ats_is_ip(addr = t_state.state_machine->ua_session->get_netvc()->get_local_addr())
6695
6777
      ) {
6696
 
        ip_text_buffer ipb;
6697
 
        /* If the connection is client side transparent and the URL was not
6698
 
         * remapped/directed to parent proxy, we can use the client destination
6699
 
         * IP address instead of doing a DNS lookup. This is controlled by the
6700
 
         * 'use_client_target_addr' configuration parameter.
 
6778
        /* If the connection is client side transparent and the URL
 
6779
         * was not remapped/directed to parent proxy, we can use the
 
6780
         * client destination IP address instead of doing a DNS
 
6781
         * lookup. This is controlled by the 'use_client_target_addr'
 
6782
         * configuration parameter.
6701
6783
         */
6702
 
        DebugSM("dns", "[HttpTransact::HandleRequest] Skipping DNS lookup for client supplied target %s.\n", ats_ip_ntop(addr, ipb, sizeof(ipb)));
 
6784
        if (is_debug_tag_set("dns")) {
 
6785
          ip_text_buffer ipb;
 
6786
          DebugSM("dns", "[HttpTransact::HandleRequest] Skipping DNS lookup for client supplied target %s.\n", ats_ip_ntop(addr, ipb, sizeof(ipb)));
 
6787
        }
6703
6788
        ats_ip_copy(t_state.host_db_info.ip(), addr);
6704
6789
        /* Since we won't know the server HTTP version (no hostdb lookup), we assume it matches the
6705
6790
         * client request version. Seems to be the most correct thing to do in the transparent use-case.
6712
6797
          t_state.host_db_info.app.http_data.http_version =  HostDBApplicationInfo::HTTP_VERSION_11;
6713
6798
 
6714
6799
        t_state.dns_info.lookup_success = true;
 
6800
        // cache this result so we don't have to unreliably duplicate the
 
6801
        // logic later if the connect fails.
 
6802
        t_state.dns_info.os_addr_style = HttpTransact::DNSLookupInfo::OS_ADDR_TRY_CLIENT;
6715
6803
        call_transact_and_set_next_state(NULL);
6716
6804
        break;
6717
6805
      } else if (t_state.parent_result.r == PARENT_UNDEFINED && t_state.dns_info.lookup_success) {