minecraft-server-ping
Version:
Minecraft server status
1 lines • 21 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.mts","../src/dnsSrv.mts","../src/minecraftPackets.mts","../src/PacketDecoder.mts"],"sourcesContent":["import {createConnection, isIP, type Socket} from 'net';\nimport type {ILoggerLike} from '@avanio/logger-like';\nimport {Err, type IResult, Ok} from '@luolapeikko/result-option';\nimport {srvRecordResult} from './dnsSrv.mjs';\nimport type {IAddress, IHandshakeData, IMinecraftData} from './interfaces.mjs';\nimport {createHandshakePacket, createPingPacket} from './minecraftPackets.mjs';\nimport {PacketDecoder} from './PacketDecoder.mjs';\nexport * from './interfaces.mjs';\nexport * from './minecraftPackets.mjs';\nexport * from './PacketDecoder.mjs';\nexport * from './dnsSrv.mjs';\n\nconst defaultAddress: IAddress = {\n\thostname: 'localhost',\n\tport: 25565,\n};\n\n/**\n * Type to get value directly, from promise or from function\n * @template T type of value\n */\nexport type Loadable<T> = T | Promise<T> | (() => T | Promise<T>);\n\n/**\n * Build Loadable Address type\n */\nexport type LoadableAddress = Loadable<Partial<IAddress>>;\n\n/**\n * Build Loadable URL type\n */\nexport type LoadableUrl = Loadable<URL | string>;\n\n/**\n * Ensure that we have Error object\n */\nfunction ensureError(error: unknown): Error {\n\tif (error instanceof Error) {\n\t\treturn error;\n\t}\n\tif (typeof error === 'string') {\n\t\treturn new Error(error);\n\t}\n\treturn new Error(`unknown error: ${JSON.stringify(error)}`);\n}\n\n/**\n * Options for ping\n * @interface Options\n * @property {number=} timeout timeout in milliseconds\n */\nexport interface CommonOptions {\n\t/** connection timeout in milliseconds, default is 10000 */\n\ttimeout?: number;\n\tlogger?: ILoggerLike;\n}\n\n/**\n * Check SRV record and return hostname and port (IAddress)\n * @param {string} hostname\n * @returns {Promise<IAddress | undefined>} Promise that resolves to IAddress or undefined\n */\nasync function checkSrvRecord(hostname: string, options: CommonOptions): Promise<IAddress | undefined> {\n\t// if hostname is IP, return undefined\n\tif (isIP(hostname) !== 0) {\n\t\toptions.logger?.debug(`checkSrvRecord: ${hostname} is IP, returning undefined`);\n\t\treturn undefined;\n\t}\n\tconst dnsResult = await srvRecordResult(`_minecraft._tcp.${hostname}`);\n\tif (dnsResult.isErr) {\n\t\toptions.logger?.debug(`checkSrvRecord: ${hostname} has no SRV record, returning undefined`);\n\t\treturn undefined;\n\t}\n\tconst {name, port} = dnsResult.ok();\n\treturn {\n\t\thostname: name,\n\t\tport,\n\t};\n}\n\nfunction urlToAddress(uri: URL | string, options: CommonOptions): Partial<IAddress> {\n\tconst address: Partial<IAddress> = {};\n\tconst {protocol, hostname, port} = typeof uri === 'string' ? new URL(uri) : uri;\n\tif (!hostname || !protocol || protocol !== 'minecraft:') {\n\t\tthrow new TypeError('not correct minecraft URI');\n\t}\n\tconst realPort = port ? parseInt(port, 10) : undefined;\n\tif (realPort && isNaN(realPort)) {\n\t\tthrow new TypeError('not correct minecraft URI');\n\t}\n\tif (hostname) {\n\t\taddress.hostname = hostname;\n\t}\n\tif (realPort) {\n\t\taddress.port = realPort;\n\t}\n\toptions.logger?.debug(`urlToAddress: ${uri.toString()} => ${JSON.stringify(address)}`);\n\treturn address;\n}\n\n/**\n * ping with URI\n * @param {LoadableUrl} uriArg minecraft://server[:port]\n * @param {CommonOptions=} options options\n * @return {Promise<IMinecraftData>}\n */\nexport async function pingUri(uriArg: LoadableUrl, options: CommonOptions = {}): Promise<IMinecraftData> {\n\tconst uri = await (typeof uriArg === 'function' ? uriArg() : uriArg);\n\treturn ping(urlToAddress(uri, options), options);\n}\n\n/**\n * ping with URI, return result object\n * @param {LoadableUrl} uriArg minecraft://server[:port]\n * @param {CommonOptions=} options options\n * @return {Promise<Result<IMinecraftData, Error>>}\n */\nexport async function pingUriResult(uriArg: LoadableUrl, options: CommonOptions = {}): Promise<IResult<IMinecraftData, Error>> {\n\ttry {\n\t\treturn Ok(await pingUri(uriArg, options));\n\t} catch (err) {\n\t\treturn Err(ensureError(err));\n\t}\n}\n\n/**\n * ping with hostname and port\n * @param {LoadableAddress=} addressArg address object (defaults {hostname: 'localhost', port: 25565})\n * @param {CommonOptions=} options options\n * @returns {Promise<IMinecraftData>}\n */\nexport async function ping(addressArg?: LoadableAddress, options: CommonOptions = {}): Promise<IMinecraftData> {\n\tlet address: IAddress = Object.assign({}, defaultAddress, await (typeof addressArg === 'function' ? addressArg() : addressArg));\n\tif (address.hostname !== 'localhost') {\n\t\tconst dnsAddress = await checkSrvRecord(address.hostname, options);\n\t\tif (dnsAddress) {\n\t\t\taddress = dnsAddress;\n\t\t}\n\t}\n\toptions.logger?.info(`ping: ${address.hostname}:${address.port.toString()}`);\n\treturn openConnection(address, options);\n}\n\n/**\n * ping with hostname and port, return result object\n * @param {LoadableAddress=} addressArg address object (defaults {hostname: 'localhost', port: 25565})\n * @param {CommonOptions=} options options\n * @returns {Promise<Result<IMinecraftData>>}\n */\nexport async function pingResult(addressArg?: LoadableAddress, options: CommonOptions = {}): Promise<IResult<IMinecraftData, Error>> {\n\ttry {\n\t\treturn Ok(await ping(addressArg, options));\n\t} catch (err) {\n\t\treturn Err(ensureError(err));\n\t}\n}\n\nfunction openConnection(address: IAddress, options: CommonOptions): Promise<IMinecraftData> {\n\tlet timeout: ReturnType<typeof setTimeout> | undefined;\n\treturn new Promise((resolve, reject) => {\n\t\tconst handleError = (error: Error, thisSocket: Socket) => {\n\t\t\tthisSocket.destroy();\n\t\t\tif (timeout) {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\t\t\toptions.logger?.error(`openConnection: error: ${error.message}`);\n\t\t\treject(error);\n\t\t};\n\t\tconst socket = createConnection(address.port, address.hostname, async () => {\n\t\t\toptions.logger?.debug(`openConnection: connected to ${address.hostname}:${address.port.toString()}`);\n\t\t\tconst packetDecoder = new PacketDecoder();\n\t\t\tsocket.pipe(packetDecoder); // attach decoder\n\t\t\tpacketDecoder.once('error', (error) => handleError(error, socket));\n\t\t\t// send handshake\n\t\t\toptions.logger?.debug(`openConnection: => sending handshake`);\n\t\t\tsocket.write(createHandshakePacket(address));\n\t\t\t// wait for handshake data\n\t\t\tconst handshakeData = await packetDecoder.oncePromise<IHandshakeData>('handshake');\n\t\t\toptions.logger?.debug(`openConnection: <= received handshake data`);\n\t\t\t// send ping\n\t\t\toptions.logger?.debug(`openConnection: => sending ping`);\n\t\t\tsocket.write(createPingPacket(BigInt(Date.now())));\n\t\t\t// wait for pong\n\t\t\tconst pingData = await packetDecoder.oncePromise<number>('pong');\n\t\t\toptions.logger?.debug(`openConnection: <= received pong`);\n\t\t\tif (timeout) {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\t\t\tsocket.end();\n\t\t\toptions.logger?.debug(`openConnection: end`);\n\n\t\t\tresolve({\n\t\t\t\t...handshakeData,\n\t\t\t\tping: pingData,\n\t\t\t});\n\t\t});\n\t\t// Destroy on error\n\t\tsocket.once('error', (error) => handleError(error, socket));\n\t\t// Destroy on timeout\n\t\tsocket.once('timeout', () => {\n\t\t\tsocket.destroy();\n\t\t\tif (timeout) {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\t\t\toptions.logger?.debug(`openConnection: timeout`);\n\t\t\treject(new Error('Timed out'));\n\t\t});\n\t\t// Packet timeout\n\t\tconst timeoutValue = options.timeout ?? 10000;\n\t\ttimeout = setTimeout(() => {\n\t\t\tsocket.end();\n\t\t\treject(new Error(`Timed out (${timeoutValue.toString()} ms)`));\n\t\t}, timeoutValue);\n\t});\n}\n","import {resolveSrv, type SrvRecord} from 'dns';\nimport {Err, type IResult, Ok} from '@luolapeikko/result-option';\n\nfunction assertAtLeastOne<T>(data: T[]): asserts data is [T, ...T[]] {\n\tif (data.length === 0) {\n\t\tthrow new Error('Expected at least one element, got none');\n\t}\n}\n\n/**\n * Resolves the SRV records for the given service name.\n * @param {string} srv The service name to resolve.\n * @returns {Promise<Result<SrvRecord[]>>} A promise of Result that resolves to an array of SRV records.\n * @example\n * const res = await srvRecordsResult('_minecraft._tcp.example.com');\n * if (res.isOk) {\n * console.log(res.ok()); // [ { name: 'example.com', port: 25565, priority: 0, weight: 5 } ]\n * } else {\n * console.error(res.err());\n * }\n */\nexport function srvRecordsResult(srv: string): Promise<IResult<[SrvRecord, ...SrvRecord[]], NodeJS.ErrnoException>> {\n\treturn new Promise((resolve) => {\n\t\tresolveSrv(srv, (error, result) => {\n\t\t\tif (error) {\n\t\t\t\tresolve(Err(error));\n\t\t\t} else {\n\t\t\t\tassertAtLeastOne(result); // This is safe because resolveSrv will always return at least one element\n\t\t\t\tresolve(Ok(result));\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Resolves the first SRV record for the given service name.\n * @param {string} srv The service name to resolve.\n * @returns {Promise<Result<SrvRecord>>} A promise of Result that resolves to the first SRV record, or Err if no records were found.\n * @example\n * const res = await srvRecordResult('_minecraft._tcp.example.com');\n * if (res.isOk) {\n * console.log(res.ok()); // { name: 'example.com', port: 25565, priority: 0, weight: 5 }\n * } else {\n * console.error(res.err());\n * }\n */\nexport async function srvRecordResult(srv: string): Promise<IResult<SrvRecord, NodeJS.ErrnoException>> {\n\tconst res = await srvRecordsResult(srv);\n\tif (res.isOk) {\n\t\treturn Ok(res.ok()[0]);\n\t} else {\n\t\treturn Err(res.err());\n\t}\n}\n","import varInt from 'varint';\nimport type {IAddress} from './interfaces.mjs';\n\nconst PROTOCOL_VERSION = 736; // Minecraft 1.16.1\n\nexport enum MinecraftPackageType {\n\tHANDSHAKE = 0,\n\tPING = 1,\n}\n\n/**\n * Wrapper for creating Minecraft packets\n * @param {MinecraftPackageType} packetId - packet id\n * @param {Buffer} data - packet data\n * @returns {Buffer} packet buffer data\n */\nfunction createPacket(packetId: MinecraftPackageType, data: Buffer): Buffer {\n\treturn Buffer.concat([Buffer.from(varInt.encode(varInt.encodingLength(packetId) + data.length)), Buffer.from(varInt.encode(packetId)), data]);\n}\n\n/**\n * Create Minecraft handshake packet\n * @param {IAddress} address\n * @returns {Buffer} handshake packet buffer data\n */\nexport function createHandshakePacket(address: IAddress): Buffer {\n\tconst portBuffer = Buffer.allocUnsafe(2);\n\tportBuffer.writeUInt16BE(address.port, 0);\n\t// Return handshake packet with request packet\n\treturn Buffer.concat([\n\t\tcreatePacket(\n\t\t\tMinecraftPackageType.HANDSHAKE,\n\t\t\tBuffer.concat([\n\t\t\t\tBuffer.from(varInt.encode(PROTOCOL_VERSION)),\n\t\t\t\tBuffer.from(varInt.encode(address.hostname.length)),\n\t\t\t\tBuffer.from(address.hostname, 'utf8'),\n\t\t\t\tportBuffer,\n\t\t\t\tBuffer.from(varInt.encode(1)),\n\t\t\t]),\n\t\t),\n\t\tcreatePacket(0, Buffer.alloc(0)),\n\t]);\n}\n\n/**\n * Create ping packet\n * @param {bigint} timestamp\n * @returns {Buffer} ping packet buffer data\n */\nexport function createPingPacket(timestamp: bigint): Buffer {\n\tconst pingBuffer = Buffer.allocUnsafe(8);\n\tpingBuffer.writeBigUInt64BE(timestamp);\n\treturn createPacket(MinecraftPackageType.PING, pingBuffer);\n}\n","import {Writable, type WritableOptions} from 'stream';\nimport varInt from 'varint';\nimport {MinecraftPackageType} from './minecraftPackets.mjs';\n\nexport interface IPacketHeader {\n\tid: MinecraftPackageType;\n\tlength: number;\n\toffset: number;\n}\n\nexport class PacketDecoder extends Writable {\n\tprivate packetInfo: IPacketHeader | undefined;\n\tprivate buffer: Buffer;\n\n\tconstructor(options?: WritableOptions) {\n\t\tsuper(options);\n\t\tthis.buffer = Buffer.alloc(0);\n\t}\n\n\t/**\n\t * Promise to wait specific packet to be received\n\t */\n\tpublic oncePromise<T>(event: string): Promise<T> {\n\t\treturn new Promise((resolve) => {\n\t\t\tthis.once(event, resolve);\n\t\t});\n\t}\n\n\tpublic _write(chunk: Buffer, _encoding: BufferEncoding, callback: (error?: Error | null) => void): void {\n\t\tif (!this.packetInfo) {\n\t\t\tthis.packetInfo = this.decodeHeader(chunk);\n\t\t}\n\t\tthis.buffer = Buffer.concat([this.buffer, chunk]);\n\n\t\tif (this.buffer.length < this.packetInfo.length) {\n\t\t\t// do we still need to read more?\n\t\t\treturn callback();\n\t\t}\n\t\tif (this.buffer.length > this.packetInfo.length) {\n\t\t\treturn callback(new Error('we did overrun expected data size!'));\n\t\t}\n\n\t\ttry {\n\t\t\tswitch (this.packetInfo.id) {\n\t\t\t\tcase MinecraftPackageType.HANDSHAKE: {\n\t\t\t\t\tthis.emit('handshake', this.decodeHandshake(this.getPayload(this.packetInfo, this.buffer)));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase MinecraftPackageType.PING: {\n\t\t\t\t\tthis.emit('pong', this.decodePong(this.getPayload(this.packetInfo, this.buffer)));\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n\t\t\t\t\tthis.emit('error', new Error(`Unknown packet id: ${this.packetInfo.id}`));\n\t\t\t}\n\n\t\t\tthis.buffer = Buffer.alloc(0);\n\t\t\tthis.packetInfo = undefined;\n\t\t} catch (err) {\n\t\t\tthis.emit('error', err);\n\t\t}\n\t\tcallback();\n\t}\n\n\tprivate decodeHeader(buffer: Buffer): IPacketHeader {\n\t\tconst length = varInt.decode(buffer);\n\t\treturn {\n\t\t\tid: buffer.readUInt8(varInt.encodingLength(length)),\n\t\t\tlength: length + varInt.encodingLength(length),\n\t\t\toffset: varInt.encodingLength(length) + 1,\n\t\t};\n\t}\n\n\tprivate getPayload(header: IPacketHeader, data: Buffer) {\n\t\treturn data.subarray(header.offset, data.length);\n\t}\n\n\t/**\n\t * Decodes the handshake JSON data\n\t */\n\tprivate decodeHandshake(buffer: Buffer): Record<string, unknown> {\n\t\tconst length = varInt.decode(buffer);\n\t\tconst data = buffer.subarray(varInt.encodingLength(length), varInt.encodingLength(length) + length);\n\t\treturn JSON.parse(data.toString());\n\t}\n\n\t/**\n\t * Decodes the pong data\n\t */\n\tprivate decodePong(data: Buffer): number {\n\t\tconst pongData = data.readBigUInt64BE(0);\n\t\treturn Number(BigInt(Date.now()) - pongData);\n\t}\n}\n"],"mappings":"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","names":["createConnection","isIP","Err","Ok","resolveSrv","Err","Ok","assertAtLeastOne","data","srvRecordsResult","srv","resolve","error","result","srvRecordResult","res","varInt","PROTOCOL_VERSION","MinecraftPackageType","createPacket","packetId","data","createHandshakePacket","address","portBuffer","createPingPacket","timestamp","pingBuffer","Writable","varInt","PacketDecoder","Writable","options","event","resolve","chunk","_encoding","callback","err","buffer","length","varInt","header","data","pongData","defaultAddress","ensureError","error","checkSrvRecord","hostname","options","isIP","dnsResult","srvRecordResult","name","port","urlToAddress","uri","address","protocol","realPort","pingUri","uriArg","ping","pingUriResult","Ok","err","Err","addressArg","dnsAddress","openConnection","pingResult","timeout","resolve","reject","handleError","thisSocket","socket","createConnection","packetDecoder","PacketDecoder","createHandshakePacket","handshakeData","createPingPacket","pingData","timeoutValue"]}