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