Line | Count | Source (jump to first uncovered line) |
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 | | .connect = nxt_conn_io_connect, |
12 | | .accept = nxt_conn_io_accept, |
13 | | |
14 | | .read = nxt_conn_io_read, |
15 | | .recvbuf = nxt_conn_io_recvbuf, |
16 | | .recv = nxt_conn_io_recv, |
17 | | |
18 | | .write = nxt_conn_io_write, |
19 | | .sendbuf = nxt_conn_io_sendbuf, |
20 | | |
21 | | #if (NXT_HAVE_LINUX_SENDFILE) |
22 | | .old_sendbuf = nxt_linux_event_conn_io_sendfile, |
23 | | #elif (NXT_HAVE_FREEBSD_SENDFILE) |
24 | | .old_sendbuf = nxt_freebsd_event_conn_io_sendfile, |
25 | | #elif (NXT_HAVE_MACOSX_SENDFILE) |
26 | | .old_sendbuf = nxt_macosx_event_conn_io_sendfile, |
27 | | #elif (NXT_HAVE_SOLARIS_SENDFILEV) |
28 | | .old_sendbuf = nxt_solaris_event_conn_io_sendfilev, |
29 | | #elif (NXT_HAVE_AIX_SEND_FILE) |
30 | | .old_sendbuf = nxt_aix_event_conn_io_send_file, |
31 | | #elif (NXT_HAVE_HPUX_SENDFILE) |
32 | | .old_sendbuf = nxt_hpux_event_conn_io_sendfile, |
33 | | #else |
34 | | .old_sendbuf = nxt_event_conn_io_sendbuf, |
35 | | #endif |
36 | | |
37 | | .writev = nxt_event_conn_io_writev, |
38 | | .send = nxt_event_conn_io_send, |
39 | | }; |
40 | | |
41 | | |
42 | | nxt_conn_t * |
43 | | nxt_conn_create(nxt_mp_t *mp, nxt_task_t *task) |
44 | 0 | { |
45 | 0 | nxt_conn_t *c; |
46 | 0 | nxt_thread_t *thr; |
47 | |
|
48 | 0 | c = nxt_mp_zget(mp, sizeof(nxt_conn_t)); |
49 | 0 | if (nxt_slow_path(c == NULL)) { |
50 | 0 | return NULL; |
51 | 0 | } |
52 | | |
53 | 0 | c->mem_pool = mp; |
54 | |
|
55 | 0 | c->socket.fd = -1; |
56 | |
|
57 | 0 | c->socket.log = &c->log; |
58 | 0 | c->log = *task->log; |
59 | | |
60 | | /* The while loop skips possible uint32_t overflow. */ |
61 | |
|
62 | 0 | while (c->log.ident == 0) { |
63 | 0 | c->log.ident = nxt_task_next_ident(); |
64 | 0 | } |
65 | |
|
66 | 0 | thr = nxt_thread(); |
67 | 0 | thr->engine->connections++; |
68 | |
|
69 | 0 | c->task.thread = thr; |
70 | 0 | c->task.log = &c->log; |
71 | 0 | c->task.ident = c->log.ident; |
72 | 0 | c->socket.task = &c->task; |
73 | 0 | c->read_timer.task = &c->task; |
74 | 0 | c->write_timer.task = &c->task; |
75 | |
|
76 | 0 | c->io = thr->engine->event.io; |
77 | 0 | c->max_chunk = NXT_INT32_T_MAX; |
78 | 0 | c->sendfile = NXT_CONN_SENDFILE_UNSET; |
79 | |
|
80 | 0 | c->socket.read_work_queue = &thr->engine->fast_work_queue; |
81 | 0 | c->socket.write_work_queue = &thr->engine->fast_work_queue; |
82 | |
|
83 | 0 | nxt_conn_timer_init(&c->read_timer, c, c->socket.read_work_queue); |
84 | 0 | nxt_conn_timer_init(&c->write_timer, c, c->socket.write_work_queue); |
85 | |
|
86 | 0 | nxt_log_debug(&c->log, "connections: %uD", thr->engine->connections); |
87 | |
|
88 | 0 | return c; |
89 | 0 | } |
90 | | |
91 | | |
92 | | void |
93 | | nxt_conn_free(nxt_task_t *task, nxt_conn_t *c) |
94 | 0 | { |
95 | 0 | nxt_mp_t *mp; |
96 | |
|
97 | 0 | task->thread->engine->connections--; |
98 | |
|
99 | 0 | mp = c->mem_pool; |
100 | 0 | nxt_mp_release(mp); |
101 | 0 | } |
102 | | |
103 | | |
104 | | void |
105 | | nxt_conn_timer(nxt_event_engine_t *engine, nxt_conn_t *c, |
106 | | const nxt_conn_state_t *state, nxt_timer_t *timer) |
107 | 0 | { |
108 | 0 | nxt_msec_t value; |
109 | |
|
110 | 0 | if (state->timer_value != NULL) { |
111 | 0 | value = state->timer_value(c, state->timer_data); |
112 | |
|
113 | 0 | if (value != 0) { |
114 | 0 | timer->handler = state->timer_handler; |
115 | 0 | nxt_timer_add(engine, timer, value); |
116 | 0 | } |
117 | 0 | } |
118 | 0 | } |
119 | | |
120 | | |
121 | | void |
122 | | nxt_conn_work_queue_set(nxt_conn_t *c, nxt_work_queue_t *wq) |
123 | 0 | { |
124 | 0 | c->read_work_queue = wq; |
125 | 0 | c->write_work_queue = wq; |
126 | 0 | c->read_timer.work_queue = wq; |
127 | 0 | c->write_timer.work_queue = wq; |
128 | 0 | } |
129 | | |
130 | | |
131 | | nxt_sockaddr_t * |
132 | | nxt_conn_local_addr(nxt_task_t *task, nxt_conn_t *c) |
133 | 0 | { |
134 | 0 | int ret; |
135 | 0 | size_t size, length; |
136 | 0 | socklen_t socklen; |
137 | 0 | nxt_sockaddr_t *sa; |
138 | |
|
139 | 0 | if (c->local != NULL) { |
140 | 0 | return c->local; |
141 | 0 | } |
142 | | |
143 | | /* AF_UNIX should not get in here. */ |
144 | | |
145 | 0 | switch (c->remote->u.sockaddr.sa_family) { |
146 | 0 | #if (NXT_INET6) |
147 | 0 | case AF_INET6: |
148 | 0 | socklen = sizeof(struct sockaddr_in6); |
149 | 0 | length = NXT_INET6_ADDR_STR_LEN; |
150 | 0 | size = offsetof(nxt_sockaddr_t, u) + socklen + length; |
151 | 0 | break; |
152 | 0 | #endif |
153 | 0 | case AF_INET: |
154 | 0 | default: |
155 | 0 | socklen = sizeof(struct sockaddr_in); |
156 | 0 | length = NXT_INET_ADDR_STR_LEN; |
157 | 0 | size = offsetof(nxt_sockaddr_t, u) + socklen + length; |
158 | 0 | break; |
159 | 0 | } |
160 | | |
161 | 0 | sa = nxt_mp_get(c->mem_pool, size); |
162 | 0 | if (nxt_slow_path(sa == NULL)) { |
163 | 0 | return NULL; |
164 | 0 | } |
165 | | |
166 | 0 | sa->socklen = socklen; |
167 | 0 | sa->length = length; |
168 | |
|
169 | 0 | ret = getsockname(c->socket.fd, &sa->u.sockaddr, &socklen); |
170 | 0 | if (nxt_slow_path(ret != 0)) { |
171 | 0 | nxt_alert(task, "getsockname(%d) failed", c->socket.fd); |
172 | 0 | return NULL; |
173 | 0 | } |
174 | | |
175 | 0 | c->local = sa; |
176 | |
|
177 | 0 | nxt_sockaddr_text(sa); |
178 | | |
179 | | /* |
180 | | * TODO: here we can adjust the end of non-freeable block |
181 | | * in c->mem_pool to the end of actual sockaddr length. |
182 | | */ |
183 | |
|
184 | 0 | return sa; |
185 | 0 | } |