1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #include <nxt_main.h>
8 
9 
10 void
nxt_job_resolve(nxt_job_resolve_t * jbr)11 nxt_job_resolve(nxt_job_resolve_t *jbr)
12 {
13     int                 err;
14     u_char              *host;
15     size_t              length;
16     nxt_mp_t            *mp;
17     nxt_uint_t          n;
18     nxt_sockaddr_t      *sa;
19     struct addrinfo     hint, *res, *r;
20     nxt_work_handler_t  handler;
21 
22     #define NXT_BUFSIZE  64
23     u_char               buf[NXT_BUFSIZE];
24 
25     handler = jbr->error_handler;
26     res = NULL;
27 
28     length = jbr->name.length + 1;
29 
30     if (nxt_fast_path(length <= NXT_BUFSIZE)) {
31         host = buf;
32 
33     } else {
34         host = nxt_mp_alloc(jbr->job.mem_pool, length);
35         if (nxt_slow_path(host == NULL)) {
36             goto fail;
37         }
38     }
39 
40     nxt_cpystrn(host, jbr->name.start, length);
41 
42     nxt_memzero(&hint, sizeof(struct addrinfo));
43     hint.ai_socktype = SOCK_STREAM;
44 
45     err = getaddrinfo((char *) host, NULL, &hint, &res);
46 
47     if (err != 0) {
48         nxt_thread_log_error(jbr->log_level,
49                              "getaddrinfo(\"%s\") failed (%d: %s)",
50                              host, err, gai_strerror(err));
51         goto fail;
52     }
53 
54     n = 0;
55     for (r = res; r != NULL; r = r->ai_next) {
56 
57         switch (r->ai_addr->sa_family) {
58 #if (NXT_INET6)
59         case AF_INET6:
60 #endif
61         case AF_INET:
62             n++;
63             break;
64 
65         default:
66             break;
67         }
68     }
69 
70     jbr->count = n;
71     mp = jbr->job.mem_pool;
72 
73     jbr->sockaddrs = nxt_mp_alloc(mp, n * sizeof(nxt_sockaddr_t *));
74     if (nxt_slow_path(jbr->sockaddrs == NULL)) {
75         goto fail;
76     }
77 
78     n = 0;
79     for (r = res; r != NULL; r = r->ai_next) {
80 
81         switch (r->ai_addr->sa_family) {
82 #if (NXT_INET6)
83         case AF_INET6:
84             length = NXT_INET6_ADDR_STR_LEN;
85             break;
86 #endif
87         case AF_INET:
88             length = NXT_INET_ADDR_STR_LEN;
89             break;
90 
91         default:
92             continue;
93         }
94 
95         sa = nxt_sockaddr_create(mp, r->ai_addr, r->ai_addrlen, length);
96         if (nxt_slow_path(sa == NULL)) {
97             goto fail;
98         }
99 
100         jbr->sockaddrs[n++] = sa;
101 
102         if (jbr->port != 0) {
103 
104             switch (sa->u.sockaddr.sa_family) {
105             case AF_INET:
106                 sa->u.sockaddr_in.sin_port = jbr->port;
107                 break;
108 #if (NXT_INET6)
109             case AF_INET6:
110                 sa->u.sockaddr_in6.sin6_port = jbr->port;
111                 break;
112 #endif
113             default:
114                 break;
115             }
116         }
117     }
118 
119     handler = jbr->ready_handler;
120 
121 fail:
122 
123     if (nxt_fast_path(res != NULL)) {
124         freeaddrinfo(res);
125     }
126 
127     if (host != buf) {
128         nxt_mp_free(jbr->job.mem_pool, host);
129     }
130 
131     nxt_job_return(jbr->job.task, &jbr->job, handler);
132 }
133