_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen, st_utime_t timeout) { int osfd, err; _st_netfd_t *newfd; while ((osfd = accept(fd->osfd, addr, (socklen_t *)addrlen)) < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) return NULL; /* Wait until the socket becomes readable */ if (st_netfd_poll(fd, POLLIN, timeout) < 0) return NULL; } /* On some platforms the new socket created by accept() inherits */ /* the nonblocking attribute of the listening socket */ #if defined (MD_ACCEPT_NB_INHERITED) newfd = _st_netfd_new(osfd, 0, 1); #elif defined (MD_ACCEPT_NB_NOT_INHERITED) newfd = _st_netfd_new(osfd, 1, 1); #else #error Unknown OS #endif if (!newfd) { err = errno; close(osfd); errno = err; } return newfd; }
_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen, st_utime_t timeout) { int osfd, err; _st_netfd_t *newfd; _st_netfd_t **p = (_st_netfd_t **) fd->aux_data; ssize_t n; char c; for ( ; ; ) { if (p == NULL) { osfd = accept(fd->osfd, addr, (socklen_t *)addrlen); } else { /* Get the lock */ n = st_read(p[0], &c, 1, timeout); if (n < 0) { return NULL; } ST_ASSERT(n == 1); /* Got the lock */ osfd = accept(fd->osfd, addr, (socklen_t *)addrlen); /* Unlock */ err = errno; n = st_write(p[1], &c, 1, timeout); ST_ASSERT(n == 1); errno = err; } if (osfd >= 0) { break; } if (errno == EINTR) { continue; } if (!_IO_NOT_READY_ERROR) { return NULL; } /* Wait until the socket becomes readable */ if (st_netfd_poll(fd, POLLIN, timeout) < 0) { return NULL; } } /* On some platforms the new socket created by accept() inherits */ /* the nonblocking attribute of the listening socket */ #if defined (MD_ACCEPT_NB_INHERITED) newfd = _st_netfd_new(osfd, 0, 1); #elif defined (MD_ACCEPT_NB_NOT_INHERITED) newfd = _st_netfd_new(osfd, 1, 1); #else #error Unknown OS #endif if (!newfd) { err = errno; close(osfd); errno = err; } return newfd; }
// 从 _st_netfd_t 中读取数据 ssize_t st_read(_st_netfd_t *fd, void *buf, size_t nbyte, st_utime_t timeout) { ssize_t n; while ((n = read(fd->osfd, buf, nbyte)) < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) return -1; /* Wait until the socket becomes readable */ if (st_netfd_poll(fd, POLLIN, timeout) < 0) return -1; } return n; }
int st_sendmsg(_st_netfd_t *fd, const struct msghdr *msg, int flags, st_utime_t timeout) { int n; while ((n = sendmsg(fd->osfd, msg, flags)) < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) return -1; /* Wait until the socket becomes writable */ if (st_netfd_poll(fd, POLLOUT, timeout) < 0) return -1; } return n; }
int st_sendto(_st_netfd_t *fd, const void *msg, int len, const struct sockaddr *to, int tolen, st_utime_t timeout) { int n; while ((n = sendto(fd->osfd, msg, len, 0, to, tolen)) < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) return -1; /* Wait until the socket becomes writable */ if (st_netfd_poll(fd, POLLOUT, timeout) < 0) return -1; } return n; }
ssize_t st_readv(_st_netfd_t *fd, const struct iovec *iov, int iov_size, st_utime_t timeout) { ssize_t n; while ((n = readv(fd->osfd, iov, iov_size)) < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) return -1; /* Wait until the socket becomes readable */ if (st_netfd_poll(fd, POLLIN, timeout) < 0) return -1; } return n; }
/* * Simple I/O functions for UDP. */ int st_recvfrom(_st_netfd_t *fd, void *buf, int len, struct sockaddr *from, int *fromlen, st_utime_t timeout) { int n; while ((n = recvfrom(fd->osfd, buf, len, 0, from, (socklen_t *)fromlen)) < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) return -1; /* Wait until the socket becomes readable */ if (st_netfd_poll(fd, POLLIN, timeout) < 0) return -1; } return n; }
int st_readv_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size, st_utime_t timeout) { ssize_t n; while (*iov_size > 0) { if (*iov_size == 1) { n = read(fd->osfd, (*iov)->iov_base, (*iov)->iov_len); } else { n = readv(fd->osfd, *iov, *iov_size); } if (n < 0) { if (errno == EINTR) { continue; } if (!_IO_NOT_READY_ERROR) { return -1; } } else if (n == 0) { break; } else { while ((size_t) n >= (*iov)->iov_len) { n -= (*iov)->iov_len; (*iov)->iov_base = (char *) (*iov)->iov_base + (*iov)->iov_len; (*iov)->iov_len = 0; (*iov)++; (*iov_size)--; if (n == 0) { break; } } if (*iov_size == 0) { break; } (*iov)->iov_base = (char *) (*iov)->iov_base + n; (*iov)->iov_len -= n; } /* Wait until the socket becomes readable */ if (st_netfd_poll(fd, POLLIN, timeout) < 0) { return -1; } } return 0; }
int st_recvmsg(_st_netfd_t *fd, struct msghdr *msg, int flags, st_utime_t timeout) { int n; while ((n = recvmsg(fd->osfd, msg, flags)) < 0) { if (errno == EINTR) { continue; } if (!_IO_NOT_READY_ERROR) { return -1; } /* Wait until the socket becomes readable */ if (st_netfd_poll(fd, POLLIN, timeout) < 0) { return -1; } } return n; }
int st_writev_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size, st_utime_t timeout) { ssize_t n; while (*iov_size > 0) { if (*iov_size == 1) n = write(fd->osfd, (*iov)->iov_base, (*iov)->iov_len); else n = writev(fd->osfd, *iov, *iov_size); if (n < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) return -1; } else { while ((size_t) n >= (*iov)->iov_len) { n -= (*iov)->iov_len; (*iov)->iov_base = (char *) (*iov)->iov_base + (*iov)->iov_len; (*iov)->iov_len = 0; (*iov)++; (*iov_size)--; if (n == 0) break; } if (*iov_size == 0) break; (*iov)->iov_base = (char *) (*iov)->iov_base + n; (*iov)->iov_len -= n; } /* Wait until the socket becomes writable */ if (st_netfd_poll(fd, POLLOUT, timeout) < 0) return -1; } return 0; }
int st_connect(_st_netfd_t *fd, const struct sockaddr *addr, int addrlen, st_utime_t timeout) { int n, err = 0; while (connect(fd->osfd, addr, addrlen) < 0) { if (errno != EINTR) { /* * On some platforms, if connect() is interrupted (errno == EINTR) * after the kernel binds the socket, a subsequent connect() * attempt will fail with errno == EADDRINUSE. Ignore EADDRINUSE * iff connect() was previously interrupted. See Rich Stevens' * "UNIX Network Programming," Vol. 1, 2nd edition, p. 413 * ("Interrupted connect"). */ if (errno != EINPROGRESS && (errno != EADDRINUSE || err == 0)) { return -1; } /* Wait until the socket becomes writable */ if (st_netfd_poll(fd, POLLOUT, timeout) < 0) { return -1; } /* Try to find out whether the connection setup succeeded or failed */ n = sizeof(int); if (getsockopt(fd->osfd, SOL_SOCKET, SO_ERROR, (char *)&err, (socklen_t *)&n) < 0) { return -1; } if (err) { errno = err; return -1; } break; } err = 1; } return 0; }
int st_write_resid(_st_netfd_t *fd, const void *buf, size_t *resid, st_utime_t timeout) { ssize_t n; while (*resid > 0) { if ((n = write(fd->osfd, buf, *resid)) < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) return -1; } else { *resid -= n; if (*resid == 0) break; buf = (const void *)((const char *)buf + n); } /* Wait until the socket becomes writable */ if (st_netfd_poll(fd, POLLOUT, timeout) < 0) return -1; } return 0; }
ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size, st_utime_t timeout) { ssize_t n, rv; size_t nleft, nbyte; int index, iov_cnt; struct iovec *tmp_iov; struct iovec local_iov[_LOCAL_MAXIOV]; /* Calculate the total number of bytes to be sent */ nbyte = 0; for (index = 0; index < iov_size; index++) nbyte += iov[index].iov_len; rv = (ssize_t)nbyte; nleft = nbyte; tmp_iov = (struct iovec *) iov; /* we promise not to modify iov */ iov_cnt = iov_size; while (nleft > 0) { if (iov_cnt == 1) { if (st_write(fd, tmp_iov[0].iov_base, nleft, timeout) != (ssize_t) nleft) rv = -1; break; } if ((n = writev(fd->osfd, tmp_iov, iov_cnt)) < 0) { if (errno == EINTR) continue; if (!_IO_NOT_READY_ERROR) { rv = -1; break; } } else { if ((size_t) n == nleft) break; nleft -= n; /* Find the next unwritten vector */ n = (ssize_t)(nbyte - nleft); for (index = 0; (size_t) n >= iov[index].iov_len; index++) n -= iov[index].iov_len; if (tmp_iov == iov) { /* Must copy iov's around */ if (iov_size - index <= _LOCAL_MAXIOV) { tmp_iov = local_iov; } else { tmp_iov = calloc(1, (iov_size - index) * sizeof(struct iovec)); if (tmp_iov == NULL) return -1; } } /* Fill in the first partial read */ tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[n]); tmp_iov[0].iov_len = iov[index].iov_len - n; index++; /* Copy the remaining vectors */ for (iov_cnt = 1; index < iov_size; iov_cnt++, index++) { tmp_iov[iov_cnt].iov_base = iov[index].iov_base; tmp_iov[iov_cnt].iov_len = iov[index].iov_len; } } /* Wait until the socket becomes writable */ if (st_netfd_poll(fd, POLLOUT, timeout) < 0) { rv = -1; break; } } if (tmp_iov != iov && tmp_iov != local_iov) free(tmp_iov); return rv; }