java.lang.Object
org.klomp.snark.ClientID
Registry of known BitTorrent client identities.
Two things live here:
- The peer ID prefix recognition table mapping the first three raw peer ID bytes (as the first four Base64 characters of the ID) to a client name. This is the single source of truth; I2PSnarkServlet delegates to it.
- Spoofing profiles for well-known clearnet clients, each bundling a peer ID prefix, the HTTP tracker User-Agent, and the BEP 10 extension handshake "v" string, with consistent version numbers across all three surfaces.
Spoofing is opt-in via the i2psnark.clientId property (empty to identify as I2PSnark, "random" to select a random profile per destination per run, or a profile name to always impersonate that client), optionally restricted to a subset via i2psnark.clientIds. Only clients recognizable by our own identification table are spoofable, so the console peers page keeps showing a real client name for our own IDs.
Version strings are pinned to upstream client releases verified as of 2026-08; bump them only when an upstream release changes the UA or "v" format, since point releases do not require updates. All three strings of a profile must carry the same version, as trackers may cross-check them.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classOne impersonatable client: peer ID prefix plus the matching tracker User-Agent and extension handshake "v" strings.Field Summary
Modifier and TypeFieldDescriptionstatic final ClientID.ProfileBiglyBT 4.1.0.0: no OS/Java suffix in either the tracker UA or handshake, matching the upstream config default.static final ClientID.ProfileDeluge 2.2.0 paired with libtorrent 2.0.13, announced in both strings.private static final StringJava version named in the client id.static final ClientID.ProfileKTorrent 26.04.3: Gear-era identity, both strings unverified against a capture.static final ClientID.ProfileLibtorrent 1.2.19: the last fully-authentic 1.2.x identity.private static final StringOperating system named in the client id.private static final List<ClientID.Profile> The known identity profiles, current one first.static final ClientID.ProfileQBittorrent 5.2.3: mixed-case "-qB5230-" prefix, no OS/Java suffix.private static final StringRandom tail charset for generated peer IDs, per the BiglyBT/Azureus convention.static final ClientID.ProfileTixati 3.44: dash-free "TIX34" peer ID; both strings unverified.static final ClientID.ProfileTransmission 4.1.3: slash-separated UA, space-separated handshake string.static final ClientID.ProfileVuze 5.7.7.0: Azureus-branded peer ID and tracker UA, plain "Vuze" handshake.Constructor Summary
ConstructorsMethod Summary
All MethodsModifier and TypeMethodDescriptionstatic ClientID.ProfileLook up a profile by name, case-insensitively.static StringgetClientName(String ch) The client name for a peer ID prefix, from the same table used to identify remote peers in the console.static ClientID.ProfilegetRandomProfile(Random random, List<ClientID.Profile> candidates) A random profile, optionally restricted to a candidate subset.static List<ClientID.Profile> parseCandidateList(String raw) Parse a comma-separated i2psnark.clientIds value into profiles, dropping whitespace, duplicates, and names that match no known client.static List<ClientID.Profile> profiles()All spoofable client profiles, unmodifiable.
Field Details
OS_NAME
Operating system named in the client id.JAVA_VERSION
Java version named in the client id.TAIL_CHARS
Random tail charset for generated peer IDs, per the BiglyBT/Azureus convention.- See Also:
VUZE
Vuze 5.7.7.0: Azureus-branded peer ID and tracker UA, plain "Vuze" handshake. The mismatch is authentic; version data verified against upstream releases and captures as of 2026-08.BIGLYBT
BiglyBT 4.1.0.0: no OS/Java suffix in either the tracker UA or handshake, matching the upstream config default.TRANSMISSION
Transmission 4.1.3: slash-separated UA, space-separated handshake string.KTORRENT
KTorrent 26.04.3: Gear-era identity, both strings unverified against a capture.DELUGE
Deluge 2.2.0 paired with libtorrent 2.0.13, announced in both strings. The libtorrent part should pair with a plausible bundled version.QBITTORRENT
QBittorrent 5.2.3: mixed-case "-qB5230-" prefix, no OS/Java suffix.LIBTORRENT
Libtorrent 1.2.19: the last fully-authentic 1.2.x identity. Real libtorrent 2.x uses a lowercase -lt prefix we do not recognize, so this profile pins 1.2.x instead.TIXATI
Tixati 3.44: dash-free "TIX34" peer ID; both strings unverified.PROFILES
The known identity profiles, current one first.
Constructor Details
ClientID
public ClientID()Constructor. The recognition table and the spoofing profiles are static, so an instance holds no state and every accessor here is static.
Method Details
getClientName
The client name for a peer ID prefix, from the same table used to identify remote peers in the console.- Parameters:
ch- the first four Base64 characters of the peer ID, i.e. the Base64 of its first three non-zero bytes- Returns:
- the client name, or null if unknown
profiles
All spoofable client profiles, unmodifiable.- Returns:
- an unmodifiable list of profiles, never null
getByName
Look up a profile by name, case-insensitively.- Parameters:
name- the profile name, e.g. "Vuze" or "qbittorrent"- Returns:
- the profile, or null if unknown
getRandomProfile
A random profile, optionally restricted to a candidate subset.- Parameters:
random- the randomness sourcecandidates- profiles to choose from; null or empty for all- Returns:
- one of the candidates, never null
parseCandidateList
Parse a comma-separated i2psnark.clientIds value into profiles, dropping whitespace, duplicates, and names that match no known client.- Parameters:
raw- the raw property value, may be null or empty- Returns:
- the recognized profiles in order, unmodifiable; empty if none