OUT NOW: FrostWire 7.1.0 for desktop, with distributed torrent search

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.

Signature: boUcPuRatTn7eB4Ox/wStwfaC2k2s8f2HlZhohFQhMDezHSFu4PRWTHbUc/gTzaKnhBl49bSff5H496xbanx3L3dnsSk6rHHFVYNUKNm1CgeEg4eC9iyPsD3+boFSg7odkIqRwYaHZAjOgLXO/BiZg4tLYqdJV+RyDrzZINGZjJDAyd/9y+49cgrqvvQj99d54GaYGqI7JxwS8hl6BHVxHe7f+tYMTXsSTabaNyAyCf5k7fDB2zCdkrLreQIqG3mex/1nYdQtYyDcc0klLouLodFJE6LtSkLn/HmRrMpBUUDrb13bJy2uu/dERCxW/uDJa/8vMvWAhvl3Wbgi4LjSw9HpE2yGOImmSwgv/mNNa6DxDuYQwj/If/Dq+/3fLmiquTrdO+c6yUHRTbwtPecIGblfE3Tcl1irmcWTdvf/P1gFRapG8jhzLetkXnLYbwcl5R7sUT92FAoLC9ez9s2vVGRrYUcayQ/s4Z+WdO+Uh1k/tsITn/Hpqg8O8sGdRGYrSGM22OtlStkq/tEY+xfM8wKlr0yGNngUr9uxYee82zgy6lK7TfTplXp5ew8SZDZPaQhRM3KljtZsfgHr3X6ekAKSDhQTXnYCM4httyLDrPM4sxKKRfDYx83bvgqGLbUwpYFPI6SFhNTKonw9MGoHFW9AyhOJbuEW/ctN0Q0nMvEgbaaxrdtu6xOWtw9XtNV

Seeding is publishing, and you are in control

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.

PeriodApr 20 to Oct 8, 2026 (170 calendar days)
Days with commits83 (about every other day)
Commits1,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 files408
Documentation and plans~7,900 lines of Markdown/text added
Translations61 language files refreshed
Average outputabout 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 relay source verification — handleRelay verifies sourcePub matches the sender’s authenticated session identity
  • 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 downloads preserve headers, ranges, cancellation, and resume behavior; Telluride build 47 uses yt-dlp 2026.8.19
  • 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:IceBridge topology limits — IceBridgeTopology + env ICEBRIDGE_MESH_FANOUT / SEARCH_PEER_FANOUT / MESH_HOP_TTL / SEARCH_TTL / SOFT_MAX (remote-config ready)
  • new:Headless IceBridge presence crawler and mirror tooling (DHT heartbeat-topic presence counts, catalog crawler, allowlist-driven re-sharing)
  • 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
  • new:Dual-envelope distributed search multi-hop (v2) — requester signature covers query only; hops preserve sig; default ttl=2; PeerRegistrySync registers self and imports IceBridge mesh peers (forwarder-first discovery)
  • 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)

FrostWire 7.0.4 — MCP Server, No More Freezes, and a Faster UI

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.

Windows Installer: frostwire-7.0.4.windows.exe

MacOS Installers:
frostwire-7.0.4-x86_64.pkg (Intel)
frostwire-7.0.4-arm64.pkg (Apple Silicone)

Linux
frostwire-7.0.4.x86_64.tar.gz (Intel)
frostwire-7.0.4.arm64.tar.gz (Arm64)

What’s New

Built-in MCP Server

FROSTWIRE_SKILL.md

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
  • Speed limit controls: Added download/upload speed limit adjustment buttons to TransferDetailGeneral
  • 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

LibraryOld VersionNew Version
BouncyCastle1.801.83
FlatLaf3.63.7.1
SQLite JDBC3.50.3.03.51.3.0
JetBrains Annotations26.0.226.1.0
JUnit5.12.25.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.

FrostWire 7.0.2 Released: Enhanced Privacy with VPN-Drop Protection & Smarter Search

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.

Windows
frostwire-7.0.2.windows.exe

MacOS
frostwire-7.0.2-x86_64.pkg (Intel)
frostwire-7.0.2-arm64.pkg (Apple Silicon)

Linux
frostwire-7.0.2.x86_64.tar.gz
frostwire-7.0.2.arm64.tar.gz

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

Screenshot 2025-12-28 at 2 15 16 PM

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.

Download FrostWire

FrostWire for Android 3.0.14: Critical Stability Fixes & Engine Optimization

Just in time for the new year, we are rolling out a vital update for our Android users. FrostWire 3.0.14 (build 768) is now available, and it addresses several critical “day-one” issues introduced with our recent V2 architecture overhaul.

This release focuses on making sure the app starts correctly, downloads reliably, and accurately reports the status of your transfers.

What’s Fixed in Build 768?

🛠 Fixing the “Error” Status Bug

Many users reported that newly started torrents would immediately show an “Error” status even when the download was healthy. We found that the app was occasionally reading from an outdated status cache. We’ve implemented a fix to invalidate that cache immediately upon starting a transfer, ensuring you see the actual download progress instead of a false error.

⚡ Solving Initialization Crashes

We’ve eliminated two major race conditions that occurred during the app’s startup sequence:

  • Port 0 Binding Failure: Previously, the BitTorrent engine (BTEngine) would sometimes try to start before your settings were loaded, causing it to fail by trying to connect to “Port 0.”
  • Session Initialization: We’ve ensured the ConfigurationManager now blocks and finishes loading preferences before the engine starts, preventing session-related crashes.

🔍 Restoring Search-to-Download Functionality

Following our recent search architecture consolidation, some results from popular sources (like TPB, 1337X, and MagnetDL) weren’t being recognized as torrents.

  • We have added support for the new CompositeFileSearchResult interface.
  • This ensures that when you click a search result, the download starts immediately as intended.

📈 Maintenance & Core Updates

We have refreshed our core dependencies to ensure maximum compatibility with the latest Android devices:

  • yt-dlp Updated to 2025.12.08: Essential for high-speed cloud video downloads.
  • Gradle Plugin 8.13.2: Optimized build performance.
  • Library Updates: Updated Firebase BOM (v34.7.0), AndroidX ExifInterface (v1.4.2), and SwipeRefreshLayout (v1.2.0).

How to Update

  • Direct Download: Visit FrostWire.com to download the latest APK directly.

If you’ve been having trouble with downloads not starting or seeing unexpected errors in your transfer list, this update is highly recommended. Thank you for helping us make FrostWire better by reporting these issues!

Happy New Year and Happy Downloading!
— The FrostWire Team