Esempio n. 1
0
/* ---------------------------------------
 * write data. 0 on failure. this assumes that dsi_len will never
 * cause an overflow in the data buffer. 
 */
int dsi_stream_send(DSI *dsi, void *buf, size_t length)
{
  char block[DSI_BLOCKSIZ];
  struct iovec iov[2];
  int iovecs = 2;
  size_t towrite;
  ssize_t len;

  LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): START", length);

  if (dsi->flags & DSI_DISCONNECTED)
      return 0;

  dsi_header_pack_reply(dsi, block);

  if (!length) { /* just write the header */
      LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): DSI header, no data", sizeof(block));
    length = (dsi_stream_write(dsi, block, sizeof(block), 0) == sizeof(block));
    return length; /* really 0 on failure, 1 on success */
  }
  
  /* block signals */
  block_sig(dsi);
  iov[0].iov_base = block;
  iov[0].iov_len = sizeof(block);
  iov[1].iov_base = buf;
  iov[1].iov_len = length;
  
  towrite = sizeof(block) + length;
  dsi->write_count += towrite;
  while (towrite > 0) {
      if (((len = writev(dsi->socket, iov, iovecs)) == -1 && errno == EINTR) || (len == 0))
          continue;
    
      if ((size_t)len == towrite) /* wrote everything out */
          break;
      else if (len < 0) { /* error */
          if (errno == EAGAIN || errno == EWOULDBLOCK) {
              if (dsi_peek(dsi) == 0) {
                  continue;
              }
          }
          LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno));
          unblock_sig(dsi);
          return 0;
      }
    
      towrite -= len;
      if (towrite > length) { /* skip part of header */
          iov[0].iov_base = (char *) iov[0].iov_base + len;
          iov[0].iov_len -= len;
      } else { /* skip to data */
          if (iovecs == 2) {
              iovecs = 1;
              len -= iov[0].iov_len;
              iov[0] = iov[1];
          }
          iov[0].iov_base = (char *) iov[0].iov_base + len;
          iov[0].iov_len -= len;
      }
  }

  LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): END", length);
  
  unblock_sig(dsi);
  return 1;
}
Esempio n. 2
0
/* ---------------------------------------
 * write data. 0 on failure. this assumes that dsi_len will never
 * cause an overflow in the data buffer. 
 */
int dsi_stream_send(DSI *dsi, void *buf, size_t length)
{
  char block[DSI_BLOCKSIZ];
  struct iovec iov[2];
  size_t towrite;
  ssize_t len;

  LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes",
      length ? length : sizeof(block));

  if (dsi->flags & DSI_DISCONNECTED)
      return 0;

  block[0] = dsi->header.dsi_flags;
  block[1] = dsi->header.dsi_command;
  memcpy(block + 2, &dsi->header.dsi_requestID, 
	 sizeof(dsi->header.dsi_requestID));
  memcpy(block + 4, &dsi->header.dsi_code, sizeof(dsi->header.dsi_code));
  memcpy(block + 8, &dsi->header.dsi_len, sizeof(dsi->header.dsi_len));
  memcpy(block + 12, &dsi->header.dsi_reserved,
	 sizeof(dsi->header.dsi_reserved));

  if (!length) { /* just write the header */
    length = (dsi_stream_write(dsi, block, sizeof(block), 0) == sizeof(block));
    return length; /* really 0 on failure, 1 on success */
  }
  
  /* block signals */
  block_sig(dsi);
  iov[0].iov_base = block;
  iov[0].iov_len = sizeof(block);
  iov[1].iov_base = buf;
  iov[1].iov_len = length;
  
  towrite = sizeof(block) + length;
  dsi->write_count += towrite;
  while (towrite > 0) {
      if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) || (len == 0))
          continue;
    
      if ((size_t)len == towrite) /* wrote everything out */
          break;
      else if (len < 0) { /* error */
          if (errno == EAGAIN || errno == EWOULDBLOCK) {
              if (!dsi_peek(dsi)) {
                  continue;
              }
          }
          LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno));
          unblock_sig(dsi);
          return 0;
      }
    
      towrite -= len;
      if (towrite > length) { /* skip part of header */
          iov[0].iov_base = (char *) iov[0].iov_base + len;
          iov[0].iov_len -= len;
      } else { /* skip to data */
          if (iov[0].iov_len) {
              len -= iov[0].iov_len;
              iov[0].iov_len = 0;
          }
          iov[1].iov_base = (char *) iov[1].iov_base + len;
          iov[1].iov_len -= len;
      }
  }
  
  unblock_sig(dsi);
  return 1;
}