Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_channel.h>
0011 
0012 
0013 ngx_int_t
0014 ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
0015     ngx_log_t *log)
0016 {
0017     ssize_t             n;
0018     ngx_err_t           err;
0019     struct iovec        iov[1];
0020     struct msghdr       msg;
0021 
0022 #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
0023 
0024     union {
0025         struct cmsghdr  cm;
0026         char            space[CMSG_SPACE(sizeof(int))];
0027     } cmsg;
0028 
0029     if (ch->fd == -1) {
0030         msg.msg_control = NULL;
0031         msg.msg_controllen = 0;
0032 
0033     } else {
0034         msg.msg_control = (caddr_t) &cmsg;
0035         msg.msg_controllen = sizeof(cmsg);
0036 
0037         ngx_memzero(&cmsg, sizeof(cmsg));
0038 
0039         cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
0040         cmsg.cm.cmsg_level = SOL_SOCKET;
0041         cmsg.cm.cmsg_type = SCM_RIGHTS;
0042 
0043         /*
0044          * We have to use ngx_memcpy() instead of simple
0045          *   *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
0046          * because some gcc 4.4 with -O2/3/s optimization issues the warning:
0047          *   dereferencing type-punned pointer will break strict-aliasing rules
0048          *
0049          * Fortunately, gcc with -O1 compiles this ngx_memcpy()
0050          * in the same simple assignment as in the code above
0051          */
0052 
0053         ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int));
0054     }
0055 
0056     msg.msg_flags = 0;
0057 
0058 #else
0059 
0060     if (ch->fd == -1) {
0061         msg.msg_accrights = NULL;
0062         msg.msg_accrightslen = 0;
0063 
0064     } else {
0065         msg.msg_accrights = (caddr_t) &ch->fd;
0066         msg.msg_accrightslen = sizeof(int);
0067     }
0068 
0069 #endif
0070 
0071     iov[0].iov_base = (char *) ch;
0072     iov[0].iov_len = size;
0073 
0074     msg.msg_name = NULL;
0075     msg.msg_namelen = 0;
0076     msg.msg_iov = iov;
0077     msg.msg_iovlen = 1;
0078 
0079     n = sendmsg(s, &msg, 0);
0080 
0081     if (n == -1) {
0082         err = ngx_errno;
0083         if (err == NGX_EAGAIN) {
0084             return NGX_AGAIN;
0085         }
0086 
0087         ngx_log_error(NGX_LOG_ALERT, log, err, "sendmsg() failed");
0088         return NGX_ERROR;
0089     }
0090 
0091     return NGX_OK;
0092 }
0093 
0094 
0095 ngx_int_t
0096 ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log)
0097 {
0098     ssize_t             n;
0099     ngx_err_t           err;
0100     struct iovec        iov[1];
0101     struct msghdr       msg;
0102 
0103 #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
0104     union {
0105         struct cmsghdr  cm;
0106         char            space[CMSG_SPACE(sizeof(int))];
0107     } cmsg;
0108 #else
0109     int                 fd;
0110 #endif
0111 
0112     iov[0].iov_base = (char *) ch;
0113     iov[0].iov_len = size;
0114 
0115     msg.msg_name = NULL;
0116     msg.msg_namelen = 0;
0117     msg.msg_iov = iov;
0118     msg.msg_iovlen = 1;
0119 
0120 #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
0121     msg.msg_control = (caddr_t) &cmsg;
0122     msg.msg_controllen = sizeof(cmsg);
0123 #else
0124     msg.msg_accrights = (caddr_t) &fd;
0125     msg.msg_accrightslen = sizeof(int);
0126 #endif
0127 
0128     n = recvmsg(s, &msg, 0);
0129 
0130     if (n == -1) {
0131         err = ngx_errno;
0132         if (err == NGX_EAGAIN) {
0133             return NGX_AGAIN;
0134         }
0135 
0136         ngx_log_error(NGX_LOG_ALERT, log, err, "recvmsg() failed");
0137         return NGX_ERROR;
0138     }
0139 
0140     if (n == 0) {
0141         ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "recvmsg() returned zero");
0142         return NGX_ERROR;
0143     }
0144 
0145     if ((size_t) n < sizeof(ngx_channel_t)) {
0146         ngx_log_error(NGX_LOG_ALERT, log, 0,
0147                       "recvmsg() returned not enough data: %z", n);
0148         return NGX_ERROR;
0149     }
0150 
0151 #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
0152 
0153     if (ch->command == NGX_CMD_OPEN_CHANNEL) {
0154 
0155         if (cmsg.cm.cmsg_len < (socklen_t) CMSG_LEN(sizeof(int))) {
0156             ngx_log_error(NGX_LOG_ALERT, log, 0,
0157                           "recvmsg() returned too small ancillary data");
0158             return NGX_ERROR;
0159         }
0160 
0161         if (cmsg.cm.cmsg_level != SOL_SOCKET || cmsg.cm.cmsg_type != SCM_RIGHTS)
0162         {
0163             ngx_log_error(NGX_LOG_ALERT, log, 0,
0164                           "recvmsg() returned invalid ancillary data "
0165                           "level %d or type %d",
0166                           cmsg.cm.cmsg_level, cmsg.cm.cmsg_type);
0167             return NGX_ERROR;
0168         }
0169 
0170         /* ch->fd = *(int *) CMSG_DATA(&cmsg.cm); */
0171 
0172         ngx_memcpy(&ch->fd, CMSG_DATA(&cmsg.cm), sizeof(int));
0173     }
0174 
0175     if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
0176         ngx_log_error(NGX_LOG_ALERT, log, 0,
0177                       "recvmsg() truncated data");
0178     }
0179 
0180 #else
0181 
0182     if (ch->command == NGX_CMD_OPEN_CHANNEL) {
0183         if (msg.msg_accrightslen != sizeof(int)) {
0184             ngx_log_error(NGX_LOG_ALERT, log, 0,
0185                           "recvmsg() returned no ancillary data");
0186             return NGX_ERROR;
0187         }
0188 
0189         ch->fd = fd;
0190     }
0191 
0192 #endif
0193 
0194     return n;
0195 }
0196 
0197 
0198 ngx_int_t
0199 ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd, ngx_int_t event,
0200     ngx_event_handler_pt handler)
0201 {
0202     ngx_event_t       *ev, *rev, *wev;
0203     ngx_connection_t  *c;
0204 
0205     c = ngx_get_connection(fd, cycle->log);
0206 
0207     if (c == NULL) {
0208         return NGX_ERROR;
0209     }
0210 
0211     c->pool = cycle->pool;
0212 
0213     rev = c->read;
0214     wev = c->write;
0215 
0216     rev->log = cycle->log;
0217     wev->log = cycle->log;
0218 
0219     rev->channel = 1;
0220     wev->channel = 1;
0221 
0222     ev = (event == NGX_READ_EVENT) ? rev : wev;
0223 
0224     ev->handler = handler;
0225 
0226     if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
0227         if (ngx_add_conn(c) == NGX_ERROR) {
0228             ngx_free_connection(c);
0229             return NGX_ERROR;
0230         }
0231 
0232     } else {
0233         if (ngx_add_event(ev, event, 0) == NGX_ERROR) {
0234             ngx_free_connection(c);
0235             return NGX_ERROR;
0236         }
0237     }
0238 
0239     return NGX_OK;
0240 }
0241 
0242 
0243 void
0244 ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log)
0245 {
0246     if (close(fd[0]) == -1) {
0247         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed");
0248     }
0249 
0250     if (close(fd[1]) == -1) {
0251         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed");
0252     }
0253 }