3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_channel.h>
14 ngx_write_channel(ngx_socket_t s
, ngx_channel_t
*ch
, size_t size
,
22 #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
26 char space
[CMSG_SPACE(sizeof(int))];
30 msg
.msg_control
= NULL
;
31 msg
.msg_controllen
= 0;
34 msg
.msg_control
= (caddr_t
) &cmsg
;
35 msg
.msg_controllen
= sizeof(cmsg
);
37 cmsg
.cm
.cmsg_len
= CMSG_LEN(sizeof(int));
38 cmsg
.cm
.cmsg_level
= SOL_SOCKET
;
39 cmsg
.cm
.cmsg_type
= SCM_RIGHTS
;
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
47 * Fortunately, gcc with -O1 compiles this ngx_memcpy()
48 * in the same simple assignment as in the code above
51 ngx_memcpy(CMSG_DATA(&cmsg
.cm
), &ch
->fd
, sizeof(int));
59 msg
.msg_accrights
= NULL
;
60 msg
.msg_accrightslen
= 0;
63 msg
.msg_accrights
= (caddr_t
) &ch
->fd
;
64 msg
.msg_accrightslen
= sizeof(int);
69 iov
[0].iov_base
= (char *) ch
;
70 iov
[0].iov_len
= size
;
77 n
= sendmsg(s
, &msg
, 0);
81 if (err
== NGX_EAGAIN
) {
85 ngx_log_error(NGX_LOG_ALERT
, log
, err
, "sendmsg() failed");
94 ngx_read_channel(ngx_socket_t s
, ngx_channel_t
*ch
, size_t size
, ngx_log_t
*log
)
101 #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
104 char space
[CMSG_SPACE(sizeof(int))];
110 iov
[0].iov_base
= (char *) ch
;
111 iov
[0].iov_len
= size
;
118 #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
119 msg
.msg_control
= (caddr_t
) &cmsg
;
120 msg
.msg_controllen
= sizeof(cmsg
);
122 msg
.msg_accrights
= (caddr_t
) &fd
;
123 msg
.msg_accrightslen
= sizeof(int);
126 n
= recvmsg(s
, &msg
, 0);
130 if (err
== NGX_EAGAIN
) {
134 ngx_log_error(NGX_LOG_ALERT
, log
, err
, "recvmsg() failed");
139 ngx_log_debug0(NGX_LOG_DEBUG_CORE
, log
, 0, "recvmsg() returned zero");
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
);
149 #if (NGX_HAVE_MSGHDR_MSG_CONTROL)
151 if (ch
->command
== NGX_CMD_OPEN_CHANNEL
) {
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");
159 if (cmsg
.cm
.cmsg_level
!= SOL_SOCKET
|| cmsg
.cm
.cmsg_type
!= SCM_RIGHTS
)
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
);
168 /* ch->fd = *(int *) CMSG_DATA(&cmsg.cm); */
170 ngx_memcpy(&ch
->fd
, CMSG_DATA(&cmsg
.cm
), sizeof(int));
173 if (msg
.msg_flags
& (MSG_TRUNC
|MSG_CTRUNC
)) {
174 ngx_log_error(NGX_LOG_ALERT
, log
, 0,
175 "recvmsg() truncated data");
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");
197 ngx_add_channel_event(ngx_cycle_t
*cycle
, ngx_fd_t fd
, ngx_int_t event
,
198 ngx_event_handler_pt handler
)
200 ngx_event_t
*ev
, *rev
, *wev
;
203 c
= ngx_get_connection(fd
, cycle
->log
);
209 c
->pool
= cycle
->pool
;
214 rev
->log
= cycle
->log
;
215 wev
->log
= cycle
->log
;
218 rev
->lock
= &c
->lock
;
219 wev
->lock
= &c
->lock
;
220 rev
->own_lock
= &c
->lock
;
221 wev
->own_lock
= &c
->lock
;
227 ev
= (event
== NGX_READ_EVENT
) ? rev
: wev
;
229 ev
->handler
= handler
;
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
);
238 if (ngx_add_event(ev
, event
, 0) == NGX_ERROR
) {
239 ngx_free_connection(c
);
249 ngx_close_channel(ngx_fd_t
*fd
, ngx_log_t
*log
)
251 if (close(fd
[0]) == -1) {
252 ngx_log_error(NGX_LOG_ALERT
, log
, ngx_errno
, "close() channel failed");
255 if (close(fd
[1]) == -1) {
256 ngx_log_error(NGX_LOG_ALERT
, log
, ngx_errno
, "close() channel failed");