java.lang.Object
net.i2p.i2ptunnel.I2PTunnelHTTPServer.Sender
- All Implemented Interfaces:
Runnable
- Enclosing class:
I2PTunnelHTTPServer
Field Summary
FieldsModifier and TypeFieldDescriptionprivate longTotal bytes transferred successfully (read from _in, written to _out).private IOExceptionThe failure that ended the copy, if any.private final InputStreamThe input stream from the browser.private longNanoTime of the last successful read from _in.private longNanoTime of the last completed write to _out.private final LogLogger, shadows the one in the superclass.private final StringConnection name used in the logs.private final OutputStreamThe output stream to the browser.private StringParsed request line for the transfer, set once known.private StringIdentity of the far side, e.g.private static final intCopy buffer size for both directions.Constructor Summary
ConstructorsConstructorDescriptionSender(OutputStream out, InputStream in, String name, String targetLabel, Log log) Create a Sender with an explicit far-side label.Sender(OutputStream out, InputStream in, String name, Log log) Create a Sender to copy data from input to output streams.Method Summary
Modifier and TypeMethodDescriptionvoidabort(IOException cause) Abort this transfer without ever running it, closing both ends so the connection is torn down promptly.(package private) static StringdescribeTarget(String label, String request) Describe the far side for a log line: label plus optional request target, e.g.(package private) static StringformatTransferRate(long bytes, double secs) Format a transfer rate as10.5K/s/1.2M/s, in bytes per second using 1000-based units.longTotal bytes successfully transferred (read from input, written to output).Get any IOException that occurred during the copy.longNanoTime of the last successful read.longNanoTime of the last completed write.getName()The label this transfer is logged and reported under.voidrun()Copy data from the input stream to the output stream, flushing after each write to push data through any intermediate buffers (e.g.(package private) voidsetRequestLabel(String request) Set the parsed request line once it is known.(package private) voidsetTargetLabel(String label) Set the far-side label.
Field Details
BUF_SIZE
private static final int BUF_SIZECopy buffer size for both directions.- See Also:
_out
The output stream to the browser._in
The input stream from the browser._name
Connection name used in the logs._targetLabel
Identity of the far side, e.g.[skank / aanoquc2]. The request direction used to log a bare "from Client -> Server" with no indication of which eepsite or client a transfer belonged to, which made slow small transfers impossible to attribute._requestLabel
Parsed request line for the transfer, set once known. The request direction builds the Sender before the request line is read, so this is applied after the fact and rendered only when present._log
Logger, shadows the one in the superclass._failure
The failure that ended the copy, if any._bytesTransferred
private volatile long _bytesTransferredTotal bytes transferred successfully (read from _in, written to _out)._lastReadNanos
private volatile long _lastReadNanosNanoTime of the last successful read from _in. Used for stall detection._lastWriteNanos
private volatile long _lastWriteNanosNanoTime of the last completed write to _out. Tracked separately from the read stamp because the two stall for entirely different reasons: a stale read stamp means the local source is not delivering, while a fresh read with a stale write stamp means the destination is not accepting, i.e. I2P egress congestion. Both used to look identical, because the read stamp was only advanced after the write returned, so a write blocked on congestion was reported as a stalled source and pointed every diagnosis at the wrong layer.
Constructor Details
Sender
Create a Sender to copy data from input to output streams. Caller MUST close streams after Sender completes.- Parameters:
out- the output stream to write toin- the input stream to read fromname- descriptive name for logginglog- the logging instance
Sender
Create a Sender with an explicit far-side label.- Parameters:
out- the output stream to write toin- the input stream to read fromname- descriptive name for loggingtargetLabel- far-side identity, e.g.[skank / aanoquc2]; may be null or emptylog- the logging instance
Method Details
setTargetLabel
Set the far-side label. The request direction constructs the Sender before the request line is parsed, so the label is applied once it is known rather than at construction.- Parameters:
label- far-side identity, or null/empty to leave unset
setRequestLabel
Set the parsed request line once it is known.- Parameters:
request- request line or path; null/empty/"Unknown request" leaves it unset
describeTarget
Describe the far side for a log line: label plus optional request target, e.g.[skank / aanoquc2] GET /installers/i2pinstall.exe. Pure and static so the formatting is testable without streams.- Parameters:
label- far-side identity; may be nullrequest- parsed request line or path; may be null- Returns:
- the suffix to append to a transfer name, "" if neither is known
formatTransferRate
Format a transfer rate as10.5K/s/1.2M/s, in bytes per second using 1000-based units. Suffixes are B/s below 1 KB/s, K/s below 1 MB/s, and M/s above, so a rate never reads as a bare number with an ambiguous "kbps" that is easy to mistake for bits per second.- Parameters:
bytes- total bytes transferred, negative if the count is not trustedsecs- elapsed seconds; a value of 0 or less formats as "0.0B/s"- Returns:
- formatted rate, e.g.
60.6K/s; "0.0B/s" if secs <= 0
run
public void run()Copy data from the input stream to the output stream, flushing after each write to push data through any intermediate buffers (e.g. GZIP or MessageOutputStream). Without explicit flushes, data can accumulate in GZIP's deflater buffer or the streaming layer's MessageOutputStream buffer, causing sawtooth throughput patterns and intermittent stalls on the receiving end.Tracks bytes transferred and detects stalls: if no data is read for
I2PTunnelHTTPServer.ioStallTimeoutMs, the loop breaks and the partial transfer is logged. This prevents a dead peer from holding a handler or I/O thread indefinitely.getFailure
Get any IOException that occurred during the copy.- Returns:
- the failure exception, or null if successful
getBytesTransferred
public long getBytesTransferred()Total bytes successfully transferred (read from input, written to output).- Returns:
- bytes transferred, updated live during the transfer
getName
The label this transfer is logged and reported under.- Returns:
- the transfer description ("Server -> Client ..."); never null
getLastReadNanos
public long getLastReadNanos()NanoTime of the last successful read. Used by callers to detect stalls without interrupting the Sender thread.- Returns:
System.nanoTime()of the last successful read
getLastWriteNanos
public long getLastWriteNanos()NanoTime of the last completed write. Compared againstgetLastReadNanos()to tell a silent local source from a congested I2P destination.- Returns:
System.nanoTime()of the last completed write
abort
Abort this transfer without ever running it, closing both ends so the connection is torn down promptly.Used when the body cannot be handed to the I/O pool. Running the body on the caller's handler thread instead would pin that thread for the whole transfer, which is how one saturated body starves the runner pool and takes the entire service offline; a client that gets a fast close retries, while one that gets a pinned thread waits indefinitely.
- Parameters:
cause- recorded as the transfer failure, propagated to the caller