if (DEBUG_GTE(IO, 3)) {
rprintf(FINFO, "[%s] perform_io(%ld, outroom) needs to flush %ld\n",
who_am_i(), (long)needed,
- iobuf.out.len > iobuf.out.size - needed
- ? (long)iobuf.out.len - (iobuf.out.size - needed) : 0L);
+ iobuf.out.len + needed > iobuf.out.size
+ ? (long)(iobuf.out.len + needed - iobuf.out.size) : 0L);
}
break;
if (DEBUG_GTE(IO, 3)) {
rprintf(FINFO, "[%s] perform_io(%ld, msgroom) needs to flush %ld\n",
who_am_i(), (long)needed,
- iobuf.out.len > iobuf.msg.size - needed
- ? (long)iobuf.out.len - (iobuf.msg.size - needed) : 0L);
+ iobuf.msg.len + needed > iobuf.msg.size
+ ? (long)(iobuf.msg.len + needed - iobuf.msg.size) : 0L);
}
break;
goto double_break;
break;
case PIO_NEED_OUTROOM:
- if (iobuf.out.len <= iobuf.out.size - needed)
+ /* Note that iobuf.out_empty_len doesn't factor into this check
+ * because iobuf.out.len already holds any needed header len. */
+ if (iobuf.out.len + needed <= iobuf.out.size)
goto double_break;
break;
case PIO_NEED_MSGROOM:
- if (iobuf.msg.len <= iobuf.msg.size - needed)
+ if (iobuf.msg.len + needed <= iobuf.msg.size)
goto double_break;
break;
}
if (iobuf.raw_flushing_ends_before
|| (!iobuf.msg.len && iobuf.out.len > iobuf.out_empty_len && !(flags & PIO_NEED_MSGROOM))) {
if (OUT_MULTIPLEXED && !iobuf.raw_flushing_ends_before) {
- size_t val;
-
/* The iobuf.raw_flushing_ends_before value can point off the end
* of the iobuf.out buffer for a while, for easier subtracting. */
iobuf.raw_flushing_ends_before = iobuf.out.pos + iobuf.out.len;
SIVAL(iobuf.out.buf + iobuf.raw_data_header_pos, 0,
((MPLEX_BASE + (int)MSG_DATA)<<24) + iobuf.out.len - 4);
- if ((val = iobuf.out.size - iobuf.raw_data_header_pos) < 4) {
+ if (iobuf.raw_data_header_pos + 4 > iobuf.out.size) {
+ int siz = (int)(iobuf.raw_data_header_pos + 4 - iobuf.out.size);
/* We used some of the overflow bytes, so move them. */
if (DEBUG_GTE(IO, 4)) {
rprintf(FINFO, "[%s] wrap-bytes moved: %d (perform_io)\n",
- who_am_i(), (int)val);
+ who_am_i(), siz);
}
- memcpy(iobuf.out.buf, iobuf.out.buf + iobuf.out.size, 4 - val);
+ memcpy(iobuf.out.buf, iobuf.out.buf + iobuf.out.size, siz);
}
if (DEBUG_GTE(IO, 1)) {
iobuf.raw_data_header_pos = iobuf.raw_flushing_ends_before;
if (iobuf.raw_data_header_pos >= iobuf.out.size)
iobuf.raw_data_header_pos -= iobuf.out.size;
+ /* Yes, it is possible for this to make len > size for a while. */
iobuf.out.len += 4;
}
char buf[1024];
kluge_around_eof = 1;
+ set_io_timeout(protocol_version >= 31 ? 10 : 1);
while (1)
read_buf(iobuf.in_fd, buf, sizeof buf);
SIVAL(hdr, 0, ((MPLEX_BASE + (int)code)<<24) + len);
/* If the header used any overflow bytes, move them to the start. */
if ((pos = hdr+4 - iobuf.msg.buf) > iobuf.msg.size) {
- size_t siz = pos - iobuf.msg.size;
+ int siz = (int)(pos - iobuf.msg.size);
if (DEBUG_GTE(IO, 4))
- rprintf(FINFO, "[%s] wrap-bytes moved: %d (send_msg)\n", who_am_i(), (int)siz);
- memcpy(iobuf.msg.buf, hdr+4 - siz, siz);
+ rprintf(FINFO, "[%s] wrap-bytes moved: %d (send_msg)\n", who_am_i(), siz);
+ memcpy(iobuf.msg.buf, iobuf.msg.buf + iobuf.msg.size, siz);
}
if (want_debug && convert > 0)
if (msg_bytes != 4 || am_sender)
goto invalid_msg;
data = perform_io(4, PIO_INPUT_AND_CONSUME);
- io_error |= IVAL(data, 0);
+ val = IVAL(data, 0);
+ io_error |= val;
if (!am_generator)
- send_msg(MSG_IO_ERROR, data, 4, 0);
+ send_msg_int(MSG_IO_ERROR, val);
break;
case MSG_IO_TIMEOUT:
if (msg_bytes != 4 || am_server || am_generator)
if (!io_timeout || io_timeout > val) {
if (INFO_GTE(MISC, 2))
rprintf(FINFO, "Setting --timeout=%d to match server\n", val);
- io_timeout = val;
+ set_io_timeout(val);
}
break;
case MSG_NOOP:
exit_cleanup(RERR_STREAMIO);
}
data = perform_io(4, PIO_INPUT_AND_CONSUME);
+ val = IVAL(data, 0);
if (am_generator)
- got_flist_entry_status(FES_SUCCESS, IVAL(data, 0));
+ got_flist_entry_status(FES_SUCCESS, val);
else
- successful_send(IVAL(data, 0));
+ successful_send(val);
break;
case MSG_NO_SEND:
if (msg_bytes != 4)
goto invalid_msg;
data = perform_io(4, PIO_INPUT_AND_CONSUME);
+ val = IVAL(data, 0);
if (am_generator)
- got_flist_entry_status(FES_NO_SEND, IVAL(data, 0));
+ got_flist_entry_status(FES_NO_SEND, val);
else
- send_msg(MSG_NO_SEND, data, 4, 0);
+ send_msg_int(MSG_NO_SEND, val);
break;
case MSG_ERROR_SOCKET:
case MSG_ERROR_UTF8:
}
break;
case MSG_ERROR_EXIT:
- if (msg_bytes != 4)
+ if (msg_bytes == 0) {
+ if (!am_sender && !am_generator) {
+ send_msg(MSG_ERROR_EXIT, "", 0, 0);
+ io_flush(FULL_FLUSH);
+ }
+ val = 0;
+ } else if (msg_bytes == 4) {
+ data = perform_io(4, PIO_INPUT_AND_CONSUME);
+ val = IVAL(data, 0);
+ if (protocol_version >= 31) {
+ if (am_generator)
+ send_msg_int(MSG_ERROR_EXIT, val);
+ else
+ send_msg(MSG_ERROR_EXIT, "", 0, 0);
+ }
+ } else
goto invalid_msg;
- data = perform_io(4, PIO_INPUT_AND_CONSUME);
- val = IVAL(data, 0);
- if (am_generator && protocol_version >= 31)
- send_msg_int(MSG_ERROR_EXIT, val);
- if (am_generator)
- val = RERR_RCVR_ERROR; /* avoids duplicate errors */
- exit_cleanup(val);
+ /* Send a negative linenum so that we don't end up
+ * with a duplicate exit message. */
+ _exit_cleanup(val, __FILE__, 0 - __LINE__);
default:
rprintf(FERROR, "unexpected tag %d [%s%s]\n",
tag, who_am_i(), inc_recurse ? "/inc" : "");
goto batch_copy;
}
- if (iobuf.out.size - iobuf.out.len < len)
+ if (iobuf.out.len + len > iobuf.out.size)
perform_io(len, PIO_NEED_OUTROOM);
pos = iobuf.out.pos + iobuf.out.len; /* Must be set after any flushing. */