/* * Interface between xdr serializer and tcp connection. * Behaves like the system calls, read & write, but keeps some error state * around for the rpc level. */ static int read_vc(void *ctp, void *buf, int len) { struct sockaddr sa; socklen_t sal; struct ct_data *ct = (struct ct_data *)ctp; struct pollfd fd; int milliseconds = (int)((ct->ct_wait.tv_sec * 1000) + (ct->ct_wait.tv_usec / 1000)); if (len == 0) return (0); fd.fd = ct->ct_fd; fd.events = POLLIN; for (;;) { switch (_poll(&fd, 1, milliseconds)) { case 0: ct->ct_error.re_status = RPC_TIMEDOUT; return (-1); case -1: if (errno == EINTR) continue; ct->ct_error.re_status = RPC_CANTRECV; ct->ct_error.re_errno = errno; return (-1); } break; } sal = sizeof(sa); if ((_getpeername(ct->ct_fd, &sa, &sal) == 0) && (sa.sa_family == AF_LOCAL)) { len = __msgread(ct->ct_fd, buf, (size_t)len); } else { len = _read(ct->ct_fd, buf, (size_t)len); } switch (len) { case 0: /* premature eof */ ct->ct_error.re_errno = ECONNRESET; ct->ct_error.re_status = RPC_CANTRECV; len = -1; /* it's really an error */ break; case -1: ct->ct_error.re_errno = errno; ct->ct_error.re_status = RPC_CANTRECV; break; } return (len); }
/* * Interface between xdr serializer and unix connection. * Behaves like the system calls, read & write, but keeps some error state * around for the rpc level. */ static int readunix (char *ctptr, char *buf, int len) { struct ct_data *ct = (struct ct_data *) ctptr; struct pollfd fd; int milliseconds = ((ct->ct_wait.tv_sec * 1000) + (ct->ct_wait.tv_usec / 1000)); if (len == 0) return 0; fd.fd = ct->ct_sock; fd.events = POLLIN; while (TRUE) { switch (poll (&fd, 1, milliseconds)) { case 0: ct->ct_error.re_status = RPC_TIMEDOUT; return -1; case -1: if (errno == EINTR) continue; ct->ct_error.re_status = RPC_CANTRECV; ct->ct_error.re_errno = errno; return -1; } break; } switch (len = __msgread (ct->ct_sock, buf, len)) { case 0: /* premature eof */ ct->ct_error.re_errno = ECONNRESET; ct->ct_error.re_status = RPC_CANTRECV; len = -1; /* it's really an error */ break; case -1: ct->ct_error.re_errno = errno; ct->ct_error.re_status = RPC_CANTRECV; break; } return len; }
/* * reads data from the unix connection. * any error is fatal and the connection is closed. * (And a read of zero bytes is a half closed stream => error.) */ static int readunix (char *xprtptr, char *buf, int len) { SVCXPRT *xprt = (SVCXPRT *) xprtptr; int sock = xprt->xp_sock; int milliseconds = 35 * 1000; struct pollfd pollfd; do { pollfd.fd = sock; pollfd.events = POLLIN; switch (__poll (&pollfd, 1, milliseconds)) { case -1: if (errno == EINTR) continue; /*FALLTHROUGH*/ case 0: goto fatal_err; default: if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) || (pollfd.revents & POLLNVAL)) goto fatal_err; break; } } while ((pollfd.revents & POLLIN) == 0); if ((len = __msgread (sock, buf, len)) > 0) return len; fatal_err: ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; return -1; }