java.lang.Object
org.klomp.snark.Message
Represents a BitTorrent protocol message for peer communication.
This class encapsulates all BitTorrent protocol message types including:
- Control messages: keep-alive, choke, unchoke, interested, uninterested
- Piece messages: have, bitfield, request, piece, cancel
- Extension messages for protocol extensions
- Fast peer extension messages (BEP 6)
- DHT messages (BEP 5, BEP 52)
Messages are created and queued for sending through a DataOutputStream. The sendMessage() method translates messages to wire format.
Message structure includes:
- type - The message type byte
- piece - The piece index (for have, request, piece, cancel)
- begin - The offset within the piece
- length - The data length
- data - Optional payload data
- See Also:
Field Summary
FieldsModifier and TypeFieldDescriptionprivate ByteArrayCache-backed buffer owned by this message, non-null between successful load and release.private static final ByteCacheCache supplying the message buffers.private booleanMessage dropped unsent; the buffer must be released and not stored late.private booleanLoader completed and returned no data.private booleanSet exactly once by the winner of the race to execute the loader.private booleanTrue while the loader is executing somewhere; cleared by completeLoad().(package private) static final byteAllow request of a piece without an unchoke (BEP 6).private static final intMax time the sender thread will wait for an in-flight prefetch before falling back to a drop.(package private) final intThe offset within the piece.(package private) static final byteBitfield of pieces the peer has.private static final intSize of a chunk part.(package private) static final byteCancel a previously sent request.(package private) static final byteStop sending piece data to the peer.(package private) byte[]The data payload.private final DataLoaderThe loader for a deferred fetch of the message data.(package private) static final byteBEP 10 extended message, sub-type in the low byte.(package private) static final byteReject a hash request (BEP 52).(package private) static final byteRequest merkle hash tree data (BEP 52).(package private) static final byteMerkle hash tree data (BEP 52).(package private) static final byteAnnounce possession of a single piece.(package private) static final byteAnnounce possession of every piece (BEP 6).(package private) static final byteAnnounce possession of no pieces (BEP 6).(package private) static final byteSignal that the peer has pieces we want.(package private) static final byteNo-op message sent periodically to keep the connection alive.(package private) final intThe payload length.(package private) final intThe data length.(package private) final intThe data offset.(package private) final intThe piece index.(package private) static final byteChunk of a piece in response to a request.(package private) static final byteAnnounce the DHT listening port (BEP 5).(package private) static final byteReject a previously accepted request (BEP 6).(package private) static final byteRequest a chunk of a piece.(package private) static final byteSuggest a piece the peer may want (BEP 6).(package private) final byteThe message type.(package private) static final byteResume sending piece data to the peer.(package private) static final byteSignal that we no longer want pieces from the peer.Constructor Summary
ConstructorsModifierConstructorDescription(package private)Message(byte type) For types KEEP_ALIVE, CHOKE, UNCHOKE, INTERESTED, UNINTERESTED, HAVE_ALL, HAVE_NONE.(package private)Message(byte[] data) For type BITFIELD.(package private)Message(byte type, int piece) For types HAVE, PORT, SUGGEST, ALLOWED_FAST.(package private)Message(byte type, int piece, int begin, int length) For types REQUEST, REJECT, CANCEL.privateMessage(byte type, int piece, int begin, int length, byte[] data, int off, int len, DataLoader loader) Creates a peer protocol message from its fields.(package private)Message(int id, byte[] data) For type EXTENSION.(package private)Message(int piece, int begin, int length, DataLoader loader) For type PIECE with deferred data.Method Summary
Modifier and TypeMethodDescription(package private) booleanAbort a claimed-but-not-yet-started prefetch because the message was purged unsent, saving the disk read entirely.private voidWait for an in-flight prefetch to finish.(package private) booleanClaim exclusive right to execute the loader for this message.(package private) voidDeliver the result of a loader run started afterclaimLoad()returned true.(package private) voiddiscard()Mark this message as dropped without sending and release any loaded buffer exactly once.(package private) booleanWhether the deferred data has been loaded and not yet released.(package private) booleanWhether this message was dropped without sending.private voidEnsure the deferred PIECE data is available before sending.private static voidReturn a cache-acquired buffer to the pool, mirroringStorage.getPiece(int, int, int)'s acquire condition; non-cache-backed partial-read buffers are simply dropped for GC.private voidRelease this message's buffer after a successful send.private voidCaller must hold the monitor.(package private) ByteArrayInvoke the deferred loader.(package private) booleanSends this message through the given DataOutputStream.toString()A string representation of the message.
Field Details
KEEP_ALIVE
static final byte KEEP_ALIVENo-op message sent periodically to keep the connection alive.- See Also:
CHOKE
UNCHOKE
INTERESTED
UNINTERESTED
static final byte UNINTERESTEDSignal that we no longer want pieces from the peer.- See Also:
HAVE
BITFIELD
REQUEST
PIECE
CANCEL
PORT
SUGGEST
HAVE_ALL
HAVE_NONE
REJECT
ALLOWED_FAST
static final byte ALLOWED_FASTAllow request of a piece without an unchoke (BEP 6).- See Also:
EXTENSION
static final byte EXTENSIONBEP 10 extended message, sub-type in the low byte.- See Also:
HASH_REQUEST
HASHES
HASH_REJECT
type
final byte typeThe message type. Not all fields are used for every message; KEEP_ALIVE has no real wire representation.piece
final int pieceThe piece index. Used for HAVE, REQUEST, PIECE and CANCEL messages, and also for SUGGEST, REJECT and ALLOWED_FAST; the low byte for EXTENSION messages and the low two bytes for PORT messages.begin
final int beginThe offset within the piece. Used for REQUEST, PIECE, CANCEL and REJECT messages.length
final int lengthThe data length.data
byte[] dataThe data payload. Used for PIECE, BITFIELD and EXTENSION messages.off
final int offThe data offset.len
final int lenThe payload length.dataLoader
The loader for a deferred fetch of the message data._ba
Cache-backed buffer owned by this message, non-null between successful load and release. It may be loaded off the sender thread by the prefetch executor, so the state transitions below are guarded by this, keeping the sender, the executor and the purge paths in agreement._loadClaimed
private boolean _loadClaimedSet exactly once by the winner of the race to execute the loader._pendingLoad
private boolean _pendingLoadTrue while the loader is executing somewhere; cleared by completeLoad()._failed
private boolean _failedLoader completed and returned no data._discarded
private boolean _discardedMessage dropped unsent; the buffer must be released and not stored late.AWAIT_PREFETCH_TIMEOUT
private static final int AWAIT_PREFETCH_TIMEOUTMax time the sender thread will wait for an in-flight prefetch before falling back to a drop.- See Also:
BUFSIZE
private static final int BUFSIZESize of a chunk part._cache
Cache supplying the message buffers.
Constructor Details
Message
Message(byte type) For types KEEP_ALIVE, CHOKE, UNCHOKE, INTERESTED, UNINTERESTED, HAVE_ALL, HAVE_NONE.- Parameters:
type- the message type
Message
Message(byte type, int piece) For types HAVE, PORT, SUGGEST, ALLOWED_FAST.- Parameters:
type- the message typepiece- the zero-based index of the piece the message refers to
Message
Message(byte type, int piece, int begin, int length) For types REQUEST, REJECT, CANCEL.- Parameters:
type- the message typepiece- the zero-based index of the piece requested, rejected or cancelledbegin- the offset within the piece, in byteslength- the number of bytes requested, rejected or cancelled
Message
Message(byte[] data) For type BITFIELD.- Parameters:
data- the encoded bitfield, sent as the message payload
Message
Message(int id, byte[] data) For type EXTENSION.- Parameters:
id- the extended message id carried in the extension headerdata- the extension payload
Message
Message(int piece, int begin, int length, DataLoader loader) For type PIECE with deferred data.- Parameters:
piece- the zero-based index of the piece being sentbegin- the offset within the piece where the data starts, in byteslength- the number of bytes of piece data to sendloader- the loader that supplies the piece data when it is sent
Message
private Message(byte type, int piece, int begin, int length, byte[] data, int off, int len, DataLoader loader) Creates a peer protocol message from its fields.- Parameters:
type- the protocol message typepiece- the piece numberbegin- the offset within the piecelength- the length of the message datadata- the data bytes, null for a deferred loadoff- the offset within the data arraylen- the length of the data in the arrayloader- the loader supplying the data
Method Details
sendMessage
Sends this message through the given DataOutputStream.- Parameters:
dos- the output stream to write to- Returns:
- true if the message was written, false if the deferred data could not be loaded and the message was dropped
- Throws:
IOException- if an I/O error occurs
loadDataForSend
private void loadDataForSend()Ensure the deferred PIECE data is available before sending.Exactly one execution site runs the loader, decided by
claimLoad(): either this sender thread (inline fallback, the pre-prefetch behavior) or PeerConnectionOut's prefetch task. If a prefetch is in flight, wait briefly for it rather than duplicating the disk read; on timeout or discard the message is dropped and the peer will re-request. The loader always runs outside the message monitor so purge paths are never blocked by disk I/O.runLoader
ByteArray runLoader()Invoke the deferred loader. Must be called only after winningclaimLoad(); executes with no locks held so slow reads never block purge paths.- Returns:
- the loaded buffer, or null on error (a REJECT has already been queued upstream)
claimLoad
boolean claimLoad()Claim exclusive right to execute the loader for this message.- Returns:
- true if the caller must run the loader and later call
completeLoad(ByteArray); false if already claimed, completed, failed, discarded, or not loader-backed
abortIfDiscarded
boolean abortIfDiscarded()Abort a claimed-but-not-yet-started prefetch because the message was purged unsent, saving the disk read entirely.- Returns:
- true if the caller should skip loading; pending state is cleared either way
completeLoad
Deliver the result of a loader run started afterclaimLoad()returned true. Stores the buffer unless the message was discarded meanwhile, in which case the buffer is released immediately; failure is recorded so the sender drops the message.- Parameters:
ba- the loaded buffer, or null on load failure
awaitLoad
private void awaitLoad()Wait for an in-flight prefetch to finish. Bounded so a wedged executor degrades to a dropped block instead of stalling the sender thread indefinitely.discard
void discard()Mark this message as dropped without sending and release any loaded buffer exactly once. Called from all purge paths (choke, cancel, disconnect, queue overflow); safe to call repeatedly and concurrently with an in-flight prefetch.releaseOwned
private void releaseOwned()Release this message's buffer after a successful send. Exactly once; a no-op for messages without loader-loaded data.releaseOwnedInLock
private void releaseOwnedInLock()Caller must hold the monitor.releaseBuffer
Return a cache-acquired buffer to the pool, mirroringStorage.getPiece(int, int, int)'s acquire condition; non-cache-backed partial-read buffers are simply dropped for GC.- Parameters:
ba- the buffer to release
isDataReady
boolean isDataReady()Whether the deferred data has been loaded and not yet released.- Returns:
- true if ready to send without further loading
isDiscarded
boolean isDiscarded()Whether this message was dropped without sending.- Returns:
- true if discarded
toString