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;