mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
research st: refine io.
This commit is contained in:
parent
f8f18fffa7
commit
fd0c85b324
1 changed files with 585 additions and 555 deletions
|
@ -78,20 +78,23 @@ int _st_io_init(void)
|
||||||
sigact.sa_handler = SIG_IGN;
|
sigact.sa_handler = SIG_IGN;
|
||||||
sigemptyset(&sigact.sa_mask);
|
sigemptyset(&sigact.sa_mask);
|
||||||
sigact.sa_flags = 0;
|
sigact.sa_flags = 0;
|
||||||
if (sigaction(SIGPIPE, &sigact, NULL) < 0)
|
if (sigaction(SIGPIPE, &sigact, NULL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set maximum number of open file descriptors */
|
/* Set maximum number of open file descriptors */
|
||||||
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
|
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
fdlim = (*_st_eventsys->fd_getlimit)();
|
fdlim = (*_st_eventsys->fd_getlimit)();
|
||||||
if (fdlim > 0 && rlim.rlim_max > (rlim_t) fdlim) {
|
if (fdlim > 0 && rlim.rlim_max > (rlim_t) fdlim) {
|
||||||
rlim.rlim_max = fdlim;
|
rlim.rlim_max = fdlim;
|
||||||
}
|
}
|
||||||
rlim.rlim_cur = rlim.rlim_max;
|
rlim.rlim_cur = rlim.rlim_max;
|
||||||
if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
|
if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
_st_osfd_limit = (int) rlim.rlim_max;
|
_st_osfd_limit = (int) rlim.rlim_max;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -106,14 +109,17 @@ int st_getfdlimit(void)
|
||||||
|
|
||||||
void st_netfd_free(_st_netfd_t *fd)
|
void st_netfd_free(_st_netfd_t *fd)
|
||||||
{
|
{
|
||||||
if (!fd->inuse)
|
if (!fd->inuse) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fd->inuse = 0;
|
fd->inuse = 0;
|
||||||
if (fd->aux_data)
|
if (fd->aux_data) {
|
||||||
_st_netfd_free_aux_data(fd);
|
_st_netfd_free_aux_data(fd);
|
||||||
if (fd->private_data && fd->destructor)
|
}
|
||||||
|
if (fd->private_data && fd->destructor) {
|
||||||
(*(fd->destructor))(fd->private_data);
|
(*(fd->destructor))(fd->private_data);
|
||||||
|
}
|
||||||
fd->private_data = NULL;
|
fd->private_data = NULL;
|
||||||
fd->destructor = NULL;
|
fd->destructor = NULL;
|
||||||
fd->next = _st_netfd_freelist;
|
fd->next = _st_netfd_freelist;
|
||||||
|
@ -126,17 +132,19 @@ static _st_netfd_t *_st_netfd_new(int osfd, int nonblock, int is_socket)
|
||||||
_st_netfd_t *fd;
|
_st_netfd_t *fd;
|
||||||
int flags = 1;
|
int flags = 1;
|
||||||
|
|
||||||
if ((*_st_eventsys->fd_new)(osfd) < 0)
|
if ((*_st_eventsys->fd_new)(osfd) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (_st_netfd_freelist) {
|
if (_st_netfd_freelist) {
|
||||||
fd = _st_netfd_freelist;
|
fd = _st_netfd_freelist;
|
||||||
_st_netfd_freelist = _st_netfd_freelist->next;
|
_st_netfd_freelist = _st_netfd_freelist->next;
|
||||||
} else {
|
} else {
|
||||||
fd = calloc(1, sizeof(_st_netfd_t));
|
fd = calloc(1, sizeof(_st_netfd_t));
|
||||||
if (!fd)
|
if (!fd) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fd->osfd = osfd;
|
fd->osfd = osfd;
|
||||||
fd->inuse = 1;
|
fd->inuse = 1;
|
||||||
|
@ -144,11 +152,11 @@ static _st_netfd_t *_st_netfd_new(int osfd, int nonblock, int is_socket)
|
||||||
|
|
||||||
if (nonblock) {
|
if (nonblock) {
|
||||||
/* Use just one system call */
|
/* Use just one system call */
|
||||||
if (is_socket && ioctl(osfd, FIONBIO, &flags) != -1)
|
if (is_socket && ioctl(osfd, FIONBIO, &flags) != -1) {
|
||||||
return fd;
|
return fd;
|
||||||
|
}
|
||||||
/* Do it the Posix way */
|
/* Do it the Posix way */
|
||||||
if ((flags = fcntl(osfd, F_GETFL, 0)) < 0 ||
|
if ((flags = fcntl(osfd, F_GETFL, 0)) < 0 || fcntl(osfd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||||
fcntl(osfd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
|
||||||
st_netfd_free(fd);
|
st_netfd_free(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -172,8 +180,9 @@ _st_netfd_t *st_netfd_open_socket(int osfd)
|
||||||
|
|
||||||
int st_netfd_close(_st_netfd_t *fd)
|
int st_netfd_close(_st_netfd_t *fd)
|
||||||
{
|
{
|
||||||
if ((*_st_eventsys->fd_close)(fd->osfd) < 0)
|
if ((*_st_eventsys->fd_close)(fd->osfd) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
st_netfd_free(fd);
|
st_netfd_free(fd);
|
||||||
return close(fd->osfd);
|
return close(fd->osfd);
|
||||||
|
@ -186,14 +195,14 @@ int st_netfd_fileno(_st_netfd_t *fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void st_netfd_setspecific(_st_netfd_t *fd, void *value,
|
void st_netfd_setspecific(_st_netfd_t *fd, void *value, _st_destructor_t destructor)
|
||||||
_st_destructor_t destructor)
|
|
||||||
{
|
{
|
||||||
if (value != fd->private_data) {
|
if (value != fd->private_data) {
|
||||||
/* Free up previously set non-NULL data value */
|
/* Free up previously set non-NULL data value */
|
||||||
if (fd->private_data && fd->destructor)
|
if (fd->private_data && fd->destructor) {
|
||||||
(*(fd->destructor))(fd->private_data);
|
(*(fd->destructor))(fd->private_data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fd->private_data = value;
|
fd->private_data = value;
|
||||||
fd->destructor = destructor;
|
fd->destructor = destructor;
|
||||||
}
|
}
|
||||||
|
@ -217,8 +226,9 @@ int st_netfd_poll(_st_netfd_t *fd, int how, st_utime_t timeout)
|
||||||
pd.events = (short) how;
|
pd.events = (short) how;
|
||||||
pd.revents = 0;
|
pd.revents = 0;
|
||||||
|
|
||||||
if ((n = st_poll(&pd, 1, timeout)) < 0)
|
if ((n = st_poll(&pd, 1, timeout)) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
/* Timed out */
|
/* Timed out */
|
||||||
errno = ETIME;
|
errno = ETIME;
|
||||||
|
@ -232,7 +242,6 @@ int st_netfd_poll(_st_netfd_t *fd, int how, st_utime_t timeout)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef MD_ALWAYS_UNSERIALIZED_ACCEPT
|
#ifdef MD_ALWAYS_UNSERIALIZED_ACCEPT
|
||||||
/* No-op */
|
/* No-op */
|
||||||
int st_netfd_serialize_accept(_st_netfd_t *fd)
|
int st_netfd_serialize_accept(_st_netfd_t *fd)
|
||||||
|
@ -247,21 +256,23 @@ static void _st_netfd_free_aux_data(_st_netfd_t *fd)
|
||||||
fd->aux_data = NULL;
|
fd->aux_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
|
_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen, st_utime_t timeout)
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
int osfd, err;
|
int osfd, err;
|
||||||
_st_netfd_t *newfd;
|
_st_netfd_t *newfd;
|
||||||
|
|
||||||
while ((osfd = accept(fd->osfd, addr, (socklen_t *)addrlen)) < 0) {
|
while ((osfd = accept(fd->osfd, addr, (socklen_t *)addrlen)) < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
/* Wait until the socket becomes readable */
|
/* Wait until the socket becomes readable */
|
||||||
if (st_netfd_poll(fd, POLLIN, timeout) < 0)
|
if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* On some platforms the new socket created by accept() inherits */
|
/* On some platforms the new socket created by accept() inherits */
|
||||||
/* the nonblocking attribute of the listening socket */
|
/* the nonblocking attribute of the listening socket */
|
||||||
|
@ -298,24 +309,25 @@ int st_netfd_serialize_accept(_st_netfd_t *fd)
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((p = (_st_netfd_t **)calloc(2, sizeof(_st_netfd_t *))) == NULL)
|
if ((p = (_st_netfd_t **)calloc(2, sizeof(_st_netfd_t *))) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
if (pipe(osfd) < 0) {
|
if (pipe(osfd) < 0) {
|
||||||
free(p);
|
free(p);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((p[0] = st_netfd_open(osfd[0])) != NULL &&
|
if ((p[0] = st_netfd_open(osfd[0])) != NULL && (p[1] = st_netfd_open(osfd[1])) != NULL && write(osfd[1], " ", 1) == 1) {
|
||||||
(p[1] = st_netfd_open(osfd[1])) != NULL &&
|
|
||||||
write(osfd[1], " ", 1) == 1) {
|
|
||||||
fd->aux_data = p;
|
fd->aux_data = p;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Error */
|
/* Error */
|
||||||
err = errno;
|
err = errno;
|
||||||
if (p[0])
|
if (p[0]) {
|
||||||
st_netfd_free(p[0]);
|
st_netfd_free(p[0]);
|
||||||
if (p[1])
|
}
|
||||||
|
if (p[1]) {
|
||||||
st_netfd_free(p[1]);
|
st_netfd_free(p[1]);
|
||||||
|
}
|
||||||
close(osfd[0]);
|
close(osfd[0]);
|
||||||
close(osfd[1]);
|
close(osfd[1]);
|
||||||
free(p);
|
free(p);
|
||||||
|
@ -334,8 +346,7 @@ static void _st_netfd_free_aux_data(_st_netfd_t *fd)
|
||||||
fd->aux_data = NULL;
|
fd->aux_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
|
_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen, st_utime_t timeout)
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
int osfd, err;
|
int osfd, err;
|
||||||
_st_netfd_t *newfd;
|
_st_netfd_t *newfd;
|
||||||
|
@ -349,8 +360,9 @@ _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
|
||||||
} else {
|
} else {
|
||||||
/* Get the lock */
|
/* Get the lock */
|
||||||
n = st_read(p[0], &c, 1, timeout);
|
n = st_read(p[0], &c, 1, timeout);
|
||||||
if (n < 0)
|
if (n < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
ST_ASSERT(n == 1);
|
ST_ASSERT(n == 1);
|
||||||
/* Got the lock */
|
/* Got the lock */
|
||||||
osfd = accept(fd->osfd, addr, (socklen_t *)addrlen);
|
osfd = accept(fd->osfd, addr, (socklen_t *)addrlen);
|
||||||
|
@ -360,16 +372,20 @@ _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
|
||||||
ST_ASSERT(n == 1);
|
ST_ASSERT(n == 1);
|
||||||
errno = err;
|
errno = err;
|
||||||
}
|
}
|
||||||
if (osfd >= 0)
|
if (osfd >= 0) {
|
||||||
break;
|
break;
|
||||||
if (errno == EINTR)
|
}
|
||||||
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
/* Wait until the socket becomes readable */
|
/* Wait until the socket becomes readable */
|
||||||
if (st_netfd_poll(fd, POLLIN, timeout) < 0)
|
if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* On some platforms the new socket created by accept() inherits */
|
/* On some platforms the new socket created by accept() inherits */
|
||||||
/* the nonblocking attribute of the listening socket */
|
/* the nonblocking attribute of the listening socket */
|
||||||
|
@ -392,8 +408,7 @@ _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
|
||||||
#endif /* MD_ALWAYS_UNSERIALIZED_ACCEPT */
|
#endif /* MD_ALWAYS_UNSERIALIZED_ACCEPT */
|
||||||
|
|
||||||
|
|
||||||
int st_connect(_st_netfd_t *fd, const struct sockaddr *addr, int addrlen,
|
int st_connect(_st_netfd_t *fd, const struct sockaddr *addr, int addrlen, st_utime_t timeout)
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
int n, err = 0;
|
int n, err = 0;
|
||||||
|
|
||||||
|
@ -407,16 +422,18 @@ int st_connect(_st_netfd_t *fd, const struct sockaddr *addr, int addrlen,
|
||||||
* "UNIX Network Programming," Vol. 1, 2nd edition, p. 413
|
* "UNIX Network Programming," Vol. 1, 2nd edition, p. 413
|
||||||
* ("Interrupted connect").
|
* ("Interrupted connect").
|
||||||
*/
|
*/
|
||||||
if (errno != EINPROGRESS && (errno != EADDRINUSE || err == 0))
|
if (errno != EINPROGRESS && (errno != EADDRINUSE || err == 0)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
/* Wait until the socket becomes writable */
|
/* Wait until the socket becomes writable */
|
||||||
if (st_netfd_poll(fd, POLLOUT, timeout) < 0)
|
if (st_netfd_poll(fd, POLLOUT, timeout) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
/* Try to find out whether the connection setup succeeded or failed */
|
/* Try to find out whether the connection setup succeeded or failed */
|
||||||
n = sizeof(int);
|
n = sizeof(int);
|
||||||
if (getsockopt(fd->osfd, SOL_SOCKET, SO_ERROR, (char *)&err,
|
if (getsockopt(fd->osfd, SOL_SOCKET, SO_ERROR, (char *)&err, (socklen_t *)&n) < 0) {
|
||||||
(socklen_t *)&n) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
errno = err;
|
errno = err;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -435,21 +452,23 @@ ssize_t st_read(_st_netfd_t *fd, void *buf, size_t nbyte, st_utime_t timeout)
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
while ((n = read(fd->osfd, buf, nbyte)) < 0) {
|
while ((n = read(fd->osfd, buf, nbyte)) < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
/* Wait until the socket becomes readable */
|
/* Wait until the socket becomes readable */
|
||||||
if (st_netfd_poll(fd, POLLIN, timeout) < 0)
|
if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int st_read_resid(_st_netfd_t *fd, void *buf, size_t *resid,
|
int st_read_resid(_st_netfd_t *fd, void *buf, size_t *resid, st_utime_t timeout)
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
struct iovec iov, *riov;
|
struct iovec iov, *riov;
|
||||||
int riov_size, rv;
|
int riov_size, rv;
|
||||||
|
@ -464,76 +483,78 @@ int st_read_resid(_st_netfd_t *fd, void *buf, size_t *resid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ssize_t st_readv(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
|
ssize_t st_readv(_st_netfd_t *fd, const struct iovec *iov, int iov_size, st_utime_t timeout)
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
while ((n = readv(fd->osfd, iov, iov_size)) < 0) {
|
while ((n = readv(fd->osfd, iov, iov_size)) < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
/* Wait until the socket becomes readable */
|
/* Wait until the socket becomes readable */
|
||||||
if (st_netfd_poll(fd, POLLIN, timeout) < 0)
|
if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int st_readv_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size,
|
int st_readv_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size, st_utime_t timeout)
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
while (*iov_size > 0) {
|
while (*iov_size > 0) {
|
||||||
if (*iov_size == 1)
|
if (*iov_size == 1) {
|
||||||
n = read(fd->osfd, (*iov)->iov_base, (*iov)->iov_len);
|
n = read(fd->osfd, (*iov)->iov_base, (*iov)->iov_len);
|
||||||
else
|
} else {
|
||||||
n = readv(fd->osfd, *iov, *iov_size);
|
n = readv(fd->osfd, *iov, *iov_size);
|
||||||
|
}
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (n == 0)
|
}
|
||||||
|
} else if (n == 0) {
|
||||||
break;
|
break;
|
||||||
else {
|
} else {
|
||||||
while ((size_t) n >= (*iov)->iov_len) {
|
while ((size_t) n >= (*iov)->iov_len) {
|
||||||
n -= (*iov)->iov_len;
|
n -= (*iov)->iov_len;
|
||||||
(*iov)->iov_base = (char *) (*iov)->iov_base + (*iov)->iov_len;
|
(*iov)->iov_base = (char *) (*iov)->iov_base + (*iov)->iov_len;
|
||||||
(*iov)->iov_len = 0;
|
(*iov)->iov_len = 0;
|
||||||
(*iov)++;
|
(*iov)++;
|
||||||
(*iov_size)--;
|
(*iov_size)--;
|
||||||
if (n == 0)
|
if (n == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (*iov_size == 0)
|
}
|
||||||
|
if (*iov_size == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
(*iov)->iov_base = (char *) (*iov)->iov_base + n;
|
(*iov)->iov_base = (char *) (*iov)->iov_base + n;
|
||||||
(*iov)->iov_len -= n;
|
(*iov)->iov_len -= n;
|
||||||
}
|
}
|
||||||
/* Wait until the socket becomes readable */
|
/* Wait until the socket becomes readable */
|
||||||
if (st_netfd_poll(fd, POLLIN, timeout) < 0)
|
if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t st_read_fully(_st_netfd_t *fd, void *buf, size_t nbyte, st_utime_t timeout)
|
||||||
ssize_t st_read_fully(_st_netfd_t *fd, void *buf, size_t nbyte,
|
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
size_t resid = nbyte;
|
size_t resid = nbyte;
|
||||||
return st_read_resid(fd, buf, &resid, timeout) == 0 ?
|
return st_read_resid(fd, buf, &resid, timeout) == 0 ? (ssize_t) (nbyte - resid) : -1;
|
||||||
(ssize_t) (nbyte - resid) : -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int st_write_resid(_st_netfd_t *fd, const void *buf, size_t *resid, st_utime_t timeout)
|
||||||
int st_write_resid(_st_netfd_t *fd, const void *buf, size_t *resid,
|
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
struct iovec iov, *riov;
|
struct iovec iov, *riov;
|
||||||
int riov_size, rv;
|
int riov_size, rv;
|
||||||
|
@ -547,18 +568,13 @@ int st_write_resid(_st_netfd_t *fd, const void *buf, size_t *resid,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t st_write(_st_netfd_t *fd, const void *buf, size_t nbyte, st_utime_t timeout)
|
||||||
ssize_t st_write(_st_netfd_t *fd, const void *buf, size_t nbyte,
|
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
size_t resid = nbyte;
|
size_t resid = nbyte;
|
||||||
return st_write_resid(fd, buf, &resid, timeout) == 0 ?
|
return st_write_resid(fd, buf, &resid, timeout) == 0 ? (ssize_t) (nbyte - resid) : -1;
|
||||||
(ssize_t) (nbyte - resid) : -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size, st_utime_t timeout)
|
||||||
ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
|
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
ssize_t n, rv;
|
ssize_t n, rv;
|
||||||
size_t nleft, nbyte;
|
size_t nleft, nbyte;
|
||||||
|
@ -568,8 +584,9 @@ ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
|
||||||
|
|
||||||
/* Calculate the total number of bytes to be sent */
|
/* Calculate the total number of bytes to be sent */
|
||||||
nbyte = 0;
|
nbyte = 0;
|
||||||
for (index = 0; index < iov_size; index++)
|
for (index = 0; index < iov_size; index++) {
|
||||||
nbyte += iov[index].iov_len;
|
nbyte += iov[index].iov_len;
|
||||||
|
}
|
||||||
|
|
||||||
rv = (ssize_t)nbyte;
|
rv = (ssize_t)nbyte;
|
||||||
nleft = nbyte;
|
nleft = nbyte;
|
||||||
|
@ -578,25 +595,29 @@ ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
|
||||||
|
|
||||||
while (nleft > 0) {
|
while (nleft > 0) {
|
||||||
if (iov_cnt == 1) {
|
if (iov_cnt == 1) {
|
||||||
if (st_write(fd, tmp_iov[0].iov_base, nleft, timeout) != (ssize_t) nleft)
|
if (st_write(fd, tmp_iov[0].iov_base, nleft, timeout) != (ssize_t) nleft) {
|
||||||
rv = -1;
|
rv = -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((n = writev(fd->osfd, tmp_iov, iov_cnt)) < 0) {
|
if ((n = writev(fd->osfd, tmp_iov, iov_cnt)) < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (!_IO_NOT_READY_ERROR) {
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
rv = -1;
|
rv = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((size_t) n == nleft)
|
if ((size_t) n == nleft) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
nleft -= n;
|
nleft -= n;
|
||||||
/* Find the next unwritten vector */
|
/* Find the next unwritten vector */
|
||||||
n = (ssize_t)(nbyte - nleft);
|
n = (ssize_t)(nbyte - nleft);
|
||||||
for (index = 0; (size_t) n >= iov[index].iov_len; index++)
|
for (index = 0; (size_t) n >= iov[index].iov_len; index++) {
|
||||||
n -= iov[index].iov_len;
|
n -= iov[index].iov_len;
|
||||||
|
}
|
||||||
|
|
||||||
if (tmp_iov == iov) {
|
if (tmp_iov == iov) {
|
||||||
/* Must copy iov's around */
|
/* Must copy iov's around */
|
||||||
|
@ -604,10 +625,11 @@ ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
|
||||||
tmp_iov = local_iov;
|
tmp_iov = local_iov;
|
||||||
} else {
|
} else {
|
||||||
tmp_iov = calloc(1, (iov_size - index) * sizeof(struct iovec));
|
tmp_iov = calloc(1, (iov_size - index) * sizeof(struct iovec));
|
||||||
if (tmp_iov == NULL)
|
if (tmp_iov == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fill in the first partial read */
|
/* Fill in the first partial read */
|
||||||
tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[n]);
|
tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[n]);
|
||||||
|
@ -626,28 +648,30 @@ ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp_iov != iov && tmp_iov != local_iov)
|
if (tmp_iov != iov && tmp_iov != local_iov) {
|
||||||
free(tmp_iov);
|
free(tmp_iov);
|
||||||
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int st_writev_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size, st_utime_t timeout)
|
||||||
int st_writev_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size,
|
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
|
|
||||||
while (*iov_size > 0) {
|
while (*iov_size > 0) {
|
||||||
if (*iov_size == 1)
|
if (*iov_size == 1) {
|
||||||
n = write(fd->osfd, (*iov)->iov_base, (*iov)->iov_len);
|
n = write(fd->osfd, (*iov)->iov_base, (*iov)->iov_len);
|
||||||
else
|
} else {
|
||||||
n = writev(fd->osfd, *iov, *iov_size);
|
n = writev(fd->osfd, *iov, *iov_size);
|
||||||
|
}
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
while ((size_t) n >= (*iov)->iov_len) {
|
while ((size_t) n >= (*iov)->iov_len) {
|
||||||
n -= (*iov)->iov_len;
|
n -= (*iov)->iov_len;
|
||||||
|
@ -655,104 +679,109 @@ int st_writev_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size,
|
||||||
(*iov)->iov_len = 0;
|
(*iov)->iov_len = 0;
|
||||||
(*iov)++;
|
(*iov)++;
|
||||||
(*iov_size)--;
|
(*iov_size)--;
|
||||||
if (n == 0)
|
if (n == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (*iov_size == 0)
|
}
|
||||||
|
if (*iov_size == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
(*iov)->iov_base = (char *) (*iov)->iov_base + n;
|
(*iov)->iov_base = (char *) (*iov)->iov_base + n;
|
||||||
(*iov)->iov_len -= n;
|
(*iov)->iov_len -= n;
|
||||||
}
|
}
|
||||||
/* Wait until the socket becomes writable */
|
/* Wait until the socket becomes writable */
|
||||||
if (st_netfd_poll(fd, POLLOUT, timeout) < 0)
|
if (st_netfd_poll(fd, POLLOUT, timeout) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Simple I/O functions for UDP.
|
* Simple I/O functions for UDP.
|
||||||
*/
|
*/
|
||||||
int st_recvfrom(_st_netfd_t *fd, void *buf, int len, struct sockaddr *from,
|
int st_recvfrom(_st_netfd_t *fd, void *buf, int len, struct sockaddr *from, int *fromlen, st_utime_t timeout)
|
||||||
int *fromlen, st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
while ((n = recvfrom(fd->osfd, buf, len, 0, from, (socklen_t *)fromlen))
|
while ((n = recvfrom(fd->osfd, buf, len, 0, from, (socklen_t *)fromlen)) < 0) {
|
||||||
< 0) {
|
if (errno == EINTR) {
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
/* Wait until the socket becomes readable */
|
/* Wait until the socket becomes readable */
|
||||||
if (st_netfd_poll(fd, POLLIN, timeout) < 0)
|
if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return n;
|
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 st_sendto(_st_netfd_t *fd, const void *msg, int len,
|
|
||||||
const struct sockaddr *to, int tolen, st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
while ((n = sendto(fd->osfd, msg, len, 0, to, tolen)) < 0) {
|
while ((n = sendto(fd->osfd, msg, len, 0, to, tolen)) < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
/* Wait until the socket becomes writable */
|
/* Wait until the socket becomes writable */
|
||||||
if (st_netfd_poll(fd, POLLOUT, timeout) < 0)
|
if (st_netfd_poll(fd, POLLOUT, timeout) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int st_recvmsg(_st_netfd_t *fd, struct msghdr *msg, int flags,
|
int st_recvmsg(_st_netfd_t *fd, struct msghdr *msg, int flags, st_utime_t timeout)
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
while ((n = recvmsg(fd->osfd, msg, flags)) < 0) {
|
while ((n = recvmsg(fd->osfd, msg, flags)) < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
/* Wait until the socket becomes readable */
|
/* Wait until the socket becomes readable */
|
||||||
if (st_netfd_poll(fd, POLLIN, timeout) < 0)
|
if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int st_sendmsg(_st_netfd_t *fd, const struct msghdr *msg, int flags, st_utime_t timeout)
|
||||||
int st_sendmsg(_st_netfd_t *fd, const struct msghdr *msg, int flags,
|
|
||||||
st_utime_t timeout)
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
while ((n = sendmsg(fd->osfd, msg, flags)) < 0) {
|
while ((n = sendmsg(fd->osfd, msg, flags)) < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) {
|
||||||
continue;
|
continue;
|
||||||
if (!_IO_NOT_READY_ERROR)
|
}
|
||||||
|
if (!_IO_NOT_READY_ERROR) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
/* Wait until the socket becomes writable */
|
/* Wait until the socket becomes writable */
|
||||||
if (st_netfd_poll(fd, POLLOUT, timeout) < 0)
|
if (st_netfd_poll(fd, POLLOUT, timeout) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To open FIFOs or other special files.
|
* To open FIFOs or other special files.
|
||||||
*/
|
*/
|
||||||
|
@ -762,9 +791,10 @@ _st_netfd_t *st_open(const char *path, int oflags, mode_t mode)
|
||||||
_st_netfd_t *newfd;
|
_st_netfd_t *newfd;
|
||||||
|
|
||||||
while ((osfd = open(path, oflags | O_NONBLOCK, mode)) < 0) {
|
while ((osfd = open(path, oflags | O_NONBLOCK, mode)) < 0) {
|
||||||
if (errno != EINTR)
|
if (errno != EINTR) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newfd = _st_netfd_new(osfd, 0, 0);
|
newfd = _st_netfd_new(osfd, 0, 0);
|
||||||
if (!newfd) {
|
if (!newfd) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue