Mercurial > hg > nginx
comparison src/os/unix/ngx_udp_sendmsg_chain.c @ 8002:cfe1284e5d1d
Core: made the ngx_sendmsg() function non-static.
The NGX_HAVE_ADDRINFO_CMSG macro is defined when at least one of methods
to deal with corresponding control message is available.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Tue, 25 Jan 2022 15:48:56 +0300 |
parents | d127837c714f |
children | 0f6cc8f73744 |
comparison
equal
deleted
inserted
replaced
8001:8206ecdcd837 | 8002:cfe1284e5d1d |
---|---|
10 #include <ngx_event.h> | 10 #include <ngx_event.h> |
11 | 11 |
12 | 12 |
13 static ngx_chain_t *ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec, | 13 static ngx_chain_t *ngx_udp_output_chain_to_iovec(ngx_iovec_t *vec, |
14 ngx_chain_t *in, ngx_log_t *log); | 14 ngx_chain_t *in, ngx_log_t *log); |
15 static ssize_t ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec); | 15 static ssize_t ngx_sendmsg_vec(ngx_connection_t *c, ngx_iovec_t *vec); |
16 | 16 |
17 | 17 |
18 ngx_chain_t * | 18 ngx_chain_t * |
19 ngx_udp_unix_sendmsg_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) | 19 ngx_udp_unix_sendmsg_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) |
20 { | 20 { |
86 return in; | 86 return in; |
87 } | 87 } |
88 | 88 |
89 send += vec.size; | 89 send += vec.size; |
90 | 90 |
91 n = ngx_sendmsg(c, &vec); | 91 n = ngx_sendmsg_vec(c, &vec); |
92 | 92 |
93 if (n == NGX_ERROR) { | 93 if (n == NGX_ERROR) { |
94 return NGX_CHAIN_ERROR; | 94 return NGX_CHAIN_ERROR; |
95 } | 95 } |
96 | 96 |
202 return in; | 202 return in; |
203 } | 203 } |
204 | 204 |
205 | 205 |
206 static ssize_t | 206 static ssize_t |
207 ngx_sendmsg(ngx_connection_t *c, ngx_iovec_t *vec) | 207 ngx_sendmsg_vec(ngx_connection_t *c, ngx_iovec_t *vec) |
208 { | 208 { |
209 ssize_t n; | 209 struct msghdr msg; |
210 ngx_err_t err; | 210 |
211 struct msghdr msg; | 211 #if (NGX_HAVE_ADDRINFO_CMSG) |
212 | 212 struct cmsghdr *cmsg; |
213 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | 213 u_char msg_control[CMSG_SPACE(sizeof(ngx_addrinfo_t))]; |
214 | |
215 #if (NGX_HAVE_IP_SENDSRCADDR) | |
216 u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))]; | |
217 #elif (NGX_HAVE_IP_PKTINFO) | |
218 u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))]; | |
219 #endif | |
220 | |
221 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
222 u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; | |
223 #endif | |
224 | |
225 #endif | 214 #endif |
226 | 215 |
227 ngx_memzero(&msg, sizeof(struct msghdr)); | 216 ngx_memzero(&msg, sizeof(struct msghdr)); |
228 | 217 |
229 if (c->socklen) { | 218 if (c->socklen) { |
232 } | 221 } |
233 | 222 |
234 msg.msg_iov = vec->iovs; | 223 msg.msg_iov = vec->iovs; |
235 msg.msg_iovlen = vec->count; | 224 msg.msg_iovlen = vec->count; |
236 | 225 |
237 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | 226 #if (NGX_HAVE_ADDRINFO_CMSG) |
238 | |
239 if (c->listening && c->listening->wildcard && c->local_sockaddr) { | 227 if (c->listening && c->listening->wildcard && c->local_sockaddr) { |
240 | 228 |
229 msg.msg_control = msg_control; | |
230 msg.msg_controllen = sizeof(msg_control); | |
231 ngx_memzero(msg_control, sizeof(msg_control)); | |
232 | |
233 cmsg = CMSG_FIRSTHDR(&msg); | |
234 | |
235 msg.msg_controllen = ngx_set_srcaddr_cmsg(cmsg, c->local_sockaddr); | |
236 } | |
237 #endif | |
238 | |
239 return ngx_sendmsg(c, &msg, 0); | |
240 } | |
241 | |
242 | |
243 #if (NGX_HAVE_ADDRINFO_CMSG) | |
244 | |
245 size_t | |
246 ngx_set_srcaddr_cmsg(struct cmsghdr *cmsg, struct sockaddr *local_sockaddr) | |
247 { | |
248 size_t len; | |
241 #if (NGX_HAVE_IP_SENDSRCADDR) | 249 #if (NGX_HAVE_IP_SENDSRCADDR) |
242 | 250 struct in_addr *addr; |
243 if (c->local_sockaddr->sa_family == AF_INET) { | 251 struct sockaddr_in *sin; |
244 struct cmsghdr *cmsg; | |
245 struct in_addr *addr; | |
246 struct sockaddr_in *sin; | |
247 | |
248 msg.msg_control = &msg_control; | |
249 msg.msg_controllen = sizeof(msg_control); | |
250 | |
251 cmsg = CMSG_FIRSTHDR(&msg); | |
252 cmsg->cmsg_level = IPPROTO_IP; | |
253 cmsg->cmsg_type = IP_SENDSRCADDR; | |
254 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); | |
255 | |
256 sin = (struct sockaddr_in *) c->local_sockaddr; | |
257 | |
258 addr = (struct in_addr *) CMSG_DATA(cmsg); | |
259 *addr = sin->sin_addr; | |
260 } | |
261 | |
262 #elif (NGX_HAVE_IP_PKTINFO) | 252 #elif (NGX_HAVE_IP_PKTINFO) |
263 | 253 struct in_pktinfo *pkt; |
264 if (c->local_sockaddr->sa_family == AF_INET) { | 254 struct sockaddr_in *sin; |
265 struct cmsghdr *cmsg; | |
266 struct in_pktinfo *pkt; | |
267 struct sockaddr_in *sin; | |
268 | |
269 msg.msg_control = &msg_control; | |
270 msg.msg_controllen = sizeof(msg_control); | |
271 | |
272 cmsg = CMSG_FIRSTHDR(&msg); | |
273 cmsg->cmsg_level = IPPROTO_IP; | |
274 cmsg->cmsg_type = IP_PKTINFO; | |
275 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); | |
276 | |
277 sin = (struct sockaddr_in *) c->local_sockaddr; | |
278 | |
279 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); | |
280 ngx_memzero(pkt, sizeof(struct in_pktinfo)); | |
281 pkt->ipi_spec_dst = sin->sin_addr; | |
282 } | |
283 | |
284 #endif | 255 #endif |
285 | 256 |
286 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | 257 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) |
287 | 258 struct in6_pktinfo *pkt6; |
288 if (c->local_sockaddr->sa_family == AF_INET6) { | 259 struct sockaddr_in6 *sin6; |
289 struct cmsghdr *cmsg; | 260 #endif |
290 struct in6_pktinfo *pkt6; | 261 |
291 struct sockaddr_in6 *sin6; | 262 |
292 | 263 #if (NGX_HAVE_IP_SENDSRCADDR) || (NGX_HAVE_IP_PKTINFO) |
293 msg.msg_control = &msg_control6; | 264 |
294 msg.msg_controllen = sizeof(msg_control6); | 265 if (local_sockaddr->sa_family == AF_INET) { |
295 | 266 |
296 cmsg = CMSG_FIRSTHDR(&msg); | 267 cmsg->cmsg_level = IPPROTO_IP; |
297 cmsg->cmsg_level = IPPROTO_IPV6; | 268 |
298 cmsg->cmsg_type = IPV6_PKTINFO; | 269 #if (NGX_HAVE_IP_SENDSRCADDR) |
299 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); | 270 |
300 | 271 cmsg->cmsg_type = IP_SENDSRCADDR; |
301 sin6 = (struct sockaddr_in6 *) c->local_sockaddr; | 272 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); |
302 | 273 len = CMSG_SPACE(sizeof(struct in_addr)); |
303 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); | 274 |
304 ngx_memzero(pkt6, sizeof(struct in6_pktinfo)); | 275 sin = (struct sockaddr_in *) local_sockaddr; |
305 pkt6->ipi6_addr = sin6->sin6_addr; | 276 |
306 } | 277 addr = (struct in_addr *) CMSG_DATA(cmsg); |
307 | 278 *addr = sin->sin_addr; |
308 #endif | 279 |
309 } | 280 #elif (NGX_HAVE_IP_PKTINFO) |
310 | 281 |
282 cmsg->cmsg_type = IP_PKTINFO; | |
283 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); | |
284 len = CMSG_SPACE(sizeof(struct in_pktinfo)); | |
285 | |
286 sin = (struct sockaddr_in *) local_sockaddr; | |
287 | |
288 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); | |
289 ngx_memzero(pkt, sizeof(struct in_pktinfo)); | |
290 pkt->ipi_spec_dst = sin->sin_addr; | |
291 | |
292 #endif | |
293 return len; | |
294 } | |
295 | |
296 #endif | |
297 | |
298 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
299 if (local_sockaddr->sa_family == AF_INET6) { | |
300 | |
301 cmsg->cmsg_level = IPPROTO_IPV6; | |
302 cmsg->cmsg_type = IPV6_PKTINFO; | |
303 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); | |
304 len = CMSG_SPACE(sizeof(struct in6_pktinfo)); | |
305 | |
306 sin6 = (struct sockaddr_in6 *) local_sockaddr; | |
307 | |
308 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); | |
309 ngx_memzero(pkt6, sizeof(struct in6_pktinfo)); | |
310 pkt6->ipi6_addr = sin6->sin6_addr; | |
311 | |
312 return len; | |
313 } | |
314 #endif | |
315 | |
316 return 0; | |
317 } | |
318 | |
319 #endif | |
320 | |
321 | |
322 ssize_t | |
323 ngx_sendmsg(ngx_connection_t *c, struct msghdr *msg, int flags) | |
324 { | |
325 ssize_t n; | |
326 ngx_err_t err; | |
327 #if (NGX_DEBUG) | |
328 size_t size; | |
329 ngx_uint_t i; | |
311 #endif | 330 #endif |
312 | 331 |
313 eintr: | 332 eintr: |
314 | 333 |
315 n = sendmsg(c->fd, &msg, 0); | 334 n = sendmsg(c->fd, msg, flags); |
316 | |
317 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
318 "sendmsg: %z of %uz", n, vec->size); | |
319 | 335 |
320 if (n == -1) { | 336 if (n == -1) { |
321 err = ngx_errno; | 337 err = ngx_errno; |
322 | 338 |
323 switch (err) { | 339 switch (err) { |
336 ngx_connection_error(c, err, "sendmsg() failed"); | 352 ngx_connection_error(c, err, "sendmsg() failed"); |
337 return NGX_ERROR; | 353 return NGX_ERROR; |
338 } | 354 } |
339 } | 355 } |
340 | 356 |
357 #if (NGX_DEBUG) | |
358 for (i = 0, size = 0; i < (size_t) msg->msg_iovlen; i++) { | |
359 size += msg->msg_iov[i].iov_len; | |
360 } | |
361 | |
362 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, | |
363 "sendmsg: %z of %uz", n, size); | |
364 #endif | |
365 | |
341 return n; | 366 return n; |
342 } | 367 } |