/* --------------------------------------- * 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; }
/* --------------------------------------- * 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; }