summaryrefslogtreecommitdiffstats
path: root/usr.sbin/nginx/src/os/unix/ngx_channel.c
diff options
context:
space:
mode:
authorrobert <robert@openbsd.org>2011-09-22 23:32:10 +0000
committerrobert <robert@openbsd.org>2011-09-22 23:32:10 +0000
commit40ffe171a7951d3019b3c8b488be87bfad405509 (patch)
tree7634bff211814a539a15e4e34db747e4d7b46006 /usr.sbin/nginx/src/os/unix/ngx_channel.c
parentAlways install all manuals on all architectures. (diff)
downloadwireguard-openbsd-40ffe171a7951d3019b3c8b488be87bfad405509.tar.xz
wireguard-openbsd-40ffe171a7951d3019b3c8b488be87bfad405509.zip
import of nginx 1.0.6 with a bundled libpcre needed for pcre to work
properly. this is not yet linked to the build but we would like to work on it in tree to provide an apache replacement for base
Diffstat (limited to 'usr.sbin/nginx/src/os/unix/ngx_channel.c')
-rw-r--r--usr.sbin/nginx/src/os/unix/ngx_channel.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/usr.sbin/nginx/src/os/unix/ngx_channel.c b/usr.sbin/nginx/src/os/unix/ngx_channel.c
new file mode 100644
index 00000000000..a0bdc2b8e96
--- /dev/null
+++ b/usr.sbin/nginx/src/os/unix/ngx_channel.c
@@ -0,0 +1,257 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_channel.h>
+
+
+ngx_int_t
+ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
+ ngx_log_t *log)
+{
+ ssize_t n;
+ ngx_err_t err;
+ struct iovec iov[1];
+ struct msghdr msg;
+
+#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
+
+ union {
+ struct cmsghdr cm;
+ char space[CMSG_SPACE(sizeof(int))];
+ } cmsg;
+
+ if (ch->fd == -1) {
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+
+ } else {
+ msg.msg_control = (caddr_t) &cmsg;
+ msg.msg_controllen = sizeof(cmsg);
+
+ cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg.cm.cmsg_level = SOL_SOCKET;
+ cmsg.cm.cmsg_type = SCM_RIGHTS;
+
+ /*
+ * We have to use ngx_memcpy() instead of simple
+ * *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
+ * because some gcc 4.4 with -O2/3/s optimization issues the warning:
+ * dereferencing type-punned pointer will break strict-aliasing rules
+ *
+ * Fortunately, gcc with -O1 compiles this ngx_memcpy()
+ * in the same simple assignment as in the code above
+ */
+
+ ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int));
+ }
+
+ msg.msg_flags = 0;
+
+#else
+
+ if (ch->fd == -1) {
+ msg.msg_accrights = NULL;
+ msg.msg_accrightslen = 0;
+
+ } else {
+ msg.msg_accrights = (caddr_t) &ch->fd;
+ msg.msg_accrightslen = sizeof(int);
+ }
+
+#endif
+
+ iov[0].iov_base = (char *) ch;
+ iov[0].iov_len = size;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+ n = sendmsg(s, &msg, 0);
+
+ if (n == -1) {
+ err = ngx_errno;
+ if (err == NGX_EAGAIN) {
+ return NGX_AGAIN;
+ }
+
+ ngx_log_error(NGX_LOG_ALERT, log, err, "sendmsg() failed");
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
+ngx_int_t
+ngx_read_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size, ngx_log_t *log)
+{
+ ssize_t n;
+ ngx_err_t err;
+ struct iovec iov[1];
+ struct msghdr msg;
+
+#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
+ union {
+ struct cmsghdr cm;
+ char space[CMSG_SPACE(sizeof(int))];
+ } cmsg;
+#else
+ int fd;
+#endif
+
+ iov[0].iov_base = (char *) ch;
+ iov[0].iov_len = size;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
+ msg.msg_control = (caddr_t) &cmsg;
+ msg.msg_controllen = sizeof(cmsg);
+#else
+ msg.msg_accrights = (caddr_t) &fd;
+ msg.msg_accrightslen = sizeof(int);
+#endif
+
+ n = recvmsg(s, &msg, 0);
+
+ if (n == -1) {
+ err = ngx_errno;
+ if (err == NGX_EAGAIN) {
+ return NGX_AGAIN;
+ }
+
+ ngx_log_error(NGX_LOG_ALERT, log, err, "recvmsg() failed");
+ return NGX_ERROR;
+ }
+
+ if (n == 0) {
+ ngx_log_debug0(NGX_LOG_DEBUG_CORE, log, 0, "recvmsg() returned zero");
+ return NGX_ERROR;
+ }
+
+ if ((size_t) n < sizeof(ngx_channel_t)) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "recvmsg() returned not enough data: %uz", n);
+ return NGX_ERROR;
+ }
+
+#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
+
+ if (ch->command == NGX_CMD_OPEN_CHANNEL) {
+
+ if (cmsg.cm.cmsg_len < (socklen_t) CMSG_LEN(sizeof(int))) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "recvmsg() returned too small ancillary data");
+ return NGX_ERROR;
+ }
+
+ if (cmsg.cm.cmsg_level != SOL_SOCKET || cmsg.cm.cmsg_type != SCM_RIGHTS)
+ {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "recvmsg() returned invalid ancillary data "
+ "level %d or type %d",
+ cmsg.cm.cmsg_level, cmsg.cm.cmsg_type);
+ return NGX_ERROR;
+ }
+
+ /* ch->fd = *(int *) CMSG_DATA(&cmsg.cm); */
+
+ ngx_memcpy(&ch->fd, CMSG_DATA(&cmsg.cm), sizeof(int));
+ }
+
+ if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "recvmsg() truncated data");
+ }
+
+#else
+
+ if (ch->command == NGX_CMD_OPEN_CHANNEL) {
+ if (msg.msg_accrightslen != sizeof(int)) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "recvmsg() returned no ancillary data");
+ return NGX_ERROR;
+ }
+
+ ch->fd = fd;
+ }
+
+#endif
+
+ return n;
+}
+
+
+ngx_int_t
+ngx_add_channel_event(ngx_cycle_t *cycle, ngx_fd_t fd, ngx_int_t event,
+ ngx_event_handler_pt handler)
+{
+ ngx_event_t *ev, *rev, *wev;
+ ngx_connection_t *c;
+
+ c = ngx_get_connection(fd, cycle->log);
+
+ if (c == NULL) {
+ return NGX_ERROR;
+ }
+
+ c->pool = cycle->pool;
+
+ rev = c->read;
+ wev = c->write;
+
+ rev->log = cycle->log;
+ wev->log = cycle->log;
+
+#if (NGX_THREADS)
+ rev->lock = &c->lock;
+ wev->lock = &c->lock;
+ rev->own_lock = &c->lock;
+ wev->own_lock = &c->lock;
+#endif
+
+ rev->channel = 1;
+ wev->channel = 1;
+
+ ev = (event == NGX_READ_EVENT) ? rev : wev;
+
+ ev->handler = handler;
+
+ if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
+ if (ngx_add_conn(c) == NGX_ERROR) {
+ ngx_free_connection(c);
+ return NGX_ERROR;
+ }
+
+ } else {
+ if (ngx_add_event(ev, event, 0) == NGX_ERROR) {
+ ngx_free_connection(c);
+ return NGX_ERROR;
+ }
+ }
+
+ return NGX_OK;
+}
+
+
+void
+ngx_close_channel(ngx_fd_t *fd, ngx_log_t *log)
+{
+ if (close(fd[0]) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed");
+ }
+
+ if (close(fd[1]) == -1) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "close() channel failed");
+ }
+}