⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ngx_resolver.c

📁 Nginx是一个高性能的HTTP和反向代理服务器
💻 C
📖 第 1 页 / 共 4 页
字号:
        }        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 + -