Mercurial > hg > nginx
comparison src/event/ngx_event_udp.c @ 7285:88a624c9b491
Events: moved ngx_recvmsg() to new file src/event/ngx_event_udp.c.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Fri, 01 Jun 2018 16:55:49 +0300 |
parents | |
children | d27aa9060c95 |
comparison
equal
deleted
inserted
replaced
7284:52aacc8ddcc5 | 7285:88a624c9b491 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Roman Arutyunyan | |
4 * Copyright (C) Nginx, Inc. | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_event.h> | |
11 | |
12 | |
13 #if !(NGX_WIN32) | |
14 | |
15 static void ngx_close_accepted_udp_connection(ngx_connection_t *c); | |
16 | |
17 | |
18 void | |
19 ngx_event_recvmsg(ngx_event_t *ev) | |
20 { | |
21 ssize_t n; | |
22 ngx_log_t *log; | |
23 ngx_err_t err; | |
24 socklen_t socklen, local_socklen; | |
25 ngx_event_t *rev, *wev; | |
26 struct iovec iov[1]; | |
27 struct msghdr msg; | |
28 ngx_sockaddr_t sa, lsa; | |
29 struct sockaddr *sockaddr, *local_sockaddr; | |
30 ngx_listening_t *ls; | |
31 ngx_event_conf_t *ecf; | |
32 ngx_connection_t *c, *lc; | |
33 static u_char buffer[65535]; | |
34 | |
35 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
36 | |
37 #if (NGX_HAVE_IP_RECVDSTADDR) | |
38 u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))]; | |
39 #elif (NGX_HAVE_IP_PKTINFO) | |
40 u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))]; | |
41 #endif | |
42 | |
43 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
44 u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; | |
45 #endif | |
46 | |
47 #endif | |
48 | |
49 if (ev->timedout) { | |
50 if (ngx_enable_accept_events((ngx_cycle_t *) ngx_cycle) != NGX_OK) { | |
51 return; | |
52 } | |
53 | |
54 ev->timedout = 0; | |
55 } | |
56 | |
57 ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module); | |
58 | |
59 if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) { | |
60 ev->available = ecf->multi_accept; | |
61 } | |
62 | |
63 lc = ev->data; | |
64 ls = lc->listening; | |
65 ev->ready = 0; | |
66 | |
67 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, | |
68 "recvmsg on %V, ready: %d", &ls->addr_text, ev->available); | |
69 | |
70 do { | |
71 ngx_memzero(&msg, sizeof(struct msghdr)); | |
72 | |
73 iov[0].iov_base = (void *) buffer; | |
74 iov[0].iov_len = sizeof(buffer); | |
75 | |
76 msg.msg_name = &sa; | |
77 msg.msg_namelen = sizeof(ngx_sockaddr_t); | |
78 msg.msg_iov = iov; | |
79 msg.msg_iovlen = 1; | |
80 | |
81 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
82 | |
83 if (ls->wildcard) { | |
84 | |
85 #if (NGX_HAVE_IP_RECVDSTADDR || NGX_HAVE_IP_PKTINFO) | |
86 if (ls->sockaddr->sa_family == AF_INET) { | |
87 msg.msg_control = &msg_control; | |
88 msg.msg_controllen = sizeof(msg_control); | |
89 } | |
90 #endif | |
91 | |
92 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
93 if (ls->sockaddr->sa_family == AF_INET6) { | |
94 msg.msg_control = &msg_control6; | |
95 msg.msg_controllen = sizeof(msg_control6); | |
96 } | |
97 #endif | |
98 } | |
99 | |
100 #endif | |
101 | |
102 n = recvmsg(lc->fd, &msg, 0); | |
103 | |
104 if (n == -1) { | |
105 err = ngx_socket_errno; | |
106 | |
107 if (err == NGX_EAGAIN) { | |
108 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err, | |
109 "recvmsg() not ready"); | |
110 return; | |
111 } | |
112 | |
113 ngx_log_error(NGX_LOG_ALERT, ev->log, err, "recvmsg() failed"); | |
114 | |
115 return; | |
116 } | |
117 | |
118 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
119 if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { | |
120 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, | |
121 "recvmsg() truncated data"); | |
122 continue; | |
123 } | |
124 #endif | |
125 | |
126 sockaddr = msg.msg_name; | |
127 socklen = msg.msg_namelen; | |
128 | |
129 if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { | |
130 socklen = sizeof(ngx_sockaddr_t); | |
131 } | |
132 | |
133 if (socklen == 0) { | |
134 | |
135 /* | |
136 * on Linux recvmsg() returns zero msg_namelen | |
137 * when receiving packets from unbound AF_UNIX sockets | |
138 */ | |
139 | |
140 socklen = sizeof(struct sockaddr); | |
141 ngx_memzero(&sa, sizeof(struct sockaddr)); | |
142 sa.sockaddr.sa_family = ls->sockaddr->sa_family; | |
143 } | |
144 | |
145 local_sockaddr = ls->sockaddr; | |
146 local_socklen = ls->socklen; | |
147 | |
148 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
149 | |
150 if (ls->wildcard) { | |
151 struct cmsghdr *cmsg; | |
152 | |
153 ngx_memcpy(&lsa, local_sockaddr, local_socklen); | |
154 local_sockaddr = &lsa.sockaddr; | |
155 | |
156 for (cmsg = CMSG_FIRSTHDR(&msg); | |
157 cmsg != NULL; | |
158 cmsg = CMSG_NXTHDR(&msg, cmsg)) | |
159 { | |
160 | |
161 #if (NGX_HAVE_IP_RECVDSTADDR) | |
162 | |
163 if (cmsg->cmsg_level == IPPROTO_IP | |
164 && cmsg->cmsg_type == IP_RECVDSTADDR | |
165 && local_sockaddr->sa_family == AF_INET) | |
166 { | |
167 struct in_addr *addr; | |
168 struct sockaddr_in *sin; | |
169 | |
170 addr = (struct in_addr *) CMSG_DATA(cmsg); | |
171 sin = (struct sockaddr_in *) local_sockaddr; | |
172 sin->sin_addr = *addr; | |
173 | |
174 break; | |
175 } | |
176 | |
177 #elif (NGX_HAVE_IP_PKTINFO) | |
178 | |
179 if (cmsg->cmsg_level == IPPROTO_IP | |
180 && cmsg->cmsg_type == IP_PKTINFO | |
181 && local_sockaddr->sa_family == AF_INET) | |
182 { | |
183 struct in_pktinfo *pkt; | |
184 struct sockaddr_in *sin; | |
185 | |
186 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); | |
187 sin = (struct sockaddr_in *) local_sockaddr; | |
188 sin->sin_addr = pkt->ipi_addr; | |
189 | |
190 break; | |
191 } | |
192 | |
193 #endif | |
194 | |
195 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
196 | |
197 if (cmsg->cmsg_level == IPPROTO_IPV6 | |
198 && cmsg->cmsg_type == IPV6_PKTINFO | |
199 && local_sockaddr->sa_family == AF_INET6) | |
200 { | |
201 struct in6_pktinfo *pkt6; | |
202 struct sockaddr_in6 *sin6; | |
203 | |
204 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); | |
205 sin6 = (struct sockaddr_in6 *) local_sockaddr; | |
206 sin6->sin6_addr = pkt6->ipi6_addr; | |
207 | |
208 break; | |
209 } | |
210 | |
211 #endif | |
212 | |
213 } | |
214 } | |
215 | |
216 #endif | |
217 | |
218 #if (NGX_STAT_STUB) | |
219 (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1); | |
220 #endif | |
221 | |
222 ngx_accept_disabled = ngx_cycle->connection_n / 8 | |
223 - ngx_cycle->free_connection_n; | |
224 | |
225 c = ngx_get_connection(lc->fd, ev->log); | |
226 if (c == NULL) { | |
227 return; | |
228 } | |
229 | |
230 c->shared = 1; | |
231 c->type = SOCK_DGRAM; | |
232 c->socklen = socklen; | |
233 | |
234 #if (NGX_STAT_STUB) | |
235 (void) ngx_atomic_fetch_add(ngx_stat_active, 1); | |
236 #endif | |
237 | |
238 c->pool = ngx_create_pool(ls->pool_size, ev->log); | |
239 if (c->pool == NULL) { | |
240 ngx_close_accepted_udp_connection(c); | |
241 return; | |
242 } | |
243 | |
244 c->sockaddr = ngx_palloc(c->pool, socklen); | |
245 if (c->sockaddr == NULL) { | |
246 ngx_close_accepted_udp_connection(c); | |
247 return; | |
248 } | |
249 | |
250 ngx_memcpy(c->sockaddr, sockaddr, socklen); | |
251 | |
252 log = ngx_palloc(c->pool, sizeof(ngx_log_t)); | |
253 if (log == NULL) { | |
254 ngx_close_accepted_udp_connection(c); | |
255 return; | |
256 } | |
257 | |
258 *log = ls->log; | |
259 | |
260 c->send = ngx_udp_send; | |
261 c->send_chain = ngx_udp_send_chain; | |
262 | |
263 c->log = log; | |
264 c->pool->log = log; | |
265 c->listening = ls; | |
266 | |
267 if (local_sockaddr == &lsa.sockaddr) { | |
268 local_sockaddr = ngx_palloc(c->pool, local_socklen); | |
269 if (local_sockaddr == NULL) { | |
270 ngx_close_accepted_udp_connection(c); | |
271 return; | |
272 } | |
273 | |
274 ngx_memcpy(local_sockaddr, &lsa, local_socklen); | |
275 } | |
276 | |
277 c->local_sockaddr = local_sockaddr; | |
278 c->local_socklen = local_socklen; | |
279 | |
280 c->buffer = ngx_create_temp_buf(c->pool, n); | |
281 if (c->buffer == NULL) { | |
282 ngx_close_accepted_udp_connection(c); | |
283 return; | |
284 } | |
285 | |
286 c->buffer->last = ngx_cpymem(c->buffer->last, buffer, n); | |
287 | |
288 rev = c->read; | |
289 wev = c->write; | |
290 | |
291 wev->ready = 1; | |
292 | |
293 rev->log = log; | |
294 wev->log = log; | |
295 | |
296 /* | |
297 * TODO: MT: - ngx_atomic_fetch_add() | |
298 * or protection by critical section or light mutex | |
299 * | |
300 * TODO: MP: - allocated in a shared memory | |
301 * - ngx_atomic_fetch_add() | |
302 * or protection by critical section or light mutex | |
303 */ | |
304 | |
305 c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); | |
306 | |
307 #if (NGX_STAT_STUB) | |
308 (void) ngx_atomic_fetch_add(ngx_stat_handled, 1); | |
309 #endif | |
310 | |
311 if (ls->addr_ntop) { | |
312 c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len); | |
313 if (c->addr_text.data == NULL) { | |
314 ngx_close_accepted_udp_connection(c); | |
315 return; | |
316 } | |
317 | |
318 c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->socklen, | |
319 c->addr_text.data, | |
320 ls->addr_text_max_len, 0); | |
321 if (c->addr_text.len == 0) { | |
322 ngx_close_accepted_udp_connection(c); | |
323 return; | |
324 } | |
325 } | |
326 | |
327 #if (NGX_DEBUG) | |
328 { | |
329 ngx_str_t addr; | |
330 u_char text[NGX_SOCKADDR_STRLEN]; | |
331 | |
332 ngx_debug_accepted_connection(ecf, c); | |
333 | |
334 if (log->log_level & NGX_LOG_DEBUG_EVENT) { | |
335 addr.data = text; | |
336 addr.len = ngx_sock_ntop(c->sockaddr, c->socklen, text, | |
337 NGX_SOCKADDR_STRLEN, 1); | |
338 | |
339 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0, | |
340 "*%uA recvmsg: %V fd:%d n:%z", | |
341 c->number, &addr, c->fd, n); | |
342 } | |
343 | |
344 } | |
345 #endif | |
346 | |
347 log->data = NULL; | |
348 log->handler = NULL; | |
349 | |
350 ls->handler(c); | |
351 | |
352 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { | |
353 ev->available -= n; | |
354 } | |
355 | |
356 } while (ev->available); | |
357 } | |
358 | |
359 | |
360 static void | |
361 ngx_close_accepted_udp_connection(ngx_connection_t *c) | |
362 { | |
363 ngx_free_connection(c); | |
364 | |
365 c->fd = (ngx_socket_t) -1; | |
366 | |
367 if (c->pool) { | |
368 ngx_destroy_pool(c->pool); | |
369 } | |
370 | |
371 #if (NGX_STAT_STUB) | |
372 (void) ngx_atomic_fetch_add(ngx_stat_active, -1); | |
373 #endif | |
374 } | |
375 | |
376 #endif |