nxt_conn_connect.c (494:7c83ddcc1c42) nxt_conn_connect.c (1263:f3e5fa1fc962)
1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7#include <nxt_main.h>
8
9
1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7#include <nxt_main.h>
8
9
10static nxt_err_t nxt_conn_connect_test_error(nxt_task_t *task, nxt_conn_t *c);
11
12
10void
11nxt_conn_sys_socket(nxt_task_t *task, void *obj, void *data)
12{
13 nxt_conn_t *c;
14 nxt_work_handler_t handler;
15
16 c = obj;
17

--- 26 unchanged lines hidden (view full) ---

44
45 case NXT_OK:
46 c->socket.write_ready = 1;
47 handler = state->ready_handler;
48 break;
49
50 case NXT_AGAIN:
51 c->socket.write_handler = nxt_conn_connect_test;
13void
14nxt_conn_sys_socket(nxt_task_t *task, void *obj, void *data)
15{
16 nxt_conn_t *c;
17 nxt_work_handler_t handler;
18
19 c = obj;
20

--- 26 unchanged lines hidden (view full) ---

47
48 case NXT_OK:
49 c->socket.write_ready = 1;
50 handler = state->ready_handler;
51 break;
52
53 case NXT_AGAIN:
54 c->socket.write_handler = nxt_conn_connect_test;
52 c->socket.error_handler = state->error_handler;
55 c->socket.error_handler = nxt_conn_connect_error;
53
54 engine = task->thread->engine;
55
56 nxt_conn_timer(engine, c, state, &c->write_timer);
57
58 nxt_fd_event_enable_write(engine, &c->socket);
59 return;
60

--- 52 unchanged lines hidden (view full) ---

113
114 return NXT_OK;
115}
116
117
118void
119nxt_conn_connect_test(nxt_task_t *task, void *obj, void *data)
120{
56
57 engine = task->thread->engine;
58
59 nxt_conn_timer(engine, c, state, &c->write_timer);
60
61 nxt_fd_event_enable_write(engine, &c->socket);
62 return;
63

--- 52 unchanged lines hidden (view full) ---

116
117 return NXT_OK;
118}
119
120
121void
122nxt_conn_connect_test(nxt_task_t *task, void *obj, void *data)
123{
121 int ret, err;
122 socklen_t len;
124 nxt_err_t err;
123 nxt_conn_t *c;
124
125 c = obj;
126
127 nxt_debug(task, "event connect test fd:%d", c->socket.fd);
128
129 nxt_fd_event_block_write(task->thread->engine, &c->socket);
130
131 if (c->write_state->timer_autoreset) {
132 nxt_timer_disable(task->thread->engine, &c->write_timer);
133 }
134
125 nxt_conn_t *c;
126
127 c = obj;
128
129 nxt_debug(task, "event connect test fd:%d", c->socket.fd);
130
131 nxt_fd_event_block_write(task->thread->engine, &c->socket);
132
133 if (c->write_state->timer_autoreset) {
134 nxt_timer_disable(task->thread->engine, &c->write_timer);
135 }
136
135 err = 0;
136 len = sizeof(int);
137 err = nxt_conn_connect_test_error(task, c);
137
138
138 /*
139 * Linux and BSDs return 0 and store a pending error in the err argument;
140 * Solaris returns -1 and sets the errno.
141 */
142
143 ret = getsockopt(c->socket.fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len);
144
145 if (nxt_slow_path(ret == -1)) {
146 err = nxt_errno;
147 }
148
149 if (err == 0) {
150 nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler,
151 task, c, data);
139 if (err == 0) {
140 nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler,
141 task, c, data);
152 return;
142 } else {
143 nxt_conn_connect_error(task, c, data);
153 }
144 }
154
155 c->socket.error = err;
156
157 nxt_log(task, nxt_socket_error_level(err), "connect(%d, %*s) failed %E",
158 c->socket.fd, (size_t) c->remote->length,
159 nxt_sockaddr_start(c->remote), err);
160
161 nxt_conn_connect_error(task, c, data);
162}
163
164
165void
166nxt_conn_connect_error(nxt_task_t *task, void *obj, void *data)
167{
145}
146
147
148void
149nxt_conn_connect_error(nxt_task_t *task, void *obj, void *data)
150{
151 nxt_err_t err;
168 nxt_conn_t *c;
169 nxt_work_handler_t handler;
170 const nxt_conn_state_t *state;
171
172 c = obj;
152 nxt_conn_t *c;
153 nxt_work_handler_t handler;
154 const nxt_conn_state_t *state;
155
156 c = obj;
157 err = c->socket.error;
173
158
159 if (err == 0) {
160 err = nxt_conn_connect_test_error(task, c);
161 }
162
174 state = c->write_state;
175
163 state = c->write_state;
164
176 switch (c->socket.error) {
165 switch (err) {
177
178 case NXT_ECONNREFUSED:
179#if (NXT_LINUX)
180 case NXT_EAGAIN:
181 /*
182 * Linux returns EAGAIN instead of ECONNREFUSED
183 * for UNIX sockets if a listen queue is full.
184 */
185#endif
186 handler = state->close_handler;
187 break;
188
189 default:
190 handler = state->error_handler;
191 break;
192 }
193
194 nxt_work_queue_add(c->write_work_queue, handler, task, c, data);
195}
166
167 case NXT_ECONNREFUSED:
168#if (NXT_LINUX)
169 case NXT_EAGAIN:
170 /*
171 * Linux returns EAGAIN instead of ECONNREFUSED
172 * for UNIX sockets if a listen queue is full.
173 */
174#endif
175 handler = state->close_handler;
176 break;
177
178 default:
179 handler = state->error_handler;
180 break;
181 }
182
183 nxt_work_queue_add(c->write_work_queue, handler, task, c, data);
184}
185
186
187static nxt_err_t
188nxt_conn_connect_test_error(nxt_task_t *task, nxt_conn_t *c)
189{
190 nxt_err_t err;
191
192 err = nxt_socket_error(c->socket.fd);
193
194 if (err != 0) {
195 c->socket.error = err;
196
197 nxt_log(task, nxt_socket_error_level(err), "connect(%d, %*s) failed %E",
198 c->socket.fd, (size_t) c->remote->length,
199 nxt_sockaddr_start(c->remote), err);
200 }
201
202 return err;
203}