private boolean sendFile(java.nio.channels.FileChannel fchan, long pos, long lmt, FileWrite fw) throws CM_Stream.BrokenPipeException
	{
		final java.nio.channels.WritableByteChannel iochan = (java.nio.channels.WritableByteChannel)chanmon.iochan;
		final long sendbytes = lmt - pos;
		try {
			//throws on closed channel (java.io.IOException) or other error, so can't be sure it's closed, but it might as well be
			final long nbytes = fchan.transferTo(pos, sendbytes, iochan);
			if (nbytes != sendbytes) {
				//We didn't write as much as we requested, so we're probably blocked, but it could also be because
				//we reached end-of-file.
				//NB: This code would also spot any reduction in file size since we started this file-send.
				final long maxlmt = fchan.size();
				pos += nbytes;
				if (lmt > maxlmt) lmt = maxlmt;
				if (pos < lmt) {
					//Not at end-of-file (or even end-of-send, if we were only sending partial file), so we're blocked
					if (fw == null) {
						// enqueue the file
						if (chanmon.dsptch.logger.isActive(WRBLOCKTRC)) {
							chanmon.dsptch.logger.log(WRBLOCKTRC, "IOExec: File-send="+sendbytes+" blocked with "+nbytes+"/"+sendbytes
									+" - "+chanmon.getClass().getName()+"/E"+chanmon.getCMID()+"/"+chanmon.iochan);
						}
						enqueue(fchan, pos, lmt);
					} else {
						// file was already enqueued, so update its progress
						fw.offset = pos;
						fw.limit = lmt;
					}
					return false;
				}
			}
		} catch (Exception ex) {
			LEVEL lvl = (ex instanceof RuntimeException ? LEVEL.ERR : LEVEL.TRC3);
			String errmsg = "IOExec: file-send="+sendbytes+" failed";
			if (chanmon.dsptch.logger.isActive(lvl)) errmsg += " on "+iochan;
			chanmon.brokenPipe(lvl, "Broken pipe on file-send", errmsg, ex);
		}
		return true;
	}