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(nxt_task_t *task, nxt_socket_t s, int backlog) 16{ 17 nxt_debug(task, "listen(%d, %d)", s, backlog); 18 19 if (nxt_fast_path(listen(s, backlog) == 0)) { 20 return NXT_OK; 21 } 22 23 nxt_alert(task, "listen(%d, %d) failed %E", s, backlog, nxt_socket_errno); 24 25 return NXT_ERROR; 26} 27 28 29nxt_int_t 30nxt_listen_socket_create(nxt_task_t *task, nxt_listen_socket_t *ls, 31 nxt_bool_t bind_test) 32{ 33 nxt_log_t log, *old; 34 nxt_uint_t family; 35 nxt_socket_t s; 36 nxt_thread_t *thr; 37 nxt_sockaddr_t *sa; 38 39 sa = ls->sockaddr; 40 41 thr = nxt_thread(); 42 old = thr->log; 43 log = *thr->log; 44 log.ctx_handler = nxt_listen_socket_log_handler; 45 log.ctx = sa; 46 thr->log = &log; 47 48 family = sa->u.sockaddr.sa_family; 49 50 s = nxt_socket_create(task, family, sa->type, 0, ls->flags); 51 if (s == -1) { 52 goto socket_fail; 53 } 54 55 if (nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_REUSEADDR, 1) != NXT_OK) { 56 goto fail; 57 } 58 59#if (NXT_INET6 && defined IPV6_V6ONLY) 60 61 if (family == AF_INET6 && ls->ipv6only) { 62 int ipv6only; 63 64 ipv6only = (ls->ipv6only == 1); 65 66 /* Ignore possible error. TODO: why? */ 67 (void) nxt_socket_setsockopt(task, s, IPPROTO_IPV6, IPV6_V6ONLY, 68 ipv6only); 69 } 70 71#endif 72 73#if 0 74 75 /* Ignore possible error. TODO: why? */ 76 (void) nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_SNDBUF, 8192); 77 78#endif 79 80 if (ls->read_after_accept) { 81 nxt_socket_defer_accept(task, s, sa); 82 } 83 84 switch (nxt_socket_bind(task, s, sa, bind_test)) { 85 86 case NXT_OK: 87 break; 88 89 case NXT_ERROR: 90 goto fail; 91 92 default: /* NXT_DECLINED: EADDRINUSE on bind() test */ 93 return NXT_OK; 94 } 95 96#if (NXT_HAVE_UNIX_DOMAIN) 97 98 if (family == AF_UNIX) { 99 nxt_file_name_t *name; 100 nxt_file_access_t access; 101 102 name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; 103 104 access = (S_IRUSR | S_IWUSR); 105 106 if (nxt_file_set_access(name, access) != NXT_OK) { 107 goto fail; 108 } 109 110 if (bind_test && nxt_file_delete(name) != NXT_OK) { 111 goto fail; 112 } 113 } 114 115#endif 116 117 nxt_debug(task, "listen(%d, %d)", s, ls->backlog); 118 119 if (listen(s, ls->backlog) != 0) { 120 nxt_alert(task, "listen(%d, %d) failed %E", 121 s, ls->backlog, nxt_socket_errno); 122 goto fail; 123 } 124 125 ls->socket = s; 126 thr->log = old; 127 128 return NXT_OK; 129 130fail: 131 132 nxt_socket_close(task, s); 133 134socket_fail: 135 136 thr->log = old; 137 138 return NXT_ERROR; 139} 140 141 142nxt_int_t 143nxt_listen_socket_update(nxt_task_t *task, nxt_listen_socket_t *ls, 144 nxt_listen_socket_t *prev) 145{ 146 nxt_log_t log, *old; 147 nxt_thread_t *thr; 148 149 ls->socket = prev->socket; 150 151 thr = nxt_thread(); 152 old = thr->log; 153 log = *thr->log; 154 log.ctx_handler = nxt_listen_socket_log_handler; 155 log.ctx = ls->sockaddr; 156 thr->log = &log; 157 158 nxt_debug(task, "listen(%d, %d)", ls->socket, ls->backlog); 159 160 if (listen(ls->socket, ls->backlog) != 0) { 161 nxt_alert(task, "listen(%d, %d) failed %E", 162 ls->socket, ls->backlog, nxt_socket_errno); 163 goto fail; 164 } 165 166 thr->log = old; 167 168 return NXT_OK; 169 170fail: 171 172 thr->log = old; 173 174 return NXT_ERROR; 175} 176 177 178void 179nxt_listen_socket_remote_size(nxt_listen_socket_t *ls) 180{ 181 switch (ls->sockaddr->u.sockaddr.sa_family) { 182 183#if (NXT_INET6) 184 185 case AF_INET6: 186 ls->socklen = sizeof(struct sockaddr_in6); 187 ls->address_length = NXT_INET6_ADDR_STR_LEN; 188 189 break; 190 191#endif 192 193#if (NXT_HAVE_UNIX_DOMAIN) 194 195 case AF_UNIX: 196 /* 197 * A remote socket is usually unbound and thus has unspecified Unix 198 * domain sockaddr_un which can be shortcut to 3 bytes. To handle 199 * a bound remote socket correctly ls->socklen should be larger, see 200 * comment in nxt_socket.h. 201 */ 202 ls->socklen = offsetof(struct sockaddr_un, sun_path) + 1;
| 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(nxt_task_t *task, nxt_socket_t s, int backlog) 16{ 17 nxt_debug(task, "listen(%d, %d)", s, backlog); 18 19 if (nxt_fast_path(listen(s, backlog) == 0)) { 20 return NXT_OK; 21 } 22 23 nxt_alert(task, "listen(%d, %d) failed %E", s, backlog, nxt_socket_errno); 24 25 return NXT_ERROR; 26} 27 28 29nxt_int_t 30nxt_listen_socket_create(nxt_task_t *task, nxt_listen_socket_t *ls, 31 nxt_bool_t bind_test) 32{ 33 nxt_log_t log, *old; 34 nxt_uint_t family; 35 nxt_socket_t s; 36 nxt_thread_t *thr; 37 nxt_sockaddr_t *sa; 38 39 sa = ls->sockaddr; 40 41 thr = nxt_thread(); 42 old = thr->log; 43 log = *thr->log; 44 log.ctx_handler = nxt_listen_socket_log_handler; 45 log.ctx = sa; 46 thr->log = &log; 47 48 family = sa->u.sockaddr.sa_family; 49 50 s = nxt_socket_create(task, family, sa->type, 0, ls->flags); 51 if (s == -1) { 52 goto socket_fail; 53 } 54 55 if (nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_REUSEADDR, 1) != NXT_OK) { 56 goto fail; 57 } 58 59#if (NXT_INET6 && defined IPV6_V6ONLY) 60 61 if (family == AF_INET6 && ls->ipv6only) { 62 int ipv6only; 63 64 ipv6only = (ls->ipv6only == 1); 65 66 /* Ignore possible error. TODO: why? */ 67 (void) nxt_socket_setsockopt(task, s, IPPROTO_IPV6, IPV6_V6ONLY, 68 ipv6only); 69 } 70 71#endif 72 73#if 0 74 75 /* Ignore possible error. TODO: why? */ 76 (void) nxt_socket_setsockopt(task, s, SOL_SOCKET, SO_SNDBUF, 8192); 77 78#endif 79 80 if (ls->read_after_accept) { 81 nxt_socket_defer_accept(task, s, sa); 82 } 83 84 switch (nxt_socket_bind(task, s, sa, bind_test)) { 85 86 case NXT_OK: 87 break; 88 89 case NXT_ERROR: 90 goto fail; 91 92 default: /* NXT_DECLINED: EADDRINUSE on bind() test */ 93 return NXT_OK; 94 } 95 96#if (NXT_HAVE_UNIX_DOMAIN) 97 98 if (family == AF_UNIX) { 99 nxt_file_name_t *name; 100 nxt_file_access_t access; 101 102 name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; 103 104 access = (S_IRUSR | S_IWUSR); 105 106 if (nxt_file_set_access(name, access) != NXT_OK) { 107 goto fail; 108 } 109 110 if (bind_test && nxt_file_delete(name) != NXT_OK) { 111 goto fail; 112 } 113 } 114 115#endif 116 117 nxt_debug(task, "listen(%d, %d)", s, ls->backlog); 118 119 if (listen(s, ls->backlog) != 0) { 120 nxt_alert(task, "listen(%d, %d) failed %E", 121 s, ls->backlog, nxt_socket_errno); 122 goto fail; 123 } 124 125 ls->socket = s; 126 thr->log = old; 127 128 return NXT_OK; 129 130fail: 131 132 nxt_socket_close(task, s); 133 134socket_fail: 135 136 thr->log = old; 137 138 return NXT_ERROR; 139} 140 141 142nxt_int_t 143nxt_listen_socket_update(nxt_task_t *task, nxt_listen_socket_t *ls, 144 nxt_listen_socket_t *prev) 145{ 146 nxt_log_t log, *old; 147 nxt_thread_t *thr; 148 149 ls->socket = prev->socket; 150 151 thr = nxt_thread(); 152 old = thr->log; 153 log = *thr->log; 154 log.ctx_handler = nxt_listen_socket_log_handler; 155 log.ctx = ls->sockaddr; 156 thr->log = &log; 157 158 nxt_debug(task, "listen(%d, %d)", ls->socket, ls->backlog); 159 160 if (listen(ls->socket, ls->backlog) != 0) { 161 nxt_alert(task, "listen(%d, %d) failed %E", 162 ls->socket, ls->backlog, nxt_socket_errno); 163 goto fail; 164 } 165 166 thr->log = old; 167 168 return NXT_OK; 169 170fail: 171 172 thr->log = old; 173 174 return NXT_ERROR; 175} 176 177 178void 179nxt_listen_socket_remote_size(nxt_listen_socket_t *ls) 180{ 181 switch (ls->sockaddr->u.sockaddr.sa_family) { 182 183#if (NXT_INET6) 184 185 case AF_INET6: 186 ls->socklen = sizeof(struct sockaddr_in6); 187 ls->address_length = NXT_INET6_ADDR_STR_LEN; 188 189 break; 190 191#endif 192 193#if (NXT_HAVE_UNIX_DOMAIN) 194 195 case AF_UNIX: 196 /* 197 * A remote socket is usually unbound and thus has unspecified Unix 198 * domain sockaddr_un which can be shortcut to 3 bytes. To handle 199 * a bound remote socket correctly ls->socklen should be larger, see 200 * comment in nxt_socket.h. 201 */ 202 ls->socklen = offsetof(struct sockaddr_un, sun_path) + 1;
|