blob: cf4b8f699ad66b779f8a1f93b8e97ac6a453bd01 [file] [log] [blame]
Igor Sysoev42feecb2002-12-15 06:25:09 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoev42feecb2002-12-15 06:25:09 +00007#include <ngx_config.h>
Igor Sysoev1c104622003-06-03 15:42:58 +00008#include <ngx_core.h>
Igor Sysoev02025fd2005-01-18 13:03:58 +00009#include <ngx_event.h>
10#include <ngx_event_connect.h>
Igor Sysoev42feecb2002-12-15 06:25:09 +000011
12
Igor Sysoev1b735832004-11-11 14:07:14 +000013/*
14 * ngx_sock_ntop() and ngx_inet_ntop() may be implemented as
Igor Sysoevc31a9bb2005-11-26 10:11:11 +000015 * "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
Igor Sysoev1b735832004-11-11 14:07:14 +000017 * and they are faster by 1.5-2.5 times, so it is worth to keep them.
18 *
19 * By the way, the implementation using ngx_sprintf() is faster by 2.5-3 times
Igor Sysoev02025fd2005-01-18 13:03:58 +000020 * than using FreeBSD libc's snprintf().
Igor Sysoev1b735832004-11-11 14:07:14 +000021 */
22
23
Igor Sysoev94e32ce2006-04-07 14:08:04 +000024static ngx_inline size_t
25ngx_sprint_uchar(u_char *text, u_char c, size_t len)
Igor Sysoev9c610952004-03-16 13:35:20 +000026{
27 size_t n;
28 ngx_uint_t c1, c2;
29
30 n = 0;
31
32 if (len == n) {
33 return n;
34 }
35
36 c1 = c / 100;
37
38 if (c1) {
39 *text++ = (u_char) (c1 + '0');
40 n++;
41
42 if (len == n) {
43 return n;
44 }
45 }
46
47 c2 = (c % 100) / 10;
48
49 if (c1 || c2) {
50 *text++ = (u_char) (c2 + '0');
51 n++;
52
53 if (len == n) {
54 return n;
55 }
56 }
57
58 c2 = c % 10;
59
60 *text++ = (u_char) (c2 + '0');
61 n++;
62
63 return n;
64}
65
66
Igor Sysoev86de4cb2003-01-30 07:28:09 +000067/* AF_INET only */
68
Igor Sysoev899b44e2005-05-12 14:58:06 +000069size_t
70ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text, size_t len)
Igor Sysoev86de4cb2003-01-30 07:28:09 +000071{
Igor Sysoev10a543a2004-03-16 07:10:12 +000072 u_char *p;
Igor Sysoev9c610952004-03-16 13:35:20 +000073 size_t n;
74 ngx_uint_t i;
Igor Sysoev02025fd2005-01-18 13:03:58 +000075 struct sockaddr_in *sin;
Igor Sysoev86de4cb2003-01-30 07:28:09 +000076
Igor Sysoev9c610952004-03-16 13:35:20 +000077 if (len == 0) {
78 return 0;
79 }
80
Igor Sysoev86de4cb2003-01-30 07:28:09 +000081 if (family != AF_INET) {
82 return 0;
83 }
84
Igor Sysoev02025fd2005-01-18 13:03:58 +000085 sin = (struct sockaddr_in *) sa;
86 p = (u_char *) &sin->sin_addr;
Igor Sysoev86de4cb2003-01-30 07:28:09 +000087
Igor Sysoev9c610952004-03-16 13:35:20 +000088 if (len > INET_ADDRSTRLEN) {
89 len = INET_ADDRSTRLEN;
90 }
91
92 n = ngx_sprint_uchar(text, p[0], len);
93
94 i = 1;
95
96 do {
97 if (len == n) {
98 text[n - 1] = '\0';
99 return n;
100 }
101
102 text[n++] = '.';
103
104 if (len == n) {
105 text[n - 1] = '\0';
106 return n;
107 }
108
109 n += ngx_sprint_uchar(&text[n], p[i++], len - n);
110
111 } while (i < 4);
112
113 if (len == n) {
114 text[n] = '\0';
115 return n;
116 }
117
118 text[n] = '\0';
119
120 return n;
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000121}
122
Igor Sysoev899b44e2005-05-12 14:58:06 +0000123size_t
124ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
Igor Sysoev42feecb2002-12-15 06:25:09 +0000125{
Igor Sysoev9c610952004-03-16 13:35:20 +0000126 u_char *p;
127 size_t n;
128 ngx_uint_t i;
129
130 if (len == 0) {
131 return 0;
132 }
133
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000134 if (family != AF_INET) {
Igor Sysoev42feecb2002-12-15 06:25:09 +0000135 return 0;
Igor Sysoev86de4cb2003-01-30 07:28:09 +0000136 }
Igor Sysoev42feecb2002-12-15 06:25:09 +0000137
Igor Sysoev9c610952004-03-16 13:35:20 +0000138 p = (u_char *) addr;
139
140 if (len > INET_ADDRSTRLEN) {
141 len = INET_ADDRSTRLEN;
142 }
143
144 n = ngx_sprint_uchar(text, p[0], len);
145
146 i = 1;
147
148 do {
149 if (len == n) {
150 text[n - 1] = '\0';
151 return n;
152 }
153
154 text[n++] = '.';
155
156 if (len == n) {
157 text[n - 1] = '\0';
158 return n;
159 }
160
161 n += ngx_sprint_uchar(&text[n], p[i++], len - n);
162
163 } while (i < 4);
164
165 if (len == n) {
166 text[n] = '\0';
167 return n;
168 }
169
170 text[n] = '\0';
171
172 return n;
Igor Sysoev42feecb2002-12-15 06:25:09 +0000173}
Igor Sysoev822834e2004-05-25 15:28:46 +0000174
175
176/* AF_INET only */
177
Igor Sysoev899b44e2005-05-12 14:58:06 +0000178ngx_int_t
179ngx_ptocidr(ngx_str_t *text, void *cidr)
Igor Sysoev822834e2004-05-25 15:28:46 +0000180{
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000181 ngx_int_t m;
Igor Sysoev822834e2004-05-25 15:28:46 +0000182 ngx_uint_t i;
183 ngx_inet_cidr_t *in_cidr;
184
185 in_cidr = cidr;
186
187 for (i = 0; i < text->len; i++) {
188 if (text->data[i] == '/') {
189 break;
190 }
191 }
192
193 if (i == text->len) {
194 return NGX_ERROR;
195 }
196
197 text->data[i] = '\0';
198 in_cidr->addr = inet_addr((char *) text->data);
199 text->data[i] = '/';
200 if (in_cidr->addr == INADDR_NONE) {
201 return NGX_ERROR;
202 }
203
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000204 m = ngx_atoi(&text->data[i + 1], text->len - (i + 1));
205 if (m == NGX_ERROR) {
Igor Sysoev822834e2004-05-25 15:28:46 +0000206 return NGX_ERROR;
207 }
208
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000209 if (m == 0) {
210
211 /* the x86 compilers use the shl instruction that shifts by modulo 32 */
212
213 in_cidr->mask = 0;
214 return NGX_OK;
215 }
216
Igor Sysoev6deb0412004-07-30 17:05:14 +0000217 in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - m))));
Igor Sysoev59f3aa32004-06-24 16:07:04 +0000218
Igor Sysoev822834e2004-05-25 15:28:46 +0000219 return NGX_OK;
220}
Igor Sysoeve2ff3ea2004-09-14 15:55:24 +0000221
222
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000223ngx_int_t
224ngx_parse_url(ngx_conf_t *cf, ngx_url_t *u)
225{
226 u_char *p;
227 size_t len;
228 ngx_int_t port;
229 ngx_uint_t i;
230#if (NGX_HAVE_UNIX_DOMAIN)
231 struct sockaddr_un *saun;
232#endif
233
234 len = u->url.len;
235 p = u->url.data;
236
237 if (ngx_strncasecmp(p, "unix:", 5) == 0) {
238
239#if (NGX_HAVE_UNIX_DOMAIN)
240
241 u->type = NGX_PARSE_URL_UNIX;
242
243 p += 5;
244 len -= 5;
245
Igor Sysoev7c20ed82006-09-24 14:45:37 +0000246 u->uri.len = len;
247 u->uri.data = p;
248
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000249 if (u->uri_part) {
250 for (i = 0; i < len; i++) {
251
252 if (p[i] == ':') {
253 len = i;
254
255 u->uri.len -= len + 1;
256 u->uri.data += len + 1;
257
258 break;
259 }
260 }
261 }
262
263 if (len == 0) {
264 u->err = "no path in the unix domain socket";
265 return NGX_ERROR;
266 }
267
268 if (len + 1 > sizeof(saun->sun_path)) {
269 u->err = "too long path in the unix domain socket";
270 return NGX_ERROR;
271 }
272
273 u->peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t));
274 if (u->peers == NULL) {
275 return NGX_ERROR;
276 }
277
278 saun = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_un));
279 if (saun == NULL) {
280 return NGX_ERROR;
281 }
282
283 u->peers->number = 1;
284
285 saun->sun_family = AF_UNIX;
286 (void) ngx_cpystrn((u_char *) saun->sun_path, p, len + 1);
287
288 u->peers->peer[0].sockaddr = (struct sockaddr *) saun;
289 u->peers->peer[0].socklen = sizeof(struct sockaddr_un);
Igor Sysoev7c20ed82006-09-24 14:45:37 +0000290 u->peers->peer[0].name.len = len + 5;
291 u->peers->peer[0].name.data = u->url.data;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000292 u->peers->peer[0].uri_separator = ":";
293
294 u->host_header.len = sizeof("localhost") - 1;
295 u->host_header.data = (u_char *) "localhost";
296
297 return NGX_OK;
298
299#else
300 u->err = "the unix domain sockets are not supported on this platform";
301
302 return NGX_ERROR;
303
304#endif
305 }
306
307 if ((p[0] == ':' || p[0] == '/') && !u->listen) {
308 u->err = "invalid host";
309 return NGX_ERROR;
310 }
311
312 u->type = NGX_PARSE_URL_INET;
313
314 u->host.data = p;
315 u->host_header.len = len;
316 u->host_header.data = p;
317
318 for (i = 0; i < len; i++) {
319
320 if (p[i] == ':') {
321 u->port.data = &p[i + 1];
322 u->host.len = i;
323
324 if (!u->uri_part) {
325 u->port.len = &p[len] - u->port.data;
326 break;
327 }
328 }
329
330 if (p[i] == '/') {
331 u->uri.len = len - i;
332 u->uri.data = &p[i];
333 u->host_header.len = i;
334
335 if (u->host.len == 0) {
336 u->host.len = i;
337 }
338
339 if (u->port.data == NULL) {
340 u->default_port = 1;
341 goto port;
342 }
343
344 u->port.len = &p[i] - u->port.data;
345
346 if (u->port.len == 0) {
347 u->err = "invalid port";
348 return NGX_ERROR;
349 }
350
351 break;
352 }
353 }
354
355 if (u->port.data) {
356
357 if (u->port.len == 0) {
358 u->port.len = &p[i] - u->port.data;
359
360 if (u->port.len == 0) {
361 u->err = "invalid port";
362 return NGX_ERROR;
363 }
364 }
365
366 port = ngx_atoi(u->port.data, u->port.len);
367
368 if (port == NGX_ERROR || port < 1 || port > 65536) {
369 u->err = "invalid port";
370 return NGX_ERROR;
371 }
372
373 } else {
374 port = ngx_atoi(p, len);
375
376 if (port == NGX_ERROR) {
377 u->default_port = 1;
378 u->host.len = len;
379
380 goto port;
381 }
382
383 u->port.len = len;
384 u->port.data = p;
385 u->wildcard = 1;
386 }
387
388 u->portn = (in_port_t) port;
389
390port:
391
392 if (u->listen) {
393 return NGX_OK;
394 }
395
396 if (u->default_port) {
397
398 if (u->upstream) {
399 return NGX_OK;
400 }
401
402 if (u->default_portn == 0) {
403 u->err = "no port";
404 return NGX_ERROR;
405 }
406
407 u->portn = u->default_portn;
408
409 u->port.data = ngx_palloc(cf->pool, sizeof("65536") - 1);
410 if (u->port.data == NULL) {
411 return NGX_ERROR;
412 }
413
414 u->port.len = ngx_sprintf(u->port.data, "%d", u->portn) - u->port.data;
415
416 } else if (u->portn) {
417 if (u->portn == u->default_portn) {
418 u->default_port = 1;
419 }
420
421 } else {
422 u->err = "no port";
423 return NGX_ERROR;
424 }
425
426 if (u->host.len == 0) {
427 u->err = "no host";
428 return NGX_ERROR;
429 }
430
431 u->peers = ngx_inet_resolve_peer(cf, &u->host, u->portn);
432
433 if (u->peers == NULL) {
434 return NGX_ERROR;
435 }
436
437 if (u->peers == NGX_CONF_ERROR) {
438 u->err = "host not found";
439 return NGX_ERROR;
440 }
441
442 return NGX_OK;
443}
444
445
446ngx_peers_t *
447ngx_inet_resolve_peer(ngx_conf_t *cf, ngx_str_t *name, in_port_t port)
448{
449 u_char *host;
450 size_t len;
451 in_addr_t in_addr;
452 ngx_uint_t i;
453 ngx_peers_t *peers;
454 struct hostent *h;
455 struct sockaddr_in *sin;
456
457 host = ngx_palloc(cf->temp_pool, name->len + 1);
458 if (host == NULL) {
459 return NULL;
460 }
461
462 (void) ngx_cpystrn(host, name->data, name->len + 1);
463
464 /* AF_INET only */
465
466 in_addr = inet_addr((char *) host);
467
468 if (in_addr == INADDR_NONE) {
469 h = gethostbyname((char *) host);
470
471 if (h == NULL || h->h_addr_list[0] == NULL) {
472 return NGX_CONF_ERROR;
473 }
474
475 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
476
477 /* MP: ngx_shared_palloc() */
478
479 peers = ngx_pcalloc(cf->pool,
480 sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (i - 1));
481 if (peers == NULL) {
482 return NULL;
483 }
484
485 peers->number = i;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000486
487 for (i = 0; h->h_addr_list[i] != NULL; i++) {
488
489 sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
490 if (sin == NULL) {
491 return NULL;
492 }
493
494 sin->sin_family = AF_INET;
495 sin->sin_port = htons(port);
496 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
497
498 peers->peer[i].sockaddr = (struct sockaddr *) sin;
499 peers->peer[i].socklen = sizeof(struct sockaddr_in);
500
501 len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1;
502
503 peers->peer[i].name.data = ngx_palloc(cf->pool, len);
504 if (peers->peer[i].name.data == NULL) {
505 return NULL;
506 }
507
508 len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin,
509 peers->peer[i].name.data, len);
510
511 peers->peer[i].name.len =
512 ngx_sprintf(&peers->peer[i].name.data[len],
513 ":%d", port)
514 - peers->peer[i].name.data;
515
516 peers->peer[i].uri_separator = "";
Igor Sysoev1765f472006-07-07 16:33:19 +0000517
518 peers->peer[i].weight = NGX_CONF_UNSET_UINT;
519 peers->peer[i].max_fails = NGX_CONF_UNSET_UINT;
520 peers->peer[i].fail_timeout = NGX_CONF_UNSET;
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000521 }
522
523 } else {
524
525 /* MP: ngx_shared_palloc() */
526
527 peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t));
528 if (peers == NULL) {
529 return NULL;
530 }
531
532 sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
533 if (sin == NULL) {
534 return NULL;
535 }
536
537 peers->number = 1;
538
539 sin->sin_family = AF_INET;
540 sin->sin_port = htons(port);
541 sin->sin_addr.s_addr = in_addr;
542
543 peers->peer[0].sockaddr = (struct sockaddr *) sin;
544 peers->peer[0].socklen = sizeof(struct sockaddr_in);
545
546 peers->peer[0].name.data = ngx_palloc(cf->pool,
547 name->len + sizeof(":65536") - 1);
548 if (peers->peer[0].name.data == NULL) {
549 return NULL;
550 }
551
552 peers->peer[0].name.len = ngx_sprintf(peers->peer[0].name.data, "%V:%d",
553 name, port)
554 - peers->peer[0].name.data;
555
556 peers->peer[0].uri_separator = "";
557 }
558
559 return peers;
560}
561
562
Igor Sysoev899b44e2005-05-12 14:58:06 +0000563ngx_peers_t *
564ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u)
Igor Sysoeve2ff3ea2004-09-14 15:55:24 +0000565{
Igor Sysoev02025fd2005-01-18 13:03:58 +0000566 char *err;
567 u_char *host;
Igor Sysoev4959ec42005-05-23 12:07:45 +0000568 size_t len;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000569 in_addr_t in_addr;
Igor Sysoev4959ec42005-05-23 12:07:45 +0000570 ngx_uint_t i;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000571 ngx_peers_t *peers;
572 struct hostent *h;
573 struct sockaddr_in *sin;
Igor Sysoeve2ff3ea2004-09-14 15:55:24 +0000574
Igor Sysoev02025fd2005-01-18 13:03:58 +0000575 err = ngx_inet_parse_host_port(u);
576
577 if (err) {
578 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
579 "%s in upstream \"%V\"", err, &u->name);
580 return NULL;
581 }
582
583 if (u->default_port) {
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000584
Igor Sysoev02025fd2005-01-18 13:03:58 +0000585 if (u->default_port_value == 0) {
586 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
587 "no port in upstream \"%V\"", &u->name);
588 return NULL;
589 }
590
591 u->port = u->default_port_value;
592
Igor Sysoevc1571722005-03-19 12:38:37 +0000593 u->port_text.data = ngx_palloc(cf->pool, sizeof("65536") - 1);
594 if (u->port_text.data == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000595 return NULL;
596 }
597
598 u->port_text.len = ngx_sprintf(u->port_text.data, "%d",
599 u->default_port_value)
600 - u->port_text.data;
601
602 } else if (u->port) {
603 if (u->port == u->default_port_value) {
604 u->default_port = 1;
605 }
606
607 } else {
608 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
609 "no port in upstream \"%V\"", &u->name);
610 return NULL;
611 }
612
613 if (u->host.len == 0) {
614 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
615 "no host in upstream \"%V\"", &u->name);
616 return NULL;
617 }
618
619 u->port = htons(u->port);
620
Igor Sysoev6f134cc2006-05-23 14:54:58 +0000621 host = ngx_palloc(cf->temp_pool, u->host.len + 1);
Igor Sysoevc1571722005-03-19 12:38:37 +0000622 if (host == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000623 return NULL;
624 }
625
Igor Sysoev4959ec42005-05-23 12:07:45 +0000626 (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
Igor Sysoev02025fd2005-01-18 13:03:58 +0000627
628 /* AF_INET only */
629
630 in_addr = inet_addr((char *) host);
631
632 if (in_addr == INADDR_NONE) {
633 h = gethostbyname((char *) host);
634
635 if (h == NULL || h->h_addr_list[0] == NULL) {
636 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
637 "host %s is not found in upstream \"%V\"",
638 host, &u->name);
639 return NULL;
640 }
641
642 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
643
644 /* MP: ngx_shared_palloc() */
645
646 peers = ngx_pcalloc(cf->pool,
647 sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (i - 1));
Igor Sysoev02025fd2005-01-18 13:03:58 +0000648 if (peers == NULL) {
649 return NULL;
650 }
651
652 peers->number = i;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000653
654 for (i = 0; h->h_addr_list[i] != NULL; i++) {
655
Igor Sysoevc1571722005-03-19 12:38:37 +0000656 sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
657 if (sin == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000658 return NULL;
659 }
660
661 sin->sin_family = AF_INET;
662 sin->sin_port = u->port;
Igor Sysoevaa828612005-02-09 14:31:07 +0000663 sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
Igor Sysoev02025fd2005-01-18 13:03:58 +0000664
665 peers->peer[i].sockaddr = (struct sockaddr *) sin;
666 peers->peer[i].socklen = sizeof(struct sockaddr_in);
667
668 len = INET_ADDRSTRLEN - 1 + 1 + u->port_text.len;
Igor Sysoev0e5dc5c2005-11-15 13:30:52 +0000669
Igor Sysoevc1571722005-03-19 12:38:37 +0000670 peers->peer[i].name.data = ngx_palloc(cf->pool, len);
671 if (peers->peer[i].name.data == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000672 return NULL;
673 }
674
675 len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin,
676 peers->peer[i].name.data, len);
677
678 peers->peer[i].name.data[len++] = ':';
679
680 ngx_memcpy(peers->peer[i].name.data + len,
681 u->port_text.data, u->port_text.len);
682
683 peers->peer[i].name.len = len + u->port_text.len;
684
685 peers->peer[i].uri_separator = "";
Igor Sysoev1765f472006-07-07 16:33:19 +0000686
687 peers->peer[i].weight = NGX_CONF_UNSET_UINT;
688 peers->peer[i].max_fails = NGX_CONF_UNSET_UINT;
689 peers->peer[i].fail_timeout = NGX_CONF_UNSET;
Igor Sysoev02025fd2005-01-18 13:03:58 +0000690 }
691
692 } else {
693
694 /* MP: ngx_shared_palloc() */
695
Igor Sysoevc1571722005-03-19 12:38:37 +0000696 peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t));
697 if (peers == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000698 return NULL;
699 }
700
Igor Sysoevc1571722005-03-19 12:38:37 +0000701 sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
702 if (sin == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000703 return NULL;
704 }
705
706 peers->number = 1;
707
708 sin->sin_family = AF_INET;
709 sin->sin_port = u->port;
710 sin->sin_addr.s_addr = in_addr;
711
712 peers->peer[0].sockaddr = (struct sockaddr *) sin;
713 peers->peer[0].socklen = sizeof(struct sockaddr_in);
714
715 len = u->host.len + 1 + u->port_text.len;
716
717 peers->peer[0].name.len = len;
718
Igor Sysoevc1571722005-03-19 12:38:37 +0000719 peers->peer[0].name.data = ngx_palloc(cf->pool, len);
720 if (peers->peer[0].name.data == NULL) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000721 return NULL;
722 }
723
724 len = u->host.len;
725
726 ngx_memcpy(peers->peer[0].name.data, u->host.data, len);
727
728 peers->peer[0].name.data[len++] = ':';
729
730 ngx_memcpy(peers->peer[0].name.data + len,
731 u->port_text.data, u->port_text.len);
732
733 peers->peer[0].uri_separator = "";
734 }
735
736 return peers;
737}
738
739
Igor Sysoev899b44e2005-05-12 14:58:06 +0000740char *
741ngx_inet_parse_host_port(ngx_inet_upstream_t *u)
Igor Sysoev02025fd2005-01-18 13:03:58 +0000742{
743 size_t i;
744 ngx_int_t port;
745 ngx_str_t *url;
746
747 url = &u->url;
748
749 if (u->port_only) {
750 i = 0;
751
752 } else {
753 if (url->data[0] == ':' || url->data[0] == '/') {
754 return "invalid host";
755 }
756
757 i = 1;
758 }
759
760 u->host.data = url->data;
761 u->host_header = *url;
762
Igor Sysoeve31e90b2005-05-19 13:25:22 +0000763 for ( /* void */ ; i < url->len; i++) {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000764
765 if (url->data[i] == ':') {
766 u->port_text.data = &url->data[i] + 1;
767 u->host.len = i;
768
769 if (!u->uri_part) {
770 u->port_text.len = &url->data[url->len] - u->port_text.data;
771 break;
772 }
773 }
774
775 if (url->data[i] == '/') {
776 u->uri.data = &url->data[i];
777 u->uri.len = url->len - i;
778 u->host_header.len = i;
779
780 if (u->host.len == 0) {
781 u->host.len = i;
782 }
783
784 if (u->port_text.data == NULL) {
785 u->default_port = 1;
786 return NULL;
787 }
788
789 u->port_text.len = &url->data[i] - u->port_text.data;
790
791 if (u->port_text.len == 0) {
792 return "invalid port";
793 }
794
Igor Sysoeve2ff3ea2004-09-14 15:55:24 +0000795 break;
796 }
797 }
798
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000799 if (u->port_text.data) {
800
801 if (u->port_text.len == 0) {
802 u->port_text.len = &url->data[i] - u->port_text.data;
803
804 if (u->port_text.len == 0) {
805 return "invalid port";
806 }
807 }
808
809 port = ngx_atoi(u->port_text.data, u->port_text.len);
810
811 if (port == NGX_ERROR || port < 1 || port > 65536) {
812 return "invalid port";
813 }
814
815 } else {
Igor Sysoev02025fd2005-01-18 13:03:58 +0000816 port = ngx_atoi(url->data, url->len);
817
818 if (port == NGX_ERROR) {
819 u->default_port = 1;
820 u->host.len = url->len;
821
822 return NULL;
823 }
824
825 u->port_text = *url;
826 u->wildcard = 1;
Igor Sysoeve2ff3ea2004-09-14 15:55:24 +0000827 }
828
Igor Sysoev02025fd2005-01-18 13:03:58 +0000829 u->port = (in_port_t) port;
Igor Sysoeve2ff3ea2004-09-14 15:55:24 +0000830
Igor Sysoev02025fd2005-01-18 13:03:58 +0000831 return NULL;
Igor Sysoeve2ff3ea2004-09-14 15:55:24 +0000832}