Mercurial > hg > nginx
comparison src/event/ngx_event_accept.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 | 52aacc8ddcc5 |
children | fdc3d40979b0 |
comparison
equal
deleted
inserted
replaced
7284:52aacc8ddcc5 | 7285:88a624c9b491 |
---|---|
8 #include <ngx_config.h> | 8 #include <ngx_config.h> |
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 #include <ngx_event.h> | 10 #include <ngx_event.h> |
11 | 11 |
12 | 12 |
13 static ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); | |
14 static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all); | 13 static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all); |
15 static void ngx_close_accepted_connection(ngx_connection_t *c); | 14 static void ngx_close_accepted_connection(ngx_connection_t *c); |
16 #if (NGX_DEBUG) | |
17 static void ngx_debug_accepted_connection(ngx_event_conf_t *ecf, | |
18 ngx_connection_t *c); | |
19 #endif | |
20 | 15 |
21 | 16 |
22 void | 17 void |
23 ngx_event_accept(ngx_event_t *ev) | 18 ngx_event_accept(ngx_event_t *ev) |
24 { | 19 { |
318 | 313 |
319 } while (ev->available); | 314 } while (ev->available); |
320 } | 315 } |
321 | 316 |
322 | 317 |
323 #if !(NGX_WIN32) | |
324 | |
325 void | |
326 ngx_event_recvmsg(ngx_event_t *ev) | |
327 { | |
328 ssize_t n; | |
329 ngx_log_t *log; | |
330 ngx_err_t err; | |
331 socklen_t socklen, local_socklen; | |
332 ngx_event_t *rev, *wev; | |
333 struct iovec iov[1]; | |
334 struct msghdr msg; | |
335 ngx_sockaddr_t sa, lsa; | |
336 struct sockaddr *sockaddr, *local_sockaddr; | |
337 ngx_listening_t *ls; | |
338 ngx_event_conf_t *ecf; | |
339 ngx_connection_t *c, *lc; | |
340 static u_char buffer[65535]; | |
341 | |
342 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
343 | |
344 #if (NGX_HAVE_IP_RECVDSTADDR) | |
345 u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))]; | |
346 #elif (NGX_HAVE_IP_PKTINFO) | |
347 u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))]; | |
348 #endif | |
349 | |
350 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
351 u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; | |
352 #endif | |
353 | |
354 #endif | |
355 | |
356 if (ev->timedout) { | |
357 if (ngx_enable_accept_events((ngx_cycle_t *) ngx_cycle) != NGX_OK) { | |
358 return; | |
359 } | |
360 | |
361 ev->timedout = 0; | |
362 } | |
363 | |
364 ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module); | |
365 | |
366 if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) { | |
367 ev->available = ecf->multi_accept; | |
368 } | |
369 | |
370 lc = ev->data; | |
371 ls = lc->listening; | |
372 ev->ready = 0; | |
373 | |
374 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, | |
375 "recvmsg on %V, ready: %d", &ls->addr_text, ev->available); | |
376 | |
377 do { | |
378 ngx_memzero(&msg, sizeof(struct msghdr)); | |
379 | |
380 iov[0].iov_base = (void *) buffer; | |
381 iov[0].iov_len = sizeof(buffer); | |
382 | |
383 msg.msg_name = &sa; | |
384 msg.msg_namelen = sizeof(ngx_sockaddr_t); | |
385 msg.msg_iov = iov; | |
386 msg.msg_iovlen = 1; | |
387 | |
388 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
389 | |
390 if (ls->wildcard) { | |
391 | |
392 #if (NGX_HAVE_IP_RECVDSTADDR || NGX_HAVE_IP_PKTINFO) | |
393 if (ls->sockaddr->sa_family == AF_INET) { | |
394 msg.msg_control = &msg_control; | |
395 msg.msg_controllen = sizeof(msg_control); | |
396 } | |
397 #endif | |
398 | |
399 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
400 if (ls->sockaddr->sa_family == AF_INET6) { | |
401 msg.msg_control = &msg_control6; | |
402 msg.msg_controllen = sizeof(msg_control6); | |
403 } | |
404 #endif | |
405 } | |
406 | |
407 #endif | |
408 | |
409 n = recvmsg(lc->fd, &msg, 0); | |
410 | |
411 if (n == -1) { | |
412 err = ngx_socket_errno; | |
413 | |
414 if (err == NGX_EAGAIN) { | |
415 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err, | |
416 "recvmsg() not ready"); | |
417 return; | |
418 } | |
419 | |
420 ngx_log_error(NGX_LOG_ALERT, ev->log, err, "recvmsg() failed"); | |
421 | |
422 return; | |
423 } | |
424 | |
425 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
426 if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { | |
427 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, | |
428 "recvmsg() truncated data"); | |
429 continue; | |
430 } | |
431 #endif | |
432 | |
433 sockaddr = msg.msg_name; | |
434 socklen = msg.msg_namelen; | |
435 | |
436 if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) { | |
437 socklen = sizeof(ngx_sockaddr_t); | |
438 } | |
439 | |
440 if (socklen == 0) { | |
441 | |
442 /* | |
443 * on Linux recvmsg() returns zero msg_namelen | |
444 * when receiving packets from unbound AF_UNIX sockets | |
445 */ | |
446 | |
447 socklen = sizeof(struct sockaddr); | |
448 ngx_memzero(&sa, sizeof(struct sockaddr)); | |
449 sa.sockaddr.sa_family = ls->sockaddr->sa_family; | |
450 } | |
451 | |
452 local_sockaddr = ls->sockaddr; | |
453 local_socklen = ls->socklen; | |
454 | |
455 #if (NGX_HAVE_MSGHDR_MSG_CONTROL) | |
456 | |
457 if (ls->wildcard) { | |
458 struct cmsghdr *cmsg; | |
459 | |
460 ngx_memcpy(&lsa, local_sockaddr, local_socklen); | |
461 local_sockaddr = &lsa.sockaddr; | |
462 | |
463 for (cmsg = CMSG_FIRSTHDR(&msg); | |
464 cmsg != NULL; | |
465 cmsg = CMSG_NXTHDR(&msg, cmsg)) | |
466 { | |
467 | |
468 #if (NGX_HAVE_IP_RECVDSTADDR) | |
469 | |
470 if (cmsg->cmsg_level == IPPROTO_IP | |
471 && cmsg->cmsg_type == IP_RECVDSTADDR | |
472 && local_sockaddr->sa_family == AF_INET) | |
473 { | |
474 struct in_addr *addr; | |
475 struct sockaddr_in *sin; | |
476 | |
477 addr = (struct in_addr *) CMSG_DATA(cmsg); | |
478 sin = (struct sockaddr_in *) local_sockaddr; | |
479 sin->sin_addr = *addr; | |
480 | |
481 break; | |
482 } | |
483 | |
484 #elif (NGX_HAVE_IP_PKTINFO) | |
485 | |
486 if (cmsg->cmsg_level == IPPROTO_IP | |
487 && cmsg->cmsg_type == IP_PKTINFO | |
488 && local_sockaddr->sa_family == AF_INET) | |
489 { | |
490 struct in_pktinfo *pkt; | |
491 struct sockaddr_in *sin; | |
492 | |
493 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg); | |
494 sin = (struct sockaddr_in *) local_sockaddr; | |
495 sin->sin_addr = pkt->ipi_addr; | |
496 | |
497 break; | |
498 } | |
499 | |
500 #endif | |
501 | |
502 #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO) | |
503 | |
504 if (cmsg->cmsg_level == IPPROTO_IPV6 | |
505 && cmsg->cmsg_type == IPV6_PKTINFO | |
506 && local_sockaddr->sa_family == AF_INET6) | |
507 { | |
508 struct in6_pktinfo *pkt6; | |
509 struct sockaddr_in6 *sin6; | |
510 | |
511 pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg); | |
512 sin6 = (struct sockaddr_in6 *) local_sockaddr; | |
513 sin6->sin6_addr = pkt6->ipi6_addr; | |
514 | |
515 break; | |
516 } | |
517 | |
518 #endif | |
519 | |
520 } | |
521 } | |
522 | |
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; | |
586 | |
587 c->buffer = ngx_create_temp_buf(c->pool, n); | |
588 if (c->buffer == NULL) { | |
589 ngx_close_accepted_connection(c); | |
590 return; | |
591 } | |
592 | |
593 c->buffer->last = ngx_cpymem(c->buffer->last, buffer, n); | |
594 | |
595 rev = c->read; | |
596 wev = c->write; | |
597 | |
598 wev->ready = 1; | |
599 | |
600 rev->log = log; | |
601 wev->log = log; | |
602 | |
603 /* | |
604 * TODO: MT: - ngx_atomic_fetch_add() | |
605 * or protection by critical section or light mutex | |
606 * | |
607 * TODO: MP: - allocated in a shared memory | |
608 * - ngx_atomic_fetch_add() | |
609 * or protection by critical section or light mutex | |
610 */ | |
611 | |
612 c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); | |
613 | |
614 #if (NGX_STAT_STUB) | |
615 (void) ngx_atomic_fetch_add(ngx_stat_handled, 1); | |
616 #endif | |
617 | |
618 if (ls->addr_ntop) { | |
619 c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len); | |
620 if (c->addr_text.data == NULL) { | |
621 ngx_close_accepted_connection(c); | |
622 return; | |
623 } | |
624 | |
625 c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->socklen, | |
626 c->addr_text.data, | |
627 ls->addr_text_max_len, 0); | |
628 if (c->addr_text.len == 0) { | |
629 ngx_close_accepted_connection(c); | |
630 return; | |
631 } | |
632 } | |
633 | |
634 #if (NGX_DEBUG) | |
635 { | |
636 ngx_str_t addr; | |
637 u_char text[NGX_SOCKADDR_STRLEN]; | |
638 | |
639 ngx_debug_accepted_connection(ecf, c); | |
640 | |
641 if (log->log_level & NGX_LOG_DEBUG_EVENT) { | |
642 addr.data = text; | |
643 addr.len = ngx_sock_ntop(c->sockaddr, c->socklen, text, | |
644 NGX_SOCKADDR_STRLEN, 1); | |
645 | |
646 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, log, 0, | |
647 "*%uA recvmsg: %V fd:%d n:%z", | |
648 c->number, &addr, c->fd, n); | |
649 } | |
650 | |
651 } | |
652 #endif | |
653 | |
654 log->data = NULL; | |
655 log->handler = NULL; | |
656 | |
657 ls->handler(c); | |
658 | |
659 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { | |
660 ev->available -= n; | |
661 } | |
662 | |
663 } while (ev->available); | |
664 } | |
665 | |
666 #endif | |
667 | |
668 | |
669 ngx_int_t | 318 ngx_int_t |
670 ngx_trylock_accept_mutex(ngx_cycle_t *cycle) | 319 ngx_trylock_accept_mutex(ngx_cycle_t *cycle) |
671 { | 320 { |
672 if (ngx_shmtx_trylock(&ngx_accept_mutex)) { | 321 if (ngx_shmtx_trylock(&ngx_accept_mutex)) { |
673 | 322 |
702 | 351 |
703 return NGX_OK; | 352 return NGX_OK; |
704 } | 353 } |
705 | 354 |
706 | 355 |
707 static ngx_int_t | 356 ngx_int_t |
708 ngx_enable_accept_events(ngx_cycle_t *cycle) | 357 ngx_enable_accept_events(ngx_cycle_t *cycle) |
709 { | 358 { |
710 ngx_uint_t i; | 359 ngx_uint_t i; |
711 ngx_listening_t *ls; | 360 ngx_listening_t *ls; |
712 ngx_connection_t *c; | 361 ngx_connection_t *c; |
777 ngx_free_connection(c); | 426 ngx_free_connection(c); |
778 | 427 |
779 fd = c->fd; | 428 fd = c->fd; |
780 c->fd = (ngx_socket_t) -1; | 429 c->fd = (ngx_socket_t) -1; |
781 | 430 |
782 if (!c->shared && ngx_close_socket(fd) == -1) { | 431 if (ngx_close_socket(fd) == -1) { |
783 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, | 432 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, |
784 ngx_close_socket_n " failed"); | 433 ngx_close_socket_n " failed"); |
785 } | 434 } |
786 | 435 |
787 if (c->pool) { | 436 if (c->pool) { |
802 } | 451 } |
803 | 452 |
804 | 453 |
805 #if (NGX_DEBUG) | 454 #if (NGX_DEBUG) |
806 | 455 |
807 static void | 456 void |
808 ngx_debug_accepted_connection(ngx_event_conf_t *ecf, ngx_connection_t *c) | 457 ngx_debug_accepted_connection(ngx_event_conf_t *ecf, ngx_connection_t *c) |
809 { | 458 { |
810 struct sockaddr_in *sin; | 459 struct sockaddr_in *sin; |
811 ngx_cidr_t *cidr; | 460 ngx_cidr_t *cidr; |
812 ngx_uint_t i; | 461 ngx_uint_t i; |