xref: /unit/src/nxt_conn.c (revision 771:f349b2d68e75)
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