Skip to content

Fix handshake never starting when using options.stream - #1518

Open
u9g wants to merge 1 commit into
PrismarineJS:masterfrom
u9g:fix-stream-connect-race
Open

Fix handshake never starting when using options.stream#1518
u9g wants to merge 1 commit into
PrismarineJS:masterfrom
u9g:fix-stream-connect-race

Conversation

@u9g

@u9g u9g commented Sep 1, 2026

Copy link
Copy Markdown
Member

Problem

Creating a client with a custom stream (options.stream) hangs forever without sending the handshake:

const socket = net.connect(PORT, host, () => {
  const client = mc.createClient({ username: 'x', version: '1.21.8', stream: socket })
  // never emits 'login', no bytes ever written
})

For offline auth, createClient calls options.connect(client) before onReady() runs. The stream branch in tcp_dns.js emits 'connect' synchronously inside that call, so setProtocol (which subscribes in onReady() and sends set_protocol on 'connect') never sees the event. The plain-socket path doesn't hit this because net.connect completes asynchronously.

It reproduces whenever the provided stream doesn't emit its own 'connect' later — e.g. an already-connected socket, or any generic Duplex (I hit this tunneling the protocol bytes over a WebSocket).

Fix

Defer the emit one tick so listeners registered after options.connect() returns still see it.

Added a regression test in serverTest.js — it times out on master and passes with the fix, across all supported versions.

tcp_dns emitted 'connect' synchronously inside options.connect(), before
setProtocol had subscribed, so clients created with a custom stream hung
without ever sending the handshake. Defer the emit one tick.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant