Esempio n. 1
0
/**
 * @brief
 * 	-DIS_tcp_wflush - flush tcp/dis write buffer
 *
 * @par Functionality:
 *	Writes "committed" data in buffer to file discriptor,
 *	packs remaining data (if any), resets pointers
 *
 * @return	int
 * @retval	0	success
 * @retval	-1	error
 *
 */
int
DIS_tcp_wflush(int fd)
{
	size_t	ct;
	int	i;
	int	j;
	char	*pb;
	struct	tcpdisbuf	*tp;
	struct	pollfd pollfds[1];

	pbs_tcp_errno = 0;
	tp = tcp_get_writebuf(fd);
	pb = tp->tdis_thebuf;

	ct = tp->tdis_trail;
	if (ct == 0)
		return 0;

	while ((i = CS_write(fd, pb, ct)) != ct) {
		if (i == CS_IO_FAIL) {
			if (errno == EINTR) {
				continue;
			}
			if (errno != EAGAIN) {
				/* fatal error on write, abort output */
				pbs_tcp_errno = errno;
				return (-1);
			}

			/* write would have blocked (EAGAIN returned) */
			/* poll for socket to be ready to accept, if  */
			/* not ready in TIMEOUT_SHORT seconds, fail   */
			/* redo the poll if EINTR		      */
			do {
				pollfds[0].fd = fd;
				pollfds[0].events = POLLOUT;
				pollfds[0].revents = 0;
				j = poll(pollfds, 1, PBS_DIS_TCP_TIMEOUT_SHORT * 1000);
			} while ((j == -1) && (errno == EINTR));

			if (j == 0) {
				/* never came ready, return error */
				/* pbs_tcp_errno will add to log message */
				pbs_tcp_errno = EAGAIN;
				return (-1);
			} else if (j == -1) {
				/* some other error - fatal */
				pbs_tcp_errno = errno;
				return (-1);
			}
			continue;	/* socket ready, retry write */
		}
		/* write succeeded, do more if needed */
		ct -= i;
		pb += i;
	}
	tp->tdis_eod = tp->tdis_lead;
	tcp_pack_buff(tp);
	return 0;
}
Esempio n. 2
0
int DIS_tcp_wflush(

  struct tcp_chan *chan)  /* I */

  {
  size_t  ct;
  int     i;
  char   *pb = NULL;
  char   *pbs_debug = NULL;
  int     rc = PBSE_NONE;

  struct tcpdisbuf *tp;

  pbs_debug = getenv("PBSDEBUG");

  tp = &chan->writebuf;
  pb = tp->tdis_thebuf;
  ct = tp->tdis_trailp - tp->tdis_thebuf;

  if (rc != PBSE_NONE)
    return(-1);
 
  while ((i = write(chan->sock, pb, ct)) != (ssize_t)ct)
    {
    if (i == -1)
      {
      if (errno == EINTR)
        {
        continue;
        }

      /* FAILURE */

      if (pbs_debug != NULL)
        {
        fprintf(stderr,
            "TCP write of %d bytes (%.32s) [sock=%d] failed, errno=%d (%s)\n",
          (int)ct, pb, chan->sock, errno, strerror(errno));
        }
      
      return(-1);
      }  /* END if (i == -1) */
    else
      {
      ct -= i;
      pb += i;
      }
    }  /* END while (i) */

  /* SUCCESS */

  tp->tdis_eod = tp->tdis_leadp;

  tcp_pack_buff(tp);

  return(0);
  }  /* END DIS_tcp_wflush() */
Esempio n. 3
0
int tcp_read(

  struct tcp_chan *chan,
  long long       *read_len,
  long long       *avail_len,
  unsigned int     timeout)

  {
  int               rc = PBSE_NONE;
  unsigned long     newsize;
  char             *ptr;
  int               tdis_buf_len = 0;
  int               max_read_len = 0;
  char             *new_data = NULL;
  struct tcpdisbuf *tp;
  int               tmp_leadp = 0;
  int               tmp_trailp = 0;
  int               tmp_eod = 0;
  char              err_msg[1024];


  tp = &chan->readbuf;

  /* must compact any uncommitted data into bottom of buffer */
  tcp_pack_buff(tp);

  chan->IsTimeout = 0;
  chan->SelectErrno = 0;
  chan->ReadErrno = 0;
  tdis_buf_len = tp->tdis_bufsize;
  max_read_len = tp->tdis_bufsize - (tp->tdis_eod - tp->tdis_thebuf);

  /*
   * we don't want to be locked out by an attack on the port to
   * deny service, so we time out the read, the network had better
   * deliver promptly
   */

  if ((rc = socket_read(chan->sock, &new_data, read_len, timeout)) != PBSE_NONE)
    {
    switch (rc)
      {
      case PBSE_TIMEOUT:

        chan->IsTimeout = 1;

        break;

      default:

        chan->SelectErrno = rc;
        chan->ReadErrno = rc;

        break;
      }

    if (new_data != NULL)
      free(new_data);

    return(rc);
    }
  /* data read is less than buffer size */
  else if (max_read_len > *read_len)
    {
    memcpy(tp->tdis_eod, new_data, *read_len);
    tp->tdis_eod += *read_len;
    *tp->tdis_eod = '\0';
    *avail_len = tp->tdis_eod - tp->tdis_leadp;
    max_read_len = tp->tdis_eod - tp->tdis_thebuf;

    if (max_read_len > tdis_buf_len)
      {
      snprintf(err_msg, sizeof(err_msg),
        "eod ptr BEYOND end of buffer!! (fit) Remaining buffer = %d, read_len = %lld",
        max_read_len, *read_len);
      log_err(PBSE_INTERNAL,__func__,err_msg);
      }

    free(new_data);
    }
  /* data read is greater than buffer size */
  else if (max_read_len <= *read_len)
    {
    newsize = (tdis_buf_len + *read_len) * 2;
    if ((ptr = (char *)calloc(1, newsize+1)) == NULL)
      {
      log_err(ENOMEM,__func__,"Could not allocate memory to read buffer");
      rc = PBSE_MEM_MALLOC;
      free(new_data);
      return rc;
      }

    tmp_leadp = tp->tdis_leadp - tp->tdis_thebuf;
    tmp_trailp = tp->tdis_trailp - tp->tdis_thebuf;
    tmp_eod = tp->tdis_eod - tp->tdis_thebuf;

    snprintf(ptr, newsize, "%s%s", tp->tdis_thebuf, new_data);
    free(tp->tdis_thebuf);
    tp->tdis_thebuf = ptr;
    tp->tdis_bufsize = newsize;
    tp->tdis_eod = tp->tdis_thebuf + tmp_eod + *read_len;
    tp->tdis_trailp = tp->tdis_thebuf + tmp_trailp;
    tp->tdis_leadp = tp->tdis_thebuf + tmp_leadp;
    *avail_len = tp->tdis_eod - tp->tdis_leadp;

    max_read_len = tp->tdis_eod - tp->tdis_thebuf;
    tdis_buf_len = newsize;

    if (max_read_len > tdis_buf_len)
      {
      snprintf(err_msg, sizeof(err_msg), "eod ptr BEYOND end of buffer!!(expand) Remaining buffer = %d, read_len = %lld", max_read_len, *read_len);
      log_err(PBSE_INTERNAL,__func__,err_msg);
      }

    free(new_data);
    }

  return(rc);
  }  /* END tcp_read() */
Esempio n. 4
0
static int
tcp_read(int fd)
{
	int i;
	int	try_decrypt_buf = 0;
	struct	pollfd pollfds[1];
	int	timeout;
	struct	tcpdisbuf	*tp;
	char   *tmcp;

	tp = tcp_get_readbuf(fd);

#if defined(PBS_SECURITY) && (PBS_SECURITY == KCRYPT )

	/* In a case where an intermediate decryption buffer
	 * is being used (e.g. Kerberized PBS with encryption) the
	 * "read" into our tcp buffer area is being satisfied outof
	 * this internal buffer.  For this situation reading begins
	 * with any unread data residing in the CS library's internal
	 * buffer area.  Only if that data source is exhausted early
	 * will the CS library code sequence to reading and decrypting
	 * data from the socket, placing it in the intermediate
	 * decryption buffer, from where it's subsequently "read".
	 *
	 * Because the CS library is organized in this manner a
	 * real possibility exists to mistakenly wait for more data
	 * to be present on the socket, when in fact all the data has
	 * been collected and is available in the decryption buffer.
	 * The clause that follows attempts to recognize this case.
	 */

	if (tp->tdis_eod && tp->tdis_eod == tp->tdis_bufsize) {

		/* don't wait, data probably in decryption buffer */
		try_decrypt_buf = 1;
	}
#endif

	/* compact (move to the front) the uncommitted data */

	tcp_pack_buff(tp);

	if ((tp->tdis_bufsize - tp->tdis_eod) < 20) {

		/* no need to lock mutex here, this is per fd resize */
		/* needing a larger buffer area for the data */

		tp->tdis_bufsize += THE_BUF_SIZE;
		tmcp = (char *)realloc(tp->tdis_thebuf,
			sizeof(char)*tp->tdis_bufsize);
		if (tmcp != NULL) {
			tp->tdis_thebuf = tmcp;
		} else {
			/* realloc failed */
			return -1;
		}
	}

	/*
	 * we don't want to be locked out by an attack on the port to
	 * deny service, so we time out the read, the network had better
	 * deliver promptly
	 */
	do {
		if (try_decrypt_buf)
			timeout = 0;
		else
			timeout = pbs_tcp_timeout;

		pollfds[0].fd = fd;
		pollfds[0].events = POLLIN;
		pollfds[0].revents = 0;

		i = poll(pollfds, 1, timeout * 1000);
		if (pbs_tcp_interrupt)
			break;
	} while ((i == -1) && (errno == EINTR));

	if ((i == 0 && try_decrypt_buf == 0) || (i < 0))
		return i;

	while ((i = CS_read(fd, &tp->tdis_thebuf[tp->tdis_eod],
		tp->tdis_bufsize - tp->tdis_eod)) == CS_IO_FAIL) {

		if (errno != EINTR)
			break;
	}
	if (i > 0)
		tp->tdis_eod += i;

	return ((i == 0) ? -2 : i);
}