xref: /unit/src/nxt_conn.c (revision 62:5e1efcc7b740)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #include <nxt_main.h>
8 
9 
10 nxt_conn_io_t  nxt_unix_conn_io = {
11     nxt_conn_io_connect,
12     nxt_conn_io_accept,
13 
14     nxt_conn_io_read,
15     nxt_conn_io_recvbuf,
16     nxt_conn_io_recv,
17 
18     nxt_conn_io_write,
19     nxt_event_conn_io_write_chunk,
20 
21 #if (NXT_HAVE_LINUX_SENDFILE)
22     nxt_linux_event_conn_io_sendfile,
23 #elif (NXT_HAVE_FREEBSD_SENDFILE)
24     nxt_freebsd_event_conn_io_sendfile,
25 #elif (NXT_HAVE_MACOSX_SENDFILE)
26     nxt_macosx_event_conn_io_sendfile,
27 #elif (NXT_HAVE_SOLARIS_SENDFILEV)
28     nxt_solaris_event_conn_io_sendfilev,
29 #elif (NXT_HAVE_AIX_SEND_FILE)
30     nxt_aix_event_conn_io_send_file,
31 #elif (NXT_HAVE_HPUX_SENDFILE)
32     nxt_hpux_event_conn_io_sendfile,
33 #else
34     nxt_event_conn_io_sendbuf,
35 #endif
36 
37     nxt_event_conn_io_writev,
38     nxt_event_conn_io_send,
39 
40     nxt_conn_io_shutdown,
41 };
42 
43 
44 nxt_conn_t *
45 nxt_conn_create(nxt_mem_pool_t *mp, nxt_task_t *task)
46 {
47     nxt_conn_t    *c;
48     nxt_thread_t  *thr;
49 
50     c = nxt_mem_zalloc(mp, sizeof(nxt_conn_t));
51     if (nxt_slow_path(c == NULL)) {
52         return NULL;
53     }
54 
55     c->mem_pool = mp;
56 
57     c->socket.fd = -1;
58 
59     c->socket.log = &c->log;
60     c->log = *task->log;
61 
62     /* The while loop skips possible uint32_t overflow. */
63 
64     while (c->log.ident == 0) {
65         c->log.ident = nxt_task_next_ident();
66     }
67 
68     thr = nxt_thread();
69     thr->engine->connections++;
70 
71     c->task.thread = thr;
72     c->task.log = &c->log;
73     c->task.ident = c->log.ident;
74     c->socket.task = &c->task;
75     c->read_timer.task = &c->task;
76     c->write_timer.task = &c->task;
77 
78     c->io = thr->engine->event.io;
79     c->max_chunk = NXT_INT32_T_MAX;
80     c->sendfile = NXT_CONN_SENDFILE_UNSET;
81 
82     c->socket.read_work_queue = &thr->engine->fast_work_queue;
83     c->socket.write_work_queue = &thr->engine->fast_work_queue;
84 
85     nxt_conn_timer_init(&c->read_timer, c, c->socket.read_work_queue);
86     nxt_conn_timer_init(&c->write_timer, c, c->socket.write_work_queue);
87 
88     nxt_log_debug(&c->log, "connections: %uD", thr->engine->connections);
89 
90     return c;
91 }
92 
93 
94 void
95 nxt_conn_io_shutdown(nxt_task_t *task, void *obj, void *data)
96 {
97     int            ret;
98     socklen_t      len;
99     nxt_conn_t     *c;
100     struct linger  linger;
101 
102     c = obj;
103 
104     nxt_debug(task, "event conn shutdown");
105 
106     if (c->socket.timedout) {
107         /*
108          * Resetting of timed out connection on close
109          * releases kernel memory associated with socket.
110          * This also causes sending TCP/IP RST to a peer.
111          */
112         linger.l_onoff = 1;
113         linger.l_linger = 0;
114         len = sizeof(struct linger);
115 
116         ret = setsockopt(c->socket.fd, SOL_SOCKET, SO_LINGER, &linger, len);
117 
118         if (nxt_slow_path(ret != 0)) {
119             nxt_log(task, NXT_LOG_CRIT, "setsockopt(%d, SO_LINGER) failed %E",
120                     c->socket.fd, nxt_socket_errno);
121         }
122     }
123 
124     c->write_state->close_handler(task, c, data);
125 }
126 
127 
128 void
129 nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c,
130     const nxt_conn_state_t *state, nxt_timer_t *timer)
131 {
132     nxt_msec_t  value;
133 
134     if (state->timer_value != NULL) {
135         value = state->timer_value(c, state->timer_data);
136 
137         if (value != 0) {
138             timer->handler = state->timer_handler;
139             nxt_timer_add(engine, timer, value);
140         }
141     }
142 }
143 
144 
145 void
146 nxt_conn_work_queue_set(nxt_conn_t *c, nxt_work_queue_t *wq)
147 {
148     c->read_work_queue = wq;
149     c->write_work_queue = wq;
150     c->read_timer.work_queue = wq;
151     c->write_timer.work_queue = wq;
152 }
153