UNPKG

knxnetjs

Version:

A TypeScript library for KNXnet/IP communication

117 lines 4.44 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HPAI = exports.HostProtocol = void 0; var HostProtocol; (function (HostProtocol) { HostProtocol[HostProtocol["IPV4_UDP"] = 1] = "IPV4_UDP"; HostProtocol[HostProtocol["IPV4_TCP"] = 2] = "IPV4_TCP"; })(HostProtocol || (exports.HostProtocol = HostProtocol = {})); class HPAI { constructor(hostProtocol, address, port) { this.hostProtocol = hostProtocol; this.address = address; this.port = port; } static fromBuffer(buffer) { if (buffer.length !== 8) { throw new Error(`Invalid buffer length: expected 8 bytes, got ${buffer.length}`); } const structureLength = buffer.readUInt8(0); if (structureLength !== 0x08) { throw new Error(`Invalid structure length: expected 0x08, got 0x${structureLength.toString(16)}`); } const hostProtocol = buffer.readUInt8(1); if (hostProtocol !== HostProtocol.IPV4_UDP && hostProtocol !== HostProtocol.IPV4_TCP) { throw new Error(`Invalid host protocol: 0x${hostProtocol.toString(16)}`); } // Read IPv4 address (4 bytes in network byte order) const addressBytes = [ buffer.readUInt8(2), buffer.readUInt8(3), buffer.readUInt8(4), buffer.readUInt8(5) ]; const address = addressBytes.join('.'); // Validate IPv4 address format if (!this.isValidIPv4(address)) { throw new Error(`Invalid IPv4 address: ${address}`); } // Read port number (2 bytes in network byte order) const port = buffer.readUInt16BE(6); if (port > 65535) { throw new Error(`Invalid port number: ${port}`); } return new HPAI(hostProtocol, address, port); } toBuffer() { if (!this.isValid()) { throw new Error('Cannot serialize invalid HPAI instance'); } const buffer = Buffer.alloc(8); // Write structure length buffer.writeUInt8(0x08, 0); // Write host protocol buffer.writeUInt8(this.hostProtocol, 1); // Write IPv4 address (4 bytes in network byte order) const addressParts = this.address.split('.').map(part => parseInt(part, 10)); if (addressParts.length !== 4) { throw new Error(`Invalid IPv4 address format: ${this.address}`); } for (let i = 0; i < 4; i++) { const part = addressParts[i]; // We already validated length is 4 if (isNaN(part) || part < 0 || part > 255) { throw new Error(`Invalid IPv4 address octet: ${part}`); } buffer.writeUInt8(part, 2 + i); } // Write port number (2 bytes in network byte order) buffer.writeUInt16BE(this.port, 6); return buffer; } isValid() { // Validate host protocol if (this.hostProtocol !== HostProtocol.IPV4_UDP && this.hostProtocol !== HostProtocol.IPV4_TCP) { return false; } // Validate IPv4 address if (!HPAI.isValidIPv4(this.address)) { return false; } // Validate port range (0 is valid in KNXnet/IP - means use source port) if (this.port < 0 || this.port > 65535) { return false; } return true; } toString() { const protocol = this.hostProtocol === HostProtocol.IPV4_UDP ? 'UDP' : 'TCP'; return `${protocol}://${this.address}:${this.port}`; } static isValidIPv4(address) { if (!address || typeof address !== 'string') { return false; } const parts = address.split('.'); if (parts.length !== 4) { return false; } for (const part of parts) { // Check if part is a valid number const num = parseInt(part, 10); if (isNaN(num) || num < 0 || num > 255) { return false; } // Check for leading zeros (except for '0' itself) if (part.length > 1 && part[0] === '0') { return false; } // Check if the string representation matches the parsed number if (part !== num.toString()) { return false; } } return true; } } exports.HPAI = HPAI; //# sourceMappingURL=hpai.js.map