- All Implemented Interfaces:
MessageOutputStream.WriteStatus
coordinate local attributes about a packet - send time, ack time, number of retries, etc.
Field Summary
FieldsModifier and TypeFieldDescriptionprivate longWhen the packet was acked, 0 while unacked.private longLOCKING: this.private longWhen the packet was cancelled, 0 while active.private final ConnectionThe connection the packet was sent on.private final I2PAppContextThe app context.private final longWhen the packet was created.private booleanWhether this packet has been enqueued for I2CP send.private longWhen the packet was last sent.private final LogLogger for the local packet record.private final AtomicIntegerNacks received for the packet.private final AtomicIntegerTimes the packet has been sent.private final AtomicIntegerResend attempts triggered by a router soft failure (NO_TUNNELS / EXPIRED / LOCAL).private static final ByteCacheCache supplying the payload buffers.private booleanTrue once the packet was retransmitted.private intTimeout used waiting for the packet's ack.private final DestinationThe peer the packet was sent to.Fields inherited from class Packet
_nacks, _offlineSignature, _optionFrom, _optionSignature, _session, _transientExpires, _transientSigningPublicKey, DEFAULT_MAX_SIZE, FLAG_CLOSE, FLAG_DELAY_REQUESTED, FLAG_ECHO, FLAG_FROM_INCLUDED, FLAG_MAX_PACKET_SIZE_INCLUDED, FLAG_NO_ACK, FLAG_PROFILE_INTERACTIVE, FLAG_RESET, FLAG_SIGNATURE_INCLUDED, FLAG_SIGNATURE_OFFLINE, FLAG_SIGNATURE_REQUESTED, FLAG_SYNCHRONIZE, MAX_DELAY_REQUEST, MAX_PAYLOAD_SIZE, MAX_STREAM_ID, MIN_DELAY_CHOKE, SEND_DELAY_CHOKE, STREAM_ID_UNKNOWNModifier and TypeFieldDescriptionprotected long[]Sequence numbers the sender has not had acknowledged.protected SignatureDestination's signature made with the transient key of an offline block.protected DestinationSending destination, when that option is included.protected SignatureTime to wait before resending, in ms, one of the four fields set only when the flags say so.protected final I2PSessionSession the packet travels over, set at construction.protected longThe transient signing key of the peer, the three fields that follow it are for offline signatures.protected SigningPublicKeyEphemeral signing public key taken from the offline signing block.static final intDEFAULT_MAX_SIZE.static final intThe sender of this packet will not be sending any more payload data.static final intThis packet includes an explicit request for the recipient to delay sending any packets with data for a given amount of time.static final intIf set, this packet is a ping (if sendStreamId is set) or a ping reply (if receiveStreamId is set).static final intThis packet includes the full I2P destination of the packet's sender.static final intThis packet includes a request that the recipient not send any subsequent packets with payloads greater than a specific size.static final intIf set, this packet doesn't really want to ack anything.static final intIf set, this packet is travelling as part of an interactive flow, meaning it is more lag sensitive than throughput sensitive.static final intThis packet is being sent to signify that the socket does not exist (or, if in response to an initial synchronize packet, that the connection was refused).static final intThis packet contains a DSA signature from the packet's sender.static final intIf set, an offline signing block is in the options.static final intThis packet wants the recipient to include signatures on subsequent packets sent to the creator of this packet.static final intThis packet is creating a new socket connection (if the receiveStreamId is STREAM_ID_UNKNOWN) or it is acknowledging a request to create a connection and in turn is accepting the socket.protected static final intLargest delay in milliseconds a peer may request before being choked.static final intLargest payload a streaming packet may carry, in bytes.static final longLargest stream ID the 32-bit field can carry.static final intDelay request at or above which the peer is treated as choked.static final intDelay sent to a choked peer, asking it to pause roughly a minute.static final longThe receiveStreamId will be set to this when the packet doesn't know what ID will be assigned by the remote peer (aka this is the initial synchronize packet).Constructor Summary
ConstructorsConstructorDescriptionPacketLocal(I2PAppContext ctx, Destination to, I2PSession session) Constructor for a packet not bound to a connection.PacketLocal(I2PAppContext ctx, Destination to, Connection con) Constructor for a packet bound to a connection.Method Summary
Modifier and TypeMethodDescriptionvoidRecord that this packet was ACKed.voidRecord that this packet was cancelled.Format as a string builder for logging, full form.formatAsString(boolean withContext) Format as a string builder for logging.intHow long after packet creation was it acked?Read the connection this packet is bound to.longRead the router clock time at which this packet was created.longTime of the last send.longLifetime of this packet.intgetNACKs()Warning: This is different than getNacks() in super.intNumber of times sent.intNumber of send attempts that were router soft failures.(package private) static ByteCacheShared outbound payload cache (MAX_PAYLOAD_SIZE buffers).intRTT sample for an ACKed packet: time between its last transmission and its ACK.intUsed byPacketQueueto feed an expiration to the router.getTo()The peer this packet was sent to.voidCount a NACK for this packet, and on theConnection.FAST_RETRANSMIT_THRESHOLDth one ask for a fast retransmit, provided the retransmit timer has demonstrably not already fired: the packet must have been sent at least max(4s, RTT) ago, and only the first such NACK storm triggers it.voidIncrement the number of times this packet has been sent.voidRecord a resend that was triggered by a router soft failure.(package private) static booleanisAckStarvation(boolean packetAcked, long highestAckedThrough, long ackProgressAtStart) Pure decision rule for the write-timeout ACK-starvation fail-fast.private booleanWhether this packet was cancelled.booleanReport whether this packet has been queued for I2CP send.voidGenerate a pcap/tcpdump-compatible format, so we can use standard debugging tools.voidFlag this packet as handed to I2CP for sending.voidReturn the payload to the shared pool instead of letting it GC.(package private) static longrttSample(long ackOn, long lastSend) Pure RTT sample computation: ACK time minus last transmission time.voidThis sets the from field in the packet to the Destination for the session provided in the constructor.voidsetTimeout(int timeout) Timeout for this packet.booleanWhether this packet should be signed.voidwaitForAccept(int maxWaitMs) Blocks until outbound window is not full.voidwaitForCompletion(int maxWaitMs) Block until the packet is acked from the far end.booleanWhether the send was accepted.booleanWhether the send failed.booleanWhether this packet's payload has been released and it can no longer be (re)transmitted.intwriteSignedPacket(byte[] buffer, int offset) Sign and write the packet to the buffer (starting at the offset) and return the number of bytes written.booleanWhether the send succeeded and was ACKed.Methods inherited from class Packet
acquirePayload, alignSignatureToType, getAckThrough, getLocalPort, getNacks, getOptionalDelay, getOptionalFrom, getOptionalMaxSize, getOptionalSignature, getPayload, getPayloadSize, getReceiveStreamId, getRemotePort, getResendDelay, getSendStreamId, getSequenceNum, getSession, getTransientSPK, isFlagSet, logTCPDump, readPacket, setAckThrough, setFlag, setFlag, setLocalPort, setNacks, setOptionalDelay, setOptionalMaxSize, setOptionalSignature, setPayload, setReceiveStreamId, setRemotePort, setResendDelay, setSendStreamId, setSequenceNum, signatureSpaceLen, toId, toString, verifySignature, verifySignature, writePacket, writePacket, writtenSizeModifier and TypeMethodDescriptionAllocate a MAX_PAYLOAD_SIZE buffer for this packet.(package private) booleanalignSignatureToType(SigType type) Recast the signature to the signing key's type when the bytes we read are long enough to be a signature of that type.longThe highest packet sequence number that received on the receiveStreamId.intLocal port.long[]getNacks()List of packet sequence numbers below thePacket.getAckThrough()value have not been received.intHow many milliseconds the sender of this packet wants the recipient to wait before sending any more data (only valid if the flag for it is set).Sender of the packet, only included if the flag for it is set.intWhat is the largest payload the sender of this packet wants to receive?The signature on the packet (only included if the flag for it is set)Actual payload of the message, may be null.intPayload size in bytes.longStream the replies should be sent on.intRemote port.intHow long is the creator of this packet going to wait before resending this packet (if it hasn't yet been ACKed).longStream we send data to the peer on.long0-indexed sequence number for this Packet in the sendStream.Return the session this packet belongs to.Transient signing public key, only if an offline signing block was included, else null.booleanisFlagSet(int flag) Is a particular flag set on this packet?voidlogTCPDump(Connection con) Generate a pcap/tcpdump-compatible format, so we can use standard debugging tools.voidreadPacket(byte[] buffer, int offset, int length) Read the packet from the buffer (starting at the offset) and return the number of bytes read.voidsetAckThrough(long id) ACK-through value to set; if < 0, sets FLAG_NO_ACK.voidsetFlag(int flag) Marks the flag(s) set.voidsetFlag(int flag, boolean set) Marks the flag(s) set or clear.voidsetLocalPort(int port) Must be called to change the port, not set by readPacket() as the port is out-of-band in the I2CP header.voidsetNacks(long[] nacks) NACK list to set.voidsetOptionalDelay(int delayMs) Caller must also call setFlag(FLAG_DELAY_REQUESTED).voidsetOptionalMaxSize(int numBytes) This also sets flag FLAG_MAX_PACKET_SIZE_INCLUDED.voidThis also sets flag FLAG_SIGNATURE_INCLUDED.voidsetPayload(ByteArray payload) Payload to set.voidsetReceiveStreamId(long id) Stream the peer will send replies on.voidsetRemotePort(int port) Must be called to change the port, not set by readPacket() as the port is out-of-band in the I2CP header.voidsetResendDelay(int numSeconds) Unused.voidsetSendStreamId(long id) Stream the peer will receive data on.voidsetSequenceNum(long num) Sequence number to set.(package private) intsignatureSpaceLen(SigType keyType) How many option bytes to reserve for the signature when this packet is written, which is also how many bytes the signature covers.(package private) static final StringtoId(long id) Format a stream ID for display.toString()String representation of this packet.booleanverifySignature(I2PAppContext ctx, byte[] buffer) Determine whether the signature on the data is valid.booleanverifySignature(I2PAppContext ctx, SigningPublicKey altSPK, byte[] buffer) Determine whether the signature on the data is valid.intwritePacket(byte[] buffer, int offset) Write the packet to the buffer (starting at the offset) and return the number of bytes written.protected intwritePacket(byte[] buffer, int offset, int fakeSigLen) Write the packet to the buffer, leaving room for a fake signature if requested.(package private) intwrittenSize(SigType keyType) Size of this packet if written to a buffer.
Field Details
_context
The app context._log
Logger for the local packet record._connection
The connection the packet was sent on._to
The peer the packet was sent to._createdOn
private final long _createdOnWhen the packet was created._numSends
Times the packet has been sent._numSoftResends
Resend attempts triggered by a router soft failure (NO_TUNNELS / EXPIRED / LOCAL)._lastSend
private volatile long _lastSendWhen the packet was last sent._acceptedOn
private long _acceptedOnWhen the packet was acked, 0 while unacked._ackOn
private long _ackOnLOCKING: this._cancelledOn
private long _cancelledOnWhen the packet was cancelled, 0 while active._nackCount
Nacks received for the packet._retransmitted
private volatile boolean _retransmittedTrue once the packet was retransmitted._timeout
private volatile int _timeoutTimeout used waiting for the packet's ack._enqueued
private volatile boolean _enqueuedWhether this packet has been enqueued for I2CP send._payloadCache
Cache supplying the payload buffers.
Constructor Details
PacketLocal
Constructor for a packet not bound to a connection.- Parameters:
ctx- the router contextto- the remote destination the packet is addressed tosession- the session used to send the packet
PacketLocal
Constructor for a packet bound to a connection.- Parameters:
ctx- the router contextto- the remote destination the packet is addressed tocon- the connection the packet is sent over
Method Details
setOptionalFrom
public void setOptionalFrom()This sets the from field in the packet to the Destination for the session provided in the constructor. This also sets flag FLAG_FROM_INCLUDED. Also, as of 0.9.39, sets the offline signing data if supported by the session.getTo
shouldSign
public boolean shouldSign()Whether this packet should be signed.- Returns:
- true if this packet should be signed
getCreatedOn
public long getCreatedOn()Read the router clock time at which this packet was created.- Returns:
- the time this packet was created
getLifetime
public long getLifetime()Lifetime of this packet.- Returns:
- the lifetime of this packet in ms
incrementSends
public void incrementSends()Increment the number of times this packet has been sent.ackReceived
public void ackReceived()Record that this packet was ACKed.releasePayload
public void releasePayload()Return the payload to the shared pool instead of letting it GC. Only returns buffers that came from the MAX_PAYLOAD_SIZE pool; zero-length or other-size payloads fall through to default no-op.Synchronized on this packet, the same monitor
writeReleased()and the send path's serialize take, so the buffer cannot go back to the pool while a copy of it is in flight.- Overrides:
releasePayloadin classPacket
getPayloadCache
Shared outbound payload cache (MAX_PAYLOAD_SIZE buffers). Must match the cache inConnectionDataReceiver._payloadCache.- Returns:
- the static cache of outbound payload buffers
cancelled
public void cancelled()Record that this packet was cancelled.getAckTime
public int getAckTime()How long after packet creation was it acked?- Returns:
- how long after packet creation the packet was ACKed in ms
getRttTime
public int getRttTime()RTT sample for an ACKed packet: time between its last transmission and its ACK.Unlike
getAckTime()(which measures lifetime since creation and is used for thestream.sendsBeforeAckstat), this excludes queueing delay: a packet may sit in the outbound queue (pacing, choke, slow tunnel) long after creation, and folding that delay into the RTT sample inflates SRTT and pins RTO at its ceiling exactly when recovery is needed. Per RFC 6298 section 3, only packets sent once are valid RTT samples; callers gate ongetNumSends()<= 1 before trusting the value.- Returns:
- the RTT sample in ms, or -1 if the packet was never sent or never ACKed
rttSample
static long rttSample(long ackOn, long lastSend) Pure RTT sample computation: ACK time minus last transmission time.The sample is only meaningful when the packet was transmitted exactly once (RFC 6298 section 3); resend bookkeeping is left to the caller so this helper stays testable without router context.
- Parameters:
ackOn- time the packet was ACKed in ms since epochlastSend- time of the last transmission in ms since epoch- Returns:
- the RTT sample in ms, or -1 if either time is unknown (<= 0)
getNumSends
public int getNumSends()Number of times sent.- Returns:
- the number of times this packet has been sent
incrementSoftResends
public void incrementSoftResends()Record a resend that was triggered by a router soft failure. Soft failures (NO_TUNNELS / EXPIRED / LOCAL) mean the packet was never put on the tunnel fabric, so the attempt should not consume the hard retransmit budget (seeConnection.hardResendBudgetExceeded(int, int, int)).getNumSoftResends
public int getNumSoftResends()Number of send attempts that were router soft failures.- Returns:
- the number of soft-failure-triggered resends
getLastSend
public long getLastSend()Time of the last send.- Returns:
- the time of the last send, or -1 if never sent
getConnection
Read the connection this packet is bound to.- Returns:
- the bound connection, or null if not bound
incrementNACKs
public void incrementNACKs()Count a NACK for this packet, and on theConnection.FAST_RETRANSMIT_THRESHOLDth one ask for a fast retransmit, provided the retransmit timer has demonstrably not already fired: the packet must have been sent at least max(4s, RTT) ago, and only the first such NACK storm triggers it. The retransmit is a no-op unless this is the lowest unacked packet (see Connection.ResendPacketEvent).getNACKs
public int getNACKs()Warning: This is different than getNacks() in super.- Returns:
- Number of times this packet has been nacked
getTimeout
public int getTimeout()Used byPacketQueueto feed an expiration to the router.- Returns:
- time from now, not absolute time. May be zero if unset.
setTimeout
public void setTimeout(int timeout) Timeout for this packet.- Parameters:
timeout- time from now, not absolute time
writeSignedPacket
Sign and write the packet to the buffer (starting at the offset) and return the number of bytes written.- Parameters:
buffer- data to be writtenoffset- starting point in the buffer- Returns:
- Count of bytes written
- Throws:
IllegalStateException- if the offline signature has expired, or if signing the packet failed
formatAsString
Format as a string builder for logging, full form.Not gated on the log level: every caller builds this from inside a log message that has already passed its own shouldXxx() test, so gating the description on INFO meant a WARN or ERROR about a packet logged an empty string - the one thing that makes such a message useless. The bulky parts (the NACK list, offline key material) stay behind shouldDebug(). The description is two lines: the header (stream IDs and sequence number), then one
" * "continuation line carrying the flags, options and payload size together.- Overrides:
formatAsStringin classPacket- Returns:
- a buffer holding the human readable form of this packet, ready to be appended to a log message
formatAsString
Format as a string builder for logging.With
withContextfalse this drops the send count and the connection pair - the caller's connection prefix already names both endpoints, and the count rides in its message.- Overrides:
formatAsStringin classPacket- Parameters:
withContext- whenfalse, omit the facts the caller's own message already carries - the stream-ID header and the sequence number here, the send count and the connection pair inPacketLocal: a caller that leads with the connection prefix must not print them a second time- Returns:
- a buffer holding the human readable form of this packet, ready to be appended to a log message
waitForAccept
Blocks until outbound window is not full. SeeConnection.packetSendChoke(long).- Specified by:
waitForAcceptin interfaceMessageOutputStream.WriteStatus- Parameters:
maxWaitMs- MessageOutputStream is the only caller, generally with -1- Throws:
IOException- if the connection is closedInterruptedException- if the thread is interrupted
waitForCompletion
Block until the packet is acked from the far end.- Specified by:
waitForCompletionin interfaceMessageOutputStream.WriteStatus- Parameters:
maxWaitMs- maximum time to wait in ms- Throws:
IOException- if the connection is reset or cancelledInterruptedException- if the thread is interrupted
isAckStarvation
static boolean isAckStarvation(boolean packetAcked, long highestAckedThrough, long ackProgressAtStart) Pure decision rule for the write-timeout ACK-starvation fail-fast.When a
waitForCompletionreaches its write timeout with this packet still unacknowledged, the send should be treated as failed (rather than silently timing out and dropping the payload) only when the connection made no forward ACK progress at all while we waited. If any other packet was acknowledged during the window, the connection is slow but alive, and this packet's ACK is likely merely coalesced or lost — we must NOT fail it (avoid a false positive that would truncate a legitimate slow-but-progressing transfer).This was extracted as a pure static method so the fail-fast rule is unit-testable without a live
Connection(mirrors thegetAdaptiveSynTimeoutevidence-gated pattern).- Parameters:
packetAcked- whether the specific packet was acknowledged (WriteStatus.writeSuccessful())highestAckedThrough- current connection-wide forward-ACK progress (Connection.getHighestAckedThrough())ackProgressAtStart- forward-ACK progress captured at wait start- Returns:
trueif this is unambiguously ACK starvation and the send should fail fast;falseif the connection made progress (or the packet was acked) and the send should be left to the normal timeout path
isCancelled
private boolean isCancelled()Whether this packet was cancelled.- Returns:
- true if this packet was cancelled
writeAccepted
public boolean writeAccepted()Whether the send was accepted.- Specified by:
writeAcceptedin interfaceMessageOutputStream.WriteStatus- Returns:
- true if this packet was accepted for sending
writeFailed
public boolean writeFailed()Whether the send failed.- Specified by:
writeFailedin interfaceMessageOutputStream.WriteStatus- Returns:
- true if this packet's send failed
writeSuccessful
public boolean writeSuccessful()Whether the send succeeded and was ACKed.- Returns:
- true if this packet was successfully sent and ACKed
writeReleased
public boolean writeReleased()Whether this packet's payload has been released and it can no longer be (re)transmitted.Both
ackReceived()andcancelled()callreleasePayload(), which returns this packet's buffer to the shared outbound payload cache and clears_payload. Once either has run the packet must never be enqueued again — a (re)send would read anullpayload and crash the I2CP write.isCancelled()alone is insufficient: an ACKed-but-not-cancelled packet also has a released payload.This is the discriminator the retransmit timer uses to skip packets that were acknowledged or cancelled after it snapshotted the outbound set (a use-after-release TOCTOU between
Connection.ackPacketsandConnection.RetransmitEvent.timeReached), mirroring the paced-path guard ongetAckTime().- Returns:
trueif the packet was ACKed or cancelled, so its payload was released;falseif it may still be transmitted
logTCPDump
public void logTCPDump()Generate a pcap/tcpdump-compatible format, so we can use standard debugging tools.markEnqueued
public void markEnqueued()Flag this packet as handed to I2CP for sending.isEnqueued
public boolean isEnqueued()Report whether this packet has been queued for I2CP send.- Returns:
- true if this packet has been queued for I2CP send