Skip to content

Commit

Permalink
Fix tcpmux stuff on Solaris
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Sustrik <sustrik@250bpm.com>
  • Loading branch information
sustrik committed Nov 21, 2014
1 parent 3cae364 commit 79ca54e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 15 deletions.
38 changes: 29 additions & 9 deletions src/aio/usock_posix.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,9 @@ static int nn_usock_recv_raw (struct nn_usock *self, void *buf, size_t *len)
struct iovec iov;
struct msghdr hdr;
unsigned char ctrl [256];
#if defined NN_HAVE_MSG_CONTROL
struct cmsghdr *cmsg;
#endif

/* If batch buffer doesn't exist, allocate it. The point of delayed
deallocation to allow non-receiving sockets, such as TCP listening
Expand Down Expand Up @@ -1093,8 +1095,14 @@ static int nn_usock_recv_raw (struct nn_usock *self, void *buf, size_t *len)
memset (&hdr, 0, sizeof (hdr));
hdr.msg_iov = &iov;
hdr.msg_iovlen = 1;
#if defined NN_HAVE_MSG_CONTROL
hdr.msg_control = ctrl;
hdr.msg_controllen = sizeof (ctrl);
#else
*((int*) ctrl) = -1;
hdr.msg_accrights = ctrl;
hdr.msg_accrightslen = sizeof (int);
#endif
nbytes = recvmsg (self->s, &hdr, 0);

/* Handle any possible errors. */
Expand All @@ -1117,23 +1125,35 @@ static int nn_usock_recv_raw (struct nn_usock *self, void *buf, size_t *len)
}

/* Extract the associated file descriptor, if any. */
if (nbytes > 0) {
#if defined NN_HAVE_MSG_CONTROL
cmsg = CMSG_FIRSTHDR (&hdr);
while (cmsg) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
cmsg = CMSG_FIRSTHDR (&hdr);
while (cmsg) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
if (self->in.pfd) {
*self->in.pfd = *((int*) CMSG_DATA (cmsg));
self->in.pfd = NULL;
}
else {
nn_closefd (*((int*) CMSG_DATA (cmsg)));
}
break;
}
cmsg = CMSG_NXTHDR (&hdr, cmsg);
}
#else
if (hdr.msg_accrightslen > 0) {
nn_assert (hdr.msg_accrightslen == sizeof (int));
if (self->in.pfd) {
*self->in.pfd = *((int*) CMSG_DATA (cmsg));
*self->in.pfd = *((int*) hdr.msg_accrights);
self->in.pfd = NULL;
}
else {
nn_closefd (*((int*) CMSG_DATA (cmsg)));
nn_closefd (*((int*) hdr.msg_accrights));
}
break;
}
cmsg = CMSG_NXTHDR (&hdr, cmsg);
}
#else
#endif
}

/* If the data were received directly into the place we can return
straight away. */
Expand Down
20 changes: 14 additions & 6 deletions src/devices/tcpmuxd.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,15 @@ static void nn_tcpmuxd_routine (void *arg)
if (conn < 0 && errno == ECONNABORTED)
continue;
errno_assert (conn >= 0);

/* Set timeouts to prevent malevolent client blocking the service.
Note that these options are not supported on Solaris. */
tv.tv_sec = 0;
tv.tv_usec = 100000;
rc = setsockopt (conn, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv));
errno_assert (rc == 0);
errno_assert (rc == 0 || (rc < 0 && errno == ENOPROTOOPT));
rc = setsockopt (conn, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof (tv));
errno_assert (rc == 0);
errno_assert (rc == 0 || (rc < 0 && errno == ENOPROTOOPT));

/* Read TCPMUX header. */
pos = 0;
Expand Down Expand Up @@ -269,7 +272,9 @@ static int send_fd (int s, int fd)
char c = 0;
struct msghdr msg;
char control [sizeof (struct cmsghdr) + 10];
#if defined NN_HAVE_MSG_CONTROL
struct cmsghdr *cmsg;
#endif

/* Compose the message. We'll send one byte long dummy message
accompanied with the fd.*/
Expand All @@ -278,19 +283,22 @@ static int send_fd (int s, int fd)
memset (&msg, 0, sizeof (msg));
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = control;
msg.msg_controllen = sizeof (control);

/* Attach the file descriptor to the message. */
#if defined NN_HAVE_MSG_CONTROL
msg.msg_control = control;
msg.msg_controllen = sizeof (control);
cmsg = CMSG_FIRSTHDR (&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN (sizeof (fd));
int *data = (int*) CMSG_DATA (cmsg);
*data = fd;

/* Adjust the size of the control to match the data. */
msg.msg_controllen = cmsg->cmsg_len;
#else
msg.msg_accrights = (caddr_t) &fd;
msg.msg_accrightslen = sizeof (fd);
#endif

/* Pass the file descriptor to the registered process. */
rc = sendmsg (s, &msg, 0);
Expand Down

0 comments on commit 79ca54e

Please sign in to comment.