Annotation of embedaddon/nginx/src/os/unix/ngx_channel.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_channel.h>
                     11: 
                     12: 
                     13: ngx_int_t
                     14: ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
                     15:     ngx_log_t *log)
                     16: {
                     17:     ssize_t             n;
                     18:     ngx_err_t           err;
                     19:     struct iovec        iov[1];
                     20:     struct msghdr       msg;
                     21: 
                     22: #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
                     23: 
                     24:     union {
                     25:         struct cmsghdr  cm;
                     26:         char            space[CMSG_SPACE(sizeof(int))];
                     27:     } cmsg;
                     28: 
                     29:     if (ch->fd == -1) {
                     30:         msg.msg_control = NULL;
                     31:         msg.msg_controllen = 0;
                     32: 
                     33:     } else {
                     34:         msg.msg_control = (caddr_t) &cmsg;
                     35:         msg.msg_controllen = sizeof(cmsg);
                     36: 
                     37:         cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
                     38:         cmsg.cm.cmsg_level = SOL_SOCKET;
                     39:         cmsg.cm.cmsg_type = SCM_RIGHTS;
                     40: 
                     41:         /*
                     42:          * We have to use ngx_memcpy() instead of simple
                     43:          *   *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
                     44:          * because some gcc 4.4 with -O2/3/s optimization issues the warning:
                     45:          *   dereferencing type-punned pointer will break strict-aliasing rules
                     46:          *
                     47:          * Fortunately, gcc with -O1 compiles this ngx_memcpy()
                     48:          * in the same simple assignment as in the code above
                     49:          */
                     50: 
                     51:         ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int));
                     52:     }
                     53: 
                     54:     msg.msg_flags = 0;
                     55: 
                     56: #else
                     57: 
                     58:     if (ch->fd == -1) {
                     59:         msg.msg_accrights = NULL;
                     60:         msg.msg_accrightslen = 0;
                     61: 
                     62:     } else {
                     63:         msg.msg_accrights = (caddr_t) &ch->fd;
                     64:         msg.msg_accrightslen = sizeof(int);
                     65:     }
                     66: 
                     67: #endif
                     68: 
                     69:     iov[0].iov_base = (char *) ch;
                     70:     iov[0].iov_len = size;
                     71: 
                     72:     msg.msg_name = NULL;
                     73:     msg.msg_namelen = 0;
                     74:     msg.msg_iov = iov;
                     75:     msg.msg_iovlen = 1;
                     76: 
                     77:     n = sendmsg(s, &msg, 0);
                     78: 
                     79:     if (n == -1) {
                     80:         err = ngx_errno;
                     81:         if (err == NGX_EAGAIN) {
                     82:             return NGX_AGAIN;
                     83:         }
                     84: 
                     85:         ngx_log_error(NGX_LOG_ALERT, log, err, "sendmsg() failed");
                     86:         return NGX_ERROR;
                     87:     }
                     88: 
                     89:     return NGX_OK;
                     90: }
                     91: 
                     92: 
                     93: ngx_int_t
                     94: ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log)
                     95: {
                     96:     ssize_t             n;
                     97:     ngx_err_t           err;
                     98:     struct iovec        iov[1];
                     99:     struct msghdr       msg;
                    100: 
                    101: #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
                    102:     union {
                    103:         struct cmsghdr  cm;
                    104:         char            space[CMSG_SPACE(sizeof(int))];
                    105:     } cmsg;
                    106: #else
                    107:     int                 fd;
                    108: #endif
                    109: 
                    110:     iov[0].iov_base = (char *) ch;
                    111:     iov[0].iov_len = size;
                    112: 
                    113:     msg.msg_name = NULL;
                    114:     msg.msg_namelen = 0;
                    115:     msg.msg_iov = iov;
                    116:     msg.msg_iovlen = 1;
                    117: 
                    118: #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
                    119:     msg.msg_control = (caddr_t) &cmsg;
                    120:     msg.msg_controllen = sizeof(cmsg);
                    121: #else
                    122:     msg.msg_accrights = (caddr_t) &fd;
                    123:     msg.msg_accrightslen = sizeof(int);
                    124: #endif
                    125: 
                    126:     n = recvmsg(s, &msg, 0);
                    127: 
                    128:     if (n == -1) {
                    129:         err = ngx_errno;
                    130:         if (err == NGX_EAGAIN) {
                    131:             return NGX_AGAIN;
                    132:         }
                    133: 
                    134:         ngx_log_error(NGX_LOG_ALERT, log, err, "recvmsg() failed");
                    135:         return NGX_ERROR;
                    136:     }
                    137: 
                    138:     if (n == 0) {
                    139:         ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "recvmsg() returned zero");
                    140:         return NGX_ERROR;
                    141:     }
                    142: 
                    143:     if ((size_t) n < sizeof(ngx_channel_t)) {
                    144:         ngx_log_error(NGX_LOG_ALERT, log, 0,
                    145:                       "recvmsg() returned not enough data: %uz", n);
                    146:         return NGX_ERROR;
                    147:     }
                    148: 
                    149: #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
                    150: 
                    151:     if (ch->command == NGX_CMD_OPEN_CHANNEL) {
                    152: 
                    153:         if (cmsg.cm.cmsg_len < (socklen_t) CMSG_LEN(sizeof(int))) {
                    154:             ngx_log_error(NGX_LOG_ALERT, log, 0,
                    155:                           "recvmsg() returned too small ancillary data");
                    156:             return NGX_ERROR;
                    157:         }
                    158: 
                    159:         if (cmsg.cm.cmsg_level != SOL_SOCKET || cmsg.cm.cmsg_type != SCM_RIGHTS)
                    160:         {
                    161:             ngx_log_error(NGX_LOG_ALERT, log, 0,
                    162:                           "recvmsg() returned invalid ancillary data "
                    163:                           "level %d or type %d",
                    164:                           cmsg.cm.cmsg_level, cmsg.cm.cmsg_type);
                    165:             return NGX_ERROR;
                    166:         }
                    167: 
                    168:         /* ch->fd = *(int *) CMSG_DATA(&cmsg.cm); */
                    169: 
                    170:         ngx_memcpy(&ch->fd, CMSG_DATA(&cmsg.cm), sizeof(int));
                    171:     }
                    172: 
                    173:     if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
                    174:         ngx_log_error(NGX_LOG_ALERT, log, 0,
                    175:                       "recvmsg() truncated data");
                    176:     }
                    177: 
                    178: #else
                    179: 
                    180:     if (ch->command == NGX_CMD_OPEN_CHANNEL) {
                    181:         if (msg.msg_accrightslen != sizeof(int)) {
                    182:             ngx_log_error(NGX_LOG_ALERT, log, 0,
                    183:                           "recvmsg() returned no ancillary data");
                    184:             return NGX_ERROR;
                    185:         }
                    186: 
                    187:         ch->fd = fd;
                    188:     }
                    189: 
                    190: #endif
                    191: 
                    192:     return n;
                    193: }
                    194: 
                    195: 
                    196: ngx_int_t
                    197: ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd, ngx_int_t event,
                    198:     ngx_event_handler_pt handler)
                    199: {
                    200:     ngx_event_t       *ev, *rev, *wev;
                    201:     ngx_connection_t  *c;
                    202: 
                    203:     c = ngx_get_connection(fd, cycle->log);
                    204: 
                    205:     if (c == NULL) {
                    206:         return NGX_ERROR;
                    207:     }
                    208: 
                    209:     c->pool = cycle->pool;
                    210: 
                    211:     rev = c->read;
                    212:     wev = c->write;
                    213: 
                    214:     rev->log = cycle->log;
                    215:     wev->log = cycle->log;
                    216: 
                    217: #if (NGX_THREADS)
                    218:     rev->lock = &c->lock;
                    219:     wev->lock = &c->lock;
                    220:     rev->own_lock = &c->lock;
                    221:     wev->own_lock = &c->lock;
                    222: #endif
                    223: 
                    224:     rev->channel = 1;
                    225:     wev->channel = 1;
                    226: 
                    227:     ev = (event == NGX_READ_EVENT) ? rev : wev;
                    228: 
                    229:     ev->handler = handler;
                    230: 
                    231:     if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
                    232:         if (ngx_add_conn(c) == NGX_ERROR) {
                    233:             ngx_free_connection(c);
                    234:             return NGX_ERROR;
                    235:         }
                    236: 
                    237:     } else {
                    238:         if (ngx_add_event(ev, event, 0) == NGX_ERROR) {
                    239:             ngx_free_connection(c);
                    240:             return NGX_ERROR;
                    241:         }
                    242:     }
                    243: 
                    244:     return NGX_OK;
                    245: }
                    246: 
                    247: 
                    248: void
                    249: ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log)
                    250: {
                    251:     if (close(fd[0]) == -1) {
                    252:         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed");
                    253:     }
                    254: 
                    255:     if (close(fd[1]) == -1) {
                    256:         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed");
                    257:     }
                    258: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>