summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_job_resolve.c
blob: 600f1aae7495d2502333739a72ad9d68cd87192a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) NGINX, Inc.
 */

#include <nxt_main.h>


void
nxt_job_resolve(nxt_job_resolve_t *jbr)
{
    int                 err;
    u_char              *host;
    size_t              len;
    nxt_uint_t          n;
    nxt_mem_pool_t      *mp;
    nxt_sockaddr_t      *sa;
    struct addrinfo     hint, *res, *r;
    nxt_work_handler_t  handler;

    #define NXT_BUFSIZE  64
    u_char               buf[NXT_BUFSIZE];

    handler = jbr->error_handler;
    res = NULL;

    len = jbr->name.len + 1;

    if (nxt_fast_path(len <= NXT_BUFSIZE)) {
        host = buf;

    } else {
        host = nxt_mem_alloc(jbr->job.mem_pool, len);
        if (nxt_slow_path(host == NULL)) {
            goto fail;
        }
    }

    nxt_cpystrn(host, jbr->name.data, len);

    nxt_memzero(&hint, sizeof(struct addrinfo));
    hint.ai_socktype = SOCK_STREAM;

    err = getaddrinfo((char *) host, NULL, &hint, &res);

    if (err != 0) {
        nxt_thread_log_error(jbr->log_level,
                             "getaddrinfo(\"%s\") failed (%d: %s)",
                             host, err, gai_strerror(err));
        goto fail;
    }

    n = 0;
    for (r = res; r != NULL; r = r->ai_next) {

        switch (r->ai_addr->sa_family) {
#if (NXT_INET6)
        case AF_INET6:
#endif
        case AF_INET:
             n++;
             break;

        default:
             break;
        }
    }

    jbr->count = n;
    mp = jbr->job.mem_pool;

    jbr->sockaddrs = nxt_mem_alloc(mp, n * sizeof(nxt_sockaddr_t *));
    if (nxt_slow_path(jbr->sockaddrs == NULL)) {
        goto fail;
    }

    n = 0;
    for (r = res; r != NULL; r = r->ai_next) {

        switch (r->ai_addr->sa_family) {
#if (NXT_INET6)
        case AF_INET6:
#endif
        case AF_INET:
             break;

        default:
             continue;
        }

        sa = nxt_sockaddr_create(mp, r->ai_addr, r->ai_addrlen);
        if (nxt_slow_path(sa == NULL)) {
            goto fail;
        }

        jbr->sockaddrs[n++] = sa;

        if (jbr->port != 0) {

            switch (sa->u.sockaddr.sa_family) {
            case AF_INET:
                sa->u.sockaddr_in.sin_port = jbr->port;
                break;
#if (NXT_INET6)
            case AF_INET6:
                sa->u.sockaddr_in6.sin6_port = jbr->port;
                break;
#endif
            default:
                break;
            }
        }
    }

    handler = jbr->ready_handler;

fail:

    if (nxt_fast_path(res != NULL)) {
        freeaddrinfo(res);
    }

    nxt_job_return(nxt_thread(), &jbr->job, handler);
}