1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_main.h> 8 9 10static u_char *nxt_listen_socket_log_handler(void *ctx, u_char *pos, 11 u_char *last); 12 13 14nxt_int_t 15nxt_listen_socket_create(nxt_task_t *task, nxt_listen_socket_t *ls, 16 nxt_bool_t bind_test) 17{ 18 nxt_log_t log, *old; 19 nxt_uint_t family; 20 nxt_socket_t s; 21 nxt_thread_t *thr; 22 nxt_sockaddr_t *sa; 23 24 sa = ls->sockaddr; 25 26 thr = nxt_thread(); 27 old = thr->log; 28 log = *thr->log; 29 log.ctx_handler = nxt_listen_socket_log_handler; 30 log.ctx = sa; 31 thr->log = &log; 32 33 family = sa->u.sockaddr.sa_family; 34 35 s = nxt_socket_create(task, family, sa->type, 0, ls->flags); 36 if (s == -1) { 37 goto socket_fail; 38 } 39 40 if (nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_REUSEADDR, 1) != NXT_OK) { 41 goto fail; 42 } 43 44#if (NXT_INET6 && defined IPV6_V6ONLY) 45 46 if (family == AF_INET6 && ls->ipv6only) { 47 int ipv6only; 48 49 ipv6only = (ls->ipv6only == 1); 50 51 /* Ignore possible error. TODO: why? */ 52 (void) nxt_socket_setsockopt(task, s, IPPROTO_IPV6, IPV6_V6ONLY, 53 ipv6only); 54 } 55 56#endif 57 58#if 0 59 60 /* Ignore possible error. TODO: why? */ 61 (void) nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_SNDBUF, 8192); 62 63#endif 64 65#ifdef TCP_DEFER_ACCEPT 66 67 if (ls->read_after_accept) { 68 /* Defer accept() maximum at 1 second. */ 69 /* Ignore possible error. TODO: why? */ 70 (void) nxt_socket_setsockopt(task, s, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1); 71 } 72 73#endif 74 75 switch (nxt_socket_bind(task, s, sa, bind_test)) { 76 77 case NXT_OK: 78 break; 79 80 case NXT_ERROR: 81 goto fail; 82 83 default: /* NXT_DECLINED: EADDRINUSE on bind() test */ 84 return NXT_OK; 85 } 86 87#if (NXT_HAVE_UNIX_DOMAIN) 88 89 if (family == AF_UNIX) { 90 nxt_file_name_t *name; 91 nxt_file_access_t access; 92 93 name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; 94 95 access = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 96 97 if (nxt_file_set_access(name, access) != NXT_OK) { 98 goto fail; 99 } 100 101 if (bind_test && nxt_file_delete(name) != NXT_OK) { 102 goto fail; 103 } 104 } 105 106#endif 107 108 nxt_debug(task, "listen(%d, %d)", s, ls->backlog); 109 110 if (listen(s, ls->backlog) != 0) { 111 nxt_log(task, NXT_LOG_CRIT, "listen(%d, %d) failed %E", 112 s, ls->backlog, nxt_socket_errno); 113 goto fail; 114 } 115 116 ls->socket = s; 117 thr->log = old; 118 119 return NXT_OK; 120 121fail: 122 123 nxt_socket_close(task, s); 124 125socket_fail: 126 127 thr->log = old; 128 129 return NXT_ERROR; 130} 131 132 133nxt_int_t 134nxt_listen_socket_update(nxt_task_t *task, nxt_listen_socket_t *ls, 135 nxt_listen_socket_t *prev) 136{ 137 nxt_log_t log, *old; 138 nxt_thread_t *thr; 139 140 ls->socket = prev->socket; 141 142 thr = nxt_thread(); 143 old = thr->log; 144 log = *thr->log; 145 log.ctx_handler = nxt_listen_socket_log_handler; 146 log.ctx = ls->sockaddr; 147 thr->log = &log; 148 149 nxt_debug(task, "listen(%d, %d)", ls->socket, ls->backlog); 150 151 if (listen(ls->socket, ls->backlog) != 0) { 152 nxt_log(task, NXT_LOG_CRIT, "listen(%d, %d) failed %E", 153 ls->socket, ls->backlog, nxt_socket_errno); 154 goto fail; 155 } 156 157 thr->log = old; 158 159 return NXT_OK; 160 161fail: 162 163 thr->log = old; 164 165 return NXT_ERROR; 166} 167 168 169size_t 170nxt_listen_socket_pool_min_size(nxt_listen_socket_t *ls) 171{ 172 size_t size; 173 174 /* 175 * The first nxt_sockaddr_t is intended for mandatory remote sockaddr 176 * and textual representaion with port. The second nxt_sockaddr_t 177 * is intended for local sockaddr without textual representaion which 178 * may be required to get specific address of connection received on 179 * wildcard AF_INET and AF_INET6 addresses. For AF_UNIX addresses 180 * the local sockaddr is not required. 181 */ 182 183 switch (ls->sockaddr->u.sockaddr.sa_family) { 184 185#if (NXT_INET6) 186 187 case AF_INET6: 188 ls->socklen = sizeof(struct sockaddr_in6); 189 ls->address_length = NXT_INET6_ADDR_STR_LEN; 190 191 size = offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in6) 192 + NXT_INET6_ADDR_STR_LEN + (sizeof(":65535") - 1); 193 194 if (IN6_IS_ADDR_UNSPECIFIED(&ls->sockaddr->u.sockaddr_in6.sin6_addr)) { 195 size += offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in6); 196 } 197 198 break; 199 200#endif 201 202#if (NXT_HAVE_UNIX_DOMAIN) 203 204 case AF_UNIX: 205 /* 206 * A remote socket is usually unbound and thus has unspecified Unix 207 * domain sockaddr_un which can be shortcut to 3 bytes. To handle 208 * a bound remote socket correctly ls->socklen should be at least 209 * sizeof(struct sockaddr_un), see comment in unix/nxt_socket.h. 210 */ 211 ls->socklen = 3; 212 size = ls->socklen + sizeof("unix:") - 1; 213 ls->address_length = sizeof("unix:") - 1; 214 215 break; 216 217#endif 218 219 default: 220 ls->socklen = sizeof(struct sockaddr_in); 221 ls->address_length = NXT_INET_ADDR_STR_LEN; 222 223 size = offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in) 224 + NXT_INET_ADDR_STR_LEN + (sizeof(":65535") - 1); 225 226 if (ls->sockaddr->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY) { 227 size += offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in); 228 } 229 230 break; 231 } 232 233#if (NXT_SSLTLS) 234 235 if (ls->ssltls) { 236 size += 4 * sizeof(void *) /* SSL/TLS connection */ 237 + sizeof(nxt_buf_mem_t) 238 + sizeof(nxt_mem_pool_cleanup_t); 239 } 240 241#endif 242 243 return size + sizeof(nxt_mem_pool_t)
| 1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_main.h> 8 9 10static u_char *nxt_listen_socket_log_handler(void *ctx, u_char *pos, 11 u_char *last); 12 13 14nxt_int_t 15nxt_listen_socket_create(nxt_task_t *task, nxt_listen_socket_t *ls, 16 nxt_bool_t bind_test) 17{ 18 nxt_log_t log, *old; 19 nxt_uint_t family; 20 nxt_socket_t s; 21 nxt_thread_t *thr; 22 nxt_sockaddr_t *sa; 23 24 sa = ls->sockaddr; 25 26 thr = nxt_thread(); 27 old = thr->log; 28 log = *thr->log; 29 log.ctx_handler = nxt_listen_socket_log_handler; 30 log.ctx = sa; 31 thr->log = &log; 32 33 family = sa->u.sockaddr.sa_family; 34 35 s = nxt_socket_create(task, family, sa->type, 0, ls->flags); 36 if (s == -1) { 37 goto socket_fail; 38 } 39 40 if (nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_REUSEADDR, 1) != NXT_OK) { 41 goto fail; 42 } 43 44#if (NXT_INET6 && defined IPV6_V6ONLY) 45 46 if (family == AF_INET6 && ls->ipv6only) { 47 int ipv6only; 48 49 ipv6only = (ls->ipv6only == 1); 50 51 /* Ignore possible error. TODO: why? */ 52 (void) nxt_socket_setsockopt(task, s, IPPROTO_IPV6, IPV6_V6ONLY, 53 ipv6only); 54 } 55 56#endif 57 58#if 0 59 60 /* Ignore possible error. TODO: why? */ 61 (void) nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_SNDBUF, 8192); 62 63#endif 64 65#ifdef TCP_DEFER_ACCEPT 66 67 if (ls->read_after_accept) { 68 /* Defer accept() maximum at 1 second. */ 69 /* Ignore possible error. TODO: why? */ 70 (void) nxt_socket_setsockopt(task, s, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1); 71 } 72 73#endif 74 75 switch (nxt_socket_bind(task, s, sa, bind_test)) { 76 77 case NXT_OK: 78 break; 79 80 case NXT_ERROR: 81 goto fail; 82 83 default: /* NXT_DECLINED: EADDRINUSE on bind() test */ 84 return NXT_OK; 85 } 86 87#if (NXT_HAVE_UNIX_DOMAIN) 88 89 if (family == AF_UNIX) { 90 nxt_file_name_t *name; 91 nxt_file_access_t access; 92 93 name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; 94 95 access = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 96 97 if (nxt_file_set_access(name, access) != NXT_OK) { 98 goto fail; 99 } 100 101 if (bind_test && nxt_file_delete(name) != NXT_OK) { 102 goto fail; 103 } 104 } 105 106#endif 107 108 nxt_debug(task, "listen(%d, %d)", s, ls->backlog); 109 110 if (listen(s, ls->backlog) != 0) { 111 nxt_log(task, NXT_LOG_CRIT, "listen(%d, %d) failed %E", 112 s, ls->backlog, nxt_socket_errno); 113 goto fail; 114 } 115 116 ls->socket = s; 117 thr->log = old; 118 119 return NXT_OK; 120 121fail: 122 123 nxt_socket_close(task, s); 124 125socket_fail: 126 127 thr->log = old; 128 129 return NXT_ERROR; 130} 131 132 133nxt_int_t 134nxt_listen_socket_update(nxt_task_t *task, nxt_listen_socket_t *ls, 135 nxt_listen_socket_t *prev) 136{ 137 nxt_log_t log, *old; 138 nxt_thread_t *thr; 139 140 ls->socket = prev->socket; 141 142 thr = nxt_thread(); 143 old = thr->log; 144 log = *thr->log; 145 log.ctx_handler = nxt_listen_socket_log_handler; 146 log.ctx = ls->sockaddr; 147 thr->log = &log; 148 149 nxt_debug(task, "listen(%d, %d)", ls->socket, ls->backlog); 150 151 if (listen(ls->socket, ls->backlog) != 0) { 152 nxt_log(task, NXT_LOG_CRIT, "listen(%d, %d) failed %E", 153 ls->socket, ls->backlog, nxt_socket_errno); 154 goto fail; 155 } 156 157 thr->log = old; 158 159 return NXT_OK; 160 161fail: 162 163 thr->log = old; 164 165 return NXT_ERROR; 166} 167 168 169size_t 170nxt_listen_socket_pool_min_size(nxt_listen_socket_t *ls) 171{ 172 size_t size; 173 174 /* 175 * The first nxt_sockaddr_t is intended for mandatory remote sockaddr 176 * and textual representaion with port. The second nxt_sockaddr_t 177 * is intended for local sockaddr without textual representaion which 178 * may be required to get specific address of connection received on 179 * wildcard AF_INET and AF_INET6 addresses. For AF_UNIX addresses 180 * the local sockaddr is not required. 181 */ 182 183 switch (ls->sockaddr->u.sockaddr.sa_family) { 184 185#if (NXT_INET6) 186 187 case AF_INET6: 188 ls->socklen = sizeof(struct sockaddr_in6); 189 ls->address_length = NXT_INET6_ADDR_STR_LEN; 190 191 size = offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in6) 192 + NXT_INET6_ADDR_STR_LEN + (sizeof(":65535") - 1); 193 194 if (IN6_IS_ADDR_UNSPECIFIED(&ls->sockaddr->u.sockaddr_in6.sin6_addr)) { 195 size += offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in6); 196 } 197 198 break; 199 200#endif 201 202#if (NXT_HAVE_UNIX_DOMAIN) 203 204 case AF_UNIX: 205 /* 206 * A remote socket is usually unbound and thus has unspecified Unix 207 * domain sockaddr_un which can be shortcut to 3 bytes. To handle 208 * a bound remote socket correctly ls->socklen should be at least 209 * sizeof(struct sockaddr_un), see comment in unix/nxt_socket.h. 210 */ 211 ls->socklen = 3; 212 size = ls->socklen + sizeof("unix:") - 1; 213 ls->address_length = sizeof("unix:") - 1; 214 215 break; 216 217#endif 218 219 default: 220 ls->socklen = sizeof(struct sockaddr_in); 221 ls->address_length = NXT_INET_ADDR_STR_LEN; 222 223 size = offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in) 224 + NXT_INET_ADDR_STR_LEN + (sizeof(":65535") - 1); 225 226 if (ls->sockaddr->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY) { 227 size += offsetof(nxt_sockaddr_t, u) + sizeof(struct sockaddr_in); 228 } 229 230 break; 231 } 232 233#if (NXT_SSLTLS) 234 235 if (ls->ssltls) { 236 size += 4 * sizeof(void *) /* SSL/TLS connection */ 237 + sizeof(nxt_buf_mem_t) 238 + sizeof(nxt_mem_pool_cleanup_t); 239 } 240 241#endif 242 243 return size + sizeof(nxt_mem_pool_t)
|