FrostWire 7.1.4 (build 337) is out. If you skipped 7.1.0 through 7.1.3, this is the one post that covers the whole series: what you will notice, what changed under the hood, and the numbers behind it.
Between April and November we shipped five desktop releases: 7.1.0, 7.1.1, 7.1.2, 7.1.3 and now 7.1.4. Together they carry 409 fixes and 68 new features, a new BitTorrent engine, and IceBridge, a peer-to-peer network that lets FrostWire users search each other directly, with no website in between.
If you only read one section
Search that no website can switch off. FrostWire now also asks other FrostWire users, over IceBridge, and shows their answers next to the web results as Distributed results. You can browse what a peer is sharing and download straight from them.
Far fewer freezes. About 160 of the 409 fixes remove a freeze or stutter, mostly on older and slower computers. Startup is lighter and steadier.
Fewer crashes. About 30 fixes target crashes and errors. In 7.1.4, FrostWire opens again on Macs running macOS 27, where it could crash at the splash screen.
Safer. The installers bundle OpenJDK 27.0.1.0.3, which fixes the severe vulnerabilities in Oracle’s October 2026 Java security advisory. You don’t need to install or update Java yourself. 26 fixes harden FrostWire against hostile input and network traffic.
A new BitTorrent engine. jlibtorrent 2.0.15.3 (from 2.0.12.7) fixes a data corruption bug, native memory leaks and DNS leaks.
For everyday users
Searching
Distributed results appear beside the usual ones. Seeding is publishing: only torrents you are actively sharing are ever served as results, and a setup page explains this. Answering catalog requests is on by default and you can turn it off.
Search results you already started downloading show a download arrow.
Bitsearch joins the search engines. Idope, which stopped working, is gone. TPB results now show up on slower connections, and archive.org gets 15 seconds to answer instead of 5.
Pasting a SoundCloud link, previewing a track and downloading it work in more cases, and a SoundCloud download that can’t start now shows an error instead of waiting forever.
Magnet links open correctly even when the name or trackers come before the hash.
Downloads and transfers
A transfer you paused stays paused after a restart. A removed transfer doesn’t come back.
Removing an unfinished transfer deletes its partial files.
Torrents that use only the new BitTorrent v2 format download only the files you picked and survive a restart.
Transfer Detail > Pieces: click a piece to set its priority (Don’t Download, Low, Normal, High). Want to preview a video before the rest arrives? Set its first pieces to High.
Create Torrent was rebuilt: drop a file or folder on the dialog, set private torrents, a comment, tracker tiers and more. Large folders no longer freeze it.
YouTube video downloads fetch the matching audio and merge it. On macOS they start instantly instead of after about 9 seconds.
IP Filter: block lists in P2P, DAT, CIDR and Hosts formats now really block. A bug had been adding ranges as allowed.
Windows
Text is sharp again at display scaling above 100%.
No more multi-second freezes waiting on the graphics driver.
FrostWire.exe is signed by FrostWire LLC.
Starting FrostWire on slow PCs no longer hangs the window.
macOS and Linux
FrostWire starts on Macs missing the Lucida Grande font and on macOS 27 (7.1.4).
“Show in Finder” can no longer be tricked by a crafted file name.
A Linux search box no longer freezes for seconds waiting on the clipboard.
For advanced users
IceBridge. A peer-to-peer proxy network over UDP. Messages are signed, nodes relay for each other across several hops, and every message names the protocol it carries, so services beyond search can join later. Each install has an Ed25519 identity, backed up as a 24-word BIP39 phrase (Options > Identity). Nodes find each other through the BitTorrent DHT. Tools > IceBridge Console shows traffic live. Traffic is signed but not yet encrypted; end-to-end encryption is planned next.
Karma. When a download from a Distributed result finishes, your node endorses the sharer. Endorsements are signed, chained, rate limited and anchored to a Bitcoin block six deep that two block explorers agree on. Since 7.1.3, a peer’s karma counts the endorsements it receives, weighted by how much your node trusts the endorser, and an endorsement counts only for a torrent that peer shared itself. Karma is young, so treat it as a hint.
Identity hardening. Handshakes can’t be replayed, peers you only heard about from another peer are not trusted until verified, and every identity carries a small proof of work, so faking identities in bulk costs real computation.
Engine. jlibtorrent 2.0.15.3 carries the libtorrent fixes from 2.0.13 to the unreleased 2.0.16 and OpenSSL 4.1.0. Fixed: a memory-mapped storage corruption bug, short reads on Windows, stuck trackers after pause, wrong seeding times, web seeds for single-file torrents. Every decoded torrent, magnet, resume file and DHT message used to leak a native copy (100,000 parses of a 13.5 KB torrent leaked 1.7 GB; now flat). JNI calls moved data byte by byte; moving 1 MB into libtorrent went from 6 ms to 0.4 ms. Torrents with emoji in file names download with correct names.
MCP server. AI agents can search, download and manage IceBridge. Streams, session setup, error replies and restarts were fixed so stricter agents work.
Fuzzing. 42 fuzz harnesses (from 0) feed malformed input to the parsers for MP3, MP4, torrents and search results. They found crashes and runaway memory use, all fixed.
Memory. FrostWire now uses up to a quarter of your RAM (minimum 512 MB, maximum 4 GB) instead of a fixed 512 MB.
How we found the freezes
Since 7.1.0, FrostWire sends anonymous reports when its window stops responding for a few seconds or hits an error. They hold no personal data: where in the code the time went, Java and OS versions, memory use. Each report became a GitHub ticket and a fix with a test that fails without it. Since 7.1.3 the reports also say which version is running and whether a run hit an error, using a random number made at launch and never stored. There is no installation or user ID. 7.1.4 adds how long FrostWire had been running, whether startup warm-up had finished and how busy the computer was, so a slow machine isn’t mistaken for a FrostWire bug.
7.1.3 sent 219 reports over its first weekend, grouped into 38 distinct problems. All were triaged and 7.1.4 fixes 36 of them. One macOS 27 font problem alone caused 165 of those reports.
By the numbers
Since 7.0.4
Count
Fixes in the changelog
409
…of which UI freezes and stutters
about 160
…of which crashes and errors
about 30
…of which security hardening
26
New features
68
GitHub tickets closed
242 (113 UI freezes, 29 crashes, 22 found by fuzzing)
Commits
2,842
Test classes (desktop, shared and Android)
44 to 652
Fuzz-testing harnesses
0 to 42
Freeze and crash counts are grouped from the changelog’s wording, so treat them as close, not exact.
Release
Date
Focus
7.1.0 build 332
Oct 10
IceBridge, distributed search, new engine
7.1.1 build 333
Oct 15
Crash and Linux freeze fixes, SoundCloud HLS, richer freeze reports
7.1.2 build 334
Oct 25
Java security update, Windows sharpness and graphics freezes
7.1.3 build 336
Nov 7
Karma overhaul, Pieces priorities, MCP, many freeze fixes
7.1.4 build 337
Nov 10
macOS 27 fix, startup on slow PCs, 36 fixes
Written 100% with AI
Every line of code in the 7.1 series was written by AI coding agents, directed and reviewed by the FrostWire team. Most commits name the model that wrote them, and in the last weeks most of the work, including all of 7.1.4, was done with Anthropic’s Claude Opus 5.5.
Get FrostWire 7.1.4
Download it now for Windows, macOS and Linux from frostwire.com/download. The in-app update is rolling out gradually, so you may not see it right away. The full list of changes is in the changelog, the code is on GitHub, and the 7.1.4 release notes are here.
FrostWire stays free, with no ads and no bundled software. If it is useful to you, chip in: donations buy the compute that finds and fixes these problems.
Keep seeding: on IceBridge, what you seed is what other people find.
FrostWire 7.1.0 for desktop turns Distributed Search into something you can rely on. Your computer can now find torrents that other FrostWire users are sharing, browse everything a person shares, and download straight from them, all without a central server. It also brings YouTube downloads with sound, a smarter search, a new identity and backup screen, and a long list of security and stability fixes.
What’s new
Distributed Search that finds more, faster
FrostWire users now form a network that searches together. Your search reaches computers and phones that only share files (and don’t help relay searches for others), which were previously missed. Results are signed by the person sharing them, answers from the mesh follow the live connection when a phone changes network, and the app stays responsive even when the network is busy. Finding the network is faster and more dependable too: FrostWire checks the dedicated IceBridge servers first, tries many peers at once instead of one by one, remembers which ones are dead, and always knows one built-in server to fall back on. Computers on the same home or office network now find each other directly, even though a router will not let them connect through their shared public address.
Browse what other people share
Right-click a Distributed Search result and choose Browse Shared Torrents to see everything that person is sharing, then download any of it straight from them. Results from people who share their catalog also show a Browse icon in the Actions column, so you do not have to find the menu. You can also open it from Tools > Browse Shared Torrents. The icon appears for results from peers running FrostWire 7.1.0 or Android 3.2.2 or newer.
A new page in the setup wizard explains that seeding a torrent makes it discoverable on the BitTorrent network, and gives you two separate choices, both on by default:
Join the IceBridge network. You can use Distributed Search, and people searching can find the torrents you are actively seeding by keyword, whether or not you share your catalog.
Share my catalog. People can browse everything you are actively seeding, and crawlers can index it. This is only available while you are on the network.
Only torrents you are actively seeding are ever shared. Your download history, paused transfers and private torrents are never published. You can change either choice in the setup wizard or in Tools > Options > IceBridge.
YouTube videos now play with sound
Videos that YouTube serves as separate video and audio streams are now downloaded together and merged automatically, so what you save has sound. If something goes wrong, you still keep the silent video.
Smarter search
Search now also matches file names inside a torrent, so looking for readme.txt can find torrents that don’t mention it in their title.
Bitsearch joins the list of search engines.
Seeds and Size columns now sort as numbers (436 seeds ranks above 64).
The dead Idope engine was removed and the default tracker list was refreshed with trackers that actually respond.
Your identity, with a backup you can write on paper
Options > Identity shows your node ID, karma and shared torrents, and lets you back up your identity as a 24-word recovery phrase, restore it, and export or import the identity file. New Karma, Peers and Shared Torrents screens show what the network knows about you and your neighbors.
Tools for power users
Tools > IceBridge Console: a live, filterable log of what the distributed search network is doing.
The built-in MCP server (off by default, and it only listens on your own computer) can now observe and control IceBridge, so AI assistants can inspect peers, metrics and your local index.
Transfer details can recheck local data with a progress bar, toggle sequential download, and add trackers safely.
The IP Filter now understands P2P, DAT, CIDR and Hosts block lists, including ZIP files.
Powered by jlibtorrent 2.0.12.9, with new NAT-PMP and multiple-connection controls in Advanced BitTorrent settings.
Meet IceBridge: the network layer under Distributed Search
7.1.0 is the first desktop release where FrostWire talks to other FrostWire users directly through IceBridge, a small peer-to-peer network layer built into the app. If BitTorrent is how files move, IceBridge is how FrostWire users talk to each other about them.
What it does. Every install gets its own cryptographic identity (the one you can back up with a 24-word phrase). IceBridge uses that identity to open authenticated, reliable connections over UDP with other FrostWire users, finds them through the BitTorrent DHT (no central server), the local network, and a short list of servers it already knows, and keeps working for people behind routers and phone networks by letting willing peers help each other connect. Desktop computers and the Android app (3.2.2) join the same network.
Where it sits. IceBridge sits underneath search and on top of the networking you already use:
FrostWire (search window, downloads, transfers)
|
Distributed Search -- signed questions and answers about torrents
|
IceBridge -- identity, peers, routing, delivery
|
UDP + BitTorrent DHT
IceBridge never looks inside the messages it carries, and it never moves your files; BitTorrent still does that. Distributed Search is simply the first thing built on it. Alongside search, it already carries the small “who has what” summaries that make routing smart, and the shared-torrent catalogs that power Browse Shared Torrents.
You are in control. IceBridge can be turned off in the settings, you choose whether your active seeds can be browsed, and your download history is never shared. Its local control interface only listens on your own computer and requires a secret token. Power users can also run IceBridge on their own server as a standalone forwarder to help the network (see ICEBRIDGE.md in the repository).
Where it could go. Because IceBridge is deliberately generic, each kind of message is labeled with a protocol number, and the code already reserves slots for things such as chat between peers, publish/subscribe channels, exchanging torrent metadata, file synchronization, node health reports, and AI-assisted tools. These are ideas we are exploring, not promises or dates. The point is that new peer-to-peer features can be added without building a new network each time, and without a company’s servers in the middle.
Compatibility, ports and firewalls
For network admins, hackers and anyone running a strict firewall:
Peers are verified over UDP. Peers used to be checked on a separate TCP “identity port”. They are now verified with the same authenticated rUDP handshake the network already uses (Ed25519 keys), so a peer that can be reached over UDP can be found, and no inbound TCP port is needed. The identity port setting is gone. Older versions (desktop 7.0.x and earlier, Android 3.2.1 and earlier) only announce a TCP port, so they and 7.1.0 / Android 3.2.2 do not discover each other through the DHT. Please update both.
UDP mesh port. Each install picks its own UDP port automatically (setting ICEBRIDGE_RUDP_PORT, 0 means automatic) so several computers behind one router no longer fight over 6889, and announces the real port on the DHT. Standalone forwarders and the built-in seed use UDP 6889.
Built-in seed.virginia1.frostwire.com:6889 is always tried when looking for the network. Override it with -Dfrostwire.icebridge.seeds=host:port,... (an empty value disables it).
LAN beacon. Every 10 seconds FrostWire multicasts its rUDP port to 239.255.70.88, UDP 6890, and listens for other nodes. Only private IPv4 senders are believed, nothing is ever answered, and every address it finds still has to pass the rUDP identity handshake before it is trusted. Android 3.2.2 does the same on Wi-Fi.
Local control API. The IceBridge control HTTP port listens on 127.0.0.1 only and requires an X-IceBridge-Token header on everything except /health.
Firewalls. The installers do not add firewall rules. If a firewall blocks inbound UDP, allow FrostWire’s UDP port so other people can reach you; outgoing connections work either way. On a server running a standalone forwarder, open UDP 6889.
Debugging. Use Tools > IceBridge Console or the control API /metrics endpoint. Standalone forwarder setup is in ICEBRIDGE.md in the repository.
Security and safety
This release includes a broad security hardening pass over the distributed search network:
Signatures: signed search results now also cover the matched file name, which a man-in-the-middle could previously alter. Responses and registrations use length-prefixed canonical forms.
Authentication: the local control interface needs a secret token; unauthenticated rUDP application packets are rejected; relayed messages and hole-punch requests need an authenticated session that matches the claimed sender.
Replays and abuse: rUDP handshakes carry a timestamp and stale ones are rejected, a timestamp-skew bypass was fixed, ingress is rate-limited before any signature is verified, sessions are capped (including per /24), and servers rate-limit abusive peers and catalog browsing per verified requester.
Denial of service: a crafted fragment index that could force a multi-billion-iteration loop was fixed, oversized or truncated payloads are rejected, HTTP bodies are capped (16 MB for search, 32 MB for torrents), and search results and queries are validated and sanitized.
IP filter: block lists that were silently being allowed now really block (#1291).
TLS: hostname checks use suffix matching instead of substring matching.
Debug ports: release builds no longer expose JMX or JDWP listeners.
Privacy: crawler data stays anonymous; presence is stored as hashed endpoints and catalogs by publisher peer id only, never IP addresses.
Fixes you may notice
macOS: the app no longer crashes at startup when an old link handler fails to load, rich file icons are back, file icons no longer stall the window, VPN detection no longer reports a VPN that is off, and installers now sign the embedded networking libraries, so they pass Apple’s checks.
Linux (Wayland): opening the Transfers tab no longer freezes or crashes the app.
Torrents: restarting no longer restores torrents at 0%, files you share from a finished download are saved correctly, and sharing a file that no longer exists is refused with a clear message.
Transfers: buttons stop flickering, rows refresh only when they change, and the Files tab keeps your selection and shows live progress.
Translations: the new screens and the setup wizard are translated into most of our 57 languages. Fourteen (Breton, Persian, Finnish, Irish, Galician, Hungarian, Icelandic, Lithuanian, Macedonian, Maltese, Norwegian Nynorsk, Punjabi, Slovak and Serbian Latin) still show the new text in English. Translators are welcome.
Many other search, YouTube and IP Filter reliability fixes. See the full list below.
By the numbers: how this release got built
7.1.0 is also the product of a very different way of working. Since 7.0.4 (April 20, 2026), the shared common and desktop code was developed by one maintainer directing AI coding agents, with an automated test suite as the referee. Figures below cover only common/ and desktop/ (the Android app has hundreds more commits of its own) and come straight from the git history.
Period
Apr 20 to Oct 8, 2026 (170 calendar days)
Days with commits
83 (about every other day)
Commits
1,077 (about 13 per active day, 6 per calendar day)
Code added (Java, Kotlin, Gradle, scripts)
~127,900 lines written, ~37,800 removed along the way
Code in the final diff
+104,600 / -14,500 lines, +90,100 net
Of which tests
~38,500 lines, 203 new test classes, about 1,370 new tests
New Java files
408
Documentation and plans
~7,900 lines of Markdown/text added
Translations
61 language files refreshed
Average output
about 1,100 net lines per active day (about 530 per calendar day)
Who wrote it. About a third of the commits (366) carry the name of the model that did the work in their message. The ones that say so: DeepSeek V4.1 Flash (185 commits), Grok 4.6 (51), Grok 4.7 (36), GPT-6 Sol (30), Claude Sonnet 5.5 (23), Muse Spark 1.3 (21), GPT-6.1 Sol (17), and GPT-6 Luna (3). The rest were committed without a model label. Model credits were recounted on October 10, after we corrected some commit labels that had been copied from older commits; the other figures in the table were measured on October 8. The maintainer chose what to build, reviewed the results, and used the 1,400-test suite and the CI builds to decide what was good enough to keep.
How much human work is that? The commit timestamps cluster into about 135 to 160 working sessions, roughly 135 to 185 hours of active work over the whole period (about two hours per active day). That is a lower bound, since agents think and run tests between commits, but it is the time a person was actually in the loop.
To estimate what the same result would cost without the agents, we used a deliberately generous rate for careful, tested, security-sensitive protocol code: 100 to 200 finished lines of code per developer per day. At that rate, 104,600 lines is about 520 to 1,050 developer-days, or roughly 4,200 to 8,400 hours, which is 2 to 4 developer-years, before design docs, reviews, and the translations. Compared with 135 to 185 hours of actual work, that is something like a 20x to 60x speedup.
These are estimates, not measurements, and lines of code is a blunt tool: many of those lines are tests and mechanical changes, and the rate varies a lot between developers. But the direction is not subtle. A distributed, signed, NAT-traversing search network with a full UI, a security pass, and a test suite used to be a multi-year, multi-person project. This time it shipped in under six months.
Installers for macOS (Intel and Apple Silicon), Linux (x86_64 and arm64) and Windows are attached below.
Full changelog
new:Computers on the same network find each other — nodes multicast their rUDP port on the LAN, since the public address the DHT reports cannot be reached from inside the same router
new:Distributed search results from peers that share their catalog show a “Browse Shared Torrents” icon in the Actions column, so browsing a peer’s catalog no longer depends on discovering the right-click menu
new:Browse the torrents a peer shares — right-click a Distributed search result whose holder allows crawling (“Browse Shared Torrents”) to list everything that peer is sharing, download any of it straight from that peer, or copy its magnet; also available from Tools → Browse Shared Torrents and the IceBridge Console
fix:The “Seeding & Publishing” setup page and Tools > Options > IceBridge now separate two choices: joining the IceBridge network (you can search, and anyone searching can find the torrents you are seeding by keyword, whether or not you share a catalog) and sharing your catalog (people can browse everything you are actively seeding and crawlers can index it); unchecking the catalog no longer reads as hiding from search, and sharing the catalog is disabled while you are off the network
new:Seeding is publishing — a new setup-wizard page explains that seeding a torrent makes it discoverable on the BitTorrent network, and lets you opt out (on by default) of having the torrents you are actively seeding browsable by the network’s crawlers
fix:Peers are now verified over rUDP instead of a TCP identity port, so a peer behind NAT that can be reached over UDP can be found; the DHT announces the rUDP port, servers and phones no longer need an open TCP port, and the “Relay listen port (identity)” setting is gone (peers on older versions that only announce a TCP port are not discovered)
new:IceBridge distributed search architecture — FrostWire now launches a local IceBridge daemon (standalone rUDP relay servent) that provides a reliable, fragmented, authenticated mesh transport between peers. The DistributedSearchPerformer sends signed search requests through the daemon’s HTTP control API; the daemon routes them over rUDP to remote peers’ daemons, which process them and send signed responses back. A single poller thread drains the daemon’s /poll endpoint and dispatches payloads to all registered listeners
new:YouTube video downloads now play with sound — DASH video-only rows auto-fetch a hidden m4a/Opus sibling and merge it (pure-Java MP4 restitch or WebM remux, same-container pairs only); sibling fetch retries with resume on throttled connections; any failure keeps the silent video
new:Tools → IceBridge Console — a live, filterable IceBridge/distributed-search event log (filter by level, category, text, or peer; pause, clear, save, copy)
new:Identity settings screen (Options > Identity) — displays node ID, fingerprint, public key, identity difficulty (leading zero bits), karma score, and shared torrent count. Buttons: Show Seed Phrase (24-word BIP39 mnemonic with copy-to-clipboard), Restore from Seed Phrase, Export Identity File, Import Identity File, Copy Fingerprint. Restore and import create a .bak backup before overwriting and trigger a restart
new:BIP39 mnemonic support for identity backup — com.frostwire.crypto.Bip39Mnemonic encodes/decodes the 32-byte Ed25519 seed as a 24-word mnemonic using the standard BIP39 English wordlist with SHA-256 checksum. Enables offline paper backup of FrostWire identities
new:Identity settings — Initialize Identity button with off-EDT proof-of-work mining (progress bar) and restart; import/restore/export now use the same libtorrent/identity.dat path as the relay stack
new:The MCP server now exposes IceBridge observability and control — logs query/tail/clear, relay metrics, peer list/remove/block, local index list/search, digest status, host-cache list/ping/add, remote relay logs, MCP status/control, and IceBridge settings via settings get/set
new:File-level search indexing — individual file paths within torrents are now indexed in a separate shared_files FTS5 table, enabling search matches on file names (e.g. “readme.txt”) even when the torrent name doesn’t contain the query. Search results that match on a file path populate the matchedFile field, surfaced as the result filename in the UI
new:Local search (and remote answers from this node) only return actively seeded/swarming transfers with full metadata by default — historical LocalIndex rows excluded unless Options → Shared Torrents Database → “Include inactive / historical shares” is enabled
new:Bitsearch added as a new REST-API torrent search engine (bitsearch.eu) — clean JSON, 200 free requests/day per IP, magnet links built client-side from DefaultTrackers. No crawling, replaces the gap left by the Idope removal
new:IP Filter now supports multiple block list formats — P2P, DAT, CIDR, and Hosts formats are auto-detected and parsed. ZIP archives are now supported alongside existing GZIP decompression. Extracted format readers into separate classes (P2PIPFilterInputStreamReader, DatFilterInputStreamReader, CidrFilterInputStreamReader, HostsFilterInputStreamReader) with shared IPFilterFormat enum
update:jlibtorrent to 2.0.12.9 with libtorrent RC_2_0 cb6fe6b9c (86 commits ahead of previous) — includes tracker URL validation hardening, SOCKS5 parsing fixes, resume-data sanitization, peer encryption improvements, symbolic link support (BEP 47), and 4 new Java APIs (natpmpGateway, allowMultipleConnectionsPerPid, natpmpLeaseDuration, pieceSizeForReq). OpenSSL upgraded to 3.6.0. Build now requires -frtti flag across all platforms due to upstream dynamic_cast in smart_ban.cpp
fix:Distributed search finds the IceBridge servers again — discovery probed DHT candidates one at a time and ran out of its 15 second budget on unreachable phones, so no peer was ever registered; probes now run in parallel, known and bootstrap servers go first, and dead endpoints back off so later passes reach the rest of the list
fix:The DHT bootstrap topic, where the dedicated IceBridge servers announce, is always queried first instead of only when the crowded relay and peer topics are empty
fix:Known IceBridge servers are retried even if they never answered before, a built-in seed server is always tried, and the Settings host ping verifies servers like discovery does instead of with a request they reject (which evicted healthy hosts)
fix:The IceBridge helper process no longer announces on the DHT with port 0, which republished our identity with a useless port and filled the shared topics with unreachable endpoints
fix:Results from peers that share their catalog are marked browsable again when a search returns more than a handful of results — the browsable flag was lost when larger result sets were streamed back in chunks, so only small answers showed the Browse Shared Torrents action
fix:Packaged desktop builds retain the IceBridge metrics used by the search transport, preventing distributed search startup from failing with a missing class; regression tests load the real application JAR without the daemon JAR
fix:Desktop IncomingSearchRequestHandler now receives LocalIndex so catalog browse works (parity with Android)
fix:Distributed search and relay responses follow live rUDP sessions after cellular NAT rebinding instead of stale registry endpoints
fix:Desktop clients now choose an automatic IceBridge UDP port instead of all using 6889 behind the same router; identity records and mesh registration advertise the actual bound port, supervised restarts retain it, and unknown peer ports are never guessed from our own port
fix:Distributed search now reaches peers that share content but do not relay (leaf/CLIENT nodes) — their published keyword fingerprint was being dropped by forwarders, so searches reached them only by fan-out luck and their torrents looked missing
fix:Distributed search and the relay stay responsive under heavy search traffic — rUDP packet processing is handed off the socket event loop, response delivery runs on a bounded lane, and concurrent torrent-metadata fetches are capped instead of exhausting threads
fix:IceBridge child supervision prevents orphan processes and preserves distributed search/TORRENT_FETCH across crashes and restarts
fix:Linux/Wayland startup no longer freezes or crashes when opening the Transfers tab — Java2D was forced onto the legacy software X11 pipeline, where on-screen icon and text blits are ~1000x slower; rendering now uses the XRender pipeline, which is fast and stable under XWayland
fix:JDK 26 HTTPS requests no longer fail after IceBridge identity initialization; Bouncy Castle is kept scoped to identity crypto instead of overriding the JVM-wide XDH provider
fix:macOS startup no longer crashes when the legacy libGURL JNI handler fails to load; magnet URLs use the Java Desktop OpenURIHandler included since Java 9, and obsolete libGURL code and binaries were removed
fix:Restored torrents stop landing at 0% — the session .torrent and its .resume sidecar now share one canonical hash (they used v1 vs v2), and restore heals installs written with the old mismatched names
fix:Born-complete torrents (per-file Share, auto-seed) now persist resume data at check completion and on every forced save — restarts no longer restore them under the default data dir at 0%
fix:Missing resume files are backfilled when a torrent is constructed, covering zero-piece torrents that never trigger a check
fix:Session .torrent files are ensured alongside resume data so magnet-origin torrents survive restarts instead of vanishing from restore
fix:SearchManager no longer cancels all global HTTP requests on stop — OkHttpClientWrapper.cancelAllRequests() was nuking non-search HTTP traffic (updates, FrostClick). Stopped performers now abort via the ‘stopped’ flag
fix:SearchMediator onResults IndexOutOfBoundsException — results.get(0) without null/empty check crashed the executor thread when a performer called onResults([])
fix:macOS installs ship icebridge.jar beside frostwire.jar and both jars’ native libraries are signed; frostwire.jar no longer duplicates daemon-only IceBridge classes
fix:Packaged JARs preserve dependency licenses without file/directory name collisions on case-insensitive filesystems, allowing macOS notarization to unpack embedded native libraries
fix:Idope search engine removed from commons, desktop, and android — idope.pics now requires TLS 1.3 and was failing handshakes on macOS arm64 and other TLS-1.2-only stacks. Removed IdopeSearchPattern, createIdopeTorrentSearch, SearchEngineID.IDOPE_ID, IDOPE_SEARCH_ENABLED, PREF_KEY_SEARCH_USE_IDOPE, all 39 localized use_idope strings, the android settings entry, and the desktop MCP engine registry. Added IdopeRemovalTest regression suite
fix:Standalone IceBridge forwarders launch with DHT and bootstrap discovery enabled, while release packages include icebridge.jar
fix:TORRENT_FETCH returns holder-signed full torrent metadata through EC2 relay hops, including piece layers for hybrid torrents
fix:The crawler sharing setting now gates both mesh browsing and DHT catalog publication; opting out withdraws the previous catalog, and only active non-private seeds are listed while ordinary distributed search still finds active downloads
fix:Only torrents you are actively seeding are shared with catalog crawlers — previously downloaded torrents that are not seeding are no longer published
fix:Crawler data stays anonymous — presence is stored as hashed endpoints and catalogs by publisher peer id only (never IP addresses)
fix:CRITICAL: matchedFile excluded from RemoteSearchResponse canonical bytes — Ed25519 signature did not cover the matched file path, allowing MITM tampering. Now included in appendRowBencode as “mf” key
fix:IP Filter critical blocking bug — add_rule() was passing flags=0 (allow) instead of ip_filter.access_flags.blocked.swigValue()=1, so blocked IP ranges were silently allowed through libtorrent (#1291) — caught by new IPFilterBlockingTest regression suite
fix:TLS hostname verification now uses proper suffix matching instead of substring contains — prevents attacker-controlled hostnames from matching whitelisted domains
fix:Timestamp-skew bypass via Math.abs(Long.MIN_VALUE) — Math.abs(Long.MIN_VALUE) returns a negative value, bypassing the >60s skew check in registration and response verification. Replaced with manual sign flip
fix:rUDP HELLO replay prevention — 8-byte Unix timestamp added to the signed message. HELLOs with timestamp skew > 300s are rejected (104-byte format only)
fix:IceBridge control API requires auth token (X-IceBridge-Token header) on all endpoints except /health — 32-byte random hex string generated at startup
fix:RegisterRequest canonical string uses length-prefixed fields to prevent delimiter injection
fix:RudpPacketCodec silent payload truncation — payloads >65535 bytes silently truncated the 2-byte length field, corrupting framing. Now rejected before encoding
fix:rUDP hole-punch requires authenticated session — unauthenticated peers can no longer trigger amplification
fix:rUDP binds to 127.0.0.1 for local daemon profile — was 0.0.0.0, exposing unauthenticated handlers to the internet
fix:rUDP max sessions cap (256) — prevents memory exhaustion from unbounded session creation
fix:HTTP response body size capped at 16 MB (search) and 32 MB (torrent downloads) to prevent OOM from malicious or misconfigured servers
fix:SearchMediator search query sanitization — control characters stripped and query length capped at 1024 characters before dispatching to performers, preventing injection into URL templates, regex patterns, and JSON request bodies
fix:matchedFile length validation (max 4096 chars) in DistributedSearchPerformer and LocalSharedTorrentSearchPerformer — rejects pathologically long values from malicious remote peers
fix:DistributedSearchPerformer validates search result row fields — name max 2048 chars, infoHash must be 20 bytes, per-row try/catch prevents NPE from malformed responses
fix:IncomingSearchRequestHandler rate-limits per source to 30 requests/minute
fix:IncomingSearchRequestHandler rate-limits catalog browse by verified requesterPub after signature check (not transport sourcePub); search rate-limit owned by RelaySearchService
fix:FragmentReassembler DoS vulnerability — DATA_END with fragIndex=Integer.MAX_VALUE forced a 2-billion-iteration loop; assemble() had int overflow causing NegativeArraySizeException that killed the rUDP channel. Added MAX_FRAGMENTS_PER_GROUP (4096), MAX_ASSEMBLED_SIZE (16MB), and long accumulation
fix:IceBridge P0 hardening — cheap-reject-first ingress (rate-limit before Ed25519 verify), per-IP + global HELLO budgets, per-/24 session caps, empty HELLO_ACK removed; helloRejected/relayRateLimited/searchRateLimited/powRejected/spamMarkedDropped counters in /metrics
fix:IceBridge rejects unauthenticated rUDP application packets and applies backpressure instead of acknowledging messages that could not be delivered
fix:IceBridge mesh security — HELLO_ACK carries signed identity so initiators learn remotePub (fixes rejected multi-hop RELAY); RELAY_RESPONSE requires authenticated session (no fire-and-forget spoof); RELAY app payload capped to single rUDP fragment; hop TTL default 3; mesh fan-out 3; per-peer RELAY rate limit; local registry targets delivered via /poll without self-UDP
fix:Desktop release distributions no longer expose unauthenticated JMX or JDWP listeners
fix:IceBridge rUDP and relay TCP listeners now default to bind 0.0.0.0 (publicly reachable). Desktop bind host default changed from 127.0.0.1; IncomingRelayServer now supports explicit bind host (used by IceBridgeServer with config.host()).
new:Transfer Detail Files row context menu now offers Share for completed files, creating and seeding a torrent from that file (same behavior as the row’s share button)
new:Transfer Detail General tab offers Check Local Data and a per-torrent Sequential download toggle; Trackers menu offers Add Tracker with strong URL validation, and Edit Trackers now trims entries and names the offending line
new:Transfer Detail Check Local Data disables while the recheck runs and swaps in a progress bar with live phase and percent, then reports the outcome
new:Advanced BitTorrent settings now expose jlibtorrent 2.0.12.9 controls for NAT-PMP gateway override, NAT-PMP lease duration, and allowing multiple connections from the same peer ID
new:icebridge:// URL protocol handler — handles URLs of the form icebridge://<peer_pubkey_hex>/. Commands: /browse (fetch and display peer’s shared torrent catalog from DHT), /search/ (send a signed search request to a specific peer), /info (show peer details from PeerDirectory or DHT identity record). Integrated into the search bar — typing an icebridge:// URL triggers the handler instead of a normal search. Clipboard monitoring for icebridge:// URLs
new:About window shows the current Telluride build number
new:Transfers default columns — Actions, Name, Seeding, Size, Status, Progress, Down Speed, Downloaded, Uploaded, Up Speed, Time, Seeds; Tips/Donations hidden, Uploaded shown (existing custom layouts untouched)
new:Karma settings screen (Options > Karma) — displays own karma chain status (current epoch, available endorsement energy, total endorsements given, karma score) and a top-peers-by-karma leaderboard (top 20, with score, endorsement count, last-endorsed timestamp). Right-click to copy peer public keys
new:Peer directory settings screen (Options > Peers) — shows all known peers in a table with public key, hostname, uTP port, trust score, verified/spam status, endorser count, and last-updated time. Right-click to copy key, block (mark as spam), remove, or browse the peer’s shared torrents catalog (fetched via DHT BEP 46 using RemoteIndexFetcher)
new:Shared torrents database viewer (Options > Shared Torrents) — browse the local shared torrents index with search, showing name, size, file count, info hash, publisher key, timestamps, and matched file. Right-click to copy info hash, copy magnet link, or copy publisher key
new:IP Filter table right-click context menu with Edit and Remove actions — edit opens the Add Range dialog pre-populated with the selected range’s values, remove deletes the range and rebuilds the IP filter and BTEngine
new:IP Filter panel description now lists supported file formats (.p2p, .dat, .cidr, .hosts) and compression types (.gz, .zip)
new:Added MCP auto-configuration support for Grok Build in the shared AgentDetector / AgentConfigWriter (common module). Grok is now detected via grok binary in PATH + ~/.grok/config.toml presence. “Configure” writes a native TOML entry under [mcp_servers.frostwire] with url + enabled=true using the HTTP/Streamable transport. This allows direct MCP connection from Grok Build TUI to the local FrostWire MCP server (port 8796 by default).
update:Share dialog posts to X (x.com) with an X icon instead of the retired Twitter branding
cleanup:Local search is diagnostic only (default off) — same LocalIndex path as inbound IceBridge answers; peer discovery is Distributed Search
fix:IP Filter persistence restored (#1291) — jlibtorrent session state does not persist ip_filter across restarts, so custom ip_filter.db persistence is required
fix:IP Filter ip_filter.db corruption root cause (#1291) — atomic writes with synchronized access prevent concurrent corruption during import and clear operations
fix:IP Filter ip_filter.db hardened against corruption (#1291) — version-byte validation, break on bad entries, graceful recovery when loading a damaged database
fix:IP Filter options pane now visible on Java 26 (#1291) — made IPFilterPaneItem constructor package-private and added setAccessible(true) in OptionsPaneFactory to prevent IllegalAccessException when creating pane items via reflection
fix:IP Filter pane duplicate settings key crash (#1291) — made IPFilterTableMediator.getInstance() thread-safe (synchronized+volatile), guarded IPFilterPaneItem.initOptions() against mediator creation failures with ipFilterTable null check, and made OptionsPaneManager.show() cache panes before initOptions to prevent infinite re-creation loops
fix:IP Filter DataLine creation on Java 26 (#1291) — added setAccessible(true) in BasicDataLineModel.createDataLine() to allow reflection access to DataLine constructors across package boundaries
fix:IP Filter edit disappearance bug (#1291) — fixed off-by-one in BasicDataLineModel.refresh() causing edited rows to vanish from the table after an edit
fix:IP Filter robust db loading + Import button disabled when empty (#1291)
fix:IP Filter disabled tooltips on table to prevent macOS Input Method EDT freeze (#1291)
fix:IP Filter HTTP errors now shown in panel + blocklist site links added (#1291)
fix:IP Filter JNI calls moved off EDT to background threads to prevent UI stalls (#1291)
fix:IP Filter JPopupMenu background theming on dark themes (#1291)
fix:Hybrid torrents use their metadata v1 hash consistently in the shared index and transfer lookup; successful canonical indexing removes only metadata-proven truncated-v2 duplicates
fix:YouTube audio muxing and other HTTP post-processing finish before automatic torrent creation or sharing, so the seeded torrent describes the final file; cancellation and failed-mux fallback are covered by completion-order regressions
fix:ThreadPool stack size increased from 4 KB to 512 KB — the previous 4 KB stack was far below the JVM default and caused StackOverflowError on deep call chains
fix:Sharing a file that no longer exists on disk is refused with a clear error instead of creating a torrent that can never complete
fix:VPN detection false positive on macOS — system utun interfaces (iCloud, Back to My Mac) were falsely detected as active VPN tunnels even when VPN was off, because they match the “utun” interface name pattern. Now validates that utun interfaces have a real routable IPv4 address before counting them as VPN. Also added “vpn” to interface name checks for broader VPN detection coverage
fix:HTTP search responses now check for 4xx/5xx error codes before returning the body — Cloudflare challenge pages and rate-limit responses are no longer passed to parsers as if they were valid search results
fix:DHT peer discovery ConcurrentModificationException — snapshot TcpEndpoint lists from dhtGetPeers before iterating (jlibtorrent alert threads can mutate live lists)
fix:MCP streamable HTTP handshake for Grok + other agents: notifications/initialized now returns 202 Accepted + “accepted” body (text/plain) + data: accepted on SSE stream. No initial data on GET SSE open. Allows grok mcp doctor frostwire (and rmcp-based clients) to complete connect instead of hanging on “Sse(session)”.
fix:YouTube search returns both best video and best audio streams, including muxed-only responses
fix:Newly created YouTube/HTTP torrents are indexed immediately after auto-seeding
fix:Search result table Seeds and Size columns now sort numerically — clicking Seeds ranks 436 above 64; previously sorted lexicographically as strings or by relevance score instead of seed count
fix:Default tracker list in TorrentUtil, CreateTorrentDialog, and UrlUtils updated to 16 trackers that responded to a BEP 15 connect_request probe on 2026-06-08 — removed 6 dead trackers (opentrackr, openbittorrent, exodus, moeking, explodie, coppersurfer) and added reliable replacements from ngosang/trackerslist per #1004. New DefaultTrackerListTest regression suite asserts all three files stay in sync
fix:SoundCloud default credentials refreshed to the values published at update.frostwire.com/android (client_id=A8wpv6WPWhcpz9BhiL66KfK8IHy6NLoz, app_version=1780910323) — pre-existing drift across SoundCloudConfigFetcher, SoundcloudSearchPattern, SoundcloudUtils, and SoftwareUpdater fallbacks now also aligned
fix:shared_files_fts switched from external content FTS5 table (with triggers) to standalone FTS5 table with manual index management — external content “delete” triggers failed silently when rowids were reused, causing stale FTS entries
fix:INSERT OR REPLACE on shared_torrents orphaned shared_files rows — REPLACE assigns a new rowid, leaving old file rows unreferenced. Now pre-deletes old shared_files rows before the replace
fix:sanitizeFtsQuery now replaces non-alphanumeric separators (underscore, dot, dash, slash) with spaces instead of dropping them — prevents mismatch between FTS5 tokenizer (which splits on these chars) and the query sanitizer (which was concatenating tokens like “real_file” into “realfile”)
fix:Knaben search query JSON now properly escaped via Gson
fix:Metadata-less magnets are replaced by the real libtorrent transfer, preserving x.pe peers and avoiding invalid piece-layer reconstruction
fix:Mesh magnets no longer advertise BitTorrent port 0 from failed listeners
fix:Stop seeding PeerDirectory with unverified IceBridge host-cache placeholders (reduces self/auth spam); host cache remains UI/history only
fix:Distributed search multi-hop disabled (ttl=0) — re-signing forwarded requests with the forwarder key while keeping original requesterPub always failed verification; v1 is direct verified-peer search only until dual-envelope hop protocol
fix:RudpSession sequence-wrap deadlock — after ~2^31 packets, signed comparison treated the wrapped sequence as a duplicate, permanently stalling the session. Fixed with Integer.compareUnsigned for all sequence comparisons and ConcurrentSkipListMap comparator
fix:RudpSessionManager pending-packet memory leak — unacked reliable packets were never purged after timeout; only cleared by ackLocal(). Now removed after MAX_RETRIES or RETRANSMIT_TIMEOUT_MS
fix:IceBridgeServer peerTtlSec*1000 overflow — for large config values, long multiply overflowed to negative, disabling eviction. Fixed with Math.multiplyExact
fix:PeerRegistry capacity enforcement — the maxPeers limit was checked AFTER merge(), so byPubHex.containsKey(key) was always true for a just-added peer; new peers were never rejected. Now checked BEFORE merge
fix:FragmentReassembler cross-session collision — group key changed from int groupId to String (sender + groupId)
fix:TORRENT_FETCH serves torrents up to 256KB (was 64KB) with signed TOO_LARGE above; holder-signed chunks are cached and restamped per request nonce (metadata protocol v2)
fix:IdentityRecord.fromEntry accepts v1/v2 again (read path) — still writes v3 with caps; fixes self-ping / peer handshake decode after capability bump
fix:SearchManager checkIfFinished race — crawl() and submitSimpleSearchTask() now add tasks inside synchronized(tasks) blocks, closing the race where a CrawlTask was enqueued between checkIfFinished’s ‘no pending’ check and the onStopped callback
fix:SearchResultDisplayer entries list now synchronized — the static ArrayList was mutated from EDT and iterated from search executor threads without synchronization, risking ConcurrentModificationException. Now a Collections.synchronizedList with synchronized blocks on all iteration paths
fix:AbstractSearchPerformer thread-safety — ‘stopped’ and ‘listener’ fields were not volatile; stop() from EDT was not visible to executor threads, causing results to be delivered after user clicked Stop
fix:DistributedSearchPerformer pending-map leak and NPE — timed-out searches leaked PendingRequest entries; malformed response rows with null infoHash caused NPE before latch countdown. Pending cleared in finally; rows validated
fix:SearchEngine TPB _domainName not volatile — background thread wrote _domainName; isReady() read it on EDT. Without volatile, TPB might never become ready. Also added try/catch and named daemon thread for mirror fetch
fix:Newly indexed torrents trigger a coalesced routing-digest refresh instead of waiting for the periodic rebuild; writes during an announcement schedule a follow-up and removing the last row withdraws previous holdership
fix:macOS native icon preloading reuses the existing Aqua file view instead of constructing a new file chooser for every file extension, avoiding repeated multi-second stalls on the Swing event thread
fix:Library media-type rescans are coalesced, so a burst of completed downloads no longer overflows the background executor and spams RejectedExecutionException
fix:right-clicking the transfer detail Files tab with no row selected no longer throws a NullPointerException
fix:Desktop UI repaints only rows that actually changed instead of every table row each second, theme icons decode once instead of on every paint, and Tip of the Day renders without subpixel-text stalls
fix:SearchMediator onResults no longer blocks search executor threads on the EDT — changed safeInvokeAndWait to safeInvokeLater so results are dispatched asynchronously
fix:JdkHttpClient.head reads response code before disconnect and drains error stream to prevent socket leaks
fix:IdentityKeys.generate() now uses jlibtorrent’s native Ed25519 for keypair generation instead of the JDK’s KeyPairGenerator — the JDK’s pure-Java Ed25519 implementation is 50-100x slower than native on some platforms (macOS arm64), causing first-run identity PoW mining to take >2 minutes instead of ~1-2 seconds
fix:InboundMessageQueue O(n²) performance — ConcurrentLinkedQueue.size() (O(n)) was called in a while-loop for overflow eviction. Replaced with AtomicInteger counter
fix:SearchMediator filter token-mutation fragility — searchTokens list was passed to filter2 which could mutate it via internal token removal. Now a defensive copy is made at the filter entry point
fix:SearchEngine.getSearchEngineByName prefix matching — fragile name.startsWith() replaced with exact name match or name + space prefix to prevent short engine names from matching longer ones
fix:SearchEngine TPB mirror fetch error handling — added try/catch and named daemon thread instead of raw new Thread()
fix:IceBridgeProcessLauncher temp log directory leak — every start/stop cycle leaked a temp directory with log files. Now recursively deleted in close()
fix:IceBridgeServer.parseArgs now skips –auth-token (handled separately by parseAuthToken) — previously threw IllegalArgumentException on unknown option
fix:Torrent crawl cache replaced with LRU eviction (LinkedHashMap, max 500 entries) — old cache had no eviction, causing unbounded memory growth in long-running sessions
fix:CrawlPagedWebSearchPerformer cache no longer uses global synchronized lock — the underlying DatabaseCrawlCache handles its own thread safety. Cache field is now volatile with local-variable snapshots
fix:parseFilesJson capped at MAX_FILES_PER_TORRENT (10000) — prevents unbounded row growth for torrents with tens of thousands of files
fix:SearchEngine.getEngines cached as static final — was allocating a new Arrays.asList on every call (per search, per result lookup, per engine lookup)
fix:SearchManager removed O(n²) nextOrdinal — the method iterated all tasks per crawlable result and was never used for sorting (no priority queue). Removed Comparable, ordinal field, and nextOrdinal method
fix:SearchMediator stripHtml regex precompiled — two String.replaceAll calls per result were recompiling regex on every search result. Now static final Pattern
fix:CrawlPagedWebSearchPerformer crawl counter is now AtomicInteger
fix:PerformersHelper.reduceHtml no longer double-allocates strings
fix:PerformersHelper relevance-ranking hot path — eliminate per-result regex compilation in sanitize/normalize (www. stripping and combining-mark removal after NFKD), speeding up fuzzy matching and result normalization on large search result sets
fix:CompositeFileSearchResult Builder no longer allocates 5 Optional wrappers per build() — nullable fields with Optional created at accessor boundary only
fix:Regex search patterns (Nyaa, Torrentz2) are now compiled once as static final fields
fix:Removed Sec-Fetch-Mode: navigate header from all HTTP requests
fix:NullTrustManager certificate list is now thread-safe (CopyOnWriteArrayList)
fix:Mesh log volume — per-packet/per-rejection logs demoted to DEBUG (metrics counters carry the signal); systemd unit caps journal spam (LogRateLimit 2000/30s)
fix:Transfer Detail Files tab keeps the selected file row highlighted while the view refreshes every second, and skips the rebuild entirely when the visible rows are unchanged
fix:transfer action buttons no longer flicker between enabled and disabled while a download is in progress; share/play availability is computed per row off the EDT instead of being cached on the single shared renderer
fix:Transfer Detail Files tab no longer freezes per-file progress while a transfer is still moving — holders rebuild on torrent progress drift, settled torrents skip native calls
fix:Slideshow / MISC HTTP no longer dies on OkHttp HTTP/2 stream header timeout (o2.php) — MISC client is HTTP/1.1, shared clients send HTTP/2 pings, slideshow retries once after evicting a stale pool
fix:macOS file rows show rich native icons again — the JFileChooser native view is used (FileSystemView returns only generic icons on JDK 26) and the bundled app passes –add-exports for com.apple.laf like frostwire.sh does
fix:Transfer detail Pieces tab now uses jlibtorrent’s v2-aware pieceSizeForReq() API for accurate piece-size display
new:rUDP (Reliable UDP) transport implemented from scratch — Ed25519-authenticated HELLO handshake, sequence-numbered DATA with ACK and retransmission (500ms interval, 5 retries, 5s timeout), application-level fragmentation/reassembly for payloads exceeding the UDP MTU (DATA_FRAG + DATA_END packet types, 1024-byte chunks with 12-byte fragment headers), HOLE_PUNCH for NAT traversal, and RELAY forwarding through forwarder peers. Built on Netty NioDatagramChannel
new:IceBridge control API — localhost-only HTTP server with endpoints: /health, /register (Ed25519-signed peer registration), /route (localhost-trusted unsigned peer routing), /lookup, /send (opaque payload delivery), /poll (drain inbound messages), /metrics
new:IceBridge multi-hop mesh RELAY — hop TTL frame, Type.RELAY delivery, forwarder mesh via RelayMesh; MultiRelayMeshSearchTest (3 FORWARDER + seeder/searcher clients)
new:IceBridge multi-protocol fabric — all mesh payloads IBP1-framed with protocolId on /send and /poll (SEARCH=1)
new:Node capability advertisement — IdentityRecord v3 caps bitflags (RELAY/SEARCH/INDEX/STORE/DHT/TORRENT/AI); PeerDirectory filters by capability; roles still derived for DHT topics
new:Streaming distributed search responses — RESULT chunks with final flag; large result sets stream multiple signed frames; performer accumulates until final
new:Distributed search forwarding (v2) — search requests now use ttl=1 and include the requester’s pubkey in the path array, enabling one-hop forwarding through trusted peers. IncomingSearchRequestHandler forwards requests to up to 3 trusted peers not already in the path, re-signing each forwarded request. Anti-amplification: max 3 forward targets, existing rate limits apply
new:Standalone IceBridge embedded DHT announce — pure FORWARDER nodes publish on frostwire-relays-v1 (+ optional bootstrap) via minimal jlibtorrent SessionManager without FrostWire desktop; ICEBRIDGE_DHT / –dht / –no-dht; DhtAdvertiser accepts SessionManager supplier
new:Remote peer catalog fetch protocol — RemoteIndexFetcher fetches a peer’s shared torrent catalog from the DHT via BEP 46 (IndexAnnouncementPublisher manifest). RemoteCatalogBrowseRequest provides a signed request/response protocol for browsing a specific peer’s catalog over the IceBridge transport. IncomingSearchRequestHandler handles both search requests and catalog browse requests
new:IndexAnnouncementPublisher wired into DhtAdvertiser — shared torrent index manifests are now published to the DHT every 5 minutes alongside identity records, enabling peers to discover each other’s shared catalogs
new:Pipeline saturation is observable — /metrics reports poll runs/errors, drain volume, request-queue depth, rejected work, and verification failures
new:IceBridge rUDP bind host configurable (ICEBRIDGE_BIND_HOST setting) — use “0.0.0.0” to accept rUDP from remote peers (cloud forwarder mode) or “127.0.0.1” for local-only daemon mode (default). Control HTTP server always binds to localhost
new:IceBridge software version announce — IdentityRecord v4 ib_ver + control /register+/lookup; Peers table IceBridge column; constants SOFTWARE_VERSION=1.1.0 / SOFTWARE_VERSION_CODE=1 for future crawler penetration stats
cleanup:Removed the legacy doctor-servlet bug report dialogs; errors report silently through Icebase, deadlocks through the crash spooler, and the fatal dialog no longer contacts the retired endpoint
fix:common/ relay identity and IceBridge file I/O no longer use java.nio.file (Android-safe File streams)
new:IdentityKeys.fromSeed() — deterministically reconstructs an Ed25519 keypair from a 32-byte seed via jlibtorrent’s Ed25519.createKeypair, enabling identity restore from a BIP39 mnemonic. X25519 keypair is freshly generated (not derivable from the Ed25519 seed). IdentityKeys.save/load are now public for import/export
new:DistributedSearchTransport abstraction — transport-agnostic listener-based interface that decouples the search performer from the concrete transport (IceBridge or future alternatives). A single background poller feeds all listeners, preventing races between the performer and incoming-request handler
new:IceBridgeClient and IceBridgeProcessLauncher — desktop HTTP client for the local IceBridge daemon, plus subprocess launcher that starts icebridge.jar with auto-allocated ports, shared identity, and redirected log output
new:IncomingSearchRequestHandler — permanent listener that processes incoming search requests through RelaySearchService and sends signed responses back via the transport
new:PeerRegistrySync — periodic daemon thread that syncs verified PeerDirectory entries into the IceBridge daemon’s registry via /route every 30 seconds, using the well-known rUDP port 6889
new:KeyspaceRouter ranks peers by XOR distance of SHA-1(keywords) for future responsibility-based routing (search still fans out trust-ordered peers first)
refactor:DistributedSearchPerformer refactored from direct-TCP OutgoingRelayClient to transport-agnostic DistributedSearchTransport — the performer now sends requests via transport.send() and collects responses through a temporary PayloadListener registered for the duration of the search. Removed thread pool; the transport’s poller handles delivery
refactor:OutgoingRelayClient verification extracted into shared SearchResponseVerifier (DRY) — both the direct-TCP and IceBridge paths now apply identical nonce, timestamp-skew, and Ed25519 signature checks
refactor:IceBridge client classes (IceBridgeClient, IceBridgeSearchTransport, IncomingSearchRequestHandler, PeerRegistrySync) moved from desktop to common for Android reuse. IceBridgeClient rewritten with OkHttp (replaces java.net.http.HttpClient). IceBridgeServer auth token stdout leak removed
refactor:PeerDiscoveryScheduler, DhtAdvertiser, KarmaChainWriter, KarmaChainPublisher, KarmaChainCommitScheduler moved from desktop to common for Android reuse. KarmaChainStore interface extracted — KarmaChainTable now implements it. KarmaChainWriter depends on the interface instead of the concrete table
new:Multi-instance distributed search test — headless integration test that simulates two FrostWire instances on the same machine with different identities, ports, and local indexes, verifying cross-instance search via real rUDP
new:LocalIndex.listAll() — enumerate all shared torrents in the local index for UI browsing
new:DistributedSearchEngineWire.getPeerDirectory() — static accessor for the shared PeerDirectory instance, enabling UI panels to access peer data
new:IceBridge hybrid EC2 topology benchmark + TopologyAutoResearch auto-loop optimizes N/M/TTLs for hit-rate vs traffic on fat EC2 hub mesh + FrostWire leaves; hybrid profile N=16 M=30; LimeWire ultrapeer baseline retained
new:Standalone IceBridge (icebridge-run-local.sh / AWS) logs successful mesh traffic at INFO — HELLO, HELLO_ACK, RELAY, SEARCH, TELEMETRY/PING and other known protocolIds
fix:PeerRegistrySync rUDP port is now configurable via constructor parameter
fix:Removed dead estimateRowsBytes() method from RemoteSearchResponse
fix:SCHEMA_VERSION bumped to 2 to reflect shared_files and shared_files_fts table additions
refactor:Tracker list consolidated into a single source of truth at com.frostwire.bittorrent.DefaultTrackers (#1004) — TorrentUtil, CreateTorrentDialog, and TorrentsCSVSearchPattern now consume DefaultTrackers.ANNOUNCE_URLS / MAGNET_URL_PARAMETERS. Removed duplicated UrlUtils.USUAL_TORRENT_TRACKERS_MAGNET_URL_PARAMETERS
cleanup:Desktop builds support JDK 26 by upgrading google-java-format from 1.24.0 to 1.36.1
fix:IceBridge ops scripts — run-local kills previous instances and detaches safely on Ctrl+C; systemd install is one-step (builds the jar, sudo self-elevation with JAVA_HOME passthrough, stops port strays, no crash-loops)
cleanup:GPL header on all post-2020 Java files missing it (79 files)
cleanup:Identity settings UI uses shared IdentityLifecycle (common/) for generate/install/seed/import/export — same logic as Android
new:ICEBRIDGE_ARCHITECTURE_REVIEW.md north-star layering + implementation status matrix
cleanup:Drop pre-alpha wire shims — no bare SEARCH payloads, no dual response signature domain, no IdentityRecord v1/v2 parse, no 96-byte HELLO auth
fix:IceBridge CLI prints identity load vs proof-of-work mining progress on stdout (first-run no longer looks hung); non-protocol TCP 6888 probes at DEBUG without stack spam
fix:IceBridge ops scripts — systemd install creates writable /opt dir; control URL is SSH tunnel only (127.0.0.1 bind); install uses absolute java path and preserves icebridge.env; no –background+–gradle; default control HTTP 8081 aligns run-local/fromEnv/.env.example
new:IceBridge fat JAR multi-arch jlibtorrent natives (Linux x86_64/arm64 + macOS) so Mac-built icebridge.jar runs DHT on EC2; scripts/icebridge-systemd-install.sh
new:ICEBRIDGE.md operator stub (ports, local vs remote, tokens, co-located pitfalls, security model)
Browse what other people share. Long-press a Distributed Search result and choose Browse Shared Torrents to see everything that person is sharing, then download straight from them. The first-run wizard now explains that seeding a torrent makes it discoverable. Browsing is on by default for torrents you are actively seeding (never your download history); you can turn it off in the wizard or in Settings > Distributed Search.
Smarter, faster search. Peers now tell the network what kind of content they hold, so your search goes to the people most likely to have it instead of random ones. Rare files turn up more reliably, even from phones and computers that are not acting as relays. Unreachable peers are forgotten instead of being retried forever, and Distributed Search is ready sooner after you open the app.
Clearer IceBridge status. Settings > Distributed Search now tells you what is actually happening: which startup step it is on, what went wrong if it failed, and a live countdown before the next automatic retry. It never gets stuck on “Starting…” without a reason.
Fixes you may notice
Distributed Search starts on release builds. A code-shrinking bug could stop the IceBridge networking layer from starting at all on installed apps. That is fixed, and the build now checks for it.
Downloads from the Peer catalog use the exact peer you picked, and failed or rejected starts (including VPN restrictions) are shown instead of silently disappearing.
Several phones on the same Wi-Fi no longer fight over one network port.
Transfers update right away when a torrent moves from Checking to Seeding, and when you come back from the details screen.
Only real audio files open in the music player; videos open with your system chooser.
Search results with accented or non-Latin names no longer go missing or appear twice.
The background service stops cleanly instead of crashing, and VPN or Wi-Fi-only rules no longer override a torrent you paused yourself.
new:You can now browse the torrents a peer shares — long-press a Distributed search result whose holder allows crawling (“Browse Shared Torrents”) to list everything that peer is sharing and download any of it straight from that peer
new:Distributed search routes to the peers that actually hold the content — nodes announce a compact keyword fingerprint and requests are forwarded to likely holders with a small bounded fan-out instead of random peers, so rare results are found reliably and faster
fix:Distributed search now finds torrents shared by peers that do not act as relays (leaf nodes) — forwarders were dropping their published keyword fingerprint, so those torrents only showed up by luck; the fingerprint is now honored when routing
fix:IceBridge settings show actual startup phases, timeout and failure status, and a live retry countdown; startup attempts are coalesced, late attempts cannot publish, and failed starts retry at most three times without bypassing cleanup or network policy
new:Seeding is publishing — the first-run wizard explains that seeding a torrent makes it discoverable on the BitTorrent network, and lets you opt out (on by default) of having the torrents you are actively seeding browsable by the network’s crawlers
fix:The crawler sharing setting now gates both mesh browsing and DHT catalog publication; only active non-private seeds are browsable, and opting out withdraws the previous catalog without disabling ordinary distributed search
fix:Only torrents you are actively seeding are shared with catalog crawlers — downloaded history that is not seeding is no longer published
fix:Distributed search becomes available sooner after startup — peer discovery, signed DHT announcements, and mesh registration now begin immediately in parallel rather than blocking the search UI; resume recovery uses one timeout budget
fix:Distributed search and the relay stay responsive under heavy search traffic — packet processing is handed off the socket event loop, response delivery runs on a bounded lane, and concurrent torrent-metadata fetches are capped
new:Peers keep an up-to-date list of reachable IceBridge nodes and never query unreachable ones — nodes that stop answering (directly or through a relay) are removed from the local list and evicted instead of being retried forever
fix:IceBridge UDP ports now default to automatic selection so multiple devices behind one router do not all claim port 6889; existing default settings are upgraded once, custom ports remain supported, and announcements use the actual bound port
fix:Peer catalog downloads preserve the selected holder’s identity, show rejected starts and VPN restrictions, and keep failed metadata transfers visible as errors instead of silently removing them
new:IceBridge participates as a full node (BOTH) by default, with a separate relay-participation switch and a node setting that restarts the relay stack when changed
new:Search progress now shows IceBridge status — “Distributed Search · N peers contacted” with starting / not-running hints, translated to every supported language
fix:Warming the mesh on relay startup lets a fresh install find peers without waiting for the first discovery tick
fix:Shared hybrid torrent indexing consistently uses the metadata v1 hash and removes only proven truncated-v2 aliases after the canonical row is stored
fix:The local search index preserves FTS rowids across reindexing and repairs triggers, fixing missing or duplicated results with unicode names
fix:VPN and seeding preference toggles suspend torrents for policy without overwriting an explicit user pause, and the transfer list is no longer cleared on reset
fix:The engine’s foreground service stops cleanly when promotion fails instead of crashing with RemoteServiceException
fix:Network status changes are no longer rebroadcast, and notifications fire only for real Wi-Fi/mobile/VPN transport changes
fix:Transfers rows now react to libtorrent state-change alerts, so Checking-to-Seeding updates do not wait for the next periodic list refresh
fix:Returning from transfer details immediately refreshes the transfers list so the row reflects the latest Checking, Downloading, or Seeding state
fix:Only real audio files open in the music player; video containers (webm/mp4/mkv/…) open with the system chooser
fix:Distributed Search settings refresh automatically while the screen is visible
fix:Deselecting every web search engine leaves Distributed Search enabled and no longer re-enables Archive.org at startup
fix:Release shrinking ignores optional Netty codec, JFR, and LDAP classes that Android does not ship, so the release build can complete
We’re happy to ship jlibtorrent 2.0.12.9, the latest Java/JNI bindings for the libtorrentRC_2_0 branch. This release advances the underlying C++ engine by 86 commits (from 46cc651d to cb6fe6b9c), pulls in OpenSSL 3.6.0, and exposes four new Java APIs that give you finer control over NAT-PMP traversal, peer connection policies, and BitTorrent v2 metadata.
If you build BitTorrent clients, media streaming tools, or decentralized data pipelines in Java, this is the build you want.
BitTorrent v2 (hybrid and v2-only torrents) introduced Merkle trees and pad blocks to align pieces with 16 KiB blocks. That means the nominal piece size you read from a .torrent file and the actual number of bytes you must hash or request can differ.
pieceSizeForReq(int piece) returns the effective piece size for hash requests — the real byte count you pass to a hasher or a piece picker. For v1 and hybrid torrents it equals pieceSize(); for v2-only torrents it strips out padding so your progress bars and verification loops stay exact.
TorrentInfo ti = new TorrentInfo(torrentBytes); long totalDataBytes = 0;
for (int i = 0; i < ti.numPieces(); i++) { int reqSize = ti.pieceSizeForReq(i); totalDataBytes += reqSize; // allocate exactly reqSize bytes for the piece buffer }
// totalDataBytes == ti.totalSize() for v1/hybrid // totalDataBytes <= ti.totalSize() for v2 (pad blocks excluded)
Use it when:
Computing precise download progress on v2 torrents
Allocating per-piece hash buffers in a cross-version client
Building telemetry that must reconcile “bytes on disk” vs “bytes of content”
2. SettingsPack.natpmpGateway() — override the NAT-PMP gateway
NAT-PMP auto-discovery fails on VPNs, container networks, and multi-homed hosts. natpmpGateway(String) lets you point libtorrent at the exact gateway address to punch through.
Leave it empty ("") and libtorrent falls back to automatic detection — the old behavior.
3. SettingsPack.allowMultipleConnectionsPerPid() — relax the duplicate-peer guard
By default libtorrent drops connections that share the same peer ID, a simple loop-prevention rule. In carrier-grade NAT (CGNAT) environments, dozens of legitimate peers can share one public IP and one peer ID. Enabling this setting lets you keep talking to all of them.
SettingsPack pack = new SettingsPack();
// Only enable on private trackers or known-CGNAT swarms if (trackerIsCGNATHeavy(announceUrl)) { pack.allowMultipleConnectionsPerPid(true) .connectionsLimit(500); // raise ceiling to match }
Security note: don’t flip this on open public swarms — it opens a trivial amplification vector.
4. SettingsPack.natpmpLeaseDuration() — control mapping lifetime
NAT-PMP mappings expire. The default lease is 3600 seconds (1 hour). For short mobile sessions you may want 300 s; for seed boxes, 7200 s reduces background chatter.
SettingsPack pack = new SettingsPack();
switch (deviceProfile) { case MOBILE_TEMPORARY -> pack.natpmpLeaseDuration(300); case DESKTOP_STANDARD -> pack.natpmpLeaseDuration(3600); // default case SEED_BOX -> pack.natpmpLeaseDuration(7200); }
Libtorrent auto-renews at roughly 50 % elapsed time, so a 300 s lease triggers a refresh every ~150 s.
Build & dependency updates
Dependency
Before
After
libtorrent
46cc651d
cb6fe6b9c (86 commits)
OpenSSL
3.5.2
3.6.0
Boost
1.88.0
1.88.0 (1.91.0 tested, ABI issue on macOS arm64)
SWIG
4.3.1
4.4.1
The upstream 86-commit delta includes hardening around tracker URL validation, SOCKS5 parsing, resume-data sanitization, peer encryption, and symbolic link support (BEP 47). Your users get those fixes for free the moment they load the new native library.
Build note: -frtti is now required
One upstream commit (d0e59960a) introduced dynamic_cast inside the smart-ban plugin. That collides with our traditional -fno-rtti builds. We added -frtti to all platform configs (macosx-arm64, linux-arm64, and by extension the Docker-based Linux/Windows/Android builds on our EC2 farm). Binary size impact is negligible; correctness is non-negotiable.
dependencies { def v = '2.0.12.9' implementation "com.frostwire:jlibtorrent:$v" implementation "com.frostwire:jlibtorrent-macosx-arm64:$v" // or your platform }
Direct download
JARs are attached to the GitHub Release. Grab the platform-independent jlibtorrent-2.0.12.9.jar plus your native artifact:
fix:Music player notification now opens a fresh AudioPlayerActivity via a no-UI trampoline that builds MainActivity under the player; MediaSession/session content intents point to the trampoline, and MainActivity forwards Android/Oplus Seedling media-launch intents to the player for compact System UI media cards
fix:Transfer Detail no longer crashes with ClassCastException when a torrent is still in fetch phase; AbstractTransferDetailFragment.ensureTorrentHandle now guards getBittorrentDownload() results with instanceof before casting, preventing TorrentFetcherDownload→UIBittorrentDownload cast failures
fix:My Music song deletion now removes items from the list adapter immediately instead of waiting for the background MediaStore deletion and loader refresh; DeleteDialog fires a pre-delete callback that optimistically removes deleted IDs from ApolloFragmentAdapter before file deletion begins
fix:SoftwareUpdaterDialog and NewTransferDialog no longer crash on Android 12 and lower with NoSuchMethodError; removed androidx BundleCompat.getSerializable() which internally calls the API 33-only typed overload, now using legacy Bundle.getSerializable(String) with explicit cast
fix:RenamePlaylist no longer crashes from background-thread getActivity() NPE when the dialog fragment detaches before MISC handler queries the playlist name; initObjects now passes application context and UI callbacks guard isAdded()/getDialog() null
fix:ArtistAlbumFragment onItemClick no longer crashes with NPE or races when calling getActivity().finish() from the MISC handler; activity is captured locally before the async post and finish() is marshalled back to the UI thread with lifecycle guards
We’re excited to announce FrostWire 7.0.4 for desktop — a release packed with a brand-new built-in MCP server, comprehensive EDT freeze fixes that eliminate UI hangs across the app, major rendering improvements to the transfer Pieces panel, and several quality-of-life features for torrent creation and management.
FrostWire now ships with a built-in Model Context Protocol (MCP) server — a first for any BitTorrent client. This opens up FrostWire to the AI tooling ecosystem with 38 desktop tools across 8 categories, settings-pane controls, and client configuration support for:
GitHub Copilot
Codex
Claude Desktop
OpenCode
Qwen
ChatGPT Desktop
AI agents can now interact with FrostWire’s desktop functionality through a standardized protocol.
Torrent Creation: Piece Sizes Up to 128 MB
The Torrent Creation Dialog now supports piece sizes up to 128 MB (previously capped at 4 MB). When creating a torrent, the dialog automatically recommends an optimal piece size based on your total content — targeting 1,000–3,000 pieces. This dramatically reduces RAM usage when seeding large files like 4K Linux ISOs.
Per-Torrent Save Location
When selecting files to download from a torrent, the dialog now shows the current save folder with Change… and Reset to Default buttons. You can pick a custom download location for each individual torrent without changing your global default.
Per-Torrent File Priority Control
The transfer detail Files tab now gives you full control over which files to download and how much bandwidth each gets:
“Show skipped files” checkbox — persisted globally (default ON). Skipped files appear dimmed in gray with a Download button to resume them individually.
Priority column — right-click any file to open an 8-level popup menu (from libtorrent’s IGNORE to SEVEN). Adjust bandwidth allocation per file within a torrent without affecting the rest.
All JNI calls for file metadata run on background threads, so the UI stays responsive even with torrents containing thousands of files.
Restart Button Dialog
When you change settings that require a restart (language, theme, network mode), FrostWire now shows a “Restart Now” / “Restart Later” dialog instead of just a passive message.
Clicking Restart Now gracefully shuts down and relaunches the app with the new settings applied.
YouTube Playlists & Channels
Pasting a YouTube channel or playlist URL now opens Telluride playlist search mode. Playlist partial results also appear correctly in the Video tab.
IP Filtering
The IP Filter settings pane is now fully wired to BTEngine — the clear and import buttons actually update the libtorrent ip_filter. The settings tab is no longer hidden.
No More UI Freezes
This release tackles the root cause of UI freezes across FrostWire. We identified and fixed 24 EDT (Event Dispatch Thread) violations that were blocking the UI during file I/O, torrent parsing, JNI calls, and dialog creation.
macOS Deadlock Fixes
Fixed a macOS EDT deadlock in FramedDialog where AppKit held awtLock during modal JDialog creation while EDT needed it for text rendering
Changed APPLICATION_MODAL to MODELESS in CreateTorrentDialog, SendFileProgressDialog, and EditTrackerDialog to prevent nested modal dialog deadlocks
Added pack() before setVisible(true) in SendFileProgressDialog, EditTrackerDialog, Options dialog, and About dialog to prevent macOS awtLock contention
Off-EDT Operations
The following operations now run on background threads instead of blocking the UI:
Theme loading at startup — Nimbus and FlatLaf Look-and-Feel initialization is now performed on the main thread before any Swing components exist, eliminating a consistent >2 second EDT freeze on every launch
Language flag image preloading — all locale flag icons are loaded into the ResourceManager cache before the setup wizard opens, so JComboBox layout no longer triggers MediaTracker.waitForID() on the EDT during startup
ApplicationHeader image preloading — header button background images are loaded on the main thread before MainFrame construction, preventing another MediaTracker.waitForID() stall
IconManager initialization — moved from the EDT to the main thread during late startup tasks
File launching via Desktop.open() — opening files with the OS default application now runs on a background thread, preventing X11 Desktop integration stalls on Linux when playing media
Transfer detail panels (General, Trackers, Peers, Pieces) — all JNI data gathering is now off-EDT
Native magnet URI generation — no longer blocks >2 seconds on large torrents
Resume data generation during pause/resume — need_save_resume_data() no longer stalls transfer actions
File progress computation — table painting no longer calls libtorrent file_progress() JNI on EDT
File I/O and torrent parsing in library table initialization
Directory scanning in library table updates
Future.get() blocking in library table selection removal
Recursive I/O guards added to DirectoryHolder.getFiles()
Drag-and-drop file existence checks — no longer triggers file.exists() syscall on EDT
File priority changes — all libtorrent filePriority() JNI calls run off-EDT via BackgroundQueuedExecutorService
Stability & Crash Fixes
JNI Crash Prevention
We’ve hardened the app against macOS Java 21 font-layout JNI crashes caused by malformed Unicode content:
Sanitize and de-HTML external text across search results, transfer names, locale labels, tooltips, and renderers
Normalize library text before Swing/Nimbus measures it, stripping Unicode format/control glyphs
Replace LineBreakMeasurer with JTextArea preferred-size calculation in tooltip UI
Sanitize transfer detail table strings (Files, Peers, Trackers) before Swing paints them
Added -Dsun.java2d.fontlayout=0 JVM argument to suppress JDK 21 SunLayoutEngine JNI warning spam during SynthComboBoxUI font layout on startup
Other Critical Fixes
Audio extraction crash: After extracting audio from a video download, selecting the newly added file in the library table could crash with IllegalArgumentException: Row index out of range if the file hadn’t been scanned yet. Added a bounds check to LimeJTable.setSelectedRow() to prevent this race condition.
Library Audio/Video nodes empty: Clicking Audio or Video in the library tree showed no files even though the Default Save Folder displayed downloads correctly. Fixed three root causes: MediaTypeSavedFilesDirectoryHolder.getFiles() was hardcoded to return an empty array instead of the cached files; LibraryMediator.scanInternal() refused to add newly downloaded files to empty caches; and SearchByMediaTypeRunnable didn’t fall back to the torrent data directory when DIRECTORIES_TO_INCLUDE was empty.
Shutdown hang: Added 30s timeout to LifecycleManager shutdown latch to prevent indefinite hangs
File size precision: BTDownload.getSize() return type changed from double to long — no more precision loss above 2GB
Library showing 0.0KB: File metadata loading now wrapped in try-catch with proper cell invalidation after background load
Library refresh (F5): Now properly re-sorts files after async lastModified load without flooding the resort executor
Transfer detail stale data: TransferDetailGeneral now discards stale async metadata updates when switching transfers quickly
Piece panel sync: TransferDetailPieces now ignores late selection updates so piece counts stay in sync with the selected transfer
Settings failures: UI notification now fires when settings load/save fails
YCCK JPEG fix: Color inversion corrected using Adobe APP14 marker Transform field
CreateTorrentDialog: Bottom buttons now visible on first open without requiring manual resize
First-view detail panel: The transfer detail panel now populates correctly on first view. A HierarchyListener detects when the Transfers tab becomes visible and triggers an initial selection update, fixing the empty detail panel bug on first open.
Checkbox flicker eliminated: The “Show skipped files” checkbox no longer flickers or corrupts its saved setting when toggled. Fixed a race condition between the 1-second refresh timer and user-initiated clicks.
Checkbox lag fixed: The “Show skipped files” checkbox now responds instantly. Checkbox-initiated updates moved from the shared single-threaded BackgroundQueuedExecutorService queue to a dedicated thread (matching Android’s HIGH_PRIORITY pattern), eliminating double-queueing with the 1-second refresh timer that caused multi-second UI lag on busy transfers.
Checkbox truly instant: The checkbox no longer re-fetches file metadata from libtorrent on every click. A cached holder list means toggling is a pure-EDT filter operation with zero JNI calls — the table updates in milliseconds even for torrents with thousands of files.
Table refresh fixed: The Files tab now rebuilds its table with fresh data on every refresh instead of calling tableMediator.update(), which was a no-op for immutable pre-computed holder objects.
Large torrent table freeze fixed: Replaced the per-row fireTableRowsInserted storm with a single bulk model replacement (setHolders) that fires fireTableDataChanged once. The EDT no longer freezes for seconds when updating a torrent with thousands of files.
Torrent file listing optimized: BTDownload.getItems() no longer performs a redundant piece-checking loop on every call. For a torrent with 10,000 pieces, this eliminates 10,000 th.havePiece() JNI calls per refresh. The tracker is now initialized once and kept up-to-date by libtorrent alerts.
Torrent switch fixed: Selecting a different transfer now correctly updates the Files tab. Replaced the broken target != btDownload guard with a monotonic sequence counter, so stale background completions are skipped without blocking legitimate torrent switches.
Library tree missing files fixed: SearchByMediaTypeRunnable no longer skips disk search when the cache is non-empty. Files that existed on disk before startup (or in directories not covered by scanInternal) now appear correctly in Audio/Video tree nodes.
Library path consistency fixed: FileUtils.listFiles() now returns absolute paths, ensuring cache deduplication and canonical path resolution work correctly across platforms.
Priority popup themed: The priority popup menu now uses FrostWire’s themed SkinMenuItem/SkinMenu components for consistent dark theme rendering.
File progress refresh: File progress percentages now update correctly after priority changes — no more stale 0% displays.
Settings Persistence
Tip of the Day: The “Show Tips at Startup” checkbox now saves immediately when toggled. Previously, the unchecked state could be lost if the app was force-quit before the normal exit save path ran.
Setup wizard infinite loop fixed: The wizard now saves its completion state synchronously instead of asynchronously. Previously, force-killing the JVM (e.g., IDE stop button) before the background save task executed caused the wizard to run again on next startup, which in turn reset SHOW_TOTD=true every time.
Setup wizard no longer resets tips unconditionally: The wizard only resets “Show Tips at Startup” on actual version updates, not when it appears for other reasons (intent window, associations, etc.).
HexHivePanel Overhaul
The transfer Pieces panel (HexHivePanel) received a complete rendering overhaul:
Fixes
Consistent hex tiling math with the fast flat-hex path for large swarms — no more overlapping piece cells
Restored the 3D cube-shaded look while keeping corrected tiling math and off-EDT cached rendering
Rows now wrap against the full viewport width — no more missing right-edge cubes
No longer cancels queued renders before rasterization starts — prevents refresh starvation (blank panel)
Coalesces rapid refresh requests through a single background render loop — 1-second detail updates no longer invalidate in-progress rendering
Merges retained viewport batches using non-overlapping seam bands — no more moving white gaps between rendered cube rows
Performance
Renders and publishes visible viewport cubes first — the Pieces tab paints quickly before the full scrollable bitmap finishes
Tracks viewport movement and resizes — only renders the visible region plus directional lookahead margins instead of repainting thousands of off-screen cubes
Retains a full-size backing bitmap and incrementally patches new viewport batches — previously drawn cubes stay visible when scrolling back
Prioritizes a smaller visible-band render with directional buffer and shorter row batches — reduces transient blank patches while scrolling
Search & Download Improvements
Tracker list refresh: Default tracker lists updated across desktop torrent creation, magnet URLs, and CreateTorrentDialog with current reliable public trackers (opentrackr, openbittorrent, stealth.si, exodus, torrent.eu.org, moeking, explodie, coppersurfer)
SoundCloud search now excludes tracks not marked as downloadable — only shows content the platform explicitly allows for download
Idope search updated to the new idope.pics domain and filters placeholder “No results returned” API responses
MagnetDL search parser now accepts both raw JSON arrays and quoted JSON-array payloads
SlideDownload now extracts .zip downloads with zip-slip protection
PerformersHelper now filters hidden files alongside pad files in search results
QuotedStringTokenizer now supports backslash quote escaping
TorrentFileFilter display string now properly internationalized
GloTorrents search engine removed (domain gtso.cc is parked and no longer functional)
Dependency Upgrades
Library
Old Version
New Version
BouncyCastle
1.80
1.83
FlatLaf
3.6
3.7.1
SQLite JDBC
3.50.3.0
3.51.3.0
JetBrains Annotations
26.0.2
26.1.0
JUnit
5.12.2
5.13.4
Cleanup
Removed dead EDT-blocking code from BTDownloadMediator, unused utility methods, ancient try/catch hacks, Thread.sleep() scroll hacks, and dozens of stale TODO comments throughout the codebase.
Much stronger playback reliability, especially for cold starts, notifications, direct-file playback, album art, queue state, and now-playing UI updates
Better torrent and transfer stability, including previous-session restore, large torrent file lists, transfer list responsiveness, and VPN or Wi-Fi protection behavior
Better search and download reliability for YouTube, SoundCloud, and Internet Archive
Safer, more modern app infrastructure with Media3, DataStore, updated dependencies, and broad deprecated-API cleanup
New Features
Added I2P support and I2P settings so users can route transfers through anonymous proxy infrastructure
Added YouTube playlist URL search and playlist-aware download flow
Added a terminal launcher for building, installing, and running FrostWire Android without Android Studio
Added a live logcat viewer to the launcher workflow for faster debugging
Added clearer VPN and Wi-Fi protection status feedback in the Transfers screen
Player And Library Improvements
Migrated the music player from the old MediaPlayer stack to ExoPlayer and Media3 for more reliable playback behavior
Migrated playback integration from RemoteControlClient to MediaSession APIs
Adopted the standard Android media notification style with output device selector support
Made player controls, metadata, play or pause state, repeat, and shuffle react faster
Fixed cold-start playback issues that could restart the first song, miss metadata, or hide the system notification
Fixed player notification behavior across next, previous, auto-advance, and direct-file playback
Fixed direct playback for freshly downloaded audio before MediaStore indexing finishes
Fixed album art fallback loading for direct-file playback and freshly downloaded tracks
Fixed the elapsed-time labels and seekbar so they refresh as soon as track metadata is available
Fixed My Music and Now Playing deletion flow on Android 11+ by using the system MediaStore delete confirmation flow
Fixed ghost entries in Recent and Favorites after deleting songs
Transfers, Torrents, And Search
Fixed previous-session torrent restores so old transfers reliably come back after relaunch
Fixed large torrent file lists that could stall, ANR, or take too long to appear in Transfer Detail
Fixed torrent status rendering that could freeze the Transfers list
Fixed transfer rows and Transfer Detail file rows getting temporarily out of sync with live state
Fixed transfer audio play buttons so they open FrostWire’s own player correctly
Fixed Wi-Fi-only and VPN guard protection behavior after Android networking API changes
Improved torrent and magnet handling from browsers and download managers
Fixed tracker edit and remove actions when the underlying tracker list changed
Fixed YouTube 403s, dropped headers, empty downloads, slow playback start, and file type detection issues
Restored SoundCloud search reliability and improved filtering of results that cannot really be downloaded
Restored Internet Archive downloads from search results
Performance And Stability
Removed dozens of ContentResolver queries and file-system operations from the UI thread
Eliminated multiple StrictMode violations across storage access, file opening, preference saves, and UI-triggered background work
Fixed crashes tied to foreground-service startup, player shutdown, rejected executor tasks, and missing native torrent libraries
Added safer handling for native jlibtorrent startup failures so the app stays usable even when the torrent engine cannot initialize
Fixed several detached-fragment and stale-activity crashes across search, profiles, playlists, settings, and dialogs
Fixed Android 13+ permission prompting so storage or media permissions no longer re-trigger repeatedly on resume
Fixed shutdown path StrictMode warnings caused by reflective task finishing
Platform And Architecture Work
Migrated app preferences from SharedPreferences to Jetpack DataStore
Added a central configuration repository for defaults, migrations, and safer preference access
Modernized fragment APIs, activity result flows, menu handling, notifications, and many deprecated Android platform calls
Updated yt-dlp, Chaquopy, Python, Firebase, AndroidX, WorkManager, Coil, and other core libraries
Removed outdated notification helpers, old media button plumbing, obsolete build flags, and unused 32-bit support
Cleaned up legacy search engines and dead code paths that no longer reflected working services
What 3.1.1 Adds On Top Of 3.1.0
Startup and foreground-service crash fixes
More reliable restore of previous-session torrents
Faster and safer Transfer Detail file loading
Fixes for My Music deletion on Android 11+
Fixes for now-playing clocks and seekbar updates
Android 13+ permission prompt loop fix
StrictMode cleanup for MainActivity shutdown
Bottom Line
3.1.1 is a cumulative stability release built on top of the major 3.1.0 modernization work. The biggest user-facing wins are smoother playback, more dependable torrent restore and transfer screens, better download reliability, and fewer Android-version-specific crashes and stalls.
FrostWire for Android 3.1.0 build 771 is a major stability and modernization release centered on one high-impact outcome: the app now behaves much more like a modern Android media and download app.
This build rebuilds the music player around Media3/ExoPlayer, restores reliable standard Android media notifications, hardens YouTube and Internet Archive downloads, migrates preferences to Jetpack DataStore, modernizes VPN/Wi-Fi protection logic, and removes a long list of UI-thread bottlenecks that could lead to freezes or ANRs.
By the numbers
FrostWire for Android 3.1.0 build 771 includes 120 documented Android release-note items:
There is no separate crash: bucket in the 3.1.0 changelog, but many of the fixes are crash-class or ANR-class hardening, especially around Chaquopy/yt-dlp startup, music playback transitions, DataStore persistence, MediaStore access, and deprecated Android API migrations.
Highlights, from most important to least important
1. The music player was rebuilt around ExoPlayer and Media3
This is the biggest change in the release.
FrostWire’s Android player moved from the deprecated MediaPlayer and RemoteControlClient stack to ExoPlayer / Jetpack Media3 / MediaSessionService. That migration fixed long-standing race conditions and made the player work like a current Android media app.
The result:
a standard Android media notification instead of a fragile custom RemoteViews implementation
output device selection in the notification for Bluetooth/Cast-style routing
more reliable play/pause, shuffle, repeat, and metadata refresh behavior
much better behavior during cold start, background playback, next/previous, and auto-advance transitions
2. Android media notifications now survive real playback use
The media notification work was not just a visual refresh. It fixed a whole class of playback-control failures that made background listening unreliable.
This release fixes:
missing media notifications on Android 12+
notification disappearance during engine-service notification refreshes
notification loss during next/previous/auto-advance transitions
stale Not playing state during active playback
notification controls failing to keep metadata, cursor state, and queue state in sync
previous-track history breaking after several songs
playback being killed when backing out through FrostWire’s “go home” dialog
In practice, the player notification is now much closer to how people expect Spotify, YouTube Music, or Pocket Casts to behave.
3. Fresh downloads and direct-file playback now work much better
3.1.0 removes a major source of frustration around newly downloaded songs.
The app now handles audio files more intelligently before MediaStore has indexed them:
freshly downloaded audio can start immediately instead of waiting for slow MediaStore indexing
YouTube audio downloads now open in FrostWire instead of a third-party app
direct-file playback no longer depends on a valid MediaStore ID
freshly completed YouTube downloads from Transfers can replace the current song correctly
album art fallback works even when MediaStore IDs or album IDs are not ready yet
This means FrostWire now behaves correctly in the exact window where users most often try to play a file: right after the download completes.
4. YouTube download reliability was substantially hardened
The YouTube pipeline got a deep reliability pass.
Notable fixes include:
fixing the Chaquopy/yt-dlp startup crash path caused by Android-incompatible subprocess behavior
threading per-format http_headers through the full download pipeline so requests keep the headers YouTube expects
preventing malformed headers from dropping all subsequent headers
treating non-2xx responses as failures so FrostWire no longer leaves behind misleading 0-byte files
improving browser-like default headers in the OkHttp wrapper
This release also updates the Python/Chaquopy environment and the yt_dlp integration so Android playback and downloading are much less brittle.
5. Search and download sources are more dependable again
Several search and download integrations were repaired or improved:
SoundCloud search was restored by validating remote credentials before caching and falling back safely when necessary
SoundCloud result filtering was corrected to match real downloadable/streamable behavior
Internet Archive downloads from search results were restored, including nested archive paths for composite crawled results
YouTube playlist URL search was added, with playlist partial-result support in Telluride
FrostWire is now offered more reliably for .torrent files and magnet links from browsers and download managers
The common theme is less silent failure and better handoff from search results into actual playback or downloads.
6. Preferences and settings were modernized with Jetpack DataStore
This release migrates FrostWire away from SharedPreferences to Jetpack DataStore, with a central configuration repository and safer default handling.
Benefits include:
atomic preference writes
safer migration from older installs
less risk of preference corruption or type mismatch crashes
settings writes moved off the UI thread to reduce ANR risk
a single source of truth for defaults and volatile preference resets
This is one of the most important under-the-hood changes in 3.1.0, even though it is less visible than the player work.
7. UI freezes, disk I/O, and ContentResolver work were pushed off the main thread
A large part of 3.1.0 is Android hygiene work that directly affects responsiveness.
The release removes:
38 ContentResolver.query() calls from the UI thread
12 disk I/O operations from the UI thread
9 unnecessary async roundtrips for simple in-memory reads
It also fixes multiple StrictMode violations across music, transfers, suggestions, settings, and file opening flows.
These are the kinds of changes that make the app feel less fragile even when they are not visible as a single headline feature.
8. VPN Guard and Wi-Fi Only protections were updated for modern Android APIs
Networking protections had been weakened by deprecated Android APIs.
3.1.0 fixes this by:
migrating network monitoring from deprecated broadcast-based connectivity APIs to NetworkCallback
Responsiveness and ANR prevention: main-thread query and disk-I/O removal, StrictMode cleanup, fewer async hops
Network protection correctness: Wi-Fi Only, VPN Guard, and modern connectivity monitoring
Developer and power-user tooling: I2P support, launcher TUI, live logcat
Why 3.1.0 matters
FrostWire for Android 3.1.0 build 771 matters because it fixes the seams between searching, downloading, and actually using media on a modern Android device.
Before this release, the most visible pain points were exactly where users notice breakage fastest: fresh downloads not opening correctly, notifications disappearing, playback controls getting stuck, settings writes freezing the UI, and modern Android API changes quietly breaking network protections or media behavior.
This build addresses those pain points directly and moves the app onto a much healthier foundation.
This update focuses on critical stability improvements, memory management, and the initial infrastructure for I2P integration. We’ve also addressed several UI bugs and search logic inconsistencies to provide a smoother user experience.
I2P Integration: Added the foundational configuration infrastructure for I2P, including a dedicated UI settings panel and registration within the options dialog
JDK 26: Updated to JDK 26 bundled runtime
Telluride Build 44: Latest Telluride Video Downloader improvements
🛠️ Bug Fixes & Stability
Memory Leak Prevention: Implemented bounds on previously unbounded image and icon caches to stop excessive memory consumption
Crash Fix: Resolved a specific crash that occurred when users pasted non-video URLs into the search bar
Linux Improvements: Fixed persistent tray icon issues specifically for users on KDE Plasma (#845)
Search Logic: Fixed the “Search Tools” filter and overhauled the logic to ensure all search filters now work independently and accurately
I2P Configuration: Fixed I2PPaneItem return value for applyOptions to ensure settings are saved correctly
📈 UI/UX Refinements
Speed Accuracy: Fixed a calculation error in the Peers Tab; download/upload speeds are now correctly converted from bytes/s to KB/s for easier reading
Note: This release is marked with High Urgency due to the memory leak and crash fixes. Users are encouraged to update immediately to ensure application stability.
📥 Download
ℹ️ About FrostWire
FrostWire is a free, open-source BitTorrent client and media player that has been actively developed since 2004. This release continues our commitment to stability, performance, and user privacy with the addition of I2P infrastructure support.
We are excited to announce the release of FrostWire 7.0.2 (Stable) for Windows, macOS, and Linux. This update is a significant milestone for user privacy and search efficiency, introducing a robust “VPN-Drop Protection” system to keep your identity safe while downloading.
Whether you are a casual downloader or a power user, 7.0.2 brings a more responsive, cleaner, and safer experience to your desktop.
🛡️ Stay Protected: New improved VPN-Drop Protection
The headline feature of this release is the VPN-Drop Protection. In the world of BitTorrent, maintaining a secure connection is paramount. We’ve added a fail-safe to ensure your real IP address is never accidentally exposed.
Quick Toggle: You’ll notice a new checkbox in the status bar. This allows you to instantly enable or disable VPN-Drop Protection.
Automatic Pausing: If this setting is on and your VPN disconnects, FrostWire will automatically pause all BitTorrent transfers.
Smart Alerts: FrostWire now checks for an active VPN connection when you start a new download, open a .torrent file, or paste a magnet link. If you aren’t protected, a dialog will alert you before the transfer begins.
Performance First: We’ve optimized the logic behind the scenes (using a new VPNDropGuard system) to ensure that checking your VPN status won’t lag your computer or freeze the interface.
🔍 Better Search, Faster Results
We’ve overhauled how FrostWire sorts your search results to help you find the highest quality files in less time.
Relevance First: Search results are now prioritized by keyword matches first, followed by seed counts and popularity. This ensures that the most relevant and “healthy” files stay at the top of your list.
Bug Fix: We’ve squashed a bug where seed counts were occasionally disappearing from the search UI. You’ll now have full visibility into the health of every file before you click download.
🎨 Clean & Compact UI
We believe a powerful tool should also be a beautiful one. FrostWire 7.0.2 features a more compact status bar layout. By reducing spacing and using a smaller font for the VPN indicators, we’ve freed up screen real estate while still keeping your vital connection stats front and center.
There is even a handy, clickable “VPN” link in the status bar that takes you directly to information on how to better protect your privacy.
Changelog Highlights:
Improved: Search result sorting (Keyword relevance > Seeds/Popularity).
New: VPN-Drop protection checkbox in the status bar.
New: VPN status checks when starting downloads or opening magnet links.
Fix: Resolved issue with disappearing seed counts in search results.
Optimization: All VPN-related logic moved to background threads to prevent UI blocking.
UI: Minimalist spacing for VPN and status indicators.