📄 ngx_resolver.c
字号:
} ctx->event->handler = ngx_resolver_timeout_handler; ctx->event->data = ctx; ctx->event->log = r->log; ctx->ident = -1; ngx_add_timer(ctx->event, ctx->timeout); } if (ngx_queue_empty(&r->name_resend_queue)) { ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); } rn->expire = ngx_time() + r->resend_timeout; ngx_queue_insert_head(&r->name_resend_queue, &rn->queue); rn->cnlen = 0; rn->naddrs = 0; rn->valid = 0; rn->waiting = ctx; ctx->state = NGX_AGAIN; return NGX_AGAIN;failed: ngx_rbtree_delete(&r->name_rbtree, &rn->node); if (rn->query) { ngx_resolver_free(r, rn->query); } ngx_resolver_free(r, rn->name); ngx_resolver_free(r, rn); return NGX_ERROR;}ngx_int_tngx_resolve_addr(ngx_resolver_ctx_t *ctx){ ngx_resolver_t *r; ngx_resolver_node_t *rn; r = ctx->resolver; ctx->addr = ntohl(ctx->addr); /* lock addr mutex */ rn = ngx_resolver_lookup_addr(r, ctx->addr); if (rn) { if (rn->valid >= ngx_time()) { ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached"); ngx_queue_remove(&rn->queue); rn->expire = ngx_time() + r->expire; ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue); ctx->name.len = rn->nlen; ctx->name.data = ngx_resolver_dup(r, rn->name, rn->nlen); if (ctx->name.data == NULL) { goto failed; } /* unlock addr mutex */ ctx->state = NGX_OK; ctx->handler(ctx); ngx_resolver_free(r, ctx->name.data); return NGX_OK; } if (rn->waiting) { ctx->next = rn->waiting; rn->waiting = ctx; return NGX_AGAIN; } ngx_queue_remove(&rn->queue); ngx_resolver_free(r, rn->query); rn->query = NULL; } else { rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t)); if (rn == NULL) { goto failed; } rn->node.key = ctx->addr; rn->query = NULL; ngx_rbtree_insert(&r->addr_rbtree, &rn->node); } if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) { goto failed; } if (ngx_resolver_send_query(r, rn) != NGX_OK) { goto failed; } ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); if (ctx->event == NULL) { goto failed; } ctx->event->handler = ngx_resolver_timeout_handler; ctx->event->data = ctx; ctx->event->log = r->log; ctx->ident = -1; ngx_add_timer(ctx->event, ctx->timeout); if (ngx_queue_empty(&r->addr_resend_queue)) { ngx_add_timer(r->event, (ngx_msec_t) (r->resend_timeout * 1000)); } rn->expire = ngx_time() + r->resend_timeout; ngx_queue_insert_head(&r->addr_resend_queue, &rn->queue); rn->cnlen = 0; rn->naddrs = 0; rn->name = NULL; rn->nlen = 0; rn->valid = 0; rn->waiting = ctx; /* unlock addr mutex */ ctx->state = NGX_AGAIN; return NGX_OK;failed: if (rn) { ngx_rbtree_delete(&r->addr_rbtree, &rn->node); if (rn->query) { ngx_resolver_free(r, rn->query); } ngx_resolver_free(r, rn); } /* unlock addr mutex */ if (ctx->event) { ngx_resolver_free(r, ctx->event); } ngx_resolver_free(r, ctx); return NGX_ERROR;}voidngx_resolve_addr_done(ngx_resolver_ctx_t *ctx){ in_addr_t addr; ngx_resolver_t *r; ngx_resolver_ctx_t *w, **p; ngx_resolver_node_t *rn; r = ctx->resolver; ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve addr done: %i", ctx->state); if (ctx->event && ctx->event->timer_set) { ngx_del_timer(ctx->event); } /* lock addr mutex */ if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { rn = ngx_resolver_lookup_addr(r, ctx->addr); if (rn) { p = &rn->waiting; w = rn->waiting; while (w) { if (w == ctx) { *p = w->next; goto done; } p = &w->next; w = w->next; } } addr = ntohl(ctx->addr); ngx_log_error(NGX_LOG_ALERT, r->log, 0, "could not cancel %ud.%ud.%ud.%ud resolving", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); }done: ngx_resolver_expire(r, &r->addr_rbtree, &r->addr_expire_queue); /* unlock addr mutex */ /* lock alloc mutex */ if (ctx->event) { ngx_resolver_free_locked(r, ctx->event); } ngx_resolver_free_locked(r, ctx); /* unlock alloc mutex */}static voidngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue){ time_t now; ngx_uint_t i; ngx_queue_t *q; ngx_resolver_node_t *rn; ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver expire"); now = ngx_time(); for (i = 0; i < 2; i++) { if (ngx_queue_empty(queue)) { return; } q = ngx_queue_last(queue); rn = ngx_queue_data(q, ngx_resolver_node_t, queue); if (now <= rn->expire) { return; } ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver expire \"%*s\"", (size_t) rn->nlen, rn->name); ngx_queue_remove(q); ngx_rbtree_delete(tree, &rn->node); ngx_resolver_free_node(r, rn); }}static ngx_int_tngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn){ ssize_t n; ngx_udp_connection_t *uc; uc = r->udp_connection; if (uc->connection == NULL) { if (ngx_udp_connect(uc) != NGX_OK) { return NGX_ERROR; } uc->connection->data = r; uc->connection->read->handler = ngx_resolver_read_response; uc->connection->read->resolver = 1; } n = ngx_send(uc->connection, rn->query, rn->qlen); if (n == -1) { return NGX_ERROR; } if ((size_t) n != (size_t) rn->qlen) { ngx_log_error(NGX_LOG_CRIT, uc->log, 0, "send() incomplete"); return NGX_ERROR; } return NGX_OK;}static voidngx_resolver_resend_handler(ngx_event_t *ev){ time_t timer, atimer, ntimer; ngx_resolver_t *r; r = ev->data; ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver resend handler"); /* lock name mutex */ ntimer = ngx_resolver_resend(r, &r->name_rbtree, &r->name_resend_queue); /* unlock name mutex */ /* lock addr mutex */ atimer = ngx_resolver_resend(r, &r->addr_rbtree, &r->addr_resend_queue); /* unlock addr mutex */ if (ntimer == 0) { timer = atimer; } else if (atimer == 0) { timer = ntimer; } else { timer = (atimer < ntimer) ? atimer : ntimer; } if (timer) { ngx_add_timer(r->event, (ngx_msec_t) (timer * 1000)); }}static time_tngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue){ time_t now; ngx_queue_t *q; ngx_resolver_node_t *rn; now = ngx_time(); for ( ;; ) { if (ngx_queue_empty(queue)) { return 0; } q = ngx_queue_last(queue); rn = ngx_queue_data(q, ngx_resolver_node_t, queue); if (now < rn->expire) { return rn->expire - now; } ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver resend \"%*s\" %p", (size_t) rn->nlen, rn->name, rn->waiting); ngx_queue_remove(q); if (rn->waiting) { if (ngx_resolver_send_query(r, rn) == NGX_OK) { rn->expire = now + r->resend_timeout; ngx_queue_insert_head(queue, &rn->queue); } continue; } ngx_rbtree_delete(tree, &rn->node); ngx_resolver_free_node(r, rn); }}static voidngx_resolver_read_response(ngx_event_t *rev){ ssize_t n; ngx_connection_t *c; u_char buf[NGX_RESOLVER_UDP_SIZE]; c = rev->data; do { n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE); if (n < 0) { return; } ngx_resolver_process_response(c->data, buf, n); } while (rev->ready);}static voidngx_resolver_process_response(ngx_resolver_t *r, u_char *buf, size_t n){ char *err; size_t len; ngx_uint_t i, ident, flags, code, nqs, nan, qtype, qclass; ngx_resolver_qs_t *qs; ngx_resolver_query_t *query; if ((size_t) n < sizeof(ngx_resolver_query_t) + 1) { goto short_response; } query = (ngx_resolver_query_t *) buf; ident = (query->ident_hi << 8) + query->ident_lo; flags = (query->flags_hi << 8) + query->flags_lo; nqs = (query->nqs_hi << 8) + query->nqs_lo; nan = (query->nan_hi << 8) + query->nan_lo; ngx_log_debug6(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver DNS response %ui fl:%04Xui %ui/%ui/%ui/%ui", ident, flags, nqs, nan, (query->nns_hi << 8) + query->nns_lo, (query->nar_hi << 8) + query->nar_lo); if (!(flags & 0x8000)) { ngx_log_error(r->log_level, r->log, 0, "invalid DNS response %ui fl:%04Xui", ident, flags); return; } code = flags & 0x7f; if (code == NGX_RESOLVE_FORMERR || code > NGX_RESOLVE_REFUSED) { ngx_log_error(r->log_level, r->log, 0, "DNS error (%ui: %s), query id:%ui", code, ngx_resolver_strerror(code), ident); return; } if (nqs != 1) { err = "invalid number of questions in DNS response"; goto done; } i = sizeof(ngx_resolver_query_t); while (i < (ngx_uint_t) n) { if (buf[i] == '\0') { goto found; } len = buf[i]; i += 1 + len; } goto short_response;found: if (i++ == 0) { err = "zero-length domain name in DNS response"; goto done; } if (i + sizeof(ngx_resolver_qs_t) + nan * (2 + sizeof(ngx_resolver_an_t)) > (ngx_uint_t) n) { goto short_response; } qs = (ngx_resolver_qs_t *) &buf[i]; qtype = (qs->type_hi << 8) + qs->type_lo; qclass = (qs->class_hi << 8) + qs->class_lo; ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver DNS response qt:%ui cl:%ui", qtype, qclass); if (qclass != 1) { ngx_log_error(r->log_level, r->log, 0, "unknown query class %ui in DNS response", qclass); return; } switch (qtype) { case NGX_RESOLVE_A: ngx_resolver_process_a(r, buf, n, ident, code, nan, i + sizeof(ngx_resolver_qs_t)); break; case NGX_RESOLVE_PTR: ngx_resolver_process_ptr(r, buf, n, ident, code, nan); break; default: ngx_log_error(r->log_level, r->log, 0, "unknown query type %ui in DNS response", qtype); return; } return;short_response: err = "short dns response";done:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -