Преглед изворни кода

A better solution to read long data.

Assign a once listener to pick up the initial data including the packet type and length.
Assign a subsequent listener to read the remainder of the data.
Daniel Scalzi пре 5 година
родитељ
комит
571b788e25
1 измењених фајлова са 43 додато и 52 уклоњено
  1. 43 52
      src/common/util/ServerStatusUtil.ts

+ 43 - 52
src/common/util/ServerStatusUtil.ts

@@ -243,74 +243,65 @@ export function getServerStatus(protocol: number, address: string, port = 25565)
 
         const maxTries = 2
         let iterations = 0
-
-        let inboundPacket!: ClientBoundPacket
-        let packetLength = 0
         let bytesLeft = -1
 
-        socket.on('data', (data) => {
+        socket.once('data', (data) => {
+
+            const inboundPacket = new ClientBoundPacket(data)
+            
+            // Length of Packet ID + Data
+            const packetLength = inboundPacket.readVarInt() // First VarInt is packet length.
+            const packetType = inboundPacket.readVarInt()   // Second VarInt is packet type.
 
-            if(iterations > maxTries) {
+            if(packetType !== 0x00) {
+                // TODO
                 socket.destroy()
-                reject(new Error(`Data read from ${address}:${port} exceeded ${maxTries} iterations, closing connection.`))
+                reject(new Error(`Invalid response. Expected packet type ${0x00}, received ${packetType}!`))
+                return
             }
 
-            let doAppend = true
-
-            // First delivery
-            if(bytesLeft == -1) {
+            // Size of packetLength VarInt is not included in the packetLength.
+            bytesLeft = packetLength + getVarIntSize(packetLength)
 
-                inboundPacket = new ClientBoundPacket(data)
+            // Listener to keep reading until we have read all the bytes into the buffer.
+            const packetReadListener = (nextData: Buffer, doAppend: boolean) => {
 
-                // First VarInt is packet length.
-                // Length of Packet ID + Data
-                packetLength = inboundPacket.readVarInt()
-
-                // Second VarInt is packet type.
-                const packetType = inboundPacket.readVarInt()
-
-                console.log(packetType, packetLength)
-
-                if(packetType !== 0x00) {
-                    // TODO
+                if(iterations > maxTries) {
                     socket.destroy()
-                    reject(new Error(`Invalid response. Expected packet type ${0x00}, received ${packetType}!`))
-                    return
+                    reject(new Error(`Data read from ${address}:${port} exceeded ${maxTries} iterations, closing connection.`))
                 }
-
-                bytesLeft = packetLength + getVarIntSize(packetLength)
-                doAppend = false
-
-            } 
-
-            if(bytesLeft > 0) {
-
                 ++iterations
-                bytesLeft -= data.length
-                if(doAppend) {
-                    inboundPacket.append(data)
-                }
-                console.log(bytesLeft, data.toString('utf-8'))
-            }
-
-            if(bytesLeft === 0) {
-                
-                // Remainder of Buffer is the server status json.
-                const result = inboundPacket.readString()
 
-                try {
-                    const parsed = JSON.parse(result)
-                    socket.end()
-                    resolve(unifyStatusResponse(parsed))
-                } catch(err) {
-                    socket.destroy()
-                    logger.error('Failed to parse server status JSON', err)
-                    console.log(result)
-                    reject(new Error('Failed to parse server status JSON'))
+                if(bytesLeft > 0) {
+                    bytesLeft -= nextData.length
+                    if(doAppend) {
+                        inboundPacket.append(nextData)
+                    }
                 }
+
+                // All bytes read, attempt conversion.
+                if(bytesLeft === 0) {
             
+                    // Remainder of Buffer is the server status json.
+                    const result = inboundPacket.readString()
+
+                    try {
+                        const parsed = JSON.parse(result)
+                        socket.end()
+                        resolve(unifyStatusResponse(parsed))
+                    } catch(err) {
+                        socket.destroy()
+                        logger.error('Failed to parse server status JSON', err)
+                        reject(new Error('Failed to parse server status JSON'))
+                    }
+                }
             }
 
+            // Read the data we just received.
+            packetReadListener(data, false)
+            // Add a listener to keep reading if the data is too long.
+            socket.on('data', (data) => packetReadListener(data, true))
+
         })
 
         socket.on('error', (err: NodeJS.ErrnoException) => {