Mercurial > hg > nginx-mail
comparison src/core/ngx_connection.c @ 665:0b460e61bdcd default tip
Merge with nginx 1.0.0.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Apr 2011 04:22:17 +0400 |
parents | b9763778e212 |
children |
comparison
equal
deleted
inserted
replaced
572:06419a2298a9 | 665:0b460e61bdcd |
---|---|
10 | 10 |
11 | 11 |
12 ngx_os_io_t ngx_io; | 12 ngx_os_io_t ngx_io; |
13 | 13 |
14 | 14 |
15 static void ngx_drain_connections(void); | |
16 | |
17 | |
15 ngx_listening_t * | 18 ngx_listening_t * |
16 ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen) | 19 ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen) |
17 { | 20 { |
21 size_t len; | |
18 ngx_listening_t *ls; | 22 ngx_listening_t *ls; |
19 struct sockaddr *sa; | 23 struct sockaddr *sa; |
20 u_char text[NGX_SOCKADDR_STRLEN]; | 24 u_char text[NGX_SOCKADDR_STRLEN]; |
21 | 25 |
22 ls = ngx_array_push(&cf->cycle->listening); | 26 ls = ngx_array_push(&cf->cycle->listening); |
34 ngx_memcpy(sa, sockaddr, socklen); | 38 ngx_memcpy(sa, sockaddr, socklen); |
35 | 39 |
36 ls->sockaddr = sa; | 40 ls->sockaddr = sa; |
37 ls->socklen = socklen; | 41 ls->socklen = socklen; |
38 | 42 |
39 ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1); | 43 len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1); |
40 | 44 ls->addr_text.len = len; |
41 ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len); | |
42 if (ls->addr_text.data == NULL) { | |
43 return NULL; | |
44 } | |
45 | |
46 ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len); | |
47 | |
48 ls->fd = (ngx_socket_t) -1; | |
49 ls->type = SOCK_STREAM; | |
50 | 45 |
51 switch (ls->sockaddr->sa_family) { | 46 switch (ls->sockaddr->sa_family) { |
52 #if (NGX_HAVE_INET6) | 47 #if (NGX_HAVE_INET6) |
53 case AF_INET6: | 48 case AF_INET6: |
54 ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN; | 49 ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN; |
50 break; | |
51 #endif | |
52 #if (NGX_HAVE_UNIX_DOMAIN) | |
53 case AF_UNIX: | |
54 ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN; | |
55 len++; | |
55 break; | 56 break; |
56 #endif | 57 #endif |
57 case AF_INET: | 58 case AF_INET: |
58 ls->addr_text_max_len = NGX_INET_ADDRSTRLEN; | 59 ls->addr_text_max_len = NGX_INET_ADDRSTRLEN; |
59 break; | 60 break; |
60 default: | 61 default: |
61 ls->addr_text_max_len = NGX_SOCKADDR_STRLEN; | 62 ls->addr_text_max_len = NGX_SOCKADDR_STRLEN; |
62 break; | 63 break; |
63 } | 64 } |
64 | 65 |
66 ls->addr_text.data = ngx_pnalloc(cf->pool, len); | |
67 if (ls->addr_text.data == NULL) { | |
68 return NULL; | |
69 } | |
70 | |
71 ngx_memcpy(ls->addr_text.data, text, len); | |
72 | |
73 ls->fd = (ngx_socket_t) -1; | |
74 ls->type = SOCK_STREAM; | |
75 | |
65 ls->backlog = NGX_LISTEN_BACKLOG; | 76 ls->backlog = NGX_LISTEN_BACKLOG; |
66 ls->rcvbuf = -1; | 77 ls->rcvbuf = -1; |
67 ls->sndbuf = -1; | 78 ls->sndbuf = -1; |
79 | |
80 #if (NGX_HAVE_SETFIB) | |
81 ls->setfib = -1; | |
82 #endif | |
68 | 83 |
69 return ls; | 84 return ls; |
70 } | 85 } |
71 | 86 |
72 | 87 |
86 #endif | 101 #endif |
87 | 102 |
88 ls = cycle->listening.elts; | 103 ls = cycle->listening.elts; |
89 for (i = 0; i < cycle->listening.nelts; i++) { | 104 for (i = 0; i < cycle->listening.nelts; i++) { |
90 | 105 |
91 /* AF_INET only */ | 106 ls[i].sockaddr = ngx_palloc(cycle->pool, NGX_SOCKADDRLEN); |
92 | |
93 ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(struct sockaddr_in)); | |
94 if (ls[i].sockaddr == NULL) { | 107 if (ls[i].sockaddr == NULL) { |
95 return NGX_ERROR; | 108 return NGX_ERROR; |
96 } | 109 } |
97 | 110 |
98 ls[i].socklen = sizeof(struct sockaddr_in); | 111 ls[i].socklen = NGX_SOCKADDRLEN; |
99 if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) { | 112 if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) { |
100 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, | 113 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, |
101 "getsockname() of the inherited " | 114 "getsockname() of the inherited " |
102 "socket #%d failed", ls[i].fd); | 115 "socket #%d failed", ls[i].fd); |
103 ls[i].ignore = 1; | 116 ls[i].ignore = 1; |
107 switch (ls[i].sockaddr->sa_family) { | 120 switch (ls[i].sockaddr->sa_family) { |
108 | 121 |
109 #if (NGX_HAVE_INET6) | 122 #if (NGX_HAVE_INET6) |
110 case AF_INET6: | 123 case AF_INET6: |
111 ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN; | 124 ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN; |
125 len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1; | |
126 break; | |
127 #endif | |
128 | |
129 #if (NGX_HAVE_UNIX_DOMAIN) | |
130 case AF_UNIX: | |
131 ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN; | |
132 len = NGX_UNIX_ADDRSTRLEN; | |
112 break; | 133 break; |
113 #endif | 134 #endif |
114 | 135 |
115 case AF_INET: | 136 case AF_INET: |
116 ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN; | 137 ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN; |
138 len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; | |
117 break; | 139 break; |
118 | 140 |
119 default: | 141 default: |
120 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, | 142 ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, |
121 "the inherited socket #%d has " | 143 "the inherited socket #%d has " |
122 "an unsupported protocol family", ls[i].fd); | 144 "an unsupported protocol family", ls[i].fd); |
123 ls[i].ignore = 1; | 145 ls[i].ignore = 1; |
124 continue; | 146 continue; |
125 } | 147 } |
126 | |
127 len = ls[i].addr_text_max_len + sizeof(":65535") - 1; | |
128 | 148 |
129 ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len); | 149 ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len); |
130 if (ls[i].addr_text.data == NULL) { | 150 if (ls[i].addr_text.data == NULL) { |
131 return NGX_ERROR; | 151 return NGX_ERROR; |
132 } | 152 } |
163 "getsockopt(SO_SNDBUF) %V failed, ignored", | 183 "getsockopt(SO_SNDBUF) %V failed, ignored", |
164 &ls[i].addr_text); | 184 &ls[i].addr_text); |
165 | 185 |
166 ls[i].sndbuf = -1; | 186 ls[i].sndbuf = -1; |
167 } | 187 } |
188 | |
189 #if 0 | |
190 /* SO_SETFIB is currently a set only option */ | |
191 | |
192 #if (NGX_HAVE_SETFIB) | |
193 | |
194 if (getsockopt(ls[i].setfib, SOL_SOCKET, SO_SETFIB, | |
195 (void *) &ls[i].setfib, &olen) | |
196 == -1) | |
197 { | |
198 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, | |
199 "getsockopt(SO_SETFIB) %V failed, ignored", | |
200 &ls[i].addr_text); | |
201 | |
202 ls[i].setfib = -1; | |
203 } | |
204 | |
205 #endif | |
206 #endif | |
168 | 207 |
169 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) | 208 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) |
170 | 209 |
171 ngx_memzero(&af, sizeof(struct accept_filter_arg)); | 210 ngx_memzero(&af, sizeof(struct accept_filter_arg)); |
172 olen = sizeof(struct accept_filter_arg); | 211 olen = sizeof(struct accept_filter_arg); |
355 failed = 1; | 394 failed = 1; |
356 | 395 |
357 continue; | 396 continue; |
358 } | 397 } |
359 | 398 |
399 #if (NGX_HAVE_UNIX_DOMAIN) | |
400 | |
401 if (ls[i].sockaddr->sa_family == AF_UNIX) { | |
402 mode_t mode; | |
403 u_char *name; | |
404 | |
405 name = ls[i].addr_text.data + sizeof("unix:") - 1; | |
406 mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); | |
407 | |
408 if (chmod((char *) name, mode) == -1) { | |
409 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
410 "chmod() \"%s\" failed", name); | |
411 } | |
412 | |
413 if (ngx_test_config) { | |
414 if (ngx_delete_file(name) == -1) { | |
415 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
416 ngx_delete_file_n " %s failed", name); | |
417 } | |
418 } | |
419 } | |
420 #endif | |
421 | |
360 if (listen(s, ls[i].backlog) == -1) { | 422 if (listen(s, ls[i].backlog) == -1) { |
361 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, | 423 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, |
362 "listen() to %V, backlog %d failed", | 424 "listen() to %V, backlog %d failed", |
363 &ls[i].addr_text, ls[i].backlog); | 425 &ls[i].addr_text, ls[i].backlog); |
364 | 426 |
434 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, | 496 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, |
435 "setsockopt(SO_SNDBUF, %d) %V failed, ignored", | 497 "setsockopt(SO_SNDBUF, %d) %V failed, ignored", |
436 ls[i].sndbuf, &ls[i].addr_text); | 498 ls[i].sndbuf, &ls[i].addr_text); |
437 } | 499 } |
438 } | 500 } |
501 | |
502 #if (NGX_HAVE_SETFIB) | |
503 if (ls[i].setfib != -1) { | |
504 if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB, | |
505 (const void *) &ls[i].setfib, sizeof(int)) | |
506 == -1) | |
507 { | |
508 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, | |
509 "setsockopt(SO_SETFIB, %d) %V failed, ignored", | |
510 ls[i].setfib, &ls[i].addr_text); | |
511 } | |
512 } | |
513 #endif | |
439 | 514 |
440 #if 0 | 515 #if 0 |
441 if (1) { | 516 if (1) { |
442 int tcp_nodelay = 1; | 517 int tcp_nodelay = 1; |
443 | 518 |
602 if (ngx_close_socket(ls[i].fd) == -1) { | 677 if (ngx_close_socket(ls[i].fd) == -1) { |
603 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, | 678 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, |
604 ngx_close_socket_n " %V failed", &ls[i].addr_text); | 679 ngx_close_socket_n " %V failed", &ls[i].addr_text); |
605 } | 680 } |
606 | 681 |
682 #if (NGX_HAVE_UNIX_DOMAIN) | |
683 | |
684 if (ls[i].sockaddr->sa_family == AF_UNIX | |
685 && ngx_process <= NGX_PROCESS_MASTER | |
686 && ngx_new_binary == 0) | |
687 { | |
688 u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1; | |
689 | |
690 if (ngx_delete_file(name) == -1) { | |
691 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, | |
692 ngx_delete_file_n " %s failed", name); | |
693 } | |
694 } | |
695 | |
696 #endif | |
697 | |
607 ls[i].fd = (ngx_socket_t) -1; | 698 ls[i].fd = (ngx_socket_t) -1; |
608 } | 699 } |
609 } | 700 } |
610 | 701 |
611 | 702 |
629 /* ngx_mutex_lock */ | 720 /* ngx_mutex_lock */ |
630 | 721 |
631 c = ngx_cycle->free_connections; | 722 c = ngx_cycle->free_connections; |
632 | 723 |
633 if (c == NULL) { | 724 if (c == NULL) { |
725 ngx_drain_connections(); | |
726 c = ngx_cycle->free_connections; | |
727 } | |
728 | |
729 if (c == NULL) { | |
634 ngx_log_error(NGX_LOG_ALERT, log, 0, | 730 ngx_log_error(NGX_LOG_ALERT, log, 0, |
635 "%ui worker_connections are not enough", | 731 "%ui worker_connections are not enough", |
636 ngx_cycle->connection_n); | 732 ngx_cycle->connection_n); |
637 | 733 |
638 /* ngx_mutex_unlock */ | 734 /* ngx_mutex_unlock */ |
771 c->read->closed = 1; | 867 c->read->closed = 1; |
772 c->write->closed = 1; | 868 c->write->closed = 1; |
773 | 869 |
774 #endif | 870 #endif |
775 | 871 |
872 ngx_reusable_connection(c, 0); | |
873 | |
776 log_error = c->log_error; | 874 log_error = c->log_error; |
777 | 875 |
778 ngx_free_connection(c); | 876 ngx_free_connection(c); |
779 | 877 |
780 fd = c->fd; | 878 fd = c->fd; |
806 | 904 |
807 /* we use ngx_cycle->log because c->log was in c->pool */ | 905 /* we use ngx_cycle->log because c->log was in c->pool */ |
808 | 906 |
809 ngx_log_error(level, ngx_cycle->log, err, | 907 ngx_log_error(level, ngx_cycle->log, err, |
810 ngx_close_socket_n " %d failed", fd); | 908 ngx_close_socket_n " %d failed", fd); |
909 } | |
910 } | |
911 | |
912 | |
913 void | |
914 ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable) | |
915 { | |
916 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, | |
917 "reusable connection: %ui", reusable); | |
918 | |
919 if (c->reusable) { | |
920 ngx_queue_remove(&c->queue); | |
921 } | |
922 | |
923 c->reusable = reusable; | |
924 | |
925 if (reusable) { | |
926 /* need cast as ngx_cycle is volatile */ | |
927 | |
928 ngx_queue_insert_head( | |
929 (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue); | |
930 } | |
931 } | |
932 | |
933 | |
934 static void | |
935 ngx_drain_connections(void) | |
936 { | |
937 ngx_int_t i; | |
938 ngx_queue_t *q; | |
939 ngx_connection_t *c; | |
940 | |
941 for (i = 0; i < 32; i++) { | |
942 if (ngx_queue_empty(&ngx_cycle->reusable_connections_queue)) { | |
943 break; | |
944 } | |
945 | |
946 q = ngx_queue_last(&ngx_cycle->reusable_connections_queue); | |
947 c = ngx_queue_data(q, ngx_connection_t, queue); | |
948 | |
949 ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, | |
950 "reusing connection"); | |
951 | |
952 c->close = 1; | |
953 c->read->handler(c->read); | |
811 } | 954 } |
812 } | 955 } |
813 | 956 |
814 | 957 |
815 ngx_int_t | 958 ngx_int_t |
856 c->local_sockaddr = ngx_palloc(c->pool, len); | 999 c->local_sockaddr = ngx_palloc(c->pool, len); |
857 if (c->local_sockaddr == NULL) { | 1000 if (c->local_sockaddr == NULL) { |
858 return NGX_ERROR; | 1001 return NGX_ERROR; |
859 } | 1002 } |
860 | 1003 |
861 c->local_socklen = len; | |
862 ngx_memcpy(c->local_sockaddr, &sa, len); | 1004 ngx_memcpy(c->local_sockaddr, &sa, len); |
863 } | 1005 } |
864 | 1006 |
865 if (s == NULL) { | 1007 if (s == NULL) { |
866 return NGX_OK; | 1008 return NGX_OK; |
915 case NGX_ERROR_IGNORE_ECONNRESET: | 1057 case NGX_ERROR_IGNORE_ECONNRESET: |
916 case NGX_ERROR_INFO: | 1058 case NGX_ERROR_INFO: |
917 level = NGX_LOG_INFO; | 1059 level = NGX_LOG_INFO; |
918 break; | 1060 break; |
919 | 1061 |
920 case NGX_ERROR_ERR: | 1062 default: |
921 level = NGX_LOG_ERR; | 1063 level = NGX_LOG_ERR; |
922 break; | |
923 | |
924 default: | |
925 level = NGX_LOG_ALERT; | |
926 } | 1064 } |
927 | 1065 |
928 } else { | 1066 } else { |
929 level = NGX_LOG_ALERT; | 1067 level = NGX_LOG_ALERT; |
930 } | 1068 } |