UNPKG

@imeaces/mcping-tool

Version:
205 lines (203 loc) 7.71 kB
import { dnsLookup } from "./lib.js"; import { resolveMinecraftServerSrvRecord } from "./srv.js"; const ipv6ExactRegex = /^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/; const ipv4ExactRegex = /^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/; /** * 检查一段字符串是否代表一个 IPV4 地址。 */ export function isIPV4(ip) { return ipv4ExactRegex.test(ip); } /** * 检查一段字符串是否代表一个 IPV6 地址。 */ export function isIPV6(ip) { return ipv6ExactRegex.test(ip); } /** * 检查一段字符串是否代表一个 IPV4 或 IPV6 地址。 */ export function isIP(ip) { return isIPV6(ip) || isIPV4(ip); } export { getServerAddressInfo }; async function getServerAddressInfo(serverAddr, option = {}) { let valid = true; let invalidReason; //let invalidReason: any = undefined; let ip = null; let port = null; let srvRecord = null; if (option === "java" || option === "bedrock") option = { serverType: option }; else if (typeof option === "number") option = { serverPort: option }; const { serverType, serverPort, resolveSrvRecord = true, family: addressFamily, preferIpv6 = false, throwsOnInvalid = false, } = option; const connectPoints = []; let serverAddr0 = serverAddr; let serverPort0 = serverPort; /* serverPort 与 serverType 至少有一个需要被指定 */ if (serverPort == null) if (serverType === "java") serverPort0 = 25565; else if (serverType === "bedrock") serverPort0 = 19132; else setInvalid(new TypeError("invalid argument: serverType")); else if (typeof serverPort === "number") serverPort0 = serverPort; // 可能有重复的步骤,但是为了可读性没有合并 else setInvalid(new ReferenceError("invalid arguments, cannot determine server type")); //都没有,参数异常 /* 如果主机名是一个IP地址 */ if (valid && isIP(serverAddr)) { ip = serverAddr; } /* 在前边的判断中没有找到不正确的参数 传入的主机名不是IP Java版服务器 端口未指定 resolveSrvRecord为真 或者 resolveSrvRecord === "force" 尝试获取SRV记录 */ if (valid && (resolveSrvRecord === "force" || (resolveSrvRecord && ip == null && serverPort == null && serverType == "java"))) { srvRecord = await resolveMinecraftServerSrvRecord(serverAddr); if (srvRecord != null) { serverAddr0 = srvRecord.ip; serverPort0 = srvRecord.port; } } // SRV解析得到的主机名可能是IP地址而不是另一个域名 if (valid && ip == null && isIP(serverAddr0)) { ip = serverAddr0; } //在这里检查可能存在的IP地址是否与参数 addressFamily 所期望的相同 //~~同时也判断 addressFamily 参数是否是合法的参数~~ 不检查了,麻烦 if (valid && ip != null && addressFamily != null) { if (addressFamily === 4 && !isIPV4(ip)) setInvalid("address family mismatch"); else if (addressFamily === 6 && !isIPV6(ip)) setInvalid("address family mismatch"); } /* 检查端口是否正确 */ if (serverPort0 != null) port = serverPort0; else { port = -1; setInvalid(new TypeError("missing port argument")); } if (isNaN(port) || port > 65535 || port < 0 /* 话说0是有效的端口嘛? */) { port = -1; setInvalid("invalid port"); } /* 书接上回,这里还没有获得实际的连接IP,并且仍然可能是有效地址(可能来源自SRV记录) 尝试dns解析 */ if (valid && ip == null) { let dnsIps = null; let dnsError = null; try { dnsIps = await dnsLookup(serverAddr0); } catch (e) { dnsError = e; } const dnsIp4 = []; const dnsIp6 = []; if (dnsIps != null) for (const dnsIp of dnsIps) { if (!addressFamily || addressFamily === 4) { if (dnsIp.family === 4) dnsIp4.push(dnsIp.address); } if (!addressFamily || addressFamily === 6) { if (dnsIp.family === 6) dnsIp6.push(dnsIp.address); } } if (preferIpv6 && dnsIp6.length > 0) { ip = dnsIp6[0]; } else if (dnsIp4.length > 0) { ip = dnsIp4[0]; } else if (dnsIp6.length > 0) { ip = dnsIp6[0]; } else { setInvalid(dnsError ?? "no dns data"); } if (dnsIp4.length > 0 && dnsIp6.length > 0) { if (preferIpv6) connectPoints.push({ ip: dnsIp4[0], port }); else connectPoints.push({ ip: dnsIp6[0], port }); } } if (ip != null && port != null) connectPoints.unshift({ ip, port }); //只是一段预防,可能永远也不会触发 if (connectPoints.length === 0 && valid) setInvalid("no connection point found"); if (valid && resolveSrvRecord === "force" && srvRecord == null) { setInvalid("no srv record found"); } if (!valid) { let finalError; if (invalidReason instanceof Error) { finalError = invalidReason; } else if (invalidReason != null) { finalError = new Error(invalidReason); } else { finalError = new Error("unknown error while resolving dns data"); } if (throwsOnInvalid) throw finalError; return { valid, invalidReason: finalError, serverAddr }; } else if (srvRecord != null) { return { valid, //@ts-ignore 也许我代码写得太复杂了 ip, port, connectPoints, srvRecord, serverAddr }; } else { return { valid, //@ts-ignore 也许我代码写得太复杂了 ip, port, connectPoints, serverAddr }; } function setInvalid(reason) { if (valid) { invalidReason = reason; valid = false; } } } //# sourceMappingURL=serverAddr.js.map