* Handle CONNECT response
()
| 10801 | * Handle CONNECT response |
| 10802 | */ |
| 10803 | handleConnectResponse() { |
| 10804 | if (this.buffer.length < 4) { |
| 10805 | return; |
| 10806 | } |
| 10807 | const version = this.buffer[0]; |
| 10808 | const reply = this.buffer[1]; |
| 10809 | const addressType = this.buffer[3]; |
| 10810 | if (version !== SOCKS_VERSION) { |
| 10811 | throw new Socks5ProxyError(`Invalid SOCKS version in reply: ${version}`, "UND_ERR_SOCKS5_REPLY_VERSION"); |
| 10812 | } |
| 10813 | let responseLength = 4; |
| 10814 | if (addressType === ADDRESS_TYPES.IPV4) { |
| 10815 | responseLength += 4 + 2; |
| 10816 | } else if (addressType === ADDRESS_TYPES.DOMAIN) { |
| 10817 | if (this.buffer.length < 5) { |
| 10818 | return; |
| 10819 | } |
| 10820 | responseLength += 1 + this.buffer[4] + 2; |
| 10821 | } else if (addressType === ADDRESS_TYPES.IPV6) { |
| 10822 | responseLength += 16 + 2; |
| 10823 | } else { |
| 10824 | throw new Socks5ProxyError(`Invalid address type in reply: ${addressType}`, "UND_ERR_SOCKS5_ADDR_TYPE"); |
| 10825 | } |
| 10826 | if (this.buffer.length < responseLength) { |
| 10827 | return; |
| 10828 | } |
| 10829 | if (reply !== REPLY_CODES.SUCCEEDED) { |
| 10830 | const errorMessage = this.getReplyErrorMessage(reply); |
| 10831 | throw new Socks5ProxyError(`SOCKS5 connection failed: ${errorMessage}`, `UND_ERR_SOCKS5_REPLY_${reply}`); |
| 10832 | } |
| 10833 | let boundAddress; |
| 10834 | let offset = 4; |
| 10835 | if (addressType === ADDRESS_TYPES.IPV4) { |
| 10836 | boundAddress = Array.from(this.buffer.subarray(offset, offset + 4)).join("."); |
| 10837 | offset += 4; |
| 10838 | } else if (addressType === ADDRESS_TYPES.DOMAIN) { |
| 10839 | const domainLength = this.buffer[offset]; |
| 10840 | offset += 1; |
| 10841 | boundAddress = this.buffer.subarray(offset, offset + domainLength).toString(); |
| 10842 | offset += domainLength; |
| 10843 | } else if (addressType === ADDRESS_TYPES.IPV6) { |
| 10844 | const parts = []; |
| 10845 | for (let i = 0; i < 8; i++) { |
| 10846 | const value = this.buffer.readUInt16BE(offset + i * 2); |
| 10847 | parts.push(value.toString(16)); |
| 10848 | } |
| 10849 | boundAddress = parts.join(":"); |
| 10850 | offset += 16; |
| 10851 | } |
| 10852 | const boundPort = this.buffer.readUInt16BE(offset); |
| 10853 | this.buffer = EMPTY_BUFFER; |
| 10854 | this.state = STATES.CONNECTED; |
| 10855 | this.socket.removeListener("data", this.onSocketData); |
| 10856 | debug("connected, bound address:", boundAddress, "port:", boundPort); |
| 10857 | this.emit("connected", { address: boundAddress, port: boundPort }); |
| 10858 | } |
| 10859 | /** |
| 10860 | * Get human-readable error message for reply code |
no test coverage detected