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