3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
10 #include <ngx_event_connect.h>
14 * ngx_sock_ntop() and ngx_inet_ntop() may be implemented as
15 * "ngx_sprintf(text, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3])", however,
16 * they had been implemented long before the ngx_sprintf() had appeared
17 * and they are faster by 1.5-2.5 times, so it is worth to keep them.
19 * By the way, the implementation using ngx_sprintf() is faster by 2.5-3 times
20 * than using FreeBSD libc's snprintf().
24 static ngx_inline
size_t
25 ngx_sprint_uchar(u_char
*text
, u_char c
, size_t len
)
39 *text
++ = (u_char
) (c1
+ '0');
50 *text
++ = (u_char
) (c2
+ '0');
60 *text
++ = (u_char
) (c2
+ '0');
70 ngx_sock_ntop(int family
, struct sockaddr
*sa
, u_char
*text
, size_t len
)
75 struct sockaddr_in
*sin
;
81 if (family
!= AF_INET
) {
85 sin
= (struct sockaddr_in
*) sa
;
86 p
= (u_char
*) &sin
->sin_addr
;
88 if (len
> INET_ADDRSTRLEN
) {
89 len
= INET_ADDRSTRLEN
;
92 n
= ngx_sprint_uchar(text
, p
[0], len
);
109 n
+= ngx_sprint_uchar(&text
[n
], p
[i
++], len
- n
);
124 ngx_inet_ntop(int family
, void *addr
, u_char
*text
, size_t len
)
134 if (family
!= AF_INET
) {
140 if (len
> INET_ADDRSTRLEN
) {
141 len
= INET_ADDRSTRLEN
;
144 n
= ngx_sprint_uchar(text
, p
[0], len
);
161 n
+= ngx_sprint_uchar(&text
[n
], p
[i
++], len
- n
);
179 ngx_ptocidr(ngx_str_t
*text
, void *cidr
)
183 ngx_inet_cidr_t
*in_cidr
;
187 for (i
= 0; i
< text
->len
; i
++) {
188 if (text
->data
[i
] == '/') {
193 if (i
== text
->len
) {
197 text
->data
[i
] = '\0';
198 in_cidr
->addr
= inet_addr((char *) text
->data
);
200 if (in_cidr
->addr
== INADDR_NONE
) {
204 m
= ngx_atoi(&text
->data
[i
+ 1], text
->len
- (i
+ 1));
205 if (m
== NGX_ERROR
) {
211 /* the x86 compilers use the shl instruction that shifts by modulo 32 */
217 in_cidr
->mask
= htonl((ngx_uint_t
) (0 - (1 << (32 - m
))));
224 ngx_parse_url(ngx_conf_t
*cf
, ngx_url_t
*u
)
231 #if (NGX_HAVE_UNIX_DOMAIN)
232 struct sockaddr_un
*saun
;
238 if (ngx_strncasecmp(p
, "unix:", 5) == 0) {
240 #if (NGX_HAVE_UNIX_DOMAIN)
242 u
->type
= NGX_PARSE_URL_UNIX
;
251 for (i
= 0; i
< len
; i
++) {
256 u
->uri
.len
-= len
+ 1;
257 u
->uri
.data
+= len
+ 1;
265 u
->err
= "no path in the unix domain socket";
269 if (len
+ 1 > sizeof(saun
->sun_path
)) {
270 u
->err
= "too long path in the unix domain socket";
274 u
->peers
= ngx_pcalloc(cf
->pool
, sizeof(ngx_peers_t
));
275 if (u
->peers
== NULL
) {
279 saun
= ngx_pcalloc(cf
->pool
, sizeof(struct sockaddr_un
));
284 u
->peers
->number
= 1;
286 saun
->sun_family
= AF_UNIX
;
287 (void) ngx_cpystrn((u_char
*) saun
->sun_path
, p
, len
+ 1);
289 u
->peers
->peer
[0].sockaddr
= (struct sockaddr
*) saun
;
290 u
->peers
->peer
[0].socklen
= sizeof(struct sockaddr_un
);
291 u
->peers
->peer
[0].name
.len
= len
+ 5;
292 u
->peers
->peer
[0].name
.data
= u
->url
.data
;
293 u
->peers
->peer
[0].uri_separator
= ":";
295 u
->host_header
.len
= sizeof("localhost") - 1;
296 u
->host_header
.data
= (u_char
*) "localhost";
301 u
->err
= "the unix domain sockets are not supported on this platform";
308 if ((p
[0] == ':' || p
[0] == '/') && !u
->listen
) {
309 u
->err
= "invalid host";
313 u
->type
= NGX_PARSE_URL_INET
;
316 u
->host_header
.len
= len
;
317 u
->host_header
.data
= p
;
319 for (i
= 0; i
< len
; i
++) {
322 u
->port
.data
= &p
[i
+ 1];
326 u
->port
.len
= &p
[len
] - u
->port
.data
;
332 u
->uri
.len
= len
- i
;
334 u
->host_header
.len
= i
;
336 if (u
->host
.len
== 0) {
340 if (u
->port
.data
== NULL
) {
345 u
->port
.len
= &p
[i
] - u
->port
.data
;
347 if (u
->port
.len
== 0) {
348 u
->err
= "invalid port";
358 if (u
->port
.len
== 0) {
359 u
->port
.len
= &p
[i
] - u
->port
.data
;
361 if (u
->port
.len
== 0) {
362 u
->err
= "invalid port";
367 port
= ngx_atoi(u
->port
.data
, u
->port
.len
);
369 if (port
== NGX_ERROR
|| port
< 1 || port
> 65536) {
370 u
->err
= "invalid port";
375 port
= ngx_atoi(p
, len
);
377 if (port
== NGX_ERROR
) {
389 u
->portn
= (in_port_t
) port
;
395 if (u
->default_portn
== 0) {
400 u
->portn
= u
->default_portn
;
403 if (u
->host
.len
== 1 && u
->host
.data
[0] == '*') {
411 host
= ngx_palloc(cf
->temp_pool
, u
->host
.len
+ 1);
416 (void) ngx_cpystrn(host
, u
->host
.data
, u
->host
.len
+ 1);
418 u
->addr
.in_addr
= inet_addr((const char *) host
);
420 if (u
->addr
.in_addr
== INADDR_NONE
) {
421 h
= gethostbyname((const char *) host
);
423 if (h
== NULL
|| h
->h_addr_list
[0] == NULL
) {
424 u
->err
= "host not found";
428 u
->addr
.in_addr
= *(in_addr_t
*)(h
->h_addr_list
[0]);
432 u
->addr
.in_addr
= INADDR_ANY
;
438 if (u
->default_port
) {
444 if (u
->default_portn
== 0) {
449 u
->portn
= u
->default_portn
;
451 u
->port
.data
= ngx_palloc(cf
->pool
, sizeof("65536") - 1);
452 if (u
->port
.data
== NULL
) {
456 u
->port
.len
= ngx_sprintf(u
->port
.data
, "%d", u
->portn
) - u
->port
.data
;
458 } else if (u
->portn
) {
459 if (u
->portn
== u
->default_portn
) {
468 if (u
->host
.len
== 0) {
473 u
->peers
= ngx_inet_resolve_peer(cf
, &u
->host
, u
->portn
);
475 if (u
->peers
== NULL
) {
479 if (u
->peers
== NGX_CONF_ERROR
) {
480 u
->err
= "host not found";
489 ngx_inet_resolve_peer(ngx_conf_t
*cf
, ngx_str_t
*name
, in_port_t port
)
497 struct sockaddr_in
*sin
;
499 host
= ngx_palloc(cf
->temp_pool
, name
->len
+ 1);
504 (void) ngx_cpystrn(host
, name
->data
, name
->len
+ 1);
508 in_addr
= inet_addr((char *) host
);
510 if (in_addr
== INADDR_NONE
) {
511 h
= gethostbyname((char *) host
);
513 if (h
== NULL
|| h
->h_addr_list
[0] == NULL
) {
514 return NGX_CONF_ERROR
;
517 for (i
= 0; h
->h_addr_list
[i
] != NULL
; i
++) { /* void */ }
519 /* MP: ngx_shared_palloc() */
521 peers
= ngx_pcalloc(cf
->pool
,
522 sizeof(ngx_peers_t
) + sizeof(ngx_peer_t
) * (i
- 1));
529 for (i
= 0; h
->h_addr_list
[i
] != NULL
; i
++) {
531 sin
= ngx_pcalloc(cf
->pool
, sizeof(struct sockaddr_in
));
536 sin
->sin_family
= AF_INET
;
537 sin
->sin_port
= htons(port
);
538 sin
->sin_addr
.s_addr
= *(in_addr_t
*) (h
->h_addr_list
[i
]);
540 peers
->peer
[i
].sockaddr
= (struct sockaddr
*) sin
;
541 peers
->peer
[i
].socklen
= sizeof(struct sockaddr_in
);
543 len
= INET_ADDRSTRLEN
- 1 + 1 + sizeof(":65536") - 1;
545 peers
->peer
[i
].name
.data
= ngx_palloc(cf
->pool
, len
);
546 if (peers
->peer
[i
].name
.data
== NULL
) {
550 len
= ngx_sock_ntop(AF_INET
, (struct sockaddr
*) sin
,
551 peers
->peer
[i
].name
.data
, len
);
553 peers
->peer
[i
].name
.len
=
554 ngx_sprintf(&peers
->peer
[i
].name
.data
[len
],
556 - peers
->peer
[i
].name
.data
;
558 peers
->peer
[i
].uri_separator
= "";
560 peers
->peer
[i
].weight
= NGX_CONF_UNSET_UINT
;
561 peers
->peer
[i
].max_fails
= NGX_CONF_UNSET_UINT
;
562 peers
->peer
[i
].fail_timeout
= NGX_CONF_UNSET
;
567 /* MP: ngx_shared_palloc() */
569 peers
= ngx_pcalloc(cf
->pool
, sizeof(ngx_peers_t
));
574 sin
= ngx_pcalloc(cf
->pool
, sizeof(struct sockaddr_in
));
581 sin
->sin_family
= AF_INET
;
582 sin
->sin_port
= htons(port
);
583 sin
->sin_addr
.s_addr
= in_addr
;
585 peers
->peer
[0].sockaddr
= (struct sockaddr
*) sin
;
586 peers
->peer
[0].socklen
= sizeof(struct sockaddr_in
);
588 peers
->peer
[0].name
.data
= ngx_palloc(cf
->pool
,
589 name
->len
+ sizeof(":65536") - 1);
590 if (peers
->peer
[0].name
.data
== NULL
) {
594 peers
->peer
[0].name
.len
= ngx_sprintf(peers
->peer
[0].name
.data
, "%V:%d",
596 - peers
->peer
[0].name
.data
;
598 peers
->peer
[0].uri_separator
= "";