comparison src/os/unix/ngx_channel.c @ 0:f0b350454894 NGINX_0_1_0

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