src/core/ngx_resolver.c - nginx source code

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. #define NGX_RESOLVER_UDP_SIZE   4096

  9. #define NGX_RESOLVER_TCP_RSIZE  (2 + 65535)
  10. #define NGX_RESOLVER_TCP_WSIZE  8192


  11. typedef struct {
  12.     u_char  ident_hi;
  13.     u_char  ident_lo;
  14.     u_char  flags_hi;
  15.     u_char  flags_lo;
  16.     u_char  nqs_hi;
  17.     u_char  nqs_lo;
  18.     u_char  nan_hi;
  19.     u_char  nan_lo;
  20.     u_char  nns_hi;
  21.     u_char  nns_lo;
  22.     u_char  nar_hi;
  23.     u_char  nar_lo;
  24. } ngx_resolver_hdr_t;


  25. typedef struct {
  26.     u_char  type_hi;
  27.     u_char  type_lo;
  28.     u_char  class_hi;
  29.     u_char  class_lo;
  30. } ngx_resolver_qs_t;


  31. typedef struct {
  32.     u_char  type_hi;
  33.     u_char  type_lo;
  34.     u_char  class_hi;
  35.     u_char  class_lo;
  36.     u_char  ttl[4];
  37.     u_char  len_hi;
  38.     u_char  len_lo;
  39. } ngx_resolver_an_t;


  40. #define ngx_resolver_node(n)  ngx_rbtree_data(n, ngx_resolver_node_t, node)


  41. static ngx_int_t ngx_udp_connect(ngx_resolver_connection_t *rec);
  42. static ngx_int_t ngx_tcp_connect(ngx_resolver_connection_t *rec);


  43. static void ngx_resolver_cleanup(void *data);
  44. static void ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree);
  45. static ngx_int_t ngx_resolve_name_locked(ngx_resolver_t *r,
  46.     ngx_resolver_ctx_t *ctx, ngx_str_t *name);
  47. static void ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree,
  48.     ngx_queue_t *queue);
  49. static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r,
  50.     ngx_resolver_node_t *rn);
  51. static ngx_int_t ngx_resolver_send_udp_query(ngx_resolver_t *r,
  52.     ngx_resolver_connection_t *rec, u_char *query, u_short qlen);
  53. static ngx_int_t ngx_resolver_send_tcp_query(ngx_resolver_t *r,
  54.     ngx_resolver_connection_t *rec, u_char *query, u_short qlen);
  55. static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_t *r,
  56.     ngx_resolver_node_t *rn, ngx_str_t *name);
  57. static ngx_int_t ngx_resolver_create_srv_query(ngx_resolver_t *r,
  58.     ngx_resolver_node_t *rn, ngx_str_t *name);
  59. static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r,
  60.     ngx_resolver_node_t *rn, ngx_resolver_addr_t *addr);
  61. static void ngx_resolver_resend_handler(ngx_event_t *ev);
  62. static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree,
  63.     ngx_queue_t *queue);
  64. static ngx_uint_t ngx_resolver_resend_empty(ngx_resolver_t *r);
  65. static void ngx_resolver_udp_read(ngx_event_t *rev);
  66. static void ngx_resolver_tcp_write(ngx_event_t *wev);
  67. static void ngx_resolver_tcp_read(ngx_event_t *rev);
  68. static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
  69.     size_t n, ngx_uint_t tcp);
  70. static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
  71.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
  72.     ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans);
  73. static void ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
  74.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan,
  75.     ngx_uint_t trunc, ngx_uint_t ans);
  76. static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
  77.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
  78. static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
  79.     ngx_str_t *name, uint32_t hash);
  80. static ngx_resolver_node_t *ngx_resolver_lookup_srv(ngx_resolver_t *r,
  81.     ngx_str_t *name, uint32_t hash);
  82. static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,
  83.     in_addr_t addr);
  84. static void ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
  85.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
  86. static ngx_int_t ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name,
  87.     u_char *buf, u_char *src, u_char *last);
  88. static ngx_int_t ngx_resolver_set_timeout(ngx_resolver_t *r,
  89.     ngx_resolver_ctx_t *ctx);
  90. static void ngx_resolver_timeout_handler(ngx_event_t *ev);
  91. static void ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn);
  92. static void *ngx_resolver_alloc(ngx_resolver_t *r, size_t size);
  93. static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
  94. static void ngx_resolver_free(ngx_resolver_t *r, void *p);
  95. static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
  96. static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
  97. static ngx_resolver_addr_t *ngx_resolver_export(ngx_resolver_t *r,
  98.     ngx_resolver_node_t *rn, ngx_uint_t rotate);
  99. static void ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx);
  100. static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
  101. static void ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx,
  102.     ngx_resolver_node_t *rn);
  103. static void ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *ctx);
  104. static ngx_int_t ngx_resolver_cmp_srvs(const void *one, const void *two);

  105. #if (NGX_HAVE_INET6)
  106. static void ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
  107.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
  108. static ngx_resolver_node_t *ngx_resolver_lookup_addr6(ngx_resolver_t *r,
  109.     struct in6_addr *addr, uint32_t hash);
  110. #endif


  111. ngx_resolver_t *
  112. ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
  113. {
  114.     ngx_str_t                   s;
  115.     ngx_url_t                   u;
  116.     ngx_uint_t                  i, j;
  117.     ngx_resolver_t             *r;
  118.     ngx_pool_cleanup_t         *cln;
  119.     ngx_resolver_connection_t  *rec;

  120.     r = ngx_pcalloc(cf->pool, sizeof(ngx_resolver_t));
  121.     if (r == NULL) {
  122.         return NULL;
  123.     }

  124.     r->event = ngx_pcalloc(cf->pool, sizeof(ngx_event_t));
  125.     if (r->event == NULL) {
  126.         return NULL;
  127.     }

  128.     cln = ngx_pool_cleanup_add(cf->pool, 0);
  129.     if (cln == NULL) {
  130.         return NULL;
  131.     }

  132.     cln->handler = ngx_resolver_cleanup;
  133.     cln->data = r;

  134.     r->ipv4 = 1;

  135.     ngx_rbtree_init(&r->name_rbtree, &r->name_sentinel,
  136.                     ngx_resolver_rbtree_insert_value);

  137.     ngx_rbtree_init(&r->srv_rbtree, &r->srv_sentinel,
  138.                     ngx_resolver_rbtree_insert_value);

  139.     ngx_rbtree_init(&r->addr_rbtree, &r->addr_sentinel,
  140.                     ngx_rbtree_insert_value);

  141.     ngx_queue_init(&r->name_resend_queue);
  142.     ngx_queue_init(&r->srv_resend_queue);
  143.     ngx_queue_init(&r->addr_resend_queue);

  144.     ngx_queue_init(&r->name_expire_queue);
  145.     ngx_queue_init(&r->srv_expire_queue);
  146.     ngx_queue_init(&r->addr_expire_queue);

  147. #if (NGX_HAVE_INET6)
  148.     r->ipv6 = 1;

  149.     ngx_rbtree_init(&r->addr6_rbtree, &r->addr6_sentinel,
  150.                     ngx_resolver_rbtree_insert_addr6_value);

  151.     ngx_queue_init(&r->addr6_resend_queue);

  152.     ngx_queue_init(&r->addr6_expire_queue);
  153. #endif

  154.     r->event->handler = ngx_resolver_resend_handler;
  155.     r->event->data = r;
  156.     r->event->log = &cf->cycle->new_log;
  157.     r->event->cancelable = 1;
  158.     r->ident = -1;

  159.     r->resend_timeout = 5;
  160.     r->tcp_timeout = 5;
  161.     r->expire = 30;
  162.     r->valid = 0;

  163.     r->log = &cf->cycle->new_log;
  164.     r->log_level = NGX_LOG_ERR;

  165.     if (n) {
  166.         if (ngx_array_init(&r->connections, cf->pool, n,
  167.                            sizeof(ngx_resolver_connection_t))
  168.             != NGX_OK)
  169.         {
  170.             return NULL;
  171.         }
  172.     }

  173.     for (i = 0; i < n; i++) {
  174.         if (ngx_strncmp(names[i].data, "valid=", 6) == 0) {
  175.             s.len = names[i].len - 6;
  176.             s.data = names[i].data + 6;

  177.             r->valid = ngx_parse_time(&s, 1);

  178.             if (r->valid == (time_t) NGX_ERROR) {
  179.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  180.                                    "invalid parameter: %V", &names[i]);
  181.                 return NULL;
  182.             }

  183.             continue;
  184.         }

  185. #if (NGX_HAVE_INET6)
  186.         if (ngx_strncmp(names[i].data, "ipv4=", 5) == 0) {

  187.             if (ngx_strcmp(&names[i].data[5], "on") == 0) {
  188.                 r->ipv4 = 1;

  189.             } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
  190.                 r->ipv4 = 0;

  191.             } else {
  192.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  193.                                    "invalid parameter: %V", &names[i]);
  194.                 return NULL;
  195.             }

  196.             continue;
  197.         }

  198.         if (ngx_strncmp(names[i].data, "ipv6=", 5) == 0) {

  199.             if (ngx_strcmp(&names[i].data[5], "on") == 0) {
  200.                 r->ipv6 = 1;

  201.             } else if (ngx_strcmp(&names[i].data[5], "off") == 0) {
  202.                 r->ipv6 = 0;

  203.             } else {
  204.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  205.                                    "invalid parameter: %V", &names[i]);
  206.                 return NULL;
  207.             }

  208.             continue;
  209.         }
  210. #endif

  211.         ngx_memzero(&u, sizeof(ngx_url_t));

  212.         u.url = names[i];
  213.         u.default_port = 53;

  214.         if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
  215.             if (u.err) {
  216.                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  217.                                    "%s in resolver \"%V\"",
  218.                                    u.err, &u.url);
  219.             }

  220.             return NULL;
  221.         }

  222.         rec = ngx_array_push_n(&r->connections, u.naddrs);
  223.         if (rec == NULL) {
  224.             return NULL;
  225.         }

  226.         ngx_memzero(rec, u.naddrs * sizeof(ngx_resolver_connection_t));

  227.         for (j = 0; j < u.naddrs; j++) {
  228.             rec[j].sockaddr = u.addrs[j].sockaddr;
  229.             rec[j].socklen = u.addrs[j].socklen;
  230.             rec[j].server = u.addrs[j].name;
  231.             rec[j].resolver = r;
  232.         }
  233.     }

  234. #if (NGX_HAVE_INET6)
  235.     if (r->ipv4 + r->ipv6 == 0) {
  236.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  237.                            "\"ipv4\" and \"ipv6\" cannot both be \"off\"");
  238.         return NULL;
  239.     }
  240. #endif

  241.     if (n && r->connections.nelts == 0) {
  242.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no name servers defined");
  243.         return NULL;
  244.     }

  245.     return r;
  246. }


  247. static void
  248. ngx_resolver_cleanup(void *data)
  249. {
  250.     ngx_resolver_t  *r = data;

  251.     ngx_uint_t                  i;
  252.     ngx_resolver_connection_t  *rec;

  253.     ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "cleanup resolver");

  254.     ngx_resolver_cleanup_tree(r, &r->name_rbtree);

  255.     ngx_resolver_cleanup_tree(r, &r->srv_rbtree);

  256.     ngx_resolver_cleanup_tree(r, &r->addr_rbtree);

  257. #if (NGX_HAVE_INET6)
  258.     ngx_resolver_cleanup_tree(r, &r->addr6_rbtree);
  259. #endif

  260.     if (r->event->timer_set) {
  261.         ngx_del_timer(r->event);
  262.     }

  263.     rec = r->connections.elts;

  264.     for (i = 0; i < r->connections.nelts; i++) {
  265.         if (rec[i].udp) {
  266.             ngx_close_connection(rec[i].udp);
  267.         }

  268.         if (rec[i].tcp) {
  269.             ngx_close_connection(rec[i].tcp);
  270.         }

  271.         if (rec[i].read_buf) {
  272.             ngx_resolver_free(r, rec[i].read_buf->start);
  273.             ngx_resolver_free(r, rec[i].read_buf);
  274.         }

  275.         if (rec[i].write_buf) {
  276.             ngx_resolver_free(r, rec[i].write_buf->start);
  277.             ngx_resolver_free(r, rec[i].write_buf);
  278.         }
  279.     }
  280. }


  281. static void
  282. ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree)
  283. {
  284.     ngx_resolver_ctx_t   *ctx, *next;
  285.     ngx_resolver_node_t  *rn;

  286.     while (tree->root != tree->sentinel) {

  287.         rn = ngx_resolver_node(ngx_rbtree_min(tree->root, tree->sentinel));

  288.         ngx_queue_remove(&rn->queue);

  289.         for (ctx = rn->waiting; ctx; ctx = next) {
  290.             next = ctx->next;

  291.             if (ctx->event) {
  292.                 if (ctx->event->timer_set) {
  293.                     ngx_del_timer(ctx->event);
  294.                 }

  295.                 ngx_resolver_free(r, ctx->event);
  296.             }

  297.             ngx_resolver_free(r, ctx);
  298.         }

  299.         ngx_rbtree_delete(tree, &rn->node);

  300.         ngx_resolver_free_node(r, rn);
  301.     }
  302. }


  303. ngx_resolver_ctx_t *
  304. ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp)
  305. {
  306.     in_addr_t            addr;
  307.     ngx_resolver_ctx_t  *ctx;

  308.     if (temp) {
  309.         addr = ngx_inet_addr(temp->name.data, temp->name.len);

  310.         if (addr != INADDR_NONE) {
  311.             temp->resolver = r;
  312.             temp->state = NGX_OK;
  313.             temp->naddrs = 1;
  314.             temp->addrs = &temp->addr;
  315.             temp->addr.sockaddr = (struct sockaddr *) &temp->sin;
  316.             temp->addr.socklen = sizeof(struct sockaddr_in);
  317.             ngx_memzero(&temp->sin, sizeof(struct sockaddr_in));
  318.             temp->sin.sin_family = AF_INET;
  319.             temp->sin.sin_addr.s_addr = addr;
  320.             temp->quick = 1;

  321.             return temp;
  322.         }
  323.     }

  324.     if (r->connections.nelts == 0) {
  325.         return NGX_NO_RESOLVER;
  326.     }

  327.     ctx = ngx_resolver_calloc(r, sizeof(ngx_resolver_ctx_t));

  328.     if (ctx) {
  329.         ctx->resolver = r;
  330.     }

  331.     return ctx;
  332. }


  333. ngx_int_t
  334. ngx_resolve_name(ngx_resolver_ctx_t *ctx)
  335. {
  336.     size_t           slen;
  337.     ngx_int_t        rc;
  338.     ngx_str_t        name;
  339.     ngx_resolver_t  *r;

  340.     r = ctx->resolver;

  341.     if (ctx->name.len > 0 && ctx->name.data[ctx->name.len - 1] == '.') {
  342.         ctx->name.len--;
  343.     }

  344.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
  345.                    "resolve: \"%V\"", &ctx->name);

  346.     if (ctx->quick) {
  347.         ctx->handler(ctx);
  348.         return NGX_OK;
  349.     }

  350.     if (ctx->service.len) {
  351.         slen = ctx->service.len;

  352.         if (ngx_strlchr(ctx->service.data,
  353.                         ctx->service.data + ctx->service.len, '.')
  354.             == NULL)
  355.         {
  356.             slen += sizeof("_._tcp") - 1;
  357.         }

  358.         name.len = slen + 1 + ctx->name.len;

  359.         name.data = ngx_resolver_alloc(r, name.len);
  360.         if (name.data == NULL) {
  361.             goto failed;
  362.         }

  363.         if (slen == ctx->service.len) {
  364.             ngx_sprintf(name.data, "%V.%V", &ctx->service, &ctx->name);

  365.         } else {
  366.             ngx_sprintf(name.data, "_%V._tcp.%V", &ctx->service, &ctx->name);
  367.         }

  368.         /* lock name mutex */

  369.         rc = ngx_resolve_name_locked(r, ctx, &name);

  370.         ngx_resolver_free(r, name.data);

  371.     } else {
  372.         /* lock name mutex */

  373.         rc = ngx_resolve_name_locked(r, ctx, &ctx->name);
  374.     }

  375.     if (rc == NGX_OK) {
  376.         return NGX_OK;
  377.     }

  378.     /* unlock name mutex */

  379.     if (rc == NGX_AGAIN) {
  380.         return NGX_OK;
  381.     }

  382.     /* NGX_ERROR */

  383.     if (ctx->event) {
  384.         ngx_resolver_free(r, ctx->event);
  385.     }

  386. failed:

  387.     ngx_resolver_free(r, ctx);

  388.     return NGX_ERROR;
  389. }


  390. void
  391. ngx_resolve_name_done(ngx_resolver_ctx_t *ctx)
  392. {
  393.     ngx_uint_t            i;
  394.     ngx_resolver_t       *r;
  395.     ngx_resolver_ctx_t   *w, **p;
  396.     ngx_resolver_node_t  *rn;

  397.     r = ctx->resolver;

  398.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
  399.                    "resolve name done: %i", ctx->state);

  400.     if (ctx->quick) {
  401.         return;
  402.     }

  403.     if (ctx->event && ctx->event->timer_set) {
  404.         ngx_del_timer(ctx->event);
  405.     }

  406.     /* lock name mutex */

  407.     if (ctx->nsrvs) {
  408.         for (i = 0; i < ctx->nsrvs; i++) {
  409.             if (ctx->srvs[i].ctx) {
  410.                 ngx_resolve_name_done(ctx->srvs[i].ctx);
  411.             }

  412.             if (ctx->srvs[i].addrs) {
  413.                 ngx_resolver_free(r, ctx->srvs[i].addrs->sockaddr);
  414.                 ngx_resolver_free(r, ctx->srvs[i].addrs);
  415.             }

  416.             ngx_resolver_free(r, ctx->srvs[i].name.data);
  417.         }

  418.         ngx_resolver_free(r, ctx->srvs);
  419.     }

  420.     if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {

  421.         rn = ctx->node;

  422.         if (rn) {
  423.             p = &rn->waiting;
  424.             w = rn->waiting;

  425.             while (w) {
  426.                 if (w == ctx) {
  427.                     *p = w->next;

  428.                     goto done;
  429.                 }

  430.                 p = &w->next;
  431.                 w = w->next;
  432.             }

  433.             ngx_log_error(NGX_LOG_ALERT, r->log, 0,
  434.                           "could not cancel %V resolving", &ctx->name);
  435.         }
  436.     }

  437. done:

  438.     if (ctx->service.len) {
  439.         ngx_resolver_expire(r, &r->srv_rbtree, &r->srv_expire_queue);

  440.     } else {
  441.         ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue);
  442.     }

  443.     /* unlock name mutex */

  444.     /* lock alloc mutex */

  445.     if (ctx->event) {
  446.         ngx_resolver_free_locked(r, ctx->event);
  447.     }

  448.     ngx_resolver_free_locked(r, ctx);

  449.     /* unlock alloc mutex */

  450.     if (r->event->timer_set && ngx_resolver_resend_empty(r)) {
  451.         ngx_del_timer(r->event);
  452.     }
  453. }


  454. static ngx_int_t
  455. ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
  456.     ngx_str_t *name)
  457. {
  458.     uint32_t              hash;
  459.     ngx_int_t             rc;
  460.     ngx_str_t             cname;
  461.     ngx_uint_t            i, naddrs;
  462.     ngx_queue_t          *resend_queue, *expire_queue;
  463.     ngx_rbtree_t         *tree;
  464.     ngx_resolver_ctx_t   *next, *last;
  465.     ngx_resolver_addr_t  *addrs;
  466.     ngx_resolver_node_t  *rn;

  467.     ngx_strlow(name->data, name->data, name->len);

  468.     hash = ngx_crc32_short(name->data, name->len);

  469.     if (ctx->service.len) {
  470.         rn = ngx_resolver_lookup_srv(r, name, hash);

  471.         tree = &r->srv_rbtree;
  472.         resend_queue = &r->srv_resend_queue;
  473.         expire_queue = &r->srv_expire_queue;

  474.     } else {
  475.         rn = ngx_resolver_lookup_name(r, name, hash);

  476.         tree = &r->name_rbtree;
  477.         resend_queue = &r->name_resend_queue;
  478.         expire_queue = &r->name_expire_queue;
  479.     }

  480.     if (rn) {

  481.         /* ctx can be a list after NGX_RESOLVE_CNAME */
  482.         for (last = ctx; last->next; last = last->next);

  483.         if (rn->valid >= ngx_time()) {

  484.             ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached");

  485.             ngx_queue_remove(&rn->queue);

  486.             rn->expire = ngx_time() + r->expire;

  487.             ngx_queue_insert_head(expire_queue, &rn->queue);

  488.             naddrs = (rn->naddrs == (u_short) -1) ? 0 : rn->naddrs;
  489. #if (NGX_HAVE_INET6)
  490.             naddrs += (rn->naddrs6 == (u_short) -1) ? 0 : rn->naddrs6;
  491. #endif

  492.             if (naddrs) {

  493.                 if (naddrs == 1 && rn->naddrs == 1) {
  494.                     addrs = NULL;

  495.                 } else {
  496.                     addrs = ngx_resolver_export(r, rn, 1);
  497.                     if (addrs == NULL) {
  498.                         return NGX_ERROR;
  499.                     }
  500.                 }

  501.                 last->next = rn->waiting;
  502.                 rn->waiting = NULL;

  503.                 /* unlock name mutex */

  504.                 do {
  505.                     ctx->state = NGX_OK;
  506.                     ctx->valid = rn->valid;
  507.                     ctx->naddrs = naddrs;

  508.                     if (addrs == NULL) {
  509.                         ctx->addrs = &ctx->addr;
  510.                         ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
  511.                         ctx->addr.socklen = sizeof(struct sockaddr_in);
  512.                         ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
  513.                         ctx->sin.sin_family = AF_INET;
  514.                         ctx->sin.sin_addr.s_addr = rn->u.addr;

  515.                     } else {
  516.                         ctx->addrs = addrs;
  517.                     }

  518.                     next = ctx->next;

  519.                     ctx->handler(ctx);

  520.                     ctx = next;
  521.                 } while (ctx);

  522.                 if (addrs != NULL) {
  523.                     ngx_resolver_free(r, addrs->sockaddr);
  524.                     ngx_resolver_free(r, addrs);
  525.                 }

  526.                 return NGX_OK;
  527.             }

  528.             if (rn->nsrvs) {
  529.                 last->next = rn->waiting;
  530.                 rn->waiting = NULL;

  531.                 /* unlock name mutex */

  532.                 do {
  533.                     next = ctx->next;

  534.                     ngx_resolver_resolve_srv_names(ctx, rn);

  535.                     ctx = next;
  536.                 } while (ctx);

  537.                 return NGX_OK;
  538.             }

  539.             /* NGX_RESOLVE_CNAME */

  540.             if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION) {

  541.                 cname.len = rn->cnlen;
  542.                 cname.data = rn->u.cname;

  543.                 return ngx_resolve_name_locked(r, ctx, &cname);
  544.             }

  545.             last->next = rn->waiting;
  546.             rn->waiting = NULL;

  547.             /* unlock name mutex */

  548.             do {
  549.                 ctx->state = NGX_RESOLVE_NXDOMAIN;
  550.                 ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
  551.                 next = ctx->next;

  552.                 ctx->handler(ctx);

  553.                 ctx = next;
  554.             } while (ctx);

  555.             return NGX_OK;
  556.         }

  557.         if (rn->waiting) {
  558.             if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) {
  559.                 return NGX_ERROR;
  560.             }

  561.             last->next = rn->waiting;
  562.             rn->waiting = ctx;
  563.             ctx->state = NGX_AGAIN;
  564.             ctx->async = 1;

  565.             do {
  566.                 ctx->node = rn;
  567.                 ctx = ctx->next;
  568.             } while (ctx);

  569.             return NGX_AGAIN;
  570.         }

  571.         ngx_queue_remove(&rn->queue);

  572.         /* lock alloc mutex */

  573.         if (rn->query) {
  574.             ngx_resolver_free_locked(r, rn->query);
  575.             rn->query = NULL;
  576. #if (NGX_HAVE_INET6)
  577.             rn->query6 = NULL;
  578. #endif
  579.         }

  580.         if (rn->cnlen) {
  581.             ngx_resolver_free_locked(r, rn->u.cname);
  582.         }

  583.         if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
  584.             ngx_resolver_free_locked(r, rn->u.addrs);
  585.         }

  586. #if (NGX_HAVE_INET6)
  587.         if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
  588.             ngx_resolver_free_locked(r, rn->u6.addrs6);
  589.         }
  590. #endif

  591.         if (rn->nsrvs) {
  592.             for (i = 0; i < (ngx_uint_t) rn->nsrvs; i++) {
  593.                 if (rn->u.srvs[i].name.data) {
  594.                     ngx_resolver_free_locked(r, rn->u.srvs[i].name.data);
  595.                 }
  596.             }

  597.             ngx_resolver_free_locked(r, rn->u.srvs);
  598.         }

  599.         /* unlock alloc mutex */

  600.     } else {

  601.         rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
  602.         if (rn == NULL) {
  603.             return NGX_ERROR;
  604.         }

  605.         rn->name = ngx_resolver_dup(r, name->data, name->len);
  606.         if (rn->name == NULL) {
  607.             ngx_resolver_free(r, rn);
  608.             return NGX_ERROR;
  609.         }

  610.         rn->node.key = hash;
  611.         rn->nlen = (u_short) name->len;
  612.         rn->query = NULL;
  613. #if (NGX_HAVE_INET6)
  614.         rn->query6 = NULL;
  615. #endif

  616.         ngx_rbtree_insert(tree, &rn->node);
  617.     }

  618.     if (ctx->service.len) {
  619.         rc = ngx_resolver_create_srv_query(r, rn, name);

  620.     } else {
  621.         rc = ngx_resolver_create_name_query(r, rn, name);
  622.     }

  623.     if (rc == NGX_ERROR) {
  624.         goto failed;
  625.     }

  626.     if (rc == NGX_DECLINED) {
  627.         ngx_rbtree_delete(tree, &rn->node);

  628.         ngx_resolver_free(r, rn->query);
  629.         ngx_resolver_free(r, rn->name);
  630.         ngx_resolver_free(r, rn);

  631.         do {
  632.             ctx->state = NGX_RESOLVE_NXDOMAIN;
  633.             next = ctx->next;

  634.             ctx->handler(ctx);

  635.             ctx = next;
  636.         } while (ctx);

  637.         return NGX_OK;
  638.     }

  639.     rn->last_connection = r->last_connection++;
  640.     if (r->last_connection == r->connections.nelts) {
  641.         r->last_connection = 0;
  642.     }

  643.     rn->naddrs = r->ipv4 ? (u_short) -1 : 0;
  644.     rn->tcp = 0;
  645. #if (NGX_HAVE_INET6)
  646.     rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
  647.     rn->tcp6 = 0;
  648. #endif
  649.     rn->nsrvs = 0;

  650.     if (ngx_resolver_send_query(r, rn) != NGX_OK) {

  651.         /* immediately retry once on failure */

  652.         rn->last_connection++;
  653.         if (rn->last_connection == r->connections.nelts) {
  654.             rn->last_connection = 0;
  655.         }

  656.         (void) ngx_resolver_send_query(r, rn);
  657.     }

  658.     if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) {
  659.         goto failed;
  660.     }

  661.     if (ngx_resolver_resend_empty(r)) {
  662.         ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
  663.     }

  664.     rn->expire = ngx_time() + r->resend_timeout;

  665.     ngx_queue_insert_head(resend_queue, &rn->queue);

  666.     rn->code = 0;
  667.     rn->cnlen = 0;
  668.     rn->valid = 0;
  669.     rn->ttl = NGX_MAX_UINT32_VALUE;
  670.     rn->waiting = ctx;

  671.     ctx->state = NGX_AGAIN;
  672.     ctx->async = 1;

  673.     do {
  674.         ctx->node = rn;
  675.         ctx = ctx->next;
  676.     } while (ctx);

  677.     return NGX_AGAIN;

  678. failed:

  679.     ngx_rbtree_delete(tree, &rn->node);

  680.     if (rn->query) {
  681.         ngx_resolver_free(r, rn->query);
  682.     }

  683.     ngx_resolver_free(r, rn->name);

  684.     ngx_resolver_free(r, rn);

  685.     return NGX_ERROR;
  686. }


  687. ngx_int_t
  688. ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
  689. {
  690.     u_char               *name;
  691.     in_addr_t             addr;
  692.     ngx_queue_t          *resend_queue, *expire_queue;
  693.     ngx_rbtree_t         *tree;
  694.     ngx_resolver_t       *r;
  695.     struct sockaddr_in   *sin;
  696.     ngx_resolver_node_t  *rn;
  697. #if (NGX_HAVE_INET6)
  698.     uint32_t              hash;
  699.     struct sockaddr_in6  *sin6;
  700. #endif

  701. #if (NGX_SUPPRESS_WARN)
  702.     addr = 0;
  703. #if (NGX_HAVE_INET6)
  704.     hash = 0;
  705.     sin6 = NULL;
  706. #endif
  707. #endif

  708.     r = ctx->resolver;

  709.     switch (ctx->addr.sockaddr->sa_family) {

  710. #if (NGX_HAVE_INET6)
  711.     case AF_INET6:
  712.         sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr;
  713.         hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16);

  714.         /* lock addr mutex */

  715.         rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash);

  716.         tree = &r->addr6_rbtree;
  717.         resend_queue = &r->addr6_resend_queue;
  718.         expire_queue = &r->addr6_expire_queue;

  719.         break;
  720. #endif

  721.     default: /* AF_INET */
  722.         sin = (struct sockaddr_in *) ctx->addr.sockaddr;
  723.         addr = ntohl(sin->sin_addr.s_addr);

  724.         /* lock addr mutex */

  725.         rn = ngx_resolver_lookup_addr(r, addr);

  726.         tree = &r->addr_rbtree;
  727.         resend_queue = &r->addr_resend_queue;
  728.         expire_queue = &r->addr_expire_queue;
  729.     }

  730.     if (rn) {

  731.         if (rn->valid >= ngx_time()) {

  732.             ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached");

  733.             ngx_queue_remove(&rn->queue);

  734.             rn->expire = ngx_time() + r->expire;

  735.             ngx_queue_insert_head(expire_queue, &rn->queue);

  736.             name = ngx_resolver_dup(r, rn->name, rn->nlen);
  737.             if (name == NULL) {
  738.                 ngx_resolver_free(r, ctx);
  739.                 return NGX_ERROR;
  740.             }

  741.             ctx->name.len = rn->nlen;
  742.             ctx->name.data = name;

  743.             /* unlock addr mutex */

  744.             ctx->state = NGX_OK;
  745.             ctx->valid = rn->valid;

  746.             ctx->handler(ctx);

  747.             ngx_resolver_free(r, name);

  748.             return NGX_OK;
  749.         }

  750.         if (rn->waiting) {
  751.             if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) {
  752.                 return NGX_ERROR;
  753.             }

  754.             ctx->next = rn->waiting;
  755.             rn->waiting = ctx;
  756.             ctx->state = NGX_AGAIN;
  757.             ctx->async = 1;
  758.             ctx->node = rn;

  759.             /* unlock addr mutex */

  760.             return NGX_OK;
  761.         }

  762.         ngx_queue_remove(&rn->queue);

  763.         ngx_resolver_free(r, rn->query);
  764.         rn->query = NULL;
  765. #if (NGX_HAVE_INET6)
  766.         rn->query6 = NULL;
  767. #endif

  768.     } else {
  769.         rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
  770.         if (rn == NULL) {
  771.             goto failed;
  772.         }

  773.         switch (ctx->addr.sockaddr->sa_family) {

  774. #if (NGX_HAVE_INET6)
  775.         case AF_INET6:
  776.             rn->addr6 = sin6->sin6_addr;
  777.             rn->node.key = hash;
  778.             break;
  779. #endif

  780.         default: /* AF_INET */
  781.             rn->node.key = addr;
  782.         }

  783.         rn->query = NULL;
  784. #if (NGX_HAVE_INET6)
  785.         rn->query6 = NULL;
  786. #endif

  787.         ngx_rbtree_insert(tree, &rn->node);
  788.     }

  789.     if (ngx_resolver_create_addr_query(r, rn, &ctx->addr) != NGX_OK) {
  790.         goto failed;
  791.     }

  792.     rn->last_connection = r->last_connection++;
  793.     if (r->last_connection == r->connections.nelts) {
  794.         r->last_connection = 0;
  795.     }

  796.     rn->naddrs = (u_short) -1;
  797.     rn->tcp = 0;
  798. #if (NGX_HAVE_INET6)
  799.     rn->naddrs6 = (u_short) -1;
  800.     rn->tcp6 = 0;
  801. #endif
  802.     rn->nsrvs = 0;

  803.     if (ngx_resolver_send_query(r, rn) != NGX_OK) {

  804.         /* immediately retry once on failure */

  805.         rn->last_connection++;
  806.         if (rn->last_connection == r->connections.nelts) {
  807.             rn->last_connection = 0;
  808.         }

  809.         (void) ngx_resolver_send_query(r, rn);
  810.     }

  811.     if (ngx_resolver_set_timeout(r, ctx) != NGX_OK) {
  812.         goto failed;
  813.     }

  814.     if (ngx_resolver_resend_empty(r)) {
  815.         ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000));
  816.     }

  817.     rn->expire = ngx_time() + r->resend_timeout;

  818.     ngx_queue_insert_head(resend_queue, &rn->queue);

  819.     rn->code = 0;
  820.     rn->cnlen = 0;
  821.     rn->name = NULL;
  822.     rn->nlen = 0;
  823.     rn->valid = 0;
  824.     rn->ttl = NGX_MAX_UINT32_VALUE;
  825.     rn->waiting = ctx;

  826.     /* unlock addr mutex */

  827.     ctx->state = NGX_AGAIN;
  828.     ctx->async = 1;
  829.     ctx->node = rn;

  830.     return NGX_OK;

  831. failed:

  832.     if (rn) {
  833.         ngx_rbtree_delete(tree, &rn->node);

  834.         if (rn->query) {
  835.             ngx_resolver_free(r, rn->query);
  836.         }

  837.         ngx_resolver_free(r, rn);
  838.     }

  839.     /* unlock addr mutex */

  840.     if (ctx->event) {
  841.         ngx_resolver_free(r, ctx->event);
  842.     }

  843.     ngx_resolver_free(r, ctx);

  844.     return NGX_ERROR;
  845. }


  846. void
  847. ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx)
  848. {
  849.     ngx_queue_t          *expire_queue;
  850.     ngx_rbtree_t         *tree;
  851.     ngx_resolver_t       *r;
  852.     ngx_resolver_ctx_t   *w, **p;
  853.     ngx_resolver_node_t  *rn;

  854.     r = ctx->resolver;

  855.     switch (ctx->addr.sockaddr->sa_family) {

  856. #if (NGX_HAVE_INET6)
  857.     case AF_INET6:
  858.         tree = &r->addr6_rbtree;
  859.         expire_queue = &r->addr6_expire_queue;
  860.         break;
  861. #endif

  862.     default: /* AF_INET */
  863.         tree = &r->addr_rbtree;
  864.         expire_queue = &r->addr_expire_queue;
  865.     }

  866.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
  867.                    "resolve addr done: %i", ctx->state);

  868.     if (ctx->event && ctx->event->timer_set) {
  869.         ngx_del_timer(ctx->event);
  870.     }

  871.     /* lock addr mutex */

  872.     if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) {

  873.         rn = ctx->node;

  874.         if (rn) {
  875.             p = &rn->waiting;
  876.             w = rn->waiting;

  877.             while (w) {
  878.                 if (w == ctx) {
  879.                     *p = w->next;

  880.                     goto done;
  881.                 }

  882.                 p = &w->next;
  883.                 w = w->next;
  884.             }
  885.         }

  886.         {
  887.             u_char     text[NGX_SOCKADDR_STRLEN];
  888.             ngx_str_t  addrtext;

  889.             addrtext.data = text;
  890.             addrtext.len = ngx_sock_ntop(ctx->addr.sockaddr, ctx->addr.socklen,
  891.                                          text, NGX_SOCKADDR_STRLEN, 0);

  892.             ngx_log_error(NGX_LOG_ALERT, r->log, 0,
  893.                           "could not cancel %V resolving", &addrtext);
  894.         }
  895.     }

  896. done:

  897.     ngx_resolver_expire(r, tree, expire_queue);

  898.     /* unlock addr mutex */

  899.     /* lock alloc mutex */

  900.     if (ctx->event) {
  901.         ngx_resolver_free_locked(r, ctx->event);
  902.     }

  903.     ngx_resolver_free_locked(r, ctx);

  904.     /* unlock alloc mutex */

  905.     if (r->event->timer_set && ngx_resolver_resend_empty(r)) {
  906.         ngx_del_timer(r->event);
  907.     }
  908. }


  909. static void
  910. ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
  911. {
  912.     time_t                now;
  913.     ngx_uint_t            i;
  914.     ngx_queue_t          *q;
  915.     ngx_resolver_node_t  *rn;

  916.     ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver expire");

  917.     now = ngx_time();

  918.     for (i = 0; i < 2; i++) {
  919.         if (ngx_queue_empty(queue)) {
  920.             return;
  921.         }

  922.         q = ngx_queue_last(queue);

  923.         rn = ngx_queue_data(q, ngx_resolver_node_t, queue);

  924.         if (now <= rn->expire) {
  925.             return;
  926.         }

  927.         ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
  928.                        "resolver expire \"%*s\"", (size_t) rn->nlen, rn->name);

  929.         ngx_queue_remove(q);

  930.         ngx_rbtree_delete(tree, &rn->node);

  931.         ngx_resolver_free_node(r, rn);
  932.     }
  933. }


  934. static ngx_int_t
  935. ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
  936. {
  937.     ngx_int_t                   rc;
  938.     ngx_resolver_connection_t  *rec;

  939.     rec = r->connections.elts;
  940.     rec = &rec[rn->last_connection];

  941.     if (rec->log.handler == NULL) {
  942.         rec->log = *r->log;
  943.         rec->log.handler = ngx_resolver_log_error;
  944.         rec->log.data = rec;
  945.         rec->log.action = "resolving";
  946.     }

  947.     if (rn->query && rn->naddrs == (u_short) -1) {
  948.         rc = rn->tcp ? ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen)
  949.                      : ngx_resolver_send_udp_query(r, rec, rn->query, rn->qlen);

  950.         if (rc != NGX_OK) {
  951.             return rc;
  952.         }
  953.     }

  954. #if (NGX_HAVE_INET6)

  955.     if (rn->query6 && rn->naddrs6 == (u_short) -1) {
  956.         rc = rn->tcp6
  957.                     ? ngx_resolver_send_tcp_query(r, rec, rn->query6, rn->qlen)
  958.                     : ngx_resolver_send_udp_query(r, rec, rn->query6, rn->qlen);

  959.         if (rc != NGX_OK) {
  960.             return rc;
  961.         }
  962.     }

  963. #endif

  964.     return NGX_OK;
  965. }


  966. static ngx_int_t
  967. ngx_resolver_send_udp_query(ngx_resolver_t *r, ngx_resolver_connection_t  *rec,
  968.     u_char *query, u_short qlen)
  969. {
  970.     ssize_t  n;

  971.     if (rec->udp == NULL) {
  972.         if (ngx_udp_connect(rec) != NGX_OK) {
  973.             return NGX_ERROR;
  974.         }

  975.         rec->udp->data = rec;
  976.         rec->udp->read->handler = ngx_resolver_udp_read;
  977.         rec->udp->read->resolver = 1;
  978.     }

  979.     n = ngx_send(rec->udp, query, qlen);

  980.     if (n == NGX_ERROR) {
  981.         goto failed;
  982.     }

  983.     if ((size_t) n != (size_t) qlen) {
  984.         ngx_log_error(NGX_LOG_CRIT, &rec->log, 0, "send() incomplete");
  985.         goto failed;
  986.     }

  987.     return NGX_OK;

  988. failed:

  989.     ngx_close_connection(rec->udp);
  990.     rec->udp = NULL;

  991.     return NGX_ERROR;
  992. }


  993. static ngx_int_t
  994. ngx_resolver_send_tcp_query(ngx_resolver_t *r, ngx_resolver_connection_t *rec,
  995.     u_char *query, u_short qlen)
  996. {
  997.     ngx_buf_t  *b;
  998.     ngx_int_t   rc;

  999.     rc = NGX_OK;

  1000.     if (rec->tcp == NULL) {
  1001.         b = rec->read_buf;

  1002.         if (b == NULL) {
  1003.             b = ngx_resolver_calloc(r, sizeof(ngx_buf_t));
  1004.             if (b == NULL) {
  1005.                 return NGX_ERROR;
  1006.             }

  1007.             b->start = ngx_resolver_alloc(r, NGX_RESOLVER_TCP_RSIZE);
  1008.             if (b->start == NULL) {
  1009.                 ngx_resolver_free(r, b);
  1010.                 return NGX_ERROR;
  1011.             }

  1012.             b->end = b->start + NGX_RESOLVER_TCP_RSIZE;

  1013.             rec->read_buf = b;
  1014.         }

  1015.         b->pos = b->start;
  1016.         b->last = b->start;

  1017.         b = rec->write_buf;

  1018.         if (b == NULL) {
  1019.             b = ngx_resolver_calloc(r, sizeof(ngx_buf_t));
  1020.             if (b == NULL) {
  1021.                 return NGX_ERROR;
  1022.             }

  1023.             b->start = ngx_resolver_alloc(r, NGX_RESOLVER_TCP_WSIZE);
  1024.             if (b->start == NULL) {
  1025.                 ngx_resolver_free(r, b);
  1026.                 return NGX_ERROR;
  1027.             }

  1028.             b->end = b->start + NGX_RESOLVER_TCP_WSIZE;

  1029.             rec->write_buf = b;
  1030.         }

  1031.         b->pos = b->start;
  1032.         b->last = b->start;

  1033.         rc = ngx_tcp_connect(rec);
  1034.         if (rc == NGX_ERROR) {
  1035.             return NGX_ERROR;
  1036.         }

  1037.         rec->tcp->data = rec;
  1038.         rec->tcp->write->handler = ngx_resolver_tcp_write;
  1039.         rec->tcp->write->cancelable = 1;
  1040.         rec->tcp->read->handler = ngx_resolver_tcp_read;
  1041.         rec->tcp->read->resolver = 1;

  1042.         ngx_add_timer(rec->tcp->write, (ngx_msec_t) (r->tcp_timeout * 1000));
  1043.     }

  1044.     b = rec->write_buf;

  1045.     if (b->end - b->last <  2 + qlen) {
  1046.         ngx_log_error(NGX_LOG_CRIT, &rec->log, 0, "buffer overflow");
  1047.         return NGX_ERROR;
  1048.     }

  1049.     *b->last++ = (u_char) (qlen >> 8);
  1050.     *b->last++ = (u_char) qlen;
  1051.     b->last = ngx_cpymem(b->last, query, qlen);

  1052.     if (rc == NGX_OK) {
  1053.         ngx_resolver_tcp_write(rec->tcp->write);
  1054.     }

  1055.     return NGX_OK;
  1056. }


  1057. static void
  1058. ngx_resolver_resend_handler(ngx_event_t *ev)
  1059. {
  1060.     time_t           timer, atimer, stimer, ntimer;
  1061. #if (NGX_HAVE_INET6)
  1062.     time_t           a6timer;
  1063. #endif
  1064.     ngx_resolver_t  *r;

  1065.     r = ev->data;

  1066.     ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0,
  1067.                    "resolver resend handler");

  1068.     /* lock name mutex */

  1069.     ntimer = ngx_resolver_resend(r, &r->name_rbtree, &r->name_resend_queue);

  1070.     stimer = ngx_resolver_resend(r, &r->srv_rbtree, &r->srv_resend_queue);

  1071.     /* unlock name mutex */

  1072.     /* lock addr mutex */

  1073.     atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue);

  1074.     /* unlock addr mutex */

  1075. #if (NGX_HAVE_INET6)

  1076.     /* lock addr6 mutex */

  1077.     a6timer = ngx_resolver_resend(r, &r->addr6_rbtree, &r->addr6_resend_queue);

  1078.     /* unlock addr6 mutex */

  1079. #endif

  1080.     timer = ntimer;

  1081.     if (timer == 0) {
  1082.         timer = atimer;

  1083.     } else if (atimer) {
  1084.         timer = ngx_min(timer, atimer);
  1085.     }

  1086.     if (timer == 0) {
  1087.         timer = stimer;

  1088.     } else if (stimer) {
  1089.         timer = ngx_min(timer, stimer);
  1090.     }

  1091. #if (NGX_HAVE_INET6)

  1092.     if (timer == 0) {
  1093.         timer = a6timer;

  1094.     } else if (a6timer) {
  1095.         timer = ngx_min(timer, a6timer);
  1096.     }

  1097. #endif

  1098.     if (timer) {
  1099.         ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000));
  1100.     }
  1101. }


  1102. static time_t
  1103. ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
  1104. {
  1105.     time_t                now;
  1106.     ngx_queue_t          *q;
  1107.     ngx_resolver_node_t  *rn;

  1108.     now = ngx_time();

  1109.     for ( ;; ) {
  1110.         if (ngx_queue_empty(queue)) {
  1111.             return 0;
  1112.         }

  1113.         q = ngx_queue_last(queue);

  1114.         rn = ngx_queue_data(q, ngx_resolver_node_t, queue);

  1115.         if (now < rn->expire) {
  1116.             return rn->expire - now;
  1117.         }

  1118.         ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
  1119.                        "resolver resend \"%*s\" %p",
  1120.                        (size_t) rn->nlen, rn->name, rn->waiting);

  1121.         ngx_queue_remove(q);

  1122.         if (rn->waiting) {

  1123.             if (++rn->last_connection == r->connections.nelts) {
  1124.                 rn->last_connection = 0;
  1125.             }

  1126.             (void) ngx_resolver_send_query(r, rn);

  1127.             rn->expire = now + r->resend_timeout;

  1128.             ngx_queue_insert_head(queue, q);

  1129.             continue;
  1130.         }

  1131.         ngx_rbtree_delete(tree, &rn->node);

  1132.         ngx_resolver_free_node(r, rn);
  1133.     }
  1134. }


  1135. static ngx_uint_t
  1136. ngx_resolver_resend_empty(ngx_resolver_t *r)
  1137. {
  1138.     return ngx_queue_empty(&r->name_resend_queue)
  1139.            && ngx_queue_empty(&r->srv_resend_queue)
  1140. #if (NGX_HAVE_INET6)
  1141.            && ngx_queue_empty(&r->addr6_resend_queue)
  1142. #endif
  1143.            && ngx_queue_empty(&r->addr_resend_queue);
  1144. }


  1145. static void
  1146. ngx_resolver_udp_read(ngx_event_t *rev)
  1147. {
  1148.     ssize_t                     n;
  1149.     ngx_connection_t           *c;
  1150.     ngx_resolver_connection_t  *rec;
  1151.     u_char                      buf[NGX_RESOLVER_UDP_SIZE];

  1152.     c = rev->data;
  1153.     rec = c->data;

  1154.     do {
  1155.         n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE);

  1156.         if (n == NGX_AGAIN) {
  1157.             break;
  1158.         }

  1159.         if (n == NGX_ERROR) {
  1160.             goto failed;
  1161.         }

  1162.         ngx_resolver_process_response(rec->resolver, buf, n, 0);

  1163.     } while (rev->ready);

  1164.     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
  1165.         goto failed;
  1166.     }

  1167.     return;

  1168. failed:

  1169.     ngx_close_connection(rec->udp);
  1170.     rec->udp = NULL;
  1171. }


  1172. static void
  1173. ngx_resolver_tcp_write(ngx_event_t *wev)
  1174. {
  1175.     off_t                       sent;
  1176.     ssize_t                     n;
  1177.     ngx_buf_t                  *b;
  1178.     ngx_resolver_t             *r;
  1179.     ngx_connection_t           *c;
  1180.     ngx_resolver_connection_t  *rec;

  1181.     c = wev->data;
  1182.     rec = c->data;
  1183.     b = rec->write_buf;
  1184.     r = rec->resolver;

  1185.     if (wev->timedout) {
  1186.         goto failed;
  1187.     }

  1188.     sent = c->sent;

  1189.     while (wev->ready && b->pos < b->last) {
  1190.         n = ngx_send(c, b->pos, b->last - b->pos);

  1191.         if (n == NGX_AGAIN) {
  1192.             break;
  1193.         }

  1194.         if (n == NGX_ERROR) {
  1195.             goto failed;
  1196.         }

  1197.         b->pos += n;
  1198.     }

  1199.     if (b->pos != b->start) {
  1200.         b->last = ngx_movemem(b->start, b->pos, b->last - b->pos);
  1201.         b->pos = b->start;
  1202.     }

  1203.     if (c->sent != sent) {
  1204.         ngx_add_timer(wev, (ngx_msec_t) (r->tcp_timeout * 1000));
  1205.     }

  1206.     if (ngx_handle_write_event(wev, 0) != NGX_OK) {
  1207.         goto failed;
  1208.     }

  1209.     return;

  1210. failed:

  1211.     ngx_close_connection(c);
  1212.     rec->tcp = NULL;
  1213. }


  1214. static void
  1215. ngx_resolver_tcp_read(ngx_event_t *rev)
  1216. {
  1217.     u_char                     *p;
  1218.     size_t                      size;
  1219.     ssize_t                     n;
  1220.     u_short                     qlen;
  1221.     ngx_buf_t                  *b;
  1222.     ngx_resolver_t             *r;
  1223.     ngx_connection_t           *c;
  1224.     ngx_resolver_connection_t  *rec;

  1225.     c = rev->data;
  1226.     rec = c->data;
  1227.     b = rec->read_buf;
  1228.     r = rec->resolver;

  1229.     while (rev->ready) {
  1230.         n = ngx_recv(c, b->last, b->end - b->last);

  1231.         if (n == NGX_AGAIN) {
  1232.             break;
  1233.         }

  1234.         if (n == NGX_ERROR || n == 0) {
  1235.             goto failed;
  1236.         }

  1237.         b->last += n;

  1238.         for ( ;; ) {
  1239.             p = b->pos;
  1240.             size = b->last - p;

  1241.             if (size < 2) {
  1242.                 break;
  1243.             }

  1244.             qlen = (u_short) *p++ << 8;
  1245.             qlen += *p++;

  1246.             if (size < (size_t) (2 + qlen)) {
  1247.                 break;
  1248.             }

  1249.             ngx_resolver_process_response(r, p, qlen, 1);

  1250.             b->pos += 2 + qlen;
  1251.         }

  1252.         if (b->pos != b->start) {
  1253.             b->last = ngx_movemem(b->start, b->pos, b->last - b->pos);
  1254.             b->pos = b->start;
  1255.         }
  1256.     }

  1257.     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
  1258.         goto failed;
  1259.     }

  1260.     return;

  1261. failed:

  1262.     ngx_close_connection(c);
  1263.     rec->tcp = NULL;
  1264. }


  1265. static void
  1266. ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n,
  1267.     ngx_uint_t tcp)
  1268. {
  1269.     char                 *err;
  1270.     ngx_uint_t            i, times, ident, qident, flags, code, nqs, nan, trunc,
  1271.                           qtype, qclass;
  1272. #if (NGX_HAVE_INET6)
  1273.     ngx_uint_t            qident6;
  1274. #endif
  1275.     ngx_queue_t          *q;
  1276.     ngx_resolver_qs_t    *qs;
  1277.     ngx_resolver_hdr_t   *response;
  1278.     ngx_resolver_node_t  *rn;

  1279.     if (n < sizeof(ngx_resolver_hdr_t)) {
  1280.         goto short_response;
  1281.     }

  1282.     response = (ngx_resolver_hdr_t *) buf;

  1283.     ident = (response->ident_hi << 8) + response->ident_lo;
  1284.     flags = (response->flags_hi << 8) + response->flags_lo;
  1285.     nqs = (response->nqs_hi << 8) + response->nqs_lo;
  1286.     nan = (response->nan_hi << 8) + response->nan_lo;
  1287.     trunc = flags & 0x0200;

  1288.     ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0,
  1289.                    "resolver DNS response %ui fl:%04Xi %ui/%ui/%ud/%ud",
  1290.                    ident, flags, nqs, nan,
  1291.                    (response->nns_hi << 8) + response->nns_lo,
  1292.                    (response->nar_hi << 8) + response->nar_lo);

  1293.     /* response to a standard query */
  1294.     if ((flags & 0xf870) != 0x8000 || (trunc && tcp)) {
  1295.         ngx_log_error(r->log_level, r->log, 0,
  1296.                       "invalid %s DNS response %ui fl:%04Xi",
  1297.                       tcp ? "TCP" : "UDP", ident, flags);
  1298.         return;
  1299.     }

  1300.     code = flags & 0xf;

  1301.     if (code == NGX_RESOLVE_FORMERR) {

  1302.         times = 0;

  1303.         for (q = ngx_queue_head(&r->name_resend_queue);
  1304.              q != ngx_queue_sentinel(&r->name_resend_queue) && times++ < 100;
  1305.              q = ngx_queue_next(q))
  1306.         {
  1307.             rn = ngx_queue_data(q, ngx_resolver_node_t, queue);

  1308.             if (rn->query) {
  1309.                 qident = (rn->query[0] << 8) + rn->query[1];

  1310.                 if (qident == ident) {
  1311.                     goto dns_error_name;
  1312.                 }
  1313.             }

  1314. #if (NGX_HAVE_INET6)
  1315.             if (rn->query6) {
  1316.                 qident6 = (rn->query6[0] << 8) + rn->query6[1];

  1317.                 if (qident6 == ident) {
  1318.                     goto dns_error_name;
  1319.                 }
  1320.             }
  1321. #endif
  1322.         }

  1323.         goto dns_error;
  1324.     }

  1325.     if (code > NGX_RESOLVE_REFUSED) {
  1326.         goto dns_error;
  1327.     }

  1328.     if (nqs != 1) {
  1329.         err = "invalid number of questions in DNS response";
  1330.         goto done;
  1331.     }

  1332.     i = sizeof(ngx_resolver_hdr_t);

  1333.     while (i < (ngx_uint_t) n) {

  1334.         if (buf[i] & 0xc0) {
  1335.             err = "unexpected compression pointer in DNS response";
  1336.             goto done;
  1337.         }

  1338.         if (buf[i] == '\0') {
  1339.             goto found;
  1340.         }

  1341.         i += 1 + buf[i];
  1342.     }

  1343.     goto short_response;

  1344. found:

  1345.     if (i++ == sizeof(ngx_resolver_hdr_t)) {
  1346.         err = "zero-length domain name in DNS response";
  1347.         goto done;
  1348.     }

  1349.     if (i + sizeof(ngx_resolver_qs_t) + nan * (2 + sizeof(ngx_resolver_an_t))
  1350.         > (ngx_uint_t) n)
  1351.     {
  1352.         goto short_response;
  1353.     }

  1354.     qs = (ngx_resolver_qs_t *) &buf[i];

  1355.     qtype = (qs->type_hi << 8) + qs->type_lo;
  1356.     qclass = (qs->class_hi << 8) + qs->class_lo;

  1357.     ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
  1358.                    "resolver DNS response qt:%ui cl:%ui", qtype, qclass);

  1359.     if (qclass != 1) {
  1360.         ngx_log_error(r->log_level, r->log, 0,
  1361.                       "unknown query class %ui in DNS response", qclass);
  1362.         return;
  1363.     }

  1364.     switch (qtype) {

  1365.     case NGX_RESOLVE_A:
  1366. #if (NGX_HAVE_INET6)
  1367.     case NGX_RESOLVE_AAAA:
  1368. #endif

  1369.         ngx_resolver_process_a(r, buf, n, ident, code, qtype, nan, trunc,
  1370.                                i + sizeof(ngx_resolver_qs_t));

  1371.         break;

  1372.     case NGX_RESOLVE_SRV:

  1373.         ngx_resolver_process_srv(r, buf, n, ident, code, nan, trunc,
  1374.                                  i + sizeof(ngx_resolver_qs_t));

  1375.         break;

  1376.     case NGX_RESOLVE_PTR:

  1377.         ngx_resolver_process_ptr(r, buf, n, ident, code, nan);

  1378.         break;

  1379.     default:
  1380.         ngx_log_error(r->log_level, r->log, 0,
  1381.                       "unknown query type %ui in DNS response", qtype);
  1382.         return;
  1383.     }

  1384.     return;

  1385. short_response:

  1386.     err = "short DNS response";

  1387. done:

  1388.     ngx_log_error(r->log_level, r->log, 0, err);

  1389.     return;

  1390. dns_error_name:

  1391.     ngx_log_error(r->log_level, r->log, 0,
  1392.                   "DNS error (%ui: %s), query id:%ui, name:\"%*s\"",
  1393.                   code, ngx_resolver_strerror(code), ident,
  1394.                   (size_t) rn->nlen, rn->name);
  1395.     return;

  1396. dns_error:

  1397.     ngx_log_error(r->log_level, r->log, 0,
  1398.                   "DNS error (%ui: %s), query id:%ui",
  1399.                   code, ngx_resolver_strerror(code), ident);
  1400.     return;
  1401. }


  1402. static void
  1403. ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
  1404.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t qtype,
  1405.     ngx_uint_t nan, ngx_uint_t trunc, ngx_uint_t ans)
  1406. {
  1407.     char                       *err;
  1408.     u_char                     *cname;
  1409.     size_t                      len;
  1410.     int32_t                     ttl;
  1411.     uint32_t                    hash;
  1412.     in_addr_t                  *addr;
  1413.     ngx_str_t                   name;
  1414.     ngx_uint_t                  type, class, qident, naddrs, a, i, j, start;
  1415. #if (NGX_HAVE_INET6)
  1416.     struct in6_addr            *addr6;
  1417. #endif
  1418.     ngx_resolver_an_t          *an;
  1419.     ngx_resolver_ctx_t         *ctx, *next;
  1420.     ngx_resolver_node_t        *rn;
  1421.     ngx_resolver_addr_t        *addrs;
  1422.     ngx_resolver_connection_t  *rec;

  1423.     if (ngx_resolver_copy(r, &name, buf,
  1424.                           buf + sizeof(ngx_resolver_hdr_t), buf + n)
  1425.         != NGX_OK)
  1426.     {
  1427.         return;
  1428.     }

  1429.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);

  1430.     hash = ngx_crc32_short(name.data, name.len);

  1431.     /* lock name mutex */

  1432.     rn = ngx_resolver_lookup_name(r, &name, hash);

  1433.     if (rn == NULL) {
  1434.         ngx_log_error(r->log_level, r->log, 0,
  1435.                       "unexpected DNS response for %V", &name);
  1436.         ngx_resolver_free(r, name.data);
  1437.         goto failed;
  1438.     }

  1439.     switch (qtype) {

  1440. #if (NGX_HAVE_INET6)
  1441.     case NGX_RESOLVE_AAAA:

  1442.         if (rn->query6 == NULL || rn->naddrs6 != (u_short) -1) {
  1443.             ngx_log_error(r->log_level, r->log, 0,
  1444.                           "unexpected DNS response for %V", &name);
  1445.             ngx_resolver_free(r, name.data);
  1446.             goto failed;
  1447.         }

  1448.         if (trunc && rn->tcp6) {
  1449.             ngx_resolver_free(r, name.data);
  1450.             goto failed;
  1451.         }

  1452.         qident = (rn->query6[0] << 8) + rn->query6[1];

  1453.         break;
  1454. #endif

  1455.     default: /* NGX_RESOLVE_A */

  1456.         if (rn->query == NULL || rn->naddrs != (u_short) -1) {
  1457.             ngx_log_error(r->log_level, r->log, 0,
  1458.                           "unexpected DNS response for %V", &name);
  1459.             ngx_resolver_free(r, name.data);
  1460.             goto failed;
  1461.         }

  1462.         if (trunc && rn->tcp) {
  1463.             ngx_resolver_free(r, name.data);
  1464.             goto failed;
  1465.         }

  1466.         qident = (rn->query[0] << 8) + rn->query[1];
  1467.     }

  1468.     if (ident != qident) {
  1469.         ngx_log_error(r->log_level, r->log, 0,
  1470.                       "wrong ident %ui in DNS response for %V, expect %ui",
  1471.                       ident, &name, qident);
  1472.         ngx_resolver_free(r, name.data);
  1473.         goto failed;
  1474.     }

  1475.     ngx_resolver_free(r, name.data);

  1476.     if (trunc) {

  1477.         ngx_queue_remove(&rn->queue);

  1478.         if (rn->waiting == NULL) {
  1479.             ngx_rbtree_delete(&r->name_rbtree, &rn->node);
  1480.             ngx_resolver_free_node(r, rn);
  1481.             goto next;
  1482.         }

  1483.         rec = r->connections.elts;
  1484.         rec = &rec[rn->last_connection];

  1485.         switch (qtype) {

  1486. #if (NGX_HAVE_INET6)
  1487.         case NGX_RESOLVE_AAAA:

  1488.             rn->tcp6 = 1;

  1489.             (void) ngx_resolver_send_tcp_query(r, rec, rn->query6, rn->qlen);

  1490.             break;
  1491. #endif

  1492.         default: /* NGX_RESOLVE_A */

  1493.             rn->tcp = 1;

  1494.             (void) ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen);
  1495.         }

  1496.         rn->expire = ngx_time() + r->resend_timeout;

  1497.         ngx_queue_insert_head(&r->name_resend_queue, &rn->queue);

  1498.         goto next;
  1499.     }

  1500.     if (code == 0 && rn->code) {
  1501.         code = rn->code;
  1502.     }

  1503.     if (code == 0 && nan == 0) {

  1504. #if (NGX_HAVE_INET6)
  1505.         switch (qtype) {

  1506.         case NGX_RESOLVE_AAAA:

  1507.             rn->naddrs6 = 0;

  1508.             if (rn->naddrs == (u_short) -1) {
  1509.                 goto next;
  1510.             }

  1511.             if (rn->naddrs) {
  1512.                 goto export;
  1513.             }

  1514.             break;

  1515.         default: /* NGX_RESOLVE_A */

  1516.             rn->naddrs = 0;

  1517.             if (rn->naddrs6 == (u_short) -1) {
  1518.                 goto next;
  1519.             }

  1520.             if (rn->naddrs6) {
  1521.                 goto export;
  1522.             }
  1523.         }
  1524. #endif

  1525.         code = NGX_RESOLVE_NXDOMAIN;
  1526.     }

  1527.     if (code) {

  1528. #if (NGX_HAVE_INET6)
  1529.         switch (qtype) {

  1530.         case NGX_RESOLVE_AAAA:

  1531.             rn->naddrs6 = 0;

  1532.             if (rn->naddrs == (u_short) -1) {
  1533.                 rn->code = (u_char) code;
  1534.                 goto next;
  1535.             }

  1536.             break;

  1537.         default: /* NGX_RESOLVE_A */

  1538.             rn->naddrs = 0;

  1539.             if (rn->naddrs6 == (u_short) -1) {
  1540.                 rn->code = (u_char) code;
  1541.                 goto next;
  1542.             }
  1543.         }
  1544. #endif

  1545.         next = rn->waiting;
  1546.         rn->waiting = NULL;

  1547.         ngx_queue_remove(&rn->queue);

  1548.         ngx_rbtree_delete(&r->name_rbtree, &rn->node);

  1549.         /* unlock name mutex */

  1550.         while (next) {
  1551.             ctx = next;
  1552.             ctx->state = code;
  1553.             ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
  1554.             next = ctx->next;

  1555.             ctx->handler(ctx);
  1556.         }

  1557.         ngx_resolver_free_node(r, rn);

  1558.         return;
  1559.     }

  1560.     i = ans;
  1561.     naddrs = 0;
  1562.     cname = NULL;

  1563.     for (a = 0; a < nan; a++) {

  1564.         start = i;

  1565.         while (i < n) {

  1566.             if (buf[i] & 0xc0) {
  1567.                 i += 2;
  1568.                 goto found;
  1569.             }

  1570.             if (buf[i] == 0) {
  1571.                 i++;
  1572.                 goto test_length;
  1573.             }

  1574.             i += 1 + buf[i];
  1575.         }

  1576.         goto short_response;

  1577.     test_length:

  1578.         if (i - start < 2) {
  1579.             err = "invalid name in DNS response";
  1580.             goto invalid;
  1581.         }

  1582.     found:

  1583.         if (i + sizeof(ngx_resolver_an_t) >= n) {
  1584.             goto short_response;
  1585.         }

  1586.         an = (ngx_resolver_an_t *) &buf[i];

  1587.         type = (an->type_hi << 8) + an->type_lo;
  1588.         class = (an->class_hi << 8) + an->class_lo;
  1589.         len = (an->len_hi << 8) + an->len_lo;
  1590.         ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
  1591.             + (an->ttl[2] << 8) + (an->ttl[3]);

  1592.         if (class != 1) {
  1593.             ngx_log_error(r->log_level, r->log, 0,
  1594.                           "unexpected RR class %ui in DNS response", class);
  1595.             goto failed;
  1596.         }

  1597.         if (ttl < 0) {
  1598.             ttl = 0;
  1599.         }

  1600.         rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl);

  1601.         i += sizeof(ngx_resolver_an_t);

  1602.         switch (type) {

  1603.         case NGX_RESOLVE_A:

  1604.             if (qtype != NGX_RESOLVE_A) {
  1605.                 err = "unexpected A record in DNS response";
  1606.                 goto invalid;
  1607.             }

  1608.             if (len != 4) {
  1609.                 err = "invalid A record in DNS response";
  1610.                 goto invalid;
  1611.             }

  1612.             if (i + 4 > n) {
  1613.                 goto short_response;
  1614.             }

  1615.             naddrs++;

  1616.             break;

  1617. #if (NGX_HAVE_INET6)
  1618.         case NGX_RESOLVE_AAAA:

  1619.             if (qtype != NGX_RESOLVE_AAAA) {
  1620.                 err = "unexpected AAAA record in DNS response";
  1621.                 goto invalid;
  1622.             }

  1623.             if (len != 16) {
  1624.                 err = "invalid AAAA record in DNS response";
  1625.                 goto invalid;
  1626.             }

  1627.             if (i + 16 > n) {
  1628.                 goto short_response;
  1629.             }

  1630.             naddrs++;

  1631.             break;
  1632. #endif

  1633.         case NGX_RESOLVE_CNAME:

  1634.             cname = &buf[i];

  1635.             break;

  1636.         case NGX_RESOLVE_DNAME:

  1637.             break;

  1638.         default:

  1639.             ngx_log_error(r->log_level, r->log, 0,
  1640.                           "unexpected RR type %ui in DNS response", type);
  1641.         }

  1642.         i += len;
  1643.     }

  1644.     ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
  1645.                    "resolver naddrs:%ui cname:%p ttl:%uD",
  1646.                    naddrs, cname, rn->ttl);

  1647.     if (naddrs) {

  1648.         switch (qtype) {

  1649. #if (NGX_HAVE_INET6)
  1650.         case NGX_RESOLVE_AAAA:

  1651.             if (naddrs == 1) {
  1652.                 addr6 = &rn->u6.addr6;
  1653.                 rn->naddrs6 = 1;

  1654.             } else {
  1655.                 addr6 = ngx_resolver_alloc(r, naddrs * sizeof(struct in6_addr));
  1656.                 if (addr6 == NULL) {
  1657.                     goto failed;
  1658.                 }

  1659.                 rn->u6.addrs6 = addr6;
  1660.                 rn->naddrs6 = (u_short) naddrs;
  1661.             }

  1662. #if (NGX_SUPPRESS_WARN)
  1663.             addr = NULL;
  1664. #endif

  1665.             break;
  1666. #endif

  1667.         default: /* NGX_RESOLVE_A */

  1668.             if (naddrs == 1) {
  1669.                 addr = &rn->u.addr;
  1670.                 rn->naddrs = 1;

  1671.             } else {
  1672.                 addr = ngx_resolver_alloc(r, naddrs * sizeof(in_addr_t));
  1673.                 if (addr == NULL) {
  1674.                     goto failed;
  1675.                 }

  1676.                 rn->u.addrs = addr;
  1677.                 rn->naddrs = (u_short) naddrs;
  1678.             }

  1679. #if (NGX_HAVE_INET6 && NGX_SUPPRESS_WARN)
  1680.             addr6 = NULL;
  1681. #endif
  1682.         }

  1683.         j = 0;
  1684.         i = ans;

  1685.         for (a = 0; a < nan; a++) {

  1686.             for ( ;; ) {

  1687.                 if (buf[i] & 0xc0) {
  1688.                     i += 2;
  1689.                     break;
  1690.                 }

  1691.                 if (buf[i] == 0) {
  1692.                     i++;
  1693.                     break;
  1694.                 }

  1695.                 i += 1 + buf[i];
  1696.             }

  1697.             an = (ngx_resolver_an_t *) &buf[i];

  1698.             type = (an->type_hi << 8) + an->type_lo;
  1699.             len = (an->len_hi << 8) + an->len_lo;

  1700.             i += sizeof(ngx_resolver_an_t);

  1701.             if (type == NGX_RESOLVE_A) {

  1702.                 addr[j] = htonl((buf[i] << 24) + (buf[i + 1] << 16)
  1703.                                 + (buf[i + 2] << 8) + (buf[i + 3]));

  1704.                 if (++j == naddrs) {

  1705. #if (NGX_HAVE_INET6)
  1706.                     if (rn->naddrs6 == (u_short) -1) {
  1707.                         goto next;
  1708.                     }
  1709. #endif

  1710.                     break;
  1711.                 }
  1712.             }

  1713. #if (NGX_HAVE_INET6)
  1714.             else if (type == NGX_RESOLVE_AAAA) {

  1715.                 ngx_memcpy(addr6[j].s6_addr, &buf[i], 16);

  1716.                 if (++j == naddrs) {

  1717.                     if (rn->naddrs == (u_short) -1) {
  1718.                         goto next;
  1719.                     }

  1720.                     break;
  1721.                 }
  1722.             }
  1723. #endif

  1724.             i += len;
  1725.         }
  1726.     }

  1727.     switch (qtype) {

  1728. #if (NGX_HAVE_INET6)
  1729.     case NGX_RESOLVE_AAAA:

  1730.         if (rn->naddrs6 == (u_short) -1) {
  1731.             rn->naddrs6 = 0;
  1732.         }

  1733.         break;
  1734. #endif

  1735.     default: /* NGX_RESOLVE_A */

  1736.         if (rn->naddrs == (u_short) -1) {
  1737.             rn->naddrs = 0;
  1738.         }
  1739.     }

  1740.     if (rn->naddrs != (u_short) -1
  1741. #if (NGX_HAVE_INET6)
  1742.         && rn->naddrs6 != (u_short) -1
  1743. #endif
  1744.         && rn->naddrs
  1745. #if (NGX_HAVE_INET6)
  1746.            + rn->naddrs6
  1747. #endif
  1748.            > 0)
  1749.     {

  1750. #if (NGX_HAVE_INET6)
  1751.     export:
  1752. #endif

  1753.         naddrs = rn->naddrs;
  1754. #if (NGX_HAVE_INET6)
  1755.         naddrs += rn->naddrs6;
  1756. #endif

  1757.         if (naddrs == 1 && rn->naddrs == 1) {
  1758.             addrs = NULL;

  1759.         } else {
  1760.             addrs = ngx_resolver_export(r, rn, 0);
  1761.             if (addrs == NULL) {
  1762.                 goto failed;
  1763.             }
  1764.         }

  1765.         ngx_queue_remove(&rn->queue);

  1766.         rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
  1767.         rn->expire = ngx_time() + r->expire;

  1768.         ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);

  1769.         next = rn->waiting;
  1770.         rn->waiting = NULL;

  1771.         /* unlock name mutex */

  1772.         while (next) {
  1773.             ctx = next;
  1774.             ctx->state = NGX_OK;
  1775.             ctx->valid = rn->valid;
  1776.             ctx->naddrs = naddrs;

  1777.             if (addrs == NULL) {
  1778.                 ctx->addrs = &ctx->addr;
  1779.                 ctx->addr.sockaddr = (struct sockaddr *) &ctx->sin;
  1780.                 ctx->addr.socklen = sizeof(struct sockaddr_in);
  1781.                 ngx_memzero(&ctx->sin, sizeof(struct sockaddr_in));
  1782.                 ctx->sin.sin_family = AF_INET;
  1783.                 ctx->sin.sin_addr.s_addr = rn->u.addr;

  1784.             } else {
  1785.                 ctx->addrs = addrs;
  1786.             }

  1787.             next = ctx->next;

  1788.             ctx->handler(ctx);
  1789.         }

  1790.         if (addrs != NULL) {
  1791.             ngx_resolver_free(r, addrs->sockaddr);
  1792.             ngx_resolver_free(r, addrs);
  1793.         }

  1794.         ngx_resolver_free(r, rn->query);
  1795.         rn->query = NULL;
  1796. #if (NGX_HAVE_INET6)
  1797.         rn->query6 = NULL;
  1798. #endif

  1799.         return;
  1800.     }

  1801.     if (cname) {

  1802.         /* CNAME only */

  1803.         if (rn->naddrs == (u_short) -1
  1804. #if (NGX_HAVE_INET6)
  1805.             || rn->naddrs6 == (u_short) -1
  1806. #endif
  1807.             )
  1808.         {
  1809.             goto next;
  1810.         }

  1811.         if (ngx_resolver_copy(r, &name, buf, cname, buf + n) != NGX_OK) {
  1812.             goto failed;
  1813.         }

  1814.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
  1815.                        "resolver cname:\"%V\"", &name);

  1816.         ngx_queue_remove(&rn->queue);

  1817.         rn->cnlen = (u_short) name.len;
  1818.         rn->u.cname = name.data;

  1819.         rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
  1820.         rn->expire = ngx_time() + r->expire;

  1821.         ngx_queue_insert_head(&r->name_expire_queue, &rn->queue);

  1822.         ngx_resolver_free(r, rn->query);
  1823.         rn->query = NULL;
  1824. #if (NGX_HAVE_INET6)
  1825.         rn->query6 = NULL;
  1826. #endif

  1827.         ctx = rn->waiting;
  1828.         rn->waiting = NULL;

  1829.         if (ctx) {

  1830.             if (ctx->recursion++ >= NGX_RESOLVER_MAX_RECURSION) {

  1831.                 /* unlock name mutex */

  1832.                 do {
  1833.                     ctx->state = NGX_RESOLVE_NXDOMAIN;
  1834.                     next = ctx->next;

  1835.                     ctx->handler(ctx);

  1836.                     ctx = next;
  1837.                 } while (ctx);

  1838.                 return;
  1839.             }

  1840.             for (next = ctx; next; next = next->next) {
  1841.                 next->node = NULL;
  1842.             }

  1843.             (void) ngx_resolve_name_locked(r, ctx, &name);
  1844.         }

  1845.         /* unlock name mutex */

  1846.         return;
  1847.     }

  1848.     ngx_log_error(r->log_level, r->log, 0,
  1849.                   "no A or CNAME types in DNS response");
  1850.     return;

  1851. short_response:

  1852.     err = "short DNS response";

  1853. invalid:

  1854.     /* unlock name mutex */

  1855.     ngx_log_error(r->log_level, r->log, 0, err);

  1856.     return;

  1857. failed:

  1858. next:

  1859.     /* unlock name mutex */

  1860.     return;
  1861. }


  1862. static void
  1863. ngx_resolver_process_srv(ngx_resolver_t *r, u_char *buf, size_t n,
  1864.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan,
  1865.     ngx_uint_t trunc, ngx_uint_t ans)
  1866. {
  1867.     char                       *err;
  1868.     u_char                     *cname;
  1869.     size_t                      len;
  1870.     int32_t                     ttl;
  1871.     uint32_t                    hash;
  1872.     ngx_str_t                   name;
  1873.     ngx_uint_t                  type, qident, class, start, nsrvs, a, i, j;
  1874.     ngx_resolver_an_t          *an;
  1875.     ngx_resolver_ctx_t         *ctx, *next;
  1876.     ngx_resolver_srv_t         *srvs;
  1877.     ngx_resolver_node_t        *rn;
  1878.     ngx_resolver_connection_t  *rec;

  1879.     if (ngx_resolver_copy(r, &name, buf,
  1880.                           buf + sizeof(ngx_resolver_hdr_t), buf + n)
  1881.         != NGX_OK)
  1882.     {
  1883.         return;
  1884.     }

  1885.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);

  1886.     hash = ngx_crc32_short(name.data, name.len);

  1887.     rn = ngx_resolver_lookup_srv(r, &name, hash);

  1888.     if (rn == NULL || rn->query == NULL) {
  1889.         ngx_log_error(r->log_level, r->log, 0,
  1890.                       "unexpected DNS response for %V", &name);
  1891.         ngx_resolver_free(r, name.data);
  1892.         goto failed;
  1893.     }

  1894.     if (trunc && rn->tcp) {
  1895.         ngx_resolver_free(r, name.data);
  1896.         goto failed;
  1897.     }

  1898.     qident = (rn->query[0] << 8) + rn->query[1];

  1899.     if (ident != qident) {
  1900.         ngx_log_error(r->log_level, r->log, 0,
  1901.                       "wrong ident %ui in DNS response for %V, expect %ui",
  1902.                       ident, &name, qident);
  1903.         ngx_resolver_free(r, name.data);
  1904.         goto failed;
  1905.     }

  1906.     ngx_resolver_free(r, name.data);

  1907.     if (trunc) {

  1908.         ngx_queue_remove(&rn->queue);

  1909.         if (rn->waiting == NULL) {
  1910.             ngx_rbtree_delete(&r->srv_rbtree, &rn->node);
  1911.             ngx_resolver_free_node(r, rn);
  1912.             return;
  1913.         }

  1914.         rec = r->connections.elts;
  1915.         rec = &rec[rn->last_connection];

  1916.         rn->tcp = 1;

  1917.         (void) ngx_resolver_send_tcp_query(r, rec, rn->query, rn->qlen);

  1918.         rn->expire = ngx_time() + r->resend_timeout;

  1919.         ngx_queue_insert_head(&r->srv_resend_queue, &rn->queue);

  1920.         return;
  1921.     }

  1922.     if (code == 0 && rn->code) {
  1923.         code = rn->code;
  1924.     }

  1925.     if (code == 0 && nan == 0) {
  1926.         code = NGX_RESOLVE_NXDOMAIN;
  1927.     }

  1928.     if (code) {
  1929.         next = rn->waiting;
  1930.         rn->waiting = NULL;

  1931.         ngx_queue_remove(&rn->queue);

  1932.         ngx_rbtree_delete(&r->srv_rbtree, &rn->node);

  1933.         while (next) {
  1934.             ctx = next;
  1935.             ctx->state = code;
  1936.             ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
  1937.             next = ctx->next;

  1938.             ctx->handler(ctx);
  1939.         }

  1940.         ngx_resolver_free_node(r, rn);

  1941.         return;
  1942.     }

  1943.     i = ans;
  1944.     nsrvs = 0;
  1945.     cname = NULL;

  1946.     for (a = 0; a < nan; a++) {

  1947.         start = i;

  1948.         while (i < n) {

  1949.             if (buf[i] & 0xc0) {
  1950.                 i += 2;
  1951.                 goto found;
  1952.             }

  1953.             if (buf[i] == 0) {
  1954.                 i++;
  1955.                 goto test_length;
  1956.             }

  1957.             i += 1 + buf[i];
  1958.         }

  1959.         goto short_response;

  1960.     test_length:

  1961.         if (i - start < 2) {
  1962.             err = "invalid name DNS response";
  1963.             goto invalid;
  1964.         }

  1965.     found:

  1966.         if (i + sizeof(ngx_resolver_an_t) >= n) {
  1967.             goto short_response;
  1968.         }

  1969.         an = (ngx_resolver_an_t *) &buf[i];

  1970.         type = (an->type_hi << 8) + an->type_lo;
  1971.         class = (an->class_hi << 8) + an->class_lo;
  1972.         len = (an->len_hi << 8) + an->len_lo;
  1973.         ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
  1974.             + (an->ttl[2] << 8) + (an->ttl[3]);

  1975.         if (class != 1) {
  1976.             ngx_log_error(r->log_level, r->log, 0,
  1977.                           "unexpected RR class %ui in DNS response", class);
  1978.             goto failed;
  1979.         }

  1980.         if (ttl < 0) {
  1981.             ttl = 0;
  1982.         }

  1983.         rn->ttl = ngx_min(rn->ttl, (uint32_t) ttl);

  1984.         i += sizeof(ngx_resolver_an_t);

  1985.         switch (type) {

  1986.         case NGX_RESOLVE_SRV:

  1987.             if (i + 6 > n) {
  1988.                 goto short_response;
  1989.             }

  1990.             if (ngx_resolver_copy(r, NULL, buf, &buf[i + 6], buf + n)
  1991.                 != NGX_OK)
  1992.             {
  1993.                 goto failed;
  1994.             }

  1995.             nsrvs++;

  1996.             break;

  1997.         case NGX_RESOLVE_CNAME:

  1998.             cname = &buf[i];

  1999.             break;

  2000.         case NGX_RESOLVE_DNAME:

  2001.             break;

  2002.         default:

  2003.             ngx_log_error(r->log_level, r->log, 0,
  2004.                           "unexpected RR type %ui in DNS response", type);
  2005.         }

  2006.         i += len;
  2007.     }

  2008.     ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
  2009.                    "resolver nsrvs:%ui cname:%p ttl:%uD",
  2010.                    nsrvs, cname, rn->ttl);

  2011.     if (nsrvs) {

  2012.         srvs = ngx_resolver_calloc(r, nsrvs * sizeof(ngx_resolver_srv_t));
  2013.         if (srvs == NULL) {
  2014.             goto failed;
  2015.         }

  2016.         rn->u.srvs = srvs;
  2017.         rn->nsrvs = (u_short) nsrvs;

  2018.         j = 0;
  2019.         i = ans;

  2020.         for (a = 0; a < nan; a++) {

  2021.             for ( ;; ) {

  2022.                 if (buf[i] & 0xc0) {
  2023.                     i += 2;
  2024.                     break;
  2025.                 }

  2026.                 if (buf[i] == 0) {
  2027.                     i++;
  2028.                     break;
  2029.                 }

  2030.                 i += 1 + buf[i];
  2031.             }

  2032.             an = (ngx_resolver_an_t *) &buf[i];

  2033.             type = (an->type_hi << 8) + an->type_lo;
  2034.             len = (an->len_hi << 8) + an->len_lo;

  2035.             i += sizeof(ngx_resolver_an_t);

  2036.             if (type == NGX_RESOLVE_SRV) {

  2037.                 srvs[j].priority = (buf[i] << 8) + buf[i + 1];
  2038.                 srvs[j].weight = (buf[i + 2] << 8) + buf[i + 3];

  2039.                 if (srvs[j].weight == 0) {
  2040.                     srvs[j].weight = 1;
  2041.                 }

  2042.                 srvs[j].port = (buf[i + 4] << 8) + buf[i + 5];

  2043.                 if (ngx_resolver_copy(r, &srvs[j].name, buf, &buf[i + 6],
  2044.                                       buf + n)
  2045.                     != NGX_OK)
  2046.                 {
  2047.                     goto failed;
  2048.                 }

  2049.                 j++;
  2050.             }

  2051.             i += len;
  2052.         }

  2053.         ngx_sort(srvs, nsrvs, sizeof(ngx_resolver_srv_t),
  2054.                  ngx_resolver_cmp_srvs);

  2055.         ngx_resolver_free(r, rn->query);
  2056.         rn->query = NULL;

  2057.         ngx_queue_remove(&rn->queue);

  2058.         rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
  2059.         rn->expire = ngx_time() + r->expire;

  2060.         ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue);

  2061.         next = rn->waiting;
  2062.         rn->waiting = NULL;

  2063.         while (next) {
  2064.             ctx = next;
  2065.             next = ctx->next;

  2066.             ngx_resolver_resolve_srv_names(ctx, rn);
  2067.         }

  2068.         return;
  2069.     }

  2070.     rn->nsrvs = 0;

  2071.     if (cname) {

  2072.         /* CNAME only */

  2073.         if (ngx_resolver_copy(r, &name, buf, cname, buf + n) != NGX_OK) {
  2074.             goto failed;
  2075.         }

  2076.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
  2077.                        "resolver cname:\"%V\"", &name);

  2078.         ngx_queue_remove(&rn->queue);

  2079.         rn->cnlen = (u_short) name.len;
  2080.         rn->u.cname = name.data;

  2081.         rn->valid = ngx_time() + (r->valid ? r->valid : (time_t) rn->ttl);
  2082.         rn->expire = ngx_time() + r->expire;

  2083.         ngx_queue_insert_head(&r->srv_expire_queue, &rn->queue);

  2084.         ngx_resolver_free(r, rn->query);
  2085.         rn->query = NULL;
  2086. #if (NGX_HAVE_INET6)
  2087.         rn->query6 = NULL;
  2088. #endif

  2089.         ctx = rn->waiting;
  2090.         rn->waiting = NULL;

  2091.         if (ctx) {

  2092.             if (ctx->recursion++ >= NGX_RESOLVER_MAX_RECURSION) {

  2093.                 /* unlock name mutex */

  2094.                 do {
  2095.                     ctx->state = NGX_RESOLVE_NXDOMAIN;
  2096.                     next = ctx->next;

  2097.                     ctx->handler(ctx);

  2098.                     ctx = next;
  2099.                 } while (ctx);

  2100.                 return;
  2101.             }

  2102.             for (next = ctx; next; next = next->next) {
  2103.                 next->node = NULL;
  2104.             }

  2105.             (void) ngx_resolve_name_locked(r, ctx, &name);
  2106.         }

  2107.         /* unlock name mutex */

  2108.         return;
  2109.     }

  2110.     ngx_log_error(r->log_level, r->log, 0, "no SRV type in DNS response");

  2111.     return;

  2112. short_response:

  2113.     err = "short DNS response";

  2114. invalid:

  2115.     /* unlock name mutex */

  2116.     ngx_log_error(r->log_level, r->log, 0, err);

  2117.     return;

  2118. failed:

  2119.     /* unlock name mutex */

  2120.     return;
  2121. }


  2122. static void
  2123. ngx_resolver_resolve_srv_names(ngx_resolver_ctx_t *ctx, ngx_resolver_node_t *rn)
  2124. {
  2125.     ngx_uint_t                i;
  2126.     ngx_resolver_t           *r;
  2127.     ngx_resolver_ctx_t       *cctx;
  2128.     ngx_resolver_srv_name_t  *srvs;

  2129.     r = ctx->resolver;

  2130.     ctx->node = NULL;
  2131.     ctx->state = NGX_OK;
  2132.     ctx->valid = rn->valid;
  2133.     ctx->count = rn->nsrvs;

  2134.     srvs = ngx_resolver_calloc(r, rn->nsrvs * sizeof(ngx_resolver_srv_name_t));
  2135.     if (srvs == NULL) {
  2136.         goto failed;
  2137.     }

  2138.     ctx->srvs = srvs;
  2139.     ctx->nsrvs = rn->nsrvs;

  2140.     if (ctx->event && ctx->event->timer_set) {
  2141.         ngx_del_timer(ctx->event);
  2142.     }

  2143.     for (i = 0; i < (ngx_uint_t) rn->nsrvs; i++) {
  2144.         srvs[i].name.data = ngx_resolver_alloc(r, rn->u.srvs[i].name.len);
  2145.         if (srvs[i].name.data == NULL) {
  2146.             goto failed;
  2147.         }

  2148.         srvs[i].name.len = rn->u.srvs[i].name.len;
  2149.         ngx_memcpy(srvs[i].name.data, rn->u.srvs[i].name.data,
  2150.                    srvs[i].name.len);

  2151.         cctx = ngx_resolve_start(r, NULL);
  2152.         if (cctx == NULL) {
  2153.             goto failed;
  2154.         }

  2155.         cctx->name = srvs[i].name;
  2156.         cctx->handler = ngx_resolver_srv_names_handler;
  2157.         cctx->data = ctx;
  2158.         cctx->srvs = &srvs[i];
  2159.         cctx->timeout = ctx->timeout;

  2160.         srvs[i].priority = rn->u.srvs[i].priority;
  2161.         srvs[i].weight = rn->u.srvs[i].weight;
  2162.         srvs[i].port = rn->u.srvs[i].port;
  2163.         srvs[i].ctx = cctx;

  2164.         if (ngx_resolve_name(cctx) == NGX_ERROR) {
  2165.             srvs[i].ctx = NULL;
  2166.             goto failed;
  2167.         }
  2168.     }

  2169.     return;

  2170. failed:

  2171.     ctx->state = NGX_ERROR;
  2172.     ctx->valid = ngx_time() + (r->valid ? r->valid : 10);

  2173.     ctx->handler(ctx);
  2174. }


  2175. static void
  2176. ngx_resolver_srv_names_handler(ngx_resolver_ctx_t *cctx)
  2177. {
  2178.     ngx_uint_t                i;
  2179.     ngx_addr_t               *addrs;
  2180.     ngx_resolver_t           *r;
  2181.     ngx_sockaddr_t           *sockaddr;
  2182.     ngx_resolver_ctx_t       *ctx;
  2183.     ngx_resolver_srv_name_t  *srv;

  2184.     r = cctx->resolver;
  2185.     ctx = cctx->data;
  2186.     srv = cctx->srvs;

  2187.     ctx->count--;
  2188.     ctx->async |= cctx->async;

  2189.     srv->ctx = NULL;
  2190.     srv->state = cctx->state;

  2191.     if (cctx->naddrs) {

  2192.         ctx->valid = ngx_min(ctx->valid, cctx->valid);

  2193.         addrs = ngx_resolver_calloc(r, cctx->naddrs * sizeof(ngx_addr_t));
  2194.         if (addrs == NULL) {
  2195.             srv->state = NGX_ERROR;
  2196.             goto done;
  2197.         }

  2198.         sockaddr = ngx_resolver_alloc(r, cctx->naddrs * sizeof(ngx_sockaddr_t));
  2199.         if (sockaddr == NULL) {
  2200.             ngx_resolver_free(r, addrs);
  2201.             srv->state = NGX_ERROR;
  2202.             goto done;
  2203.         }

  2204.         for (i = 0; i < cctx->naddrs; i++) {
  2205.             addrs[i].sockaddr = &sockaddr[i].sockaddr;
  2206.             addrs[i].socklen = cctx->addrs[i].socklen;

  2207.             ngx_memcpy(&sockaddr[i], cctx->addrs[i].sockaddr,
  2208.                        addrs[i].socklen);

  2209.             ngx_inet_set_port(addrs[i].sockaddr, srv->port);
  2210.         }

  2211.         srv->addrs = addrs;
  2212.         srv->naddrs = cctx->naddrs;
  2213.     }

  2214. done:

  2215.     ngx_resolve_name_done(cctx);

  2216.     if (ctx->count == 0) {
  2217.         ngx_resolver_report_srv(r, ctx);
  2218.     }
  2219. }


  2220. static void
  2221. ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
  2222.     ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)
  2223. {
  2224.     char                 *err;
  2225.     size_t                len;
  2226.     in_addr_t             addr;
  2227.     int32_t               ttl;
  2228.     ngx_int_t             octet;
  2229.     ngx_str_t             name;
  2230.     ngx_uint_t            mask, type, class, qident, a, i, start;
  2231.     ngx_queue_t          *expire_queue;
  2232.     ngx_rbtree_t         *tree;
  2233.     ngx_resolver_an_t    *an;
  2234.     ngx_resolver_ctx_t   *ctx, *next;
  2235.     ngx_resolver_node_t  *rn;
  2236. #if (NGX_HAVE_INET6)
  2237.     uint32_t              hash;
  2238.     ngx_int_t             digit;
  2239.     struct in6_addr       addr6;
  2240. #endif

  2241.     if (ngx_resolver_copy(r, &name, buf,
  2242.                           buf + sizeof(ngx_resolver_hdr_t), buf + n)
  2243.         != NGX_OK)
  2244.     {
  2245.         return;
  2246.     }

  2247.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver qs:%V", &name);

  2248.     /* AF_INET */

  2249.     addr = 0;
  2250.     i = sizeof(ngx_resolver_hdr_t);

  2251.     for (mask = 0; mask < 32; mask += 8) {
  2252.         len = buf[i++];

  2253.         octet = ngx_atoi(&buf[i], len);
  2254.         if (octet == NGX_ERROR || octet > 255) {
  2255.             goto invalid_in_addr_arpa;
  2256.         }

  2257.         addr += octet << mask;
  2258.         i += len;
  2259.     }

  2260.     if (ngx_strcasecmp(&buf[i], (u_char *) "\7in-addr\4arpa") == 0) {
  2261.         i += sizeof("\7in-addr\4arpa");

  2262.         /* lock addr mutex */

  2263.         rn = ngx_resolver_lookup_addr(r, addr);

  2264.         tree = &r->addr_rbtree;
  2265.         expire_queue = &r->addr_expire_queue;

  2266.         goto valid;
  2267.     }

  2268. invalid_in_addr_arpa:

  2269. #if (NGX_HAVE_INET6)

  2270.     i = sizeof(ngx_resolver_hdr_t);

  2271.     for (octet = 15; octet >= 0; octet--) {
  2272.         if (buf[i++] != '\1') {
  2273.             goto invalid_ip6_arpa;
  2274.         }

  2275.         digit = ngx_hextoi(&buf[i++], 1);
  2276.         if (digit == NGX_ERROR) {
  2277.             goto invalid_ip6_arpa;
  2278.         }

  2279.         addr6.s6_addr[octet] = (u_char) digit;

  2280.         if (buf[i++] != '\1') {
  2281.             goto invalid_ip6_arpa;
  2282.         }

  2283.         digit = ngx_hextoi(&buf[i++], 1);
  2284.         if (digit == NGX_ERROR) {
  2285.             goto invalid_ip6_arpa;
  2286.         }

  2287.         addr6.s6_addr[octet] += (u_char) (digit * 16);
  2288.     }

  2289.     if (ngx_strcasecmp(&buf[i], (u_char *) "\3ip6\4arpa") == 0) {
  2290.         i += sizeof("\3ip6\4arpa");

  2291.         /* lock addr mutex */

  2292.         hash = ngx_crc32_short(addr6.s6_addr, 16);
  2293.         rn = ngx_resolver_lookup_addr6(r, &addr6, hash);

  2294.         tree = &r->addr6_rbtree;
  2295.         expire_queue = &r->addr6_expire_queue;

  2296.         goto valid;
  2297.     }

  2298. invalid_ip6_arpa:
  2299. #endif

  2300.     ngx_log_error(r->log_level, r->log, 0,
  2301.                   "invalid in-addr.arpa or ip6.arpa name in DNS response");
  2302.     ngx_resolver_free(r, name.data);
  2303.     return;

  2304. valid:

  2305.     if (rn == NULL || rn->query == NULL) {
  2306.         ngx_log_error(r->log_level, r->log, 0,
  2307.                       "unexpected DNS response for %V", &name);
  2308.         ngx_resolver_free(r, name.data);
  2309.         goto failed;
  2310.     }

  2311.     qident = (rn->query[0] << 8) + rn->query[1];

  2312.     if (ident != qident) {
  2313.         ngx_log_error(r->log_level, r->log, 0,
  2314.                       "wrong ident %ui in DNS response for %V, expect %ui",
  2315.                       ident, &name, qident);
  2316.         ngx_resolver_free(r, name.data);
  2317.         goto failed;
  2318.     }

  2319.     ngx_resolver_free(r, name.data);

  2320.     if (code == 0 && nan == 0) {
  2321.         code = NGX_RESOLVE_NXDOMAIN;
  2322.     }

  2323.     if (code) {
  2324.         next = rn->waiting;
  2325.         rn->waiting = NULL;

  2326.         ngx_queue_remove(&rn->queue);

  2327.         ngx_rbtree_delete(tree, &rn->node);

  2328.         /* unlock addr mutex */

  2329.         while (next) {
  2330.             ctx = next;
  2331.             ctx->state = code;
  2332.             ctx->valid = ngx_time() + (r->valid ? r->valid : 10);
  2333.             next = ctx->next;

  2334.             ctx->handler(ctx);
  2335.         }

  2336.         ngx_resolver_free_node(r, rn);

  2337.         return;
  2338.     }

  2339.     i += sizeof(ngx_resolver_qs_t);

  2340.     for (a = 0; a < nan; a++) {

  2341.         start = i;

  2342.         while (i < n) {

  2343.             if (buf[i] & 0xc0) {
  2344.                 i += 2;
  2345.                 goto found;
  2346.             }

  2347.             if (buf[i] == 0) {
  2348.                 i++;
  2349.                 goto test_length;
  2350.             }

  2351.             i += 1 + buf[i];
  2352.         }

  2353.         goto short_response;

  2354.     test_length:

  2355.         if (i - start < 2) {
  2356.             err = "invalid name in DNS response";
  2357.             goto invalid;
  2358.         }

  2359.     found:

  2360.         if (i + sizeof(ngx_resolver_an_t) >= n) {
  2361.             goto short_response;
  2362.         }

  2363.         an = (ngx_resolver_an_t *) &buf[i];

  2364.         type = (an->type_hi << 8) + an->type_lo;
  2365.         class = (an->class_hi << 8) + an->class_lo;
  2366.         len = (an->len_hi << 8) + an->len_lo;
  2367.         ttl = (an->ttl[0] << 24) + (an->ttl[1] << 16)
  2368.             + (an->ttl[2] << 8) + (an->ttl[3]);

  2369.         if (class != 1) {
  2370.             ngx_log_error(r->log_level, r->log, 0,
  2371.                           "unexpected RR class %ui in DNS response", class);
  2372.             goto failed;
  2373.         }

  2374.         if (ttl < 0) {
  2375.             ttl = 0;
  2376.         }

  2377.         ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
  2378.                       "resolver qt:%ui cl:%ui len:%uz",
  2379.                       type, class, len);

  2380.         i += sizeof(ngx_resolver_an_t);

  2381.         switch (type) {

  2382.         case NGX_RESOLVE_PTR:

  2383.             goto ptr;

  2384.         case NGX_RESOLVE_CNAME:

  2385.             break;

  2386.         default:

  2387.             ngx_log_error(r->log_level, r->log, 0,
  2388.                           "unexpected RR type %ui in DNS response", type);
  2389.         }

  2390.         i += len;
  2391.     }

  2392.     /* unlock addr mutex */

  2393.     ngx_log_error(r->log_level, r->log, 0,
  2394.                   "no PTR type in DNS response");
  2395.     return;

  2396. ptr:

  2397.     if (ngx_resolver_copy(r, &name, buf, buf + i, buf + n) != NGX_OK) {
  2398.         goto failed;
  2399.     }

  2400.     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name);

  2401.     if (name.len != (size_t) rn->nlen
  2402.         || ngx_strncmp(name.data, rn->name, name.len) != 0)
  2403.     {
  2404.         if (rn->nlen) {
  2405.             ngx_resolver_free(r, rn->name);
  2406.         }

  2407.         rn->nlen = (u_short) name.len;
  2408.         rn->name = name.data;

  2409.         name.data = ngx_resolver_dup(r, rn->name, name.len);
  2410.         if (name.data == NULL) {
  2411.             goto failed;
  2412.         }
  2413.     }

  2414.     ngx_queue_remove(&rn->queue);

  2415.     rn->valid = ngx_time() + (r->valid ? r->valid : ttl);
  2416.     rn->expire = ngx_time() + r->expire;

  2417.     ngx_queue_insert_head(expire_queue, &rn->queue);

  2418.     next = rn->waiting;
  2419.     rn->waiting = NULL;

  2420.     /* unlock addr mutex */

  2421.     while (next) {
  2422.         ctx = next;
  2423.         ctx->state = NGX_OK;
  2424.         ctx->valid = rn->valid;
  2425.         ctx->name = name;
  2426.         next = ctx->next;

  2427.         ctx->handler(ctx);
  2428.     }

  2429.     ngx_resolver_free(r, name.data);

  2430.     return;

  2431. short_response:

  2432.     err = "short DNS response";

  2433. invalid:

  2434.     /* unlock addr mutex */

  2435.     ngx_log_error(r->log_level, r->log, 0, err);

  2436.     return;

  2437. failed:

  2438.     /* unlock addr mutex */

  2439.     return;
  2440. }


  2441. static ngx_resolver_node_t *
  2442. ngx_resolver_lookup_name(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
  2443. {
  2444.     ngx_int_t             rc;
  2445.     ngx_rbtree_node_t    *node, *sentinel;
  2446.     ngx_resolver_node_t  *rn;

  2447.     node = r->name_rbtree.root;
  2448.     sentinel = r->name_rbtree.sentinel;

  2449.     while (node != sentinel) {

  2450.         if (hash < node->key) {
  2451.             node = node->left;
  2452.             continue;
  2453.         }

  2454.         if (hash > node->key) {
  2455.             node = node->right;
  2456.             continue;
  2457.         }

  2458.         /* hash == node->key */

  2459.         rn = ngx_resolver_node(node);

  2460.         rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);

  2461.         if (rc == 0) {
  2462.             return rn;
  2463.         }

  2464.         node = (rc < 0) ? node->left : node->right;
  2465.     }

  2466.     /* not found */

  2467.     return NULL;
  2468. }


  2469. static ngx_resolver_node_t *
  2470. ngx_resolver_lookup_srv(ngx_resolver_t *r, ngx_str_t *name, uint32_t hash)
  2471. {
  2472.     ngx_int_t             rc;
  2473.     ngx_rbtree_node_t    *node, *sentinel;
  2474.     ngx_resolver_node_t  *rn;

  2475.     node = r->srv_rbtree.root;
  2476.     sentinel = r->srv_rbtree.sentinel;

  2477.     while (node != sentinel) {

  2478.         if (hash < node->key) {
  2479.             node = node->left;
  2480.             continue;
  2481.         }

  2482.         if (hash > node->key) {
  2483.             node = node->right;
  2484.             continue;
  2485.         }

  2486.         /* hash == node->key */

  2487.         rn = ngx_resolver_node(node);

  2488.         rc = ngx_memn2cmp(name->data, rn->name, name->len, rn->nlen);

  2489.         if (rc == 0) {
  2490.             return rn;
  2491.         }

  2492.         node = (rc < 0) ? node->left : node->right;
  2493.     }

  2494.     /* not found */

  2495.     return NULL;
  2496. }


  2497. static ngx_resolver_node_t *
  2498. ngx_resolver_lookup_addr(ngx_resolver_t *r, in_addr_t addr)
  2499. {
  2500.     ngx_rbtree_node_t  *node, *sentinel;

  2501.     node = r->addr_rbtree.root;
  2502.     sentinel = r->addr_rbtree.sentinel;

  2503.     while (node != sentinel) {

  2504.         if (addr < node->key) {
  2505.             node = node->left;
  2506.             continue;
  2507.         }

  2508.         if (addr > node->key) {
  2509.             node = node->right;
  2510.             continue;
  2511.         }

  2512.         /* addr == node->key */

  2513.         return ngx_resolver_node(node);
  2514.     }

  2515.     /* not found */

  2516.     return NULL;
  2517. }


  2518. #if (NGX_HAVE_INET6)

  2519. static ngx_resolver_node_t *
  2520. ngx_resolver_lookup_addr6(ngx_resolver_t *r, struct in6_addr *addr,
  2521.     uint32_t hash)
  2522. {
  2523.     ngx_int_t             rc;
  2524.     ngx_rbtree_node_t    *node, *sentinel;
  2525.     ngx_resolver_node_t  *rn;

  2526.     node = r->addr6_rbtree.root;
  2527.     sentinel = r->addr6_rbtree.sentinel;

  2528.     while (node != sentinel) {

  2529.         if (hash < node->key) {
  2530.             node = node->left;
  2531.             continue;
  2532.         }

  2533.         if (hash > node->key) {
  2534.             node = node->right;
  2535.             continue;
  2536.         }

  2537.         /* hash == node->key */

  2538.         rn = ngx_resolver_node(node);

  2539.         rc = ngx_memcmp(addr, &rn->addr6, 16);

  2540.         if (rc == 0) {
  2541.             return rn;
  2542.         }

  2543.         node = (rc < 0) ? node->left : node->right;
  2544.     }

  2545.     /* not found */

  2546.     return NULL;
  2547. }

  2548. #endif


  2549. static void
  2550. ngx_resolver_rbtree_insert_value(ngx_rbtree_node_t *temp,
  2551.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
  2552. {
  2553.     ngx_rbtree_node_t    **p;
  2554.     ngx_resolver_node_t   *rn, *rn_temp;

  2555.     for ( ;; ) {

  2556.         if (node->key < temp->key) {

  2557.             p = &temp->left;

  2558.         } else if (node->key > temp->key) {

  2559.             p = &temp->right;

  2560.         } else { /* node->key == temp->key */

  2561.             rn = ngx_resolver_node(node);
  2562.             rn_temp = ngx_resolver_node(temp);

  2563.             p = (ngx_memn2cmp(rn->name, rn_temp->name, rn->nlen, rn_temp->nlen)
  2564.                  < 0) ? &temp->left : &temp->right;
  2565.         }

  2566.         if (*p == sentinel) {
  2567.             break;
  2568.         }

  2569.         temp = *p;
  2570.     }

  2571.     *p = node;
  2572.     node->parent = temp;
  2573.     node->left = sentinel;
  2574.     node->right = sentinel;
  2575.     ngx_rbt_red(node);
  2576. }


  2577. #if (NGX_HAVE_INET6)

  2578. static void
  2579. ngx_resolver_rbtree_insert_addr6_value(ngx_rbtree_node_t *temp,
  2580.     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
  2581. {
  2582.     ngx_rbtree_node_t    **p;
  2583.     ngx_resolver_node_t   *rn, *rn_temp;

  2584.     for ( ;; ) {

  2585.         if (node->key < temp->key) {

  2586.             p = &temp->left;

  2587.         } else if (node->key > temp->key) {

  2588.             p = &temp->right;

  2589.         } else { /* node->key == temp->key */

  2590.             rn = ngx_resolver_node(node);
  2591.             rn_temp = ngx_resolver_node(temp);

  2592.             p = (ngx_memcmp(&rn->addr6, &rn_temp->addr6, 16)
  2593.                  < 0) ? &temp->left : &temp->right;
  2594.         }

  2595.         if (*p == sentinel) {
  2596.             break;
  2597.         }

  2598.         temp = *p;
  2599.     }

  2600.     *p = node;
  2601.     node->parent = temp;
  2602.     node->left = sentinel;
  2603.     node->right = sentinel;
  2604.     ngx_rbt_red(node);
  2605. }

  2606. #endif


  2607. static ngx_int_t
  2608. ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
  2609.     ngx_str_t *name)
  2610. {
  2611.     u_char              *p, *s;
  2612.     size_t               len, nlen;
  2613.     ngx_uint_t           ident;
  2614.     ngx_resolver_qs_t   *qs;
  2615.     ngx_resolver_hdr_t  *query;

  2616.     nlen = name->len ? (1 + name->len + 1) : 1;

  2617.     len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);

  2618. #if (NGX_HAVE_INET6)
  2619.     p = ngx_resolver_alloc(r, len * (r->ipv4 + r->ipv6));
  2620. #else
  2621.     p = ngx_resolver_alloc(r, len);
  2622. #endif
  2623.     if (p == NULL) {
  2624.         return NGX_ERROR;
  2625.     }

  2626.     rn->qlen = (u_short) len;
  2627.     rn->query = p;

  2628. #if (NGX_HAVE_INET6)
  2629.     if (r->ipv6) {
  2630.         rn->query6 = r->ipv4 ? (p + len) : p;
  2631.     }
  2632. #endif

  2633.     query = (ngx_resolver_hdr_t *) p;

  2634.     if (r->ipv4) {
  2635.         ident = ngx_random();

  2636.         ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
  2637.                        "resolve: \"%V\" A %i", name, ident & 0xffff);

  2638.         query->ident_hi = (u_char) ((ident >> 8) & 0xff);
  2639.         query->ident_lo = (u_char) (ident & 0xff);
  2640.     }

  2641.     /* recursion query */
  2642.     query->flags_hi = 1; query->flags_lo = 0;

  2643.     /* one question */
  2644.     query->nqs_hi = 0; query->nqs_lo = 1;
  2645.     query->nan_hi = 0; query->nan_lo = 0;
  2646.     query->nns_hi = 0; query->nns_lo = 0;
  2647.     query->nar_hi = 0; query->nar_lo = 0;

  2648.     p += sizeof(ngx_resolver_hdr_t) + nlen;

  2649.     qs = (ngx_resolver_qs_t *) p;

  2650.     /* query type */
  2651.     qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_A;

  2652.     /* IN query class */
  2653.     qs->class_hi = 0; qs->class_lo = 1;

  2654.     /* convert "www.example.com" to "\3www\7example\3com\0" */

  2655.     len = 0;
  2656.     p--;
  2657.     *p-- = '\0';

  2658.     if (name->len == 0)  {
  2659.         return NGX_DECLINED;
  2660.     }

  2661.     for (s = name->data + name->len - 1; s >= name->data; s--) {
  2662.         if (*s != '.') {
  2663.             *p = *s;
  2664.             len++;

  2665.         } else {
  2666.             if (len == 0 || len > 255) {
  2667.                 return NGX_DECLINED;
  2668.             }

  2669.             *p = (u_char) len;
  2670.             len = 0;
  2671.         }

  2672.         p--;
  2673.     }

  2674.     if (len == 0 || len > 255) {
  2675.         return NGX_DECLINED;
  2676.     }

  2677.     *p = (u_char) len;

  2678. #if (NGX_HAVE_INET6)
  2679.     if (!r->ipv6) {
  2680.         return NGX_OK;
  2681.     }

  2682.     p = rn->query6;

  2683.     if (r->ipv4) {
  2684.         ngx_memcpy(p, rn->query, rn->qlen);
  2685.     }

  2686.     query = (ngx_resolver_hdr_t *) p;

  2687.     ident = ngx_random();

  2688.     ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
  2689.                    "resolve: \"%V\" AAAA %i", name, ident & 0xffff);

  2690.     query->ident_hi = (u_char) ((ident >> 8) & 0xff);
  2691.     query->ident_lo = (u_char) (ident & 0xff);

  2692.     p += sizeof(ngx_resolver_hdr_t) + nlen;

  2693.     qs = (ngx_resolver_qs_t *) p;

  2694.     qs->type_lo = NGX_RESOLVE_AAAA;
  2695. #endif

  2696.     return NGX_OK;
  2697. }


  2698. static ngx_int_t
  2699. ngx_resolver_create_srv_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
  2700.     ngx_str_t *name)
  2701. {
  2702.     u_char              *p, *s;
  2703.     size_t               len, nlen;
  2704.     ngx_uint_t           ident;
  2705.     ngx_resolver_qs_t   *qs;
  2706.     ngx_resolver_hdr_t  *query;

  2707.     nlen = name->len ? (1 + name->len + 1) : 1;

  2708.     len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t);

  2709.     p = ngx_resolver_alloc(r, len);
  2710.     if (p == NULL) {
  2711.         return NGX_ERROR;
  2712.     }

  2713.     rn->qlen = (u_short) len;
  2714.     rn->query = p;

  2715.     query = (ngx_resolver_hdr_t *) p;

  2716.     ident = ngx_random();

  2717.     ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
  2718.                    "resolve: \"%V\" SRV %i", name, ident & 0xffff);

  2719.     query->ident_hi = (u_char) ((ident >> 8) & 0xff);
  2720.     query->ident_lo = (u_char) (ident & 0xff);

  2721.     /* recursion query */
  2722.     query->flags_hi = 1; query->flags_lo = 0;

  2723.     /* one question */
  2724.     query->nqs_hi = 0; query->nqs_lo = 1;
  2725.     query->nan_hi = 0; query->nan_lo = 0;
  2726.     query->nns_hi = 0; query->nns_lo = 0;
  2727.     query->nar_hi = 0; query->nar_lo = 0;

  2728.     p += sizeof(ngx_resolver_hdr_t) + nlen;

  2729.     qs = (ngx_resolver_qs_t *) p;

  2730.     /* query type */
  2731.     qs->type_hi = 0; qs->type_lo = NGX_RESOLVE_SRV;

  2732.     /* IN query class */
  2733.     qs->class_hi = 0; qs->class_lo = 1;

  2734.     /* converts "www.example.com" to "\3www\7example\3com\0" */

  2735.     len = 0;
  2736.     p--;
  2737.     *p-- = '\0';

  2738.     if (name->len == 0)  {
  2739.         return NGX_DECLINED;
  2740.     }

  2741.     for (s = name->data + name->len - 1; s >= name->data; s--) {
  2742.         if (*s != '.') {
  2743.             *p = *s;
  2744.             len++;

  2745.         } else {
  2746.             if (len == 0 || len > 255) {
  2747.                 return NGX_DECLINED;
  2748.             }

  2749.             *p = (u_char) len;
  2750.             len = 0;
  2751.         }

  2752.         p--;
  2753.     }

  2754.     if (len == 0 || len > 255) {
  2755.         return NGX_DECLINED;
  2756.     }

  2757.     *p = (u_char) len;

  2758.     return NGX_OK;
  2759. }


  2760. static ngx_int_t
  2761. ngx_resolver_create_addr_query(ngx_resolver_t *r, ngx_resolver_node_t *rn,
  2762.     ngx_resolver_addr_t *addr)
  2763. {
  2764.     u_char               *p, *d;
  2765.     size_t                len;
  2766.     in_addr_t             inaddr;
  2767.     ngx_int_t             n;
  2768.     ngx_uint_t            ident;
  2769.     ngx_resolver_hdr_t   *query;
  2770.     struct sockaddr_in   *sin;
  2771. #if (NGX_HAVE_INET6)
  2772.     struct sockaddr_in6  *sin6;
  2773. #endif

  2774.     switch (addr->sockaddr->sa_family) {

  2775. #if (NGX_HAVE_INET6)
  2776.     case AF_INET6:
  2777.         len = sizeof(ngx_resolver_hdr_t)
  2778.               + 64 + sizeof(".ip6.arpa.") - 1
  2779.               + sizeof(ngx_resolver_qs_t);

  2780.         break;
  2781. #endif

  2782.     default: /* AF_INET */
  2783.         len = sizeof(ngx_resolver_hdr_t)
  2784.               + sizeof(".255.255.255.255.in-addr.arpa.") - 1
  2785.               + sizeof(ngx_resolver_qs_t);
  2786.     }

  2787.     p = ngx_resolver_alloc(r, len);
  2788.     if (p == NULL) {
  2789.         return NGX_ERROR;
  2790.     }

  2791.     rn->query = p;
  2792.     query = (ngx_resolver_hdr_t *) p;

  2793.     ident = ngx_random();

  2794.     query->ident_hi = (u_char) ((ident >> 8) & 0xff);
  2795.     query->ident_lo = (u_char) (ident & 0xff);

  2796.     /* recursion query */
  2797.     query->flags_hi = 1; query->flags_lo = 0;

  2798.     /* one question */
  2799.     query->nqs_hi = 0; query->nqs_lo = 1;
  2800.     query->nan_hi = 0; query->nan_lo = 0;
  2801.     query->nns_hi = 0; query->nns_lo = 0;
  2802.     query->nar_hi = 0; query->nar_lo = 0;

  2803.     p += sizeof(ngx_resolver_hdr_t);

  2804.     switch (addr->sockaddr->sa_family) {

  2805. #if (NGX_HAVE_INET6)
  2806.     case AF_INET6:
  2807.         sin6 = (struct sockaddr_in6 *) addr->sockaddr;

  2808.         for (n = 15; n >= 0; n--) {
  2809.             p = ngx_sprintf(p, "\1%xd\1%xd",
  2810.                             sin6->sin6_addr.s6_addr[n] & 0xf,
  2811.                             (sin6->sin6_addr.s6_addr[n] >> 4) & 0xf);
  2812.         }

  2813.         p = ngx_cpymem(p, "\3ip6\4arpa\0", 10);

  2814.         break;
  2815. #endif

  2816.     default: /* AF_INET */

  2817.         sin = (struct sockaddr_in *) addr->sockaddr;
  2818.         inaddr = ntohl(sin->sin_addr.s_addr);

  2819.         for (n = 0; n < 32; n += 8) {
  2820.             d = ngx_sprintf(&p[1], "%ud", (inaddr >> n) & 0xff);
  2821.             *p = (u_char) (d - &p[1]);
  2822.             p = d;
  2823.         }

  2824.         p = ngx_cpymem(p, "\7in-addr\4arpa\0", 14);
  2825.     }

  2826.     /* query type "PTR", IN query class */
  2827.     p = ngx_cpymem(p, "\0\14\0\1", 4);

  2828.     rn->qlen = (u_short) (p - rn->query);

  2829.     return NGX_OK;
  2830. }


  2831. static ngx_int_t
  2832. ngx_resolver_copy(ngx_resolver_t *r, ngx_str_t *name, u_char *buf, u_char *src,
  2833.     u_char *last)
  2834. {
  2835.     char        *err;
  2836.     u_char      *p, *dst;
  2837.     size_t       len;
  2838.     ngx_uint_t   i, n;

  2839.     p = src;
  2840.     len = 0;

  2841.     /*
  2842.      * compression pointers allow to create endless loop, so we set limit;
  2843.      * 128 pointers should be enough to store 255-byte name
  2844.      */

  2845.     for (i = 0; i < 128; i++) {
  2846.         n = *p++;

  2847.         if (n == 0) {
  2848.             goto done;
  2849.         }

  2850.         if (n & 0xc0) {
  2851.             if ((n & 0xc0) != 0xc0) {
  2852.                 err = "invalid label type in DNS response";
  2853.                 goto invalid;
  2854.             }

  2855.             if (p >= last) {
  2856.                 err = "name is out of DNS response";
  2857.                 goto invalid;
  2858.             }

  2859.             n = ((n & 0x3f) << 8) + *p;
  2860.             p = &buf[n];

  2861.         } else {
  2862.             len += 1 + n;
  2863.             p = &p[n];
  2864.         }

  2865.         if (p >= last) {
  2866.             err = "name is out of DNS response";
  2867.             goto invalid;
  2868.         }
  2869.     }

  2870.     err = "compression pointers loop in DNS response";

  2871. invalid:

  2872.     ngx_log_error(r->log_level, r->log, 0, err);

  2873.     return NGX_ERROR;

  2874. done:

  2875.     if (name == NULL) {
  2876.         return NGX_OK;
  2877.     }

  2878.     if (len == 0) {
  2879.         ngx_str_null(name);
  2880.         return NGX_OK;
  2881.     }

  2882.     dst = ngx_resolver_alloc(r, len);
  2883.     if (dst == NULL) {
  2884.         return NGX_ERROR;
  2885.     }

  2886.     name->data = dst;

  2887.     for ( ;; ) {
  2888.         n = *src++;

  2889.         if (n == 0) {
  2890.             name->len = dst - name->data - 1;
  2891.             return NGX_OK;
  2892.         }

  2893.         if (n & 0xc0) {
  2894.             n = ((n & 0x3f) << 8) + *src;
  2895.             src = &buf[n];

  2896.         } else {
  2897.             ngx_strlow(dst, src, n);
  2898.             dst += n;
  2899.             src += n;
  2900.             *dst++ = '.';
  2901.         }
  2902.     }
  2903. }


  2904. static ngx_int_t
  2905. ngx_resolver_set_timeout(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
  2906. {
  2907.     if (ctx->event || ctx->timeout == 0) {
  2908.         return NGX_OK;
  2909.     }

  2910.     ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t));
  2911.     if (ctx->event == NULL) {
  2912.         return NGX_ERROR;
  2913.     }

  2914.     ctx->event->handler = ngx_resolver_timeout_handler;
  2915.     ctx->event->data = ctx;
  2916.     ctx->event->log = r->log;
  2917.     ctx->event->cancelable = ctx->cancelable;
  2918.     ctx->ident = -1;

  2919.     ngx_add_timer(ctx->event, ctx->timeout);

  2920.     return NGX_OK;
  2921. }


  2922. static void
  2923. ngx_resolver_timeout_handler(ngx_event_t *ev)
  2924. {
  2925.     ngx_resolver_ctx_t  *ctx;

  2926.     ctx = ev->data;

  2927.     ctx->state = NGX_RESOLVE_TIMEDOUT;

  2928.     ctx->handler(ctx);
  2929. }


  2930. static void
  2931. ngx_resolver_free_node(ngx_resolver_t *r, ngx_resolver_node_t *rn)
  2932. {
  2933.     ngx_uint_t  i;

  2934.     /* lock alloc mutex */

  2935.     if (rn->query) {
  2936.         ngx_resolver_free_locked(r, rn->query);
  2937.     }

  2938.     if (rn->name) {
  2939.         ngx_resolver_free_locked(r, rn->name);
  2940.     }

  2941.     if (rn->cnlen) {
  2942.         ngx_resolver_free_locked(r, rn->u.cname);
  2943.     }

  2944.     if (rn->naddrs > 1 && rn->naddrs != (u_short) -1) {
  2945.         ngx_resolver_free_locked(r, rn->u.addrs);
  2946.     }

  2947. #if (NGX_HAVE_INET6)
  2948.     if (rn->naddrs6 > 1 && rn->naddrs6 != (u_short) -1) {
  2949.         ngx_resolver_free_locked(r, rn->u6.addrs6);
  2950.     }
  2951. #endif

  2952.     if (rn->nsrvs) {
  2953.         for (i = 0; i < (ngx_uint_t) rn->nsrvs; i++) {
  2954.             if (rn->u.srvs[i].name.data) {
  2955.                 ngx_resolver_free_locked(r, rn->u.srvs[i].name.data);
  2956.             }
  2957.         }

  2958.         ngx_resolver_free_locked(r, rn->u.srvs);
  2959.     }

  2960.     ngx_resolver_free_locked(r, rn);

  2961.     /* unlock alloc mutex */
  2962. }


  2963. static void *
  2964. ngx_resolver_alloc(ngx_resolver_t *r, size_t size)
  2965. {
  2966.     u_char  *p;

  2967.     /* lock alloc mutex */

  2968.     p = ngx_alloc(size, r->log);

  2969.     /* unlock alloc mutex */

  2970.     return p;
  2971. }


  2972. static void *
  2973. ngx_resolver_calloc(ngx_resolver_t *r, size_t size)
  2974. {
  2975.     u_char  *p;

  2976.     p = ngx_resolver_alloc(r, size);

  2977.     if (p) {
  2978.         ngx_memzero(p, size);
  2979.     }

  2980.     return p;
  2981. }


  2982. static void
  2983. ngx_resolver_free(ngx_resolver_t *r, void *p)
  2984. {
  2985.     /* lock alloc mutex */

  2986.     ngx_free(p);

  2987.     /* unlock alloc mutex */
  2988. }


  2989. static void
  2990. ngx_resolver_free_locked(ngx_resolver_t *r, void *p)
  2991. {
  2992.     ngx_free(p);
  2993. }


  2994. static void *
  2995. ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)
  2996. {
  2997.     void  *dst;

  2998.     dst = ngx_resolver_alloc(r, size);

  2999.     if (dst == NULL) {
  3000.         return dst;
  3001.     }

  3002.     ngx_memcpy(dst, src, size);

  3003.     return dst;
  3004. }


  3005. static ngx_resolver_addr_t *
  3006. ngx_resolver_export(ngx_resolver_t *r, ngx_resolver_node_t *rn,
  3007.     ngx_uint_t rotate)
  3008. {
  3009.     ngx_uint_t            d, i, j, n;
  3010.     in_addr_t            *addr;
  3011.     ngx_sockaddr_t       *sockaddr;
  3012.     struct sockaddr_in   *sin;
  3013.     ngx_resolver_addr_t  *dst;
  3014. #if (NGX_HAVE_INET6)
  3015.     struct in6_addr      *addr6;
  3016.     struct sockaddr_in6  *sin6;
  3017. #endif

  3018.     n = rn->naddrs;
  3019. #if (NGX_HAVE_INET6)
  3020.     n += rn->naddrs6;
  3021. #endif

  3022.     dst = ngx_resolver_calloc(r, n * sizeof(ngx_resolver_addr_t));
  3023.     if (dst == NULL) {
  3024.         return NULL;
  3025.     }

  3026.     sockaddr = ngx_resolver_calloc(r, n * sizeof(ngx_sockaddr_t));
  3027.     if (sockaddr == NULL) {
  3028.         ngx_resolver_free(r, dst);
  3029.         return NULL;
  3030.     }

  3031.     i = 0;
  3032.     d = rotate ? ngx_random() % n : 0;

  3033.     if (rn->naddrs) {
  3034.         j = rotate ? ngx_random() % rn->naddrs : 0;

  3035.         addr = (rn->naddrs == 1) ? &rn->u.addr : rn->u.addrs;

  3036.         do {
  3037.             sin = &sockaddr[d].sockaddr_in;
  3038.             sin->sin_family = AF_INET;
  3039.             sin->sin_addr.s_addr = addr[j++];
  3040.             dst[d].sockaddr = (struct sockaddr *) sin;
  3041.             dst[d++].socklen = sizeof(struct sockaddr_in);

  3042.             if (d == n) {
  3043.                 d = 0;
  3044.             }

  3045.             if (j == (ngx_uint_t) rn->naddrs) {
  3046.                 j = 0;
  3047.             }
  3048.         } while (++i < (ngx_uint_t) rn->naddrs);
  3049.     }

  3050. #if (NGX_HAVE_INET6)
  3051.     if (rn->naddrs6) {
  3052.         j = rotate ? ngx_random() % rn->naddrs6 : 0;

  3053.         addr6 = (rn->naddrs6 == 1) ? &rn->u6.addr6 : rn->u6.addrs6;

  3054.         do {
  3055.             sin6 = &sockaddr[d].sockaddr_in6;
  3056.             sin6->sin6_family = AF_INET6;
  3057.             ngx_memcpy(sin6->sin6_addr.s6_addr, addr6[j++].s6_addr, 16);
  3058.             dst[d].sockaddr = (struct sockaddr *) sin6;
  3059.             dst[d++].socklen = sizeof(struct sockaddr_in6);

  3060.             if (d == n) {
  3061.                 d = 0;
  3062.             }

  3063.             if (j == rn->naddrs6) {
  3064.                 j = 0;
  3065.             }
  3066.         } while (++i < n);
  3067.     }
  3068. #endif

  3069.     return dst;
  3070. }


  3071. static void
  3072. ngx_resolver_report_srv(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
  3073. {
  3074.     ngx_uint_t                naddrs, nsrvs, nw, i, j, k, l, m, n, w;
  3075.     ngx_resolver_addr_t      *addrs;
  3076.     ngx_resolver_srv_name_t  *srvs;

  3077.     srvs = ctx->srvs;
  3078.     nsrvs = ctx->nsrvs;

  3079.     naddrs = 0;

  3080.     for (i = 0; i < nsrvs; i++) {
  3081.         if (srvs[i].state == NGX_ERROR) {
  3082.             ctx->state = NGX_ERROR;
  3083.             ctx->valid = ngx_time() + (r->valid ? r->valid : 10);

  3084.             ctx->handler(ctx);
  3085.             return;
  3086.         }

  3087.         naddrs += srvs[i].naddrs;
  3088.     }

  3089.     if (naddrs == 0) {
  3090.         ctx->state = srvs[0].state;

  3091.         for (i = 0; i < nsrvs; i++) {
  3092.             if (srvs[i].state == NGX_RESOLVE_NXDOMAIN) {
  3093.                 ctx->state = NGX_RESOLVE_NXDOMAIN;
  3094.                 break;
  3095.             }
  3096.         }

  3097.         ctx->valid = ngx_time() + (r->valid ? r->valid : 10);

  3098.         ctx->handler(ctx);
  3099.         return;
  3100.     }

  3101.     addrs = ngx_resolver_calloc(r, naddrs * sizeof(ngx_resolver_addr_t));
  3102.     if (addrs == NULL) {
  3103.         ctx->state = NGX_ERROR;
  3104.         ctx->valid = ngx_time() + (r->valid ? r->valid : 10);

  3105.         ctx->handler(ctx);
  3106.         return;
  3107.     }

  3108.     i = 0;
  3109.     n = 0;

  3110.     do {
  3111.         nw = 0;

  3112.         for (j = i; j < nsrvs; j++) {
  3113.             if (srvs[j].priority != srvs[i].priority) {
  3114.                 break;
  3115.             }

  3116.             nw += srvs[j].naddrs * srvs[j].weight;
  3117.         }

  3118.         if (nw == 0) {
  3119.             goto next_srv;
  3120.         }

  3121.         w = ngx_random() % nw;

  3122.         for (k = i; k < j; k++) {
  3123.             if (w < srvs[k].naddrs * srvs[k].weight) {
  3124.                 break;
  3125.             }

  3126.             w -= srvs[k].naddrs * srvs[k].weight;
  3127.         }

  3128.         for (l = i; l < j; l++) {

  3129.             for (m = 0; m < srvs[k].naddrs; m++) {
  3130.                 addrs[n].socklen = srvs[k].addrs[m].socklen;
  3131.                 addrs[n].sockaddr = srvs[k].addrs[m].sockaddr;
  3132.                 addrs[n].name = srvs[k].name;
  3133.                 addrs[n].priority = srvs[k].priority;
  3134.                 addrs[n].weight = srvs[k].weight;
  3135.                 n++;
  3136.             }

  3137.             if (++k == j) {
  3138.                 k = i;
  3139.             }
  3140.         }

  3141. next_srv:

  3142.         i = j;

  3143.     } while (i < ctx->nsrvs);

  3144.     ctx->state = NGX_OK;
  3145.     ctx->addrs = addrs;
  3146.     ctx->naddrs = naddrs;

  3147.     ctx->handler(ctx);

  3148.     ngx_resolver_free(r, addrs);
  3149. }


  3150. char *
  3151. ngx_resolver_strerror(ngx_int_t err)
  3152. {
  3153.     static char *errors[] = {
  3154.         "Format error",     /* FORMERR */
  3155.         "Server failure",   /* SERVFAIL */
  3156.         "Host not found",   /* NXDOMAIN */
  3157.         "Unimplemented",    /* NOTIMP */
  3158.         "Operation refused" /* REFUSED */
  3159.     };

  3160.     if (err > 0 && err < 6) {
  3161.         return errors[err - 1];
  3162.     }

  3163.     if (err == NGX_RESOLVE_TIMEDOUT) {
  3164.         return "Operation timed out";
  3165.     }

  3166.     return "Unknown error";
  3167. }


  3168. static u_char *
  3169. ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len)
  3170. {
  3171.     u_char                     *p;
  3172.     ngx_resolver_connection_t  *rec;

  3173.     p = buf;

  3174.     if (log->action) {
  3175.         p = ngx_snprintf(buf, len, " while %s", log->action);
  3176.         len -= p - buf;
  3177.     }

  3178.     rec = log->data;

  3179.     if (rec) {
  3180.         p = ngx_snprintf(p, len, ", resolver: %V", &rec->server);
  3181.     }

  3182.     return p;
  3183. }


  3184. static ngx_int_t
  3185. ngx_udp_connect(ngx_resolver_connection_t *rec)
  3186. {
  3187.     int                rc;
  3188.     ngx_int_t          event;
  3189.     ngx_event_t       *rev, *wev;
  3190.     ngx_socket_t       s;
  3191.     ngx_connection_t  *c;

  3192.     s = ngx_socket(rec->sockaddr->sa_family, SOCK_DGRAM, 0);

  3193.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "UDP socket %d", s);

  3194.     if (s == (ngx_socket_t) -1) {
  3195.         ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
  3196.                       ngx_socket_n " failed");
  3197.         return NGX_ERROR;
  3198.     }

  3199.     c = ngx_get_connection(s, &rec->log);

  3200.     if (c == NULL) {
  3201.         if (ngx_close_socket(s) == -1) {
  3202.             ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
  3203.                           ngx_close_socket_n " failed");
  3204.         }

  3205.         return NGX_ERROR;
  3206.     }

  3207.     if (ngx_nonblocking(s) == -1) {
  3208.         ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
  3209.                       ngx_nonblocking_n " failed");

  3210.         goto failed;
  3211.     }

  3212.     rev = c->read;
  3213.     wev = c->write;

  3214.     rev->log = &rec->log;
  3215.     wev->log = &rec->log;

  3216.     rec->udp = c;

  3217.     c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);

  3218.     c->start_time = ngx_current_msec;

  3219.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0,
  3220.                    "connect to %V, fd:%d #%uA", &rec->server, s, c->number);

  3221.     rc = connect(s, rec->sockaddr, rec->socklen);

  3222.     /* TODO: iocp */

  3223.     if (rc == -1) {
  3224.         ngx_log_error(NGX_LOG_CRIT, &rec->log, ngx_socket_errno,
  3225.                       "connect() failed");

  3226.         goto failed;
  3227.     }

  3228.     /* UDP sockets are always ready to write */
  3229.     wev->ready = 1;

  3230.     event = (ngx_event_flags & NGX_USE_CLEAR_EVENT) ?
  3231.                 /* kqueue, epoll */                 NGX_CLEAR_EVENT:
  3232.                 /* select, poll, /dev/poll */       NGX_LEVEL_EVENT;
  3233.                 /* eventport event type has no meaning: oneshot only */

  3234.     if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
  3235.         goto failed;
  3236.     }

  3237.     return NGX_OK;

  3238. failed:

  3239.     ngx_close_connection(c);
  3240.     rec->udp = NULL;

  3241.     return NGX_ERROR;
  3242. }


  3243. static ngx_int_t
  3244. ngx_tcp_connect(ngx_resolver_connection_t *rec)
  3245. {
  3246.     int                rc;
  3247.     ngx_int_t          event;
  3248.     ngx_err_t          err;
  3249.     ngx_uint_t         level;
  3250.     ngx_socket_t       s;
  3251.     ngx_event_t       *rev, *wev;
  3252.     ngx_connection_t  *c;

  3253.     s = ngx_socket(rec->sockaddr->sa_family, SOCK_STREAM, 0);

  3254.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "TCP socket %d", s);

  3255.     if (s == (ngx_socket_t) -1) {
  3256.         ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
  3257.                       ngx_socket_n " failed");
  3258.         return NGX_ERROR;
  3259.     }

  3260.     c = ngx_get_connection(s, &rec->log);

  3261.     if (c == NULL) {
  3262.         if (ngx_close_socket(s) == -1) {
  3263.             ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
  3264.                           ngx_close_socket_n " failed");
  3265.         }

  3266.         return NGX_ERROR;
  3267.     }

  3268.     if (ngx_nonblocking(s) == -1) {
  3269.         ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
  3270.                       ngx_nonblocking_n " failed");

  3271.         goto failed;
  3272.     }

  3273.     rev = c->read;
  3274.     wev = c->write;

  3275.     rev->log = &rec->log;
  3276.     wev->log = &rec->log;

  3277.     rec->tcp = c;

  3278.     c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);

  3279.     c->start_time = ngx_current_msec;

  3280.     if (ngx_add_conn) {
  3281.         if (ngx_add_conn(c) == NGX_ERROR) {
  3282.             goto failed;
  3283.         }
  3284.     }

  3285.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0,
  3286.                    "connect to %V, fd:%d #%uA", &rec->server, s, c->number);

  3287.     rc = connect(s, rec->sockaddr, rec->socklen);

  3288.     if (rc == -1) {
  3289.         err = ngx_socket_errno;


  3290.         if (err != NGX_EINPROGRESS
  3291. #if (NGX_WIN32)
  3292.             /* Winsock returns WSAEWOULDBLOCK (NGX_EAGAIN) */
  3293.             && err != NGX_EAGAIN
  3294. #endif
  3295.             )
  3296.         {
  3297.             if (err == NGX_ECONNREFUSED
  3298. #if (NGX_LINUX)
  3299.                 /*
  3300.                  * Linux returns EAGAIN instead of ECONNREFUSED
  3301.                  * for unix sockets if listen queue is full
  3302.                  */
  3303.                 || err == NGX_EAGAIN
  3304. #endif
  3305.                 || err == NGX_ECONNRESET
  3306.                 || err == NGX_ENETDOWN
  3307.                 || err == NGX_ENETUNREACH
  3308.                 || err == NGX_EHOSTDOWN
  3309.                 || err == NGX_EHOSTUNREACH)
  3310.             {
  3311.                 level = NGX_LOG_ERR;

  3312.             } else {
  3313.                 level = NGX_LOG_CRIT;
  3314.             }

  3315.             ngx_log_error(level, &rec->log, err, "connect() to %V failed",
  3316.                           &rec->server);

  3317.             ngx_close_connection(c);
  3318.             rec->tcp = NULL;

  3319.             return NGX_ERROR;
  3320.         }
  3321.     }

  3322.     if (ngx_add_conn) {
  3323.         if (rc == -1) {

  3324.             /* NGX_EINPROGRESS */

  3325.             return NGX_AGAIN;
  3326.         }

  3327.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "connected");

  3328.         wev->ready = 1;

  3329.         return NGX_OK;
  3330.     }

  3331.     if (ngx_event_flags & NGX_USE_IOCP_EVENT) {

  3332.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &rec->log, ngx_socket_errno,
  3333.                        "connect(): %d", rc);

  3334.         if (ngx_blocking(s) == -1) {
  3335.             ngx_log_error(NGX_LOG_ALERT, &rec->log, ngx_socket_errno,
  3336.                           ngx_blocking_n " failed");
  3337.             goto failed;
  3338.         }

  3339.         /*
  3340.          * FreeBSD's aio allows to post an operation on non-connected socket.
  3341.          * NT does not support it.
  3342.          *
  3343.          * TODO: check in Win32, etc. As workaround we can use NGX_ONESHOT_EVENT
  3344.          */

  3345.         rev->ready = 1;
  3346.         wev->ready = 1;

  3347.         return NGX_OK;
  3348.     }

  3349.     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {

  3350.         /* kqueue */

  3351.         event = NGX_CLEAR_EVENT;

  3352.     } else {

  3353.         /* select, poll, /dev/poll */

  3354.         event = NGX_LEVEL_EVENT;
  3355.     }

  3356.     if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
  3357.         goto failed;
  3358.     }

  3359.     if (rc == -1) {

  3360.         /* NGX_EINPROGRESS */

  3361.         if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) {
  3362.             goto failed;
  3363.         }

  3364.         return NGX_AGAIN;
  3365.     }

  3366.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "connected");

  3367.     wev->ready = 1;

  3368.     return NGX_OK;

  3369. failed:

  3370.     ngx_close_connection(c);
  3371.     rec->tcp = NULL;

  3372.     return NGX_ERROR;
  3373. }


  3374. static ngx_int_t
  3375. ngx_resolver_cmp_srvs(const void *one, const void *two)
  3376. {
  3377.     ngx_int_t            p1, p2;
  3378.     ngx_resolver_srv_t  *first, *second;

  3379.     first = (ngx_resolver_srv_t *) one;
  3380.     second = (ngx_resolver_srv_t *) two;

  3381.     p1 = first->priority;
  3382.     p2 = second->priority;

  3383.     return p1 - p2;
  3384. }