Mercurial > hg > nginx-quic
comparison src/event/ngx_event_accept.c @ 7284:52aacc8ddcc5
Events: get remote addresses before creating udp connection.
Previously, ngx_event_recvmsg() got remote socket addresses after creating
the connection object. In preparation to handling multiple UDP packets in a
single session, this code was moved up.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Fri, 01 Jun 2018 13:12:57 +0300 |
parents | d0b897c0bb5b |
children | 88a624c9b491 |
comparison
equal
deleted
inserted
replaced
7283:d0b897c0bb5b | 7284:52aacc8ddcc5 |
---|---|
326 ngx_event_recvmsg(ngx_event_t *ev) | 326 ngx_event_recvmsg(ngx_event_t *ev) |
327 { | 327 { |
328 ssize_t n; | 328 ssize_t n; |
329 ngx_log_t *log; | 329 ngx_log_t *log; |
330 ngx_err_t err; | 330 ngx_err_t err; |
331 socklen_t socklen, local_socklen; | |
331 ngx_event_t *rev, *wev; | 332 ngx_event_t *rev, *wev; |
332 struct iovec iov[1]; | 333 struct iovec iov[1]; |
333 struct msghdr msg; | 334 struct msghdr msg; |
334 ngx_sockaddr_t sa; | 335 ngx_sockaddr_t sa, lsa; |
336 struct sockaddr *sockaddr, *local_sockaddr; | |
335 ngx_listening_t *ls; | 337 ngx_listening_t *ls; |
336 ngx_event_conf_t *ecf; | 338 ngx_event_conf_t *ecf; |
337 ngx_connection_t *c, *lc; | 339 ngx_connection_t *c, *lc; |
338 static u_char buffer[65535]; | 340 static u_char buffer[65535]; |
339 | 341 |
417 | 419 |
418 ngx_log_error(NGX_LOG_ALERT, ev->log, err, "recvmsg() failed"); | 420 ngx_log_error(NGX_LOG_ALERT, ev->log, err, "recvmsg() failed"); |
419 | 421 |
420 return; | 422 return; |
421 } | 423 } |
422 | |
423 #if (NGX_STAT_STUB) | |
424 (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1); | |
425 #endif | |
426 | 424 |
427 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | 425 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) |
428 if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { | 426 if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { |
429 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, | 427 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, |
430 "recvmsg() truncated data"); | 428 "recvmsg() truncated data"); |
431 continue; | 429 continue; |
432 } | 430 } |
433 #endif | 431 #endif |
434 | 432 |
435 ngx_accept_disabled = ngx_cycle->connection_n / 8 | 433 sockaddr = msg.msg_name; |
436 - ngx_cycle->free_connection_n; | 434 socklen = msg.msg_namelen; |
437 | 435 |
438 c = ngx_get_connection(lc->fd, ev->log); | 436 if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { |
439 if (c == NULL) { | 437 socklen = sizeof(ngx_sockaddr_t); |
440 return; | 438 } |
441 } | 439 |
442 | 440 if (socklen == 0) { |
443 c->shared = 1; | |
444 c->type = SOCK_DGRAM; | |
445 c->socklen = msg.msg_namelen; | |
446 | |
447 if (c->socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { | |
448 c->socklen = sizeof(ngx_sockaddr_t); | |
449 } | |
450 | |
451 if (c->socklen == 0) { | |
452 | 441 |
453 /* | 442 /* |
454 * on Linux recvmsg() returns zero msg_namelen | 443 * on Linux recvmsg() returns zero msg_namelen |
455 * when receiving packets from unbound AF_UNIX sockets | 444 * when receiving packets from unbound AF_UNIX sockets |
456 */ | 445 */ |
457 | 446 |
458 c->socklen = sizeof(struct sockaddr); | 447 socklen = sizeof(struct sockaddr); |
459 ngx_memzero(&sa, sizeof(struct sockaddr)); | 448 ngx_memzero(&sa, sizeof(struct sockaddr)); |
460 sa.sockaddr.sa_family = ls->sockaddr->sa_family; | 449 sa.sockaddr.sa_family = ls->sockaddr->sa_family; |
461 } | 450 } |
462 | 451 |
463 #if (NGX_STAT_STUB) | 452 local_sockaddr = ls->sockaddr; |
464 (void) ngx_atomic_fetch_add(ngx_stat_active, 1); | 453 local_socklen = ls->socklen; |
465 #endif | |
466 | |
467 c->pool = ngx_create_pool(ls->pool_size, ev->log); | |
468 if (c->pool == NULL) { | |
469 ngx_close_accepted_connection(c); | |
470 return; | |
471 } | |
472 | |
473 c->sockaddr = ngx_palloc(c->pool, c->socklen); | |
474 if (c->sockaddr == NULL) { | |
475 ngx_close_accepted_connection(c); | |
476 return; | |
477 } | |
478 | |
479 ngx_memcpy(c->sockaddr, msg.msg_name, c->socklen); | |
480 | |
481 log = ngx_palloc(c->pool, sizeof(ngx_log_t)); | |
482 if (log == NULL) { | |
483 ngx_close_accepted_connection(c); | |
484 return; | |
485 } | |
486 | |
487 *log = ls->log; | |
488 | |
489 c->send = ngx_udp_send; | |
490 c->send_chain = ngx_udp_send_chain; | |
491 | |
492 c->log = log; | |
493 c->pool->log = log; | |
494 | |
495 c->listening = ls; | |
496 c->local_sockaddr = ls->sockaddr; | |
497 c->local_socklen = ls->socklen; | |
498 | 454 |
499 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | 455 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) |
500 | 456 |
501 if (ls->wildcard) { | 457 if (ls->wildcard) { |
502 struct cmsghdr *cmsg; | 458 struct cmsghdr *cmsg; |
503 struct sockaddr *sockaddr; | 459 |
504 | 460 ngx_memcpy(&lsa, local_sockaddr, local_socklen); |
505 sockaddr = ngx_palloc(c->pool, c->local_socklen); | 461 local_sockaddr = &lsa.sockaddr; |
506 if (sockaddr == NULL) { | |
507 ngx_close_accepted_connection(c); | |
508 return; | |
509 } | |
510 | |
511 ngx_memcpy(sockaddr, c->local_sockaddr, c->local_socklen); | |
512 c->local_sockaddr = sockaddr; | |
513 | 462 |
514 for (cmsg = CMSG_FIRSTHDR(&msg); | 463 for (cmsg = CMSG_FIRSTHDR(&msg); |
515 cmsg != NULL; | 464 cmsg != NULL; |
516 cmsg = CMSG_NXTHDR(&msg, cmsg)) | 465 cmsg = CMSG_NXTHDR(&msg, cmsg)) |
517 { | 466 { |
518 | 467 |
519 #if (NGX_HAVE_IP_RECVDSTADDR) | 468 #if (NGX_HAVE_IP_RECVDSTADDR) |
520 | 469 |
521 if (cmsg->cmsg_level == IPPROTO_IP | 470 if (cmsg->cmsg_level == IPPROTO_IP |
522 && cmsg->cmsg_type == IP_RECVDSTADDR | 471 && cmsg->cmsg_type == IP_RECVDSTADDR |
523 && sockaddr->sa_family == AF_INET) | 472 && local_sockaddr->sa_family == AF_INET) |
524 { | 473 { |
525 struct in_addr *addr; | 474 struct in_addr *addr; |
526 struct sockaddr_in *sin; | 475 struct sockaddr_in *sin; |
527 | 476 |
528 addr = (struct in_addr *) CMSG_DATA(cmsg); | 477 addr = (struct in_addr *) CMSG_DATA(cmsg); |
529 sin = (struct sockaddr_in *) sockaddr; | 478 sin = (struct sockaddr_in *) local_sockaddr; |
530 sin->sin_addr = *addr; | 479 sin->sin_addr = *addr; |
531 | 480 |
532 break; | 481 break; |
533 } | 482 } |
534 | 483 |
535 #elif (NGX_HAVE_IP_PKTINFO) | 484 #elif (NGX_HAVE_IP_PKTINFO) |
536 | 485 |
537 if (cmsg->cmsg_level == IPPROTO_IP | 486 if (cmsg->cmsg_level == IPPROTO_IP |
538 && cmsg->cmsg_type == IP_PKTINFO | 487 && cmsg->cmsg_type == IP_PKTINFO |
539 && sockaddr->sa_family == AF_INET) | 488 && local_sockaddr->sa_family == AF_INET) |
540 { | 489 { |
541 struct in_pktinfo *pkt; | 490 struct in_pktinfo *pkt; |
542 struct sockaddr_in *sin; | 491 struct sockaddr_in *sin; |
543 | 492 |
544 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); | 493 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); |
545 sin = (struct sockaddr_in *) sockaddr; | 494 sin = (struct sockaddr_in *) local_sockaddr; |
546 sin->sin_addr = pkt->ipi_addr; | 495 sin->sin_addr = pkt->ipi_addr; |
547 | 496 |
548 break; | 497 break; |
549 } | 498 } |
550 | 499 |
552 | 501 |
553 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | 502 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) |
554 | 503 |
555 if (cmsg->cmsg_level == IPPROTO_IPV6 | 504 if (cmsg->cmsg_level == IPPROTO_IPV6 |
556 && cmsg->cmsg_type == IPV6_PKTINFO | 505 && cmsg->cmsg_type == IPV6_PKTINFO |
557 && sockaddr->sa_family == AF_INET6) | 506 && local_sockaddr->sa_family == AF_INET6) |
558 { | 507 { |
559 struct in6_pktinfo *pkt6; | 508 struct in6_pktinfo *pkt6; |
560 struct sockaddr_in6 *sin6; | 509 struct sockaddr_in6 *sin6; |
561 | 510 |
562 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); | 511 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); |
563 sin6 = (struct sockaddr_in6 *) sockaddr; | 512 sin6 = (struct sockaddr_in6 *) local_sockaddr; |
564 sin6->sin6_addr = pkt6->ipi6_addr; | 513 sin6->sin6_addr = pkt6->ipi6_addr; |
565 | 514 |
566 break; | 515 break; |
567 } | 516 } |
568 | 517 |
570 | 519 |
571 } | 520 } |
572 } | 521 } |
573 | 522 |
574 #endif | 523 #endif |
524 | |
525 #if (NGX_STAT_STUB) | |
526 (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1); | |
527 #endif | |
528 | |
529 ngx_accept_disabled = ngx_cycle->connection_n / 8 | |
530 - ngx_cycle->free_connection_n; | |
531 | |
532 c = ngx_get_connection(lc->fd, ev->log); | |
533 if (c == NULL) { | |
534 return; | |
535 } | |
536 | |
537 c->shared = 1; | |
538 c->type = SOCK_DGRAM; | |
539 c->socklen = socklen; | |
540 | |
541 #if (NGX_STAT_STUB) | |
542 (void) ngx_atomic_fetch_add(ngx_stat_active, 1); | |
543 #endif | |
544 | |
545 c->pool = ngx_create_pool(ls->pool_size, ev->log); | |
546 if (c->pool == NULL) { | |
547 ngx_close_accepted_connection(c); | |
548 return; | |
549 } | |
550 | |
551 c->sockaddr = ngx_palloc(c->pool, socklen); | |
552 if (c->sockaddr == NULL) { | |
553 ngx_close_accepted_connection(c); | |
554 return; | |
555 } | |
556 | |
557 ngx_memcpy(c->sockaddr, sockaddr, socklen); | |
558 | |
559 log = ngx_palloc(c->pool, sizeof(ngx_log_t)); | |
560 if (log == NULL) { | |
561 ngx_close_accepted_connection(c); | |
562 return; | |
563 } | |
564 | |
565 *log = ls->log; | |
566 | |
567 c->send = ngx_udp_send; | |
568 c->send_chain = ngx_udp_send_chain; | |
569 | |
570 c->log = log; | |
571 c->pool->log = log; | |
572 c->listening = ls; | |
573 | |
574 if (local_sockaddr == &lsa.sockaddr) { | |
575 local_sockaddr = ngx_palloc(c->pool, local_socklen); | |
576 if (local_sockaddr == NULL) { | |
577 ngx_close_accepted_connection(c); | |
578 return; | |
579 } | |
580 | |
581 ngx_memcpy(local_sockaddr, &lsa, local_socklen); | |
582 } | |
583 | |
584 c->local_sockaddr = local_sockaddr; | |
585 c->local_socklen = local_socklen; | |
575 | 586 |
576 c->buffer = ngx_create_temp_buf(c->pool, n); | 587 c->buffer = ngx_create_temp_buf(c->pool, n); |
577 if (c->buffer == NULL) { | 588 if (c->buffer == NULL) { |
578 ngx_close_accepted_connection(c); | 589 ngx_close_accepted_connection(c); |
579 return; | 590 return; |