diff options
author | Igor Sysoev <igor@sysoev.ru> | 2017-06-14 15:18:52 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2017-06-14 15:18:52 +0300 |
commit | 7574c64992b98d3dfbc3dd101bd0f7d78bad0823 (patch) | |
tree | 3a98c46e88d9023df34be3e6cce4f762d53aad36 /src/nxt_conn_connect.c | |
parent | 3e2632688f53c4cb08e7ac03c61e71facd038df4 (diff) | |
download | unit-7574c64992b98d3dfbc3dd101bd0f7d78bad0823.tar.gz unit-7574c64992b98d3dfbc3dd101bd0f7d78bad0823.tar.bz2 |
nxt_event_conn_... functions and structures have been renamed
to nxt_conn_...
Diffstat (limited to 'src/nxt_conn_connect.c')
-rw-r--r-- | src/nxt_conn_connect.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/nxt_conn_connect.c b/src/nxt_conn_connect.c new file mode 100644 index 00000000..94d25c30 --- /dev/null +++ b/src/nxt_conn_connect.c @@ -0,0 +1,194 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_main.h> + + +void +nxt_conn_sys_socket(nxt_task_t *task, void *obj, void *data) +{ + nxt_conn_t *c; + nxt_work_handler_t handler; + + c = obj; + + if (nxt_conn_socket(task, c) == NXT_OK) { + c->socket.write_work_queue = c->write_work_queue; + handler = c->io->connect; + + } else { + handler = c->write_state->error_handler; + } + + nxt_work_queue_add(&task->thread->engine->connect_work_queue, + handler, task, c, data); +} + + +void +nxt_conn_io_connect(nxt_task_t *task, void *obj, void *data) +{ + nxt_conn_t *c; + nxt_work_handler_t handler; + nxt_event_engine_t *engine; + const nxt_conn_state_t *state; + + c = obj; + + state = c->write_state; + + switch (nxt_socket_connect(task, c->socket.fd, c->remote)) { + + case NXT_OK: + c->socket.write_ready = 1; + handler = state->ready_handler; + break; + + case NXT_AGAIN: + c->socket.write_handler = nxt_conn_connect_test; + c->socket.error_handler = state->error_handler; + + engine = task->thread->engine; + + nxt_conn_timer(engine, c, state, &c->write_timer); + + nxt_fd_event_enable_write(engine, &c->socket); + return; + + case NXT_DECLINED: + handler = state->close_handler; + break; + + default: /* NXT_ERROR */ + handler = state->error_handler; + break; + } + + nxt_work_queue_add(c->write_work_queue, handler, task, c, data); +} + + +nxt_int_t +nxt_conn_socket(nxt_task_t *task, nxt_conn_t *c) +{ + nxt_uint_t family; + nxt_socket_t s; + + nxt_debug(task, "event conn socket"); + + family = c->remote->u.sockaddr.sa_family; + + s = nxt_socket_create(task, family, c->remote->type, 0, NXT_NONBLOCK); + + if (nxt_slow_path(s == -1)) { + return NXT_ERROR; + } + + c->sendfile = 1; + +#if (NXT_HAVE_UNIX_DOMAIN && NXT_SOLARIS) + + if (family == AF_UNIX) { + /* Solaris AF_UNIX does not support sendfilev(). */ + c->sendfile = 0; + } + +#endif + + c->socket.fd = s; + + c->socket.task = task; + c->read_timer.task = task; + c->write_timer.task = task; + + if (c->local != NULL) { + if (nxt_slow_path(nxt_socket_bind(task, s, c->local, 0) != NXT_OK)) { + nxt_socket_close(task, s); + return NXT_ERROR; + } + } + + return NXT_OK; +} + + +void +nxt_conn_connect_test(nxt_task_t *task, void *obj, void *data) +{ + int ret, err; + socklen_t len; + nxt_conn_t *c; + + c = obj; + + nxt_debug(task, "event connect test fd:%d", c->socket.fd); + + nxt_fd_event_block_write(task->thread->engine, &c->socket); + + if (c->write_state->timer_autoreset) { + nxt_timer_disable(task->thread->engine, &c->write_timer); + } + + err = 0; + len = sizeof(int); + + /* + * Linux and BSDs return 0 and store a pending error in the err argument; + * Solaris returns -1 and sets the errno. + */ + + ret = getsockopt(c->socket.fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len); + + if (nxt_slow_path(ret == -1)) { + err = nxt_errno; + } + + if (err == 0) { + nxt_work_queue_add(c->write_work_queue, c->write_state->ready_handler, + task, c, data); + return; + } + + c->socket.error = err; + + nxt_log(task, nxt_socket_error_level(err), "connect(%d, %*s) failed %E", + c->socket.fd, c->remote->length, nxt_sockaddr_start(c->remote)); + + nxt_conn_connect_error(task, c, data); +} + + +void +nxt_conn_connect_error(nxt_task_t *task, void *obj, void *data) +{ + nxt_conn_t *c; + nxt_work_handler_t handler; + const nxt_conn_state_t *state; + + c = obj; + + state = c->write_state; + + switch (c->socket.error) { + + case NXT_ECONNREFUSED: +#if (NXT_LINUX) + case NXT_EAGAIN: + /* + * Linux returns EAGAIN instead of ECONNREFUSED + * for UNIX sockets if a listen queue is full. + */ +#endif + handler = state->close_handler; + break; + + default: + handler = state->error_handler; + break; + } + + nxt_work_queue_add(c->write_work_queue, handler, task, c, data); +} |