@@ -23,9 +23,9 @@ import {
2323 readVarInt ,
2424 writeVarInt ,
2525 resolveHostname ,
26- generateSharedSecret ,
2726 mcHexDigest ,
28- protocolMap
27+ protocolMap ,
28+ getRandomBytes
2929} from './utils'
3030import { Certificate , joinMinecraftSession } from './api/mojang'
3131
@@ -59,6 +59,7 @@ export class ServerConnection extends events.EventEmitter {
5959 disconnectReason ?: string
6060 aesDecipher ?: Decipher
6161 aesCipher ?: Cipher
62+ msgSalt ?: Buffer
6263
6364 constructor ( socket : net . Socket , options : ConnectionOptions ) {
6465 super ( )
@@ -180,39 +181,44 @@ const initiateConnection = async (opts: ConnectionOptions) => {
180181 ? Buffer . alloc ( 0 ) // Avoid errors shortening.
181182 : conn . bufferedData . slice ( packet . packetLength )
182183 // Internally handle login packets.
183- if ( packet . id === 0x03 && ! conn . loggedIn ) {
184+ const is119 = conn . options . protocolVersion >= protocolMap [ 1.19 ]
185+ if ( packet . id === 0x03 && ! conn . loggedIn /* Set Compression */ ) {
184186 const [ threshold ] = readVarInt ( packet . data )
185187 conn . compressionThreshold = threshold
186188 conn . compressionEnabled = threshold >= 0
187189 } else if ( packet . id === 0x02 && ! conn . loggedIn ) {
188- conn . loggedIn = true
189- } else if ( packet . id === 0x21 ) {
190+ conn . loggedIn = true // Login Success
191+ } else if (
192+ // Keep Alive (clientbound)
193+ ( packet . id === 0x21 && ! is119 ) ||
194+ ( packet . id === 0x1e && is119 )
195+ ) {
190196 conn
191- . writePacket ( 0x0f , packet . data )
197+ . writePacket ( is119 ? 0x11 : 0x0f , packet . data )
192198 . catch ( err => conn . emit ( 'error' , err ) )
193199 } else if (
200+ // Disconnect (login) or Disconnect (play)
194201 ( packet . id === 0x00 && ! conn . loggedIn ) ||
195- ( packet . id === 0x1a &&
196- conn . loggedIn &&
197- opts . protocolVersion < protocolMap [ 1.19 ] ) ||
198- ( packet . id === 0x17 &&
199- conn . loggedIn &&
200- opts . protocolVersion >= protocolMap [ 1.19 ] )
202+ ( packet . id === 0x1a && conn . loggedIn && ! is119 ) ||
203+ ( packet . id === 0x17 && conn . loggedIn && is119 )
201204 ) {
202205 const [ chatLength , chatVarIntLength ] = readVarInt ( packet . data )
203206 conn . disconnectReason = packet . data
204207 . slice ( chatVarIntLength , chatVarIntLength + chatLength )
205208 . toString ( 'utf8' )
206- } else if ( packet . id === 0x01 && ! conn . loggedIn && ! accessToken ) {
207- conn . disconnectReason =
208- '{"text":"This server requires a premium account to be logged in!"}'
209- conn . close ( )
210209 } else if ( packet . id === 0x01 && ! conn . loggedIn ) {
210+ /* Encryption Request */
211+ if ( ! accessToken || ! selectedProfile ) {
212+ conn . disconnectReason =
213+ '{"text":"This server requires a premium account to be logged in!"}'
214+ conn . close ( )
215+ continue
216+ }
211217 // https://wiki.vg/Protocol_Encryption
212218 const [ serverId , publicKey , verifyToken ] =
213219 parseEncryptionRequestPacket ( packet )
214220 ; ( async ( ) => {
215- const secret = await generateSharedSecret ( ) // Generate random 16-byte shared secret.
221+ const secret = await getRandomBytes ( 16 ) // Generate random 16-byte shared secret.
216222 // Generate hash.
217223 const sha1 = createHash ( 'sha1' )
218224 sha1 . update ( serverId ) // ASCII encoding of the server id string from Encryption Request
@@ -221,8 +227,8 @@ const initiateConnection = async (opts: ConnectionOptions) => {
221227 const hash = mcHexDigest ( sha1 . digest ( ) )
222228 // Send hash to Mojang servers.
223229 const req = await joinMinecraftSession (
224- accessToken as string ,
225- selectedProfile as string ,
230+ accessToken ,
231+ selectedProfile ,
226232 hash
227233 )
228234 if ( ! req . ok ) {
@@ -244,7 +250,8 @@ const initiateConnection = async (opts: ConnectionOptions) => {
244250 writeVarInt ( encryptedVerifyToken . byteLength ) ,
245251 encryptedVerifyToken
246252 ]
247- if ( opts . protocolVersion >= protocolMap [ 1.19 ] ) {
253+ if ( is119 ) {
254+ conn . msgSalt = await getRandomBytes ( 8 )
248255 response . splice ( 2 , 0 , true )
249256 }
250257 const AES_ALG = 'aes-128-cfb8'
0 commit comments