Repository navigation
Releases: KyokoBot/koe
Release list
3.1.0
What's Changed
Significant optimizations for transport encryption and a lot of bug fixes for long-standing issues.
Two defaults changed, see Behavior changes and the migration guide.
Security
- With DAVE enabled, audio and video were sent without E2EE until the key ratchet was ready. Koe now waits for it before polling audio. Anything sent before then is replaced with silence or dropped. See GHSA-pw4q-x846-j45m.
Performance
- XChaCha20-Poly1305 is ~20% faster and no longer allocates per packet (it used to allocate 2-10 KB per packet).
- XSalsa20-Poly1305 is ~14% faster.
- AES-GCM uses JCE directly instead of going through Tink, and reuses the
Cipherand key for the whole session. - Koe prefers AES-GCM only if the JVM uses AES instructions, otherwise XChaCha20-Poly1305. Without them AES-GCM is several times slower, e.g. on JDK 17 on Apple Silicon.
- DAVE can use FFM (Java 22+) instead of JNI, which has lower call overhead.
Average time and memory allocated to encrypt one packet on a single thread, measured with JMH, 3.0.0 → 3.1.0:
| Mode | Payload | Zen 4 x86-64, Temurin 25 | Apple M2, Temurin 17 | Allocated per packet (x86-64) |
|---|---|---|---|---|
aead_xchacha20_poly1305_rtpsize |
160 B | 1600 ns → 1261 ns | 1670 ns → 1338 ns | 2184 B → 0 B |
aead_xchacha20_poly1305_rtpsize |
1276 B | 8664 ns → 6995 ns | 9774 ns → 7576 ns | 10600 B → 0 B |
xsalsa20_poly1305_lite |
160 B | 1164 ns → 998 ns | 1267 ns → 1067 ns | 0 B |
xsalsa20_poly1305_lite |
1276 B | 7713 ns → 6644 ns | 8263 ns → 7224 ns | 0 B |
aead_aes256_gcm_rtpsize |
160 B | 347 ns → 339 ns | 3567 ns → 3368 ns | 1440 B → 1456 B |
aead_aes256_gcm_rtpsize |
1276 B | 698 ns → 701 ns | 20826 ns → 19931 ns | 3808 B → 2848 B |
160 B is a 20 ms Opus frame at 64 kbps, 1276 B is the largest Opus frame.
On the M2, switching to XChaCha20-Poly1305 makes encryption ~2.5x faster.
Removed dependencies
- Tink. AES-GCM now uses JCE and XChaCha20-Poly1305 is implemented in Koe.
Bug fixes
connect()never completed if the voice gateway connection failed, e.g. for an endpoint with awss://prefix. Endpoints with a scheme now work, and failed connections complete exceptionally. (#23)- udp-queue kept sending packets to the old voice server after a server change.
- Fixed race and reentrancy bugs in DAVE handling.
- Fixed SSRCs above 2^31 being sent as negative numbers, which could make bots silent in stage channels. Stage channels also need a workaround for a Discord bug, see DISCORD_VOICE_QUIRKS.md. (#43)
- Fixed the speaking state not being resent after a new session description.
- Fixed packets sent with an RTP header extension (
ConnectionHandler.sendFramewithextension = true) failing to decrypt with the_rtpsizemodes, and the extension being end-to-end encrypted by DAVE along with the frame. - Fixed various internal minor bugs
Behavior changes
- Voice gateway connections time out after 10 seconds. Change it with
KoeOptionsBuilder.setGatewayConnectTimeout(0disables it). - Koe no longer sends a speaking update with an empty mask when playback stops, since it could cut off buffered audio.
KoeOptionsBuilder.setSendSpeakingStop(true)restores the old behavior. (#21) - The encryption mode is picked by preference instead of the server's order, see Performance.
Improvements
- To use DAVE over FFM, add
moe.kyokobot.libdave:impl-ffm. Koe falls back to JNI if it's missing or fails to load. It's built for Java 22, so projects targeting older Java need:runtimeOnly("moe.kyokobot.libdave:impl-ffm:VERSION") { attributes { attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 22) } }
- The secret key from the voice server is validated.
- When resuming fails with 4006 (session no longer valid), Koe now starts a new session instead of giving up. If that fails too, the new
KoeEventListener.sessionLostevent tells you to rejoin the voice channel. - Added
MediaConnection.setSpeakingMaskandgetSpeakingMask. - Added the
aead_aes256_gcmandxsalsa20_poly1305_lite_rtpsizeencryption modes, so every documented mode is supported. Discord itself no longer offers them. - All
KoeEventListenermethods now have empty default implementations, so you can implement only the events you need.KoeEventAdapteris deprecated. - Updated Netty to 4.2.18.Final and libdave-jvm to 0.2.0.
New experimental APIs
May change in minor releases.
KoeOptionsBuilderExperimental.setCipherPreferencePolicyto choose the encryption mode yourself.CipherBenchmarkto measure the encryption modes on the current JVM and build a policy from the results. Results can be saved as JSON.KoeOptionsBuilderExperimental.setDaveFactoryProviderto use your own DAVE implementation selection strategy.
Documentation
- Added JVM flags for Java 24+ to the README. Without them Netty can't use
sun.misc.Unsafeand falls back to slower buffers. - Added DISCORD_VOICE_QUIRKS.md that publicly documents known Discord voice server quirks :)
- Interfaces only Koe implements are now marked
@ApiStatus.NonExtendable, so they may get new methods in minor releases.
Development
- Added unit tests and CI for pull requests.
- API compatibility is checked against the last release with japicmp.
- Snapshots are no longer uploaded to Maven Central.
Full Changelog: 3.0.0...3.1.0
3.0.0
What's Changed
THIS IS A MAJOR RELEASE WITH MANY BREAKING CHANGES
PLEASE READ THE MIGRATION GUIDE (for this specific release)
https://github.com/KyokoBot/koe/blob/3.0.0/MIGRATION.md
Full Changelog: 2.2.0...3.0.0
3.0.0-pre6
What's Changed
THIS IS A MAJOR RELEASE WITH MANY BREAKING CHANGES
PLEASE READ THE MIGRATION GUIDE (for this specific release)
- Updated libdave-jvm to
0.1.2(published on Maven Central) - Set up publishing on Maven Central.
https://github.com/KyokoBot/koe/blob/3.0.0-pre6/MIGRATION.md
Full Changelog: 2.2.0-rc2...3.0.0-pre6
** Changelog since last prerelease**: 3.0.0-pre5...3.0.0-pre6
3.0.0-pre5
What's Changed
THIS IS A MAJOR RELEASE WITH MANY BREAKING CHANGES
PLEASE READ THE MIGRATION GUIDE (for this specific release)
- Added support for forwarding logs from libdave (Requires at least libdave-jvm
5e12c7dff) - Fixed data races in DAVEManager leading to JVM crashes.
https://github.com/KyokoBot/koe/blob/3.0.0-pre5/MIGRATION.md
Full Changelog: 2.2.0-rc2...3.0.0-pre5
** Changelog since last prerelease**: 3.0.0-pre4...3.0.0-pre5
3.0.0-pre4
What's Changed
THIS IS A MAJOR RELEASE WITH MANY BREAKING CHANGES
PLEASE READ THE MIGRATION GUIDE (for this specific release)
- Fixed data races in DAVEManager leading to JVM crashes.
https://github.com/KyokoBot/koe/blob/3.0.0-pre4/MIGRATION.md
Full Changelog: 2.2.0-rc2...3.0.0-pre4
** Changelog since last prerelease**: 3.0.0-pre3...3.0.0-pre4
3.0.0-pre3
What's Changed
THIS IS A MAJOR RELEASE WITH MANY BREAKING CHANGES
PLEASE READ THE MIGRATION GUIDE (for this specific release)
- Fixed a bug with DAVE not working unless the Netty allocator is configured to always allocate direct buffers.
https://github.com/KyokoBot/koe/blob/3.0.0-pre3/MIGRATION.md
Full Changelog: 2.2.0-rc2...3.0.0-pre3
** Changelog since last prerelease**: 3.0.0-pre2...3.0.0-pre3
3.0.0-pre2
What's Changed
THIS IS A MAJOR RELEASE WITH MANY BREAKING CHANGES
PLEASE READ THE MIGRATION GUIDE (for this specific release)
- Fixed memory leaks
- Fixed bugs caued by incomplete MLS groups
https://github.com/KyokoBot/koe/blob/3.0.0-pre2/MIGRATION.md
Full Changelog: 2.2.0-rc2...3.0.0-pre2
** Changelog since last prerelease**: 3.0.0-pre1...3.0.0-pre2
3.0.0-pre1
What's Changed
THIS IS A MAJOR RELEASE WITH MANY BREAKING CHANGES
PLEASE READ THE MIGRATION GUIDE (for this specific release)
https://github.com/KyokoBot/koe/blob/3.0.0-pre1/MIGRATION.md
- Actually keep track of the last received sequence by @viztea in #40
- add github actions to publish koe by @topi314 in #42
Full Changelog: 2.2.0-rc2...3.0.0-pre1
Note: This release has been retagged from 317ab86 to 374c321 to disable JitPack builds
2.2.0
What's Changed
- add close code constants & handle reconnect of more close codes by @topi314 in #36
- fix: remove unnecessary close codes from reconnect handling by @topi314 in #39
- Actually keep track of the last received sequence by @viztea in #40
This is the final release in 2.x series. It does not support DAVE and will remain broken as of 2nd March 2026.
Full Changelog: 2.1.1...2.2.0
2.2.0-rc2
What's Changed
- add close code constants & handle reconnect of more close codes by @topi314 in #36
- fix: remove unnecessary close codes from reconnect handling by @topi314 in #39
- fix: port :80 stripping logic (#38) and added an option (
KoeOptionsBuilder#setEnableWSSPortOverride()) to disable this behavior completely (Koe will always use the specified port)
API Changes
- Deprecated public
KoeOptionsconstructor. UseKoeOptions.builder()if you're not using it already.
Full Changelog: 2.1.1...2.2.0-rc2