src/os/unix/ngx_channel.c - nginx-1.31.7 nginx/ @ 939334eff

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_channel.h>


  8. ngx_int_t
  9. ‌ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
  10.     ngx_log_t *log)
  11. {
  12.     ssize_t             n;
  13.     ngx_err_t           err;
  14.     struct iovec        iov[1];
  15.     struct msghdr       msg;

  16. #if (NGX_HAVE_MSGHDR_MSG_CONTROL)

  17. ‌    union {
  18.         struct cmsghdr  cm;
  19.         char            space[CMSG_SPACE(sizeof(int))];
  20.     } cmsg;

  21.     if (ch->fd == -1) {
  22.         msg.msg_control = NULL;
  23.         msg.msg_controllen = 0;

  24.     } else {
  25.         msg.msg_control = (caddr_t) &cmsg;
  26.         msg.msg_controllen = sizeof(cmsg);

  27.         ngx_memzero(&cmsg, sizeof(cmsg));

  28.         cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
  29.         cmsg.cm.cmsg_level = SOL_SOCKET;
  30.         cmsg.cm.cmsg_type = SCM_RIGHTS;

  31.         /*
  32.          * We have to use ngx_memcpy() instead of simple
  33.          *   *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
  34.          * because some gcc 4.4 with -O2/3/s optimization issues the warning:
  35.          *   dereferencing type-punned pointer will break strict-aliasing rules
  36.          *
  37.          * Fortunately, gcc with -O1 compiles this ngx_memcpy()
  38.          * in the same simple assignment as in the code above
  39.          */

  40.         ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int));
  41.     }

  42.     msg.msg_flags = 0;

  43. #else

  44.     if (ch->fd == -1) {
  45.         msg.msg_accrights = NULL;
  46.         msg.msg_accrightslen = 0;

  47.     } else {
  48.         msg.msg_accrights = (caddr_t) &ch->fd;
  49.         msg.msg_accrightslen = sizeof(int);
  50.     }

  51. #endif

  52.     iov[0].iov_base = (char *) ch;
  53.     iov[0].iov_len = size;

  54.     msg.msg_name = NULL;
  55.     msg.msg_namelen = 0;
  56.     msg.msg_iov = iov;
  57.     msg.msg_iovlen = 1;

  58.     n = sendmsg(s, &msg, 0);

  59.     if (n == -1) {
  60.         err = ngx_errno;
  61.         if (err == NGX_EAGAIN) {
  62.             return NGX_AGAIN;
  63.         }

  64.         ngx_log_error(NGX_LOG_ALERT, log, err, "sendmsg() failed");
  65.         return NGX_ERROR;
  66.     }

  67.     return NGX_OK;
  68. }


  69. ngx_int_t
  70. ‌ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log)
  71. {
  72.     ssize_t             n;
  73.     ngx_err_t           err;
  74.     struct iovec        iov[1];
  75.     struct msghdr       msg;

  76. #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
  77. ‌    union {
  78.         struct cmsghdr  cm;
  79.         char            space[CMSG_SPACE(sizeof(int))];
  80.     } cmsg;
  81. #else
  82.     int                 fd;
  83. #endif

  84.     iov[0].iov_base = (char *) ch;
  85.     iov[0].iov_len = size;

  86.     msg.msg_name = NULL;
  87.     msg.msg_namelen = 0;
  88.     msg.msg_iov = iov;
  89.     msg.msg_iovlen = 1;

  90. #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
  91.     msg.msg_control = (caddr_t) &cmsg;
  92.     msg.msg_controllen = sizeof(cmsg);
  93. #else
  94.     msg.msg_accrights = (caddr_t) &fd;
  95.     msg.msg_accrightslen = sizeof(int);
  96. #endif

  97.     n = recvmsg(s, &msg, 0);

  98.     if (n == -1) {
  99.         err = ngx_errno;
  100.         if (err == NGX_EAGAIN) {
  101.             return NGX_AGAIN;
  102.         }

  103.         ngx_log_error(NGX_LOG_ALERT, log, err, "recvmsg() failed");

  104.         if (err == NGX_EMSGSIZE || err == NGX_EMFILE) {
  105.             /* file descriptor table is full */
  106.             ngx_memzero(ch, size);
  107.             return 0;
  108.         }

  109.         return NGX_ERROR;
  110.     }

  111.     if (n == 0) {
  112.         ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "recvmsg() returned zero");
  113.         return NGX_ERROR;
  114.     }

  115.     if ((size_t) n < sizeof(ngx_channel_t)) {
  116.         ngx_log_error(NGX_LOG_ALERT, log, 0,
  117.                       "recvmsg() returned not enough data: %z", n);
  118.         return NGX_ERROR;
  119.     }

  120. #if (NGX_HAVE_MSGHDR_MSG_CONTROL)

  121.     if (ch->command == NGX_CMD_OPEN_CHANNEL) {

  122.         if (msg.msg_controllen < (socklen_t) CMSG_LEN(sizeof(int))) {
  123.             ngx_log_error(NGX_LOG_ALERT, log, 0,
  124.                           "recvmsg() returned too small ancillary data");
  125.             ch->fd = -1;

  126.         } else if (cmsg.cm.cmsg_level != SOL_SOCKET
  127.                    || cmsg.cm.cmsg_type != SCM_RIGHTS)
  128.         {
  129.             ngx_log_error(NGX_LOG_ALERT, log, 0,
  130.                           "recvmsg() returned invalid ancillary data "
  131.                           "level %d or type %d",
  132.                           cmsg.cm.cmsg_level, cmsg.cm.cmsg_type);
  133.             return NGX_ERROR;

  134.         } else {

  135.             /* ch->fd = *(int *) CMSG_DATA(&cmsg.cm); */

  136.             ngx_memcpy(&ch->fd, CMSG_DATA(&cmsg.cm), sizeof(int));
  137.         }
  138.     }

  139.     if (msg.msg_flags & MSG_TRUNC) {
  140.         ngx_log_error(NGX_LOG_ALERT, log, 0,
  141.                       "recvmsg() truncated data");
  142.     }

  143. #else

  144.     if (ch->command == NGX_CMD_OPEN_CHANNEL) {
  145.         if (msg.msg_accrightslen != sizeof(int)) {
  146.             ngx_log_error(NGX_LOG_ALERT, log, 0,
  147.                           "recvmsg() returned no ancillary data");
  148.             ch->fd = -1;

  149.         } else {
  150.             ch->fd = fd;
  151.         }
  152.     }

  153. #endif

  154.     return n;
  155. }


  156. ngx_int_t
  157. ‌ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd, ngx_int_t event,
  158.     ngx_event_handler_pt handler)
  159. {
  160.     ngx_event_t       *ev, *rev, *wev;
  161.     ngx_connection_t  *c;

  162.     c = ngx_get_connection(fd, cycle->log);

  163.     if (c == NULL) {
  164.         return NGX_ERROR;
  165.     }

  166.     c->pool = cycle->pool;

  167.     rev = c->read;
  168.     wev = c->write;

  169.     rev->log = cycle->log;
  170.     wev->log = cycle->log;

  171.     rev->channel = 1;
  172.     wev->channel = 1;

  173.     ev = (event == NGX_READ_EVENT) ? rev : wev;

  174.     ev->handler = handler;

  175.     if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
  176.         if (ngx_add_conn(c) == NGX_ERROR) {
  177.             ngx_free_connection(c);
  178.             return NGX_ERROR;
  179.         }

  180.     } else {
  181.         if (ngx_add_event(ev, event, 0) == NGX_ERROR) {
  182.             ngx_free_connection(c);
  183.             return NGX_ERROR;
  184.         }
  185.     }

  186.     return NGX_OK;
  187. }


  188. void
  189. ‌ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log)
  190. {
  191.     if (close(fd[0]) == -1) {
  192.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed");
  193.     }

  194.     if (close(fd[1]) == -1) {
  195.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed");
  196.     }
  197. }