HttpTransact::OSDNSLookup(State* s)
{
  static int max_dns_lookups = 3 + s->http_config_param->num_url_expansions;
  ++s->dns_info.attempts;

  DebugTxn("http_trans", "[HttpTransact::OSDNSLookup] This was attempt %d", s->dns_info.attempts);

  ink_assert(s->dns_info.looking_up == ORIGIN_SERVER);

  // detect whether we are about to self loop. the client may have
  // specified the proxy as the origin server (badness).

  // Check if this procedure is already done - YTS Team, yamsat
  if (!s->request_will_not_selfloop) {
    if (will_this_request_self_loop(s)) {
      DebugTxn("http_trans", "[OSDNSLookup] request will selfloop - bailing out");
      SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
      TRANSACT_RETURN(SM_ACTION_SEND_ERROR_CACHE_NOOP, NULL);
    }
  }

  if (!s->dns_info.lookup_success) {
    // maybe the name can be expanded (e.g cnn -> www.cnn.com)
    HostNameExpansionError_t host_name_expansion = try_to_expand_host_name(s);

    switch (host_name_expansion) {
    case RETRY_EXPANDED_NAME:
      // expansion successful, do a dns lookup on expanded name
      HTTP_RELEASE_ASSERT(s->dns_info.attempts < max_dns_lookups);
      HTTP_RELEASE_ASSERT(s->http_config_param->enable_url_expandomatic);
      TRANSACT_RETURN(SM_ACTION_DNS_LOOKUP, OSDNSLookup);
      break;
    case EXPANSION_NOT_ALLOWED:
    case EXPANSION_FAILED:
    case DNS_ATTEMPTS_EXHAUSTED:
      if (DNSLookupInfo::OS_ADDR_TRY_HOSTDB == s->dns_info.os_addr_style) {
        // No HostDB data, just keep on with the CTA.
        s->dns_info.lookup_success = true;
        s->dns_info.os_addr_style = DNSLookupInfo::OS_ADDR_USE_CLIENT;
        DebugTxn("http_seq", "[HttpTransact::OSDNSLookup] DNS lookup unsuccessful reverting to force client target address use");
      } else {
        if (host_name_expansion == EXPANSION_NOT_ALLOWED) {
          // config file doesn't allow automatic expansion of host names
          HTTP_RELEASE_ASSERT(!(s->http_config_param->enable_url_expandomatic));
          DebugTxn("http_seq", "[HttpTransact::OSDNSLookup] DNS Lookup unsuccessful");
        } else if (host_name_expansion == EXPANSION_FAILED) {
          // not able to expand the hostname. dns lookup failed
          DebugTxn("http_seq", "[HttpTransact::OSDNSLookup] DNS Lookup unsuccessful");
        } else if (host_name_expansion == DNS_ATTEMPTS_EXHAUSTED) {
          // retry attempts exhausted --- can't find dns entry for this host name
          HTTP_RELEASE_ASSERT(s->dns_info.attempts >= max_dns_lookups);
          DebugTxn("http_seq", "[HttpTransact::OSDNSLookup] DNS Lookup unsuccessful");
        }
        // output the DNS failure error message
        SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
        build_error_response(s, HTTP_STATUS_BAD_GATEWAY, "Cannot find server.", "connect#dns_failed", NULL);
        // s->cache_info.action = CACHE_DO_NO_ACTION;
        TRANSACT_RETURN(SM_ACTION_SEND_ERROR_CACHE_NOOP, NULL);
      }
      break;
    default:
      ink_assert(!("try_to_expand_hostname returned an unsupported code"));
      break;
    }
    return;
  }
  // ok, so the dns lookup succeeded
  ink_assert(s->dns_info.lookup_success);
  DebugTxn("http_seq", "[HttpTransact::OSDNSLookup] DNS Lookup successful");

  if (DNSLookupInfo::OS_ADDR_TRY_HOSTDB == s->dns_info.os_addr_style) {
    // We've backed off from a client supplied address and found some
    // HostDB addresses. We use those if they're different from the CTA.
    // In all cases we now commit to client or HostDB for our source.
    if (s->host_db_info.round_robin) {
      HostDBInfo* cta = s->host_db_info.rr()->select_next(&s->current.server->addr.sa);
      if (cta) {
        // found another addr, lock in host DB.
        s->host_db_info = *cta;
        s->dns_info.os_addr_style = DNSLookupInfo::OS_ADDR_USE_HOSTDB;
      } else {
        // nothing else there, continue with CTA.
        s->dns_info.os_addr_style = DNSLookupInfo::OS_ADDR_USE_CLIENT;
      }
    } else if (ats_ip_addr_eq(s->host_db_info.ip(), &s->server_info.addr.sa)) {
      s->dns_info.os_addr_style = DNSLookupInfo::OS_ADDR_USE_CLIENT;
    } else {
      s->dns_info.os_addr_style = DNSLookupInfo::OS_ADDR_USE_HOSTDB;
    }
  }

  // Check to see if can fullfill expect requests based on the cached
  // update some state variables with hostdb information that has
  // been provided.
  ats_ip_copy(&s->server_info.addr, s->host_db_info.ip());
  ats_ip_copy(&s->request_data.dest_ip, &s->server_info.addr);
  get_ka_info_from_host_db(s, &s->server_info, &s->client_info, &s->host_db_info);
  s->server_info.dns_round_robin = s->host_db_info.round_robin;

  char addrbuf[INET6_ADDRSTRLEN];
  DebugTxn("http_trans", "[OSDNSLookup] DNS lookup for O.S. successful "
        "IP: %s", ats_ip_ntop(&s->server_info.addr.sa, addrbuf, sizeof(addrbuf)));

  // so the dns lookup was a success, but the lookup succeeded on
  // a hostname which was expanded by the traffic server. we should
  // not automatically forward the request to this expanded hostname.
  // return a response to the client with the expanded host name
  // and a tasty little blurb explaining what happened.

  // if a DNS lookup succeeded on a user-defined
  // hostname expansion, forward the request to the expanded hostname.
  // On the other hand, if the lookup succeeded on a www.<hostname>.com
  // expansion, return a 302 response.
  // [amc] Also don't redirect if we backed off using HostDB instead of CTA.
  if (s->dns_info.attempts == max_dns_lookups && s->dns_info.looking_up == ORIGIN_SERVER && DNSLookupInfo::OS_ADDR_USE_CLIENT != s->dns_info.os_addr_style) {
    DebugTxn("http_trans", "[OSDNSLookup] DNS name resolution on expansion");
    DebugTxn("http_seq", "[OSDNSLookup] DNS name resolution on expansion - returning");
    build_redirect_response(s);
    // s->cache_info.action = CACHE_DO_NO_ACTION;
    TRANSACT_RETURN(SM_ACTION_INTERNAL_CACHE_NOOP, NULL);
  }
  // everything succeeded with the DNS lookup so do an API callout
  //   that allows for filtering.  We'll do traffic_server internal
  //   filtering after API filtering


  // After SM_ACTION_DNS_LOOKUP, goto the saved action/state ORIGIN_SERVER_(RAW_)OPEN.
  // Should we skip the StartAccessControl()? why?

  if (s->cdn_remap_complete) {
    DebugTxn("cdn", "This is a late DNS lookup.  We are going to the OS, " "not to HandleFiltering.");
    ink_assert(s->cdn_saved_next_action == SM_ACTION_ORIGIN_SERVER_OPEN || s->cdn_saved_next_action == SM_ACTION_ORIGIN_SERVER_RAW_OPEN);
    DebugTxn("cdn", "outgoing version -- (pre  conversion) %d", s->hdr_info.server_request.m_http->m_version);
    (&s->hdr_info.server_request)->version_set(HTTPVersion(1, 1));
    HttpTransactHeaders::convert_request(s->current.server->http_version, &s->hdr_info.server_request);
    DebugTxn("cdn", "outgoing version -- (post conversion) %d", s->hdr_info.server_request.m_http->m_version);
    TRANSACT_RETURN(s->cdn_saved_next_action, NULL);
  } else if (DNSLookupInfo::OS_ADDR_USE_CLIENT == s->dns_info.os_addr_style ||
             DNSLookupInfo::OS_ADDR_USE_HOSTDB == s->dns_info.os_addr_style) {
    // we've come back after already trying the server to get a better address
    // and finished with all backtracking - return to trying the server.
    TRANSACT_RETURN(how_to_open_connection(s), HttpTransact::HandleResponse);
  } else if (s->dns_info.lookup_name[0] <= '9' &&
             s->dns_info.lookup_name[0] >= '0' &&
             s->parent_params->ParentTable->hostMatch &&
             !s->http_config_param->no_dns_forward_to_parent) {
    // note, broken logic: ACC fudges the OR stmt to always be true,
    // 'AuthHttpAdapter' should do the rev-dns if needed, not here .
    TRANSACT_RETURN(SM_ACTION_DNS_REVERSE_LOOKUP, HttpTransact::StartAccessControl);
  } else {
    //(s->state_machine->authAdapter).StartLookup (s);
    // TRANSACT_RETURN(SM_ACTION_AUTH_LOOKUP, NULL);

    if (s->force_dns) {
      StartAccessControl(s);    // If skip_dns is enabled and no ip based rules in cache.config and parent.config
      // Access Control is called after DNS response
    } else {
      if ((s->cache_info.action == CACHE_DO_NO_ACTION) &&
          (((s->hdr_info.client_request.presence(MIME_PRESENCE_RANGE) && !s->txn_conf->cache_range_write) ||
            s->range_setup == RANGE_NOT_SATISFIABLE || s->range_setup == RANGE_NOT_HANDLED))) {
        TRANSACT_RETURN(SM_ACTION_API_OS_DNS, HandleCacheOpenReadMiss);
      } else if (s->cache_lookup_result == HttpTransact::CACHE_LOOKUP_SKIPPED) {
        TRANSACT_RETURN(SM_ACTION_API_OS_DNS, LookupSkipOpenServer);
        // DNS Lookup is done after LOOKUP Skipped  and after we get response
        // from the DNS we need to call LookupSkipOpenServer
      } else if (s->cache_lookup_result == CACHE_LOOKUP_HIT_FRESH ||
                 s->cache_lookup_result == CACHE_LOOKUP_HIT_WARNING ||
                 s->cache_lookup_result == CACHE_LOOKUP_HIT_STALE) {
        //DNS lookup is done if the content is state need to call handle cache open read hit
        TRANSACT_RETURN(SM_ACTION_API_OS_DNS, HandleCacheOpenReadHit);
      } else if (s->cache_lookup_result == CACHE_LOOKUP_MISS || s->cache_info.action == CACHE_DO_NO_ACTION) {
        TRANSACT_RETURN(SM_ACTION_API_OS_DNS, HandleCacheOpenReadMiss);
        //DNS lookup is done if the lookup failed and need to call Handle Cache Open Read Miss
      } else {
        build_error_response(s, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Invalid Cache Lookup result", "default", NULL);
        Log::error("HTTP: Invalid CACHE LOOKUP RESULT : %d", s->cache_lookup_result);
        TRANSACT_RETURN(SM_ACTION_SEND_ERROR_CACHE_NOOP, NULL);
      }
    }
  }
}