Esempio n. 1
0
void
ngx_resolve_name_done(ngx_resolver_ctx_t *ctx)
{
    uint32_t              hash;
    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 name done: %i", ctx->state);

    if (ctx->quick) {
        return;
    }

    if (ctx->event && ctx->event->timer_set) {
        ngx_del_timer(ctx->event);
    }

    /* lock name mutex */

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

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

        rn = ngx_resolver_lookup_name(r, &ctx->name, hash);

        if (rn) {
            p = &rn->waiting;
            w = rn->waiting;

            while (w) {
                if (w == ctx) {
                    *p = w->next;

                    goto done;
                }

                p = &w->next;
                w = w->next;
            }
        }

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

done:

    ngx_resolver_expire(r, &r->name_rbtree, &r->name_expire_queue);

    /* unlock name mutex */

    /* lock alloc mutex */

    if (ctx->event) {
        ngx_resolver_free_locked(r, ctx->event);
    }

    ngx_resolver_free_locked(r, ctx);

    /* unlock alloc mutex */
}
Esempio n. 2
0
static ngx_int_t
ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
{
    uint32_t              hash;
    in_addr_t             addr, *addrs;
    ngx_int_t             rc;
    ngx_uint_t            naddrs;
    ngx_resolver_ctx_t   *next;
    ngx_resolver_node_t  *rn;

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

    rn = ngx_resolver_lookup_name(r, &ctx->name, hash);

    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->name_expire_queue, &rn->queue);

            naddrs = rn->naddrs;

            if (naddrs) {

                /* NGX_RESOLVE_A answer */

                if (naddrs != 1) {
                    addr = 0;
                    addrs = ngx_resolver_dup(r, rn->u.addrs,
                                             naddrs * sizeof(in_addr_t));
                    if (addrs == NULL) {
                        return NGX_ERROR;
                    }

                } else {
                    addr = rn->u.addr;
                    addrs = NULL;
                }

                ctx->next = rn->waiting;
                rn->waiting = NULL;

                /* unlock name mutex */

                do {
                    ctx->state = NGX_OK;
                    ctx->naddrs = naddrs;
                    ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs;
                    ctx->addr = addr;
                    next = ctx->next;

                    ctx->handler(ctx);

                    ctx = next;
                } while (ctx);

                if (addrs) {
                    ngx_resolver_free(r, addrs);
                }

                return NGX_OK;
            }

            /* NGX_RESOLVE_CNAME */

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

                ctx->name.len = rn->cnlen;
                ctx->name.data = rn->u.cname;

                return ngx_resolve_name_locked(r, ctx);
            }

            ctx->next = rn->waiting;
            rn->waiting = NULL;

            /* unlock name mutex */

            do {
                ctx->state = NGX_RESOLVE_NXDOMAIN;
                next = ctx->next;

                ctx->handler(ctx);

                ctx = next;
            } while (ctx);

            return NGX_OK;
        }

        if (rn->waiting) {

            ctx->next = rn->waiting;
            rn->waiting = ctx;
            ctx->state = NGX_AGAIN;

            return NGX_AGAIN;
        }

        ngx_queue_remove(&rn->queue);

        /* lock alloc mutex */

        if (rn->query) {
            ngx_resolver_free_locked(r, rn->query);
            rn->query = NULL;
        }

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

        if (rn->naddrs > 1) {
            ngx_resolver_free_locked(r, rn->u.addrs);
        }

        /* unlock alloc mutex */

    } else {

        rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t));
        if (rn == NULL) {
            return NGX_ERROR;
        }

        rn->name = ngx_resolver_dup(r, ctx->name.data, ctx->name.len);
        if (rn->name == NULL) {
            ngx_resolver_free(r, rn);
            return NGX_ERROR;
        }

        rn->node.key = hash;
        rn->nlen = (u_short) ctx->name.len;
        rn->query = NULL;

        ngx_rbtree_insert(&r->name_rbtree, &rn->node);
    }

    rc = ngx_resolver_create_name_query(rn, ctx);

    if (rc == NGX_ERROR) {
        goto failed;
    }

    if (rc == NGX_DECLINED) {
        ngx_rbtree_delete(&r->name_rbtree, &rn->node);

        ngx_resolver_free(r, rn->query);
        ngx_resolver_free(r, rn->name);
        ngx_resolver_free(r, rn);

        ctx->state = NGX_RESOLVE_NXDOMAIN;
        ctx->handler(ctx);

        return NGX_OK;
    }

    if (ngx_resolver_send_query(r, rn) != NGX_OK) {
        goto failed;
    }

    if (ctx->event == NULL) {
        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->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;
}