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>