162Sigor@sysoev.ru
262Sigor@sysoev.ru /*
362Sigor@sysoev.ru * Copyright (C) Igor Sysoev
462Sigor@sysoev.ru * Copyright (C) NGINX, Inc.
562Sigor@sysoev.ru */
662Sigor@sysoev.ru
762Sigor@sysoev.ru #include <nxt_main.h>
862Sigor@sysoev.ru
962Sigor@sysoev.ru
1062Sigor@sysoev.ru nxt_conn_io_t nxt_unix_conn_io = {
11*771Sigor@sysoev.ru .connect = nxt_conn_io_connect,
12*771Sigor@sysoev.ru .accept = nxt_conn_io_accept,
1362Sigor@sysoev.ru
14*771Sigor@sysoev.ru .read = nxt_conn_io_read,
15*771Sigor@sysoev.ru .recvbuf = nxt_conn_io_recvbuf,
16*771Sigor@sysoev.ru .recv = nxt_conn_io_recv,
1762Sigor@sysoev.ru
18*771Sigor@sysoev.ru .write = nxt_conn_io_write,
19*771Sigor@sysoev.ru .sendbuf = nxt_conn_io_sendbuf,
2062Sigor@sysoev.ru
2162Sigor@sysoev.ru #if (NXT_HAVE_LINUX_SENDFILE)
22*771Sigor@sysoev.ru .old_sendbuf = nxt_linux_event_conn_io_sendfile,
2362Sigor@sysoev.ru #elif (NXT_HAVE_FREEBSD_SENDFILE)
24*771Sigor@sysoev.ru .old_sendbuf = nxt_freebsd_event_conn_io_sendfile,
2562Sigor@sysoev.ru #elif (NXT_HAVE_MACOSX_SENDFILE)
26*771Sigor@sysoev.ru .old_sendbuf = nxt_macosx_event_conn_io_sendfile,
2762Sigor@sysoev.ru #elif (NXT_HAVE_SOLARIS_SENDFILEV)
28*771Sigor@sysoev.ru .old_sendbuf = nxt_solaris_event_conn_io_sendfilev,
2962Sigor@sysoev.ru #elif (NXT_HAVE_AIX_SEND_FILE)
30*771Sigor@sysoev.ru .old_sendbuf = nxt_aix_event_conn_io_send_file,
3162Sigor@sysoev.ru #elif (NXT_HAVE_HPUX_SENDFILE)
32*771Sigor@sysoev.ru .old_sendbuf = nxt_hpux_event_conn_io_sendfile,
3362Sigor@sysoev.ru #else
34*771Sigor@sysoev.ru .old_sendbuf = nxt_event_conn_io_sendbuf,
3562Sigor@sysoev.ru #endif
3662Sigor@sysoev.ru
37*771Sigor@sysoev.ru .writev = nxt_event_conn_io_writev,
38*771Sigor@sysoev.ru .send = nxt_event_conn_io_send,
3962Sigor@sysoev.ru };
4062Sigor@sysoev.ru
4162Sigor@sysoev.ru
4262Sigor@sysoev.ru nxt_conn_t *
nxt_conn_create(nxt_mp_t * mp,nxt_task_t * task)4365Sigor@sysoev.ru nxt_conn_create(nxt_mp_t *mp, nxt_task_t *task)
4462Sigor@sysoev.ru {
4562Sigor@sysoev.ru nxt_conn_t *c;
4662Sigor@sysoev.ru nxt_thread_t *thr;
4762Sigor@sysoev.ru
4865Sigor@sysoev.ru c = nxt_mp_zget(mp, sizeof(nxt_conn_t));
4962Sigor@sysoev.ru if (nxt_slow_path(c == NULL)) {
5062Sigor@sysoev.ru return NULL;
5162Sigor@sysoev.ru }
5262Sigor@sysoev.ru
5362Sigor@sysoev.ru c->mem_pool = mp;
5462Sigor@sysoev.ru
5562Sigor@sysoev.ru c->socket.fd = -1;
5662Sigor@sysoev.ru
5762Sigor@sysoev.ru c->socket.log = &c->log;
5862Sigor@sysoev.ru c->log = *task->log;
5962Sigor@sysoev.ru
6062Sigor@sysoev.ru /* The while loop skips possible uint32_t overflow. */
6162Sigor@sysoev.ru
6262Sigor@sysoev.ru while (c->log.ident == 0) {
6362Sigor@sysoev.ru c->log.ident = nxt_task_next_ident();
6462Sigor@sysoev.ru }
6562Sigor@sysoev.ru
6662Sigor@sysoev.ru thr = nxt_thread();
6762Sigor@sysoev.ru thr->engine->connections++;
6862Sigor@sysoev.ru
6962Sigor@sysoev.ru c->task.thread = thr;
7062Sigor@sysoev.ru c->task.log = &c->log;
7162Sigor@sysoev.ru c->task.ident = c->log.ident;
7262Sigor@sysoev.ru c->socket.task = &c->task;
7362Sigor@sysoev.ru c->read_timer.task = &c->task;
7462Sigor@sysoev.ru c->write_timer.task = &c->task;
7562Sigor@sysoev.ru
7662Sigor@sysoev.ru c->io = thr->engine->event.io;
7762Sigor@sysoev.ru c->max_chunk = NXT_INT32_T_MAX;
7862Sigor@sysoev.ru c->sendfile = NXT_CONN_SENDFILE_UNSET;
7962Sigor@sysoev.ru
8062Sigor@sysoev.ru c->socket.read_work_queue = &thr->engine->fast_work_queue;
8162Sigor@sysoev.ru c->socket.write_work_queue = &thr->engine->fast_work_queue;
8262Sigor@sysoev.ru
8362Sigor@sysoev.ru nxt_conn_timer_init(&c->read_timer, c, c->socket.read_work_queue);
8462Sigor@sysoev.ru nxt_conn_timer_init(&c->write_timer, c, c->socket.write_work_queue);
8562Sigor@sysoev.ru
8662Sigor@sysoev.ru nxt_log_debug(&c->log, "connections: %uD", thr->engine->connections);
8762Sigor@sysoev.ru
8862Sigor@sysoev.ru return c;
8962Sigor@sysoev.ru }
9062Sigor@sysoev.ru
9162Sigor@sysoev.ru
9262Sigor@sysoev.ru void
nxt_conn_free(nxt_task_t * task,nxt_conn_t * c)93386Sigor@sysoev.ru nxt_conn_free(nxt_task_t *task, nxt_conn_t *c)
94386Sigor@sysoev.ru {
95430Sigor@sysoev.ru nxt_mp_t *mp;
96430Sigor@sysoev.ru
97386Sigor@sysoev.ru task->thread->engine->connections--;
98386Sigor@sysoev.ru
99430Sigor@sysoev.ru mp = c->mem_pool;
100430Sigor@sysoev.ru nxt_mp_release(mp);
101386Sigor@sysoev.ru }
102386Sigor@sysoev.ru
103386Sigor@sysoev.ru
104386Sigor@sysoev.ru void
nxt_conn_timer(nxt_event_engine_t * engine,nxt_conn_t * c,const nxt_conn_state_t * state,nxt_timer_t * timer)10562Sigor@sysoev.ru nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c,
10662Sigor@sysoev.ru const nxt_conn_state_t *state, nxt_timer_t *timer)
10762Sigor@sysoev.ru {
10862Sigor@sysoev.ru nxt_msec_t value;
10962Sigor@sysoev.ru
11062Sigor@sysoev.ru if (state->timer_value != NULL) {
11162Sigor@sysoev.ru value = state->timer_value(c, state->timer_data);
11262Sigor@sysoev.ru
11362Sigor@sysoev.ru if (value != 0) {
11462Sigor@sysoev.ru timer->handler = state->timer_handler;
11562Sigor@sysoev.ru nxt_timer_add(engine, timer, value);
11662Sigor@sysoev.ru }
11762Sigor@sysoev.ru }
11862Sigor@sysoev.ru }
11962Sigor@sysoev.ru
12062Sigor@sysoev.ru
12162Sigor@sysoev.ru void
nxt_conn_work_queue_set(nxt_conn_t * c,nxt_work_queue_t * wq)12262Sigor@sysoev.ru nxt_conn_work_queue_set(nxt_conn_t *c, nxt_work_queue_t *wq)
12362Sigor@sysoev.ru {
12462Sigor@sysoev.ru c->read_work_queue = wq;
12562Sigor@sysoev.ru c->write_work_queue = wq;
12662Sigor@sysoev.ru c->read_timer.work_queue = wq;
12762Sigor@sysoev.ru c->write_timer.work_queue = wq;
12862Sigor@sysoev.ru }
129431Sigor@sysoev.ru
130431Sigor@sysoev.ru
131431Sigor@sysoev.ru nxt_sockaddr_t *
nxt_conn_local_addr(nxt_task_t * task,nxt_conn_t * c)132431Sigor@sysoev.ru nxt_conn_local_addr(nxt_task_t *task, nxt_conn_t *c)
133431Sigor@sysoev.ru {
134431Sigor@sysoev.ru int ret;
135431Sigor@sysoev.ru size_t size, length;
136431Sigor@sysoev.ru socklen_t socklen;
137431Sigor@sysoev.ru nxt_sockaddr_t *sa;
138431Sigor@sysoev.ru
139431Sigor@sysoev.ru if (c->local != NULL) {
140431Sigor@sysoev.ru return c->local;
141431Sigor@sysoev.ru }
142431Sigor@sysoev.ru
143431Sigor@sysoev.ru /* AF_UNIX should not get in here. */
144431Sigor@sysoev.ru
145431Sigor@sysoev.ru switch (c->remote->u.sockaddr.sa_family) {
146431Sigor@sysoev.ru #if (NXT_INET6)
147431Sigor@sysoev.ru case AF_INET6:
148431Sigor@sysoev.ru socklen = sizeof(struct sockaddr_in6);
149431Sigor@sysoev.ru length = NXT_INET6_ADDR_STR_LEN;
150431Sigor@sysoev.ru size = offsetof(nxt_sockaddr_t, u) + socklen + length;
151431Sigor@sysoev.ru break;
152431Sigor@sysoev.ru #endif
153431Sigor@sysoev.ru case AF_INET:
154431Sigor@sysoev.ru default:
155431Sigor@sysoev.ru socklen = sizeof(struct sockaddr_in);
156431Sigor@sysoev.ru length = NXT_INET_ADDR_STR_LEN;
157431Sigor@sysoev.ru size = offsetof(nxt_sockaddr_t, u) + socklen + length;
158431Sigor@sysoev.ru break;
159431Sigor@sysoev.ru }
160431Sigor@sysoev.ru
161431Sigor@sysoev.ru sa = nxt_mp_get(c->mem_pool, size);
162431Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) {
163431Sigor@sysoev.ru return NULL;
164431Sigor@sysoev.ru }
165431Sigor@sysoev.ru
166431Sigor@sysoev.ru sa->socklen = socklen;
167431Sigor@sysoev.ru sa->length = length;
168431Sigor@sysoev.ru
169431Sigor@sysoev.ru ret = getsockname(c->socket.fd, &sa->u.sockaddr, &socklen);
170431Sigor@sysoev.ru if (nxt_slow_path(ret != 0)) {
171564Svbart@nginx.com nxt_alert(task, "getsockname(%d) failed", c->socket.fd);
172431Sigor@sysoev.ru return NULL;
173431Sigor@sysoev.ru }
174431Sigor@sysoev.ru
175431Sigor@sysoev.ru c->local = sa;
176431Sigor@sysoev.ru
177431Sigor@sysoev.ru nxt_sockaddr_text(sa);
178431Sigor@sysoev.ru
179431Sigor@sysoev.ru /*
180431Sigor@sysoev.ru * TODO: here we can adjust the end of non-freeable block
181431Sigor@sysoev.ru * in c->mem_pool to the end of actual sockaddr length.
182431Sigor@sysoev.ru */
183431Sigor@sysoev.ru
184431Sigor@sysoev.ru return sa;
185431Sigor@sysoev.ru }
186