Exemple #1
0
_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;
}
Exemple #2
0
_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;
}
Exemple #3
0
// 从 _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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
/*
 * 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;
}
Exemple #8
0
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;
}
Exemple #9
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;
}
Exemple #10
0
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;
}
Exemple #11
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;
}
Exemple #12
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;
}
Exemple #13
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;
}