1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.ipToBuffer = exports.int32ToIpv4 = exports.ipv4ToInt32 = exports.validateSocksClientChainOptions = exports.validateSocksClientOptions = void 0;
4const util_1 = require("./util");
5const constants_1 = require("./constants");
6const stream = require("stream");
7const ip_address_1 = require("ip-address");
8const net = require("net");
9/**
10 * Validates the provided SocksClientOptions
11 * @param options { SocksClientOptions }
12 * @param acceptedCommands { string[] } A list of accepted SocksProxy commands.
13 */
14function validateSocksClientOptions(options, acceptedCommands = ['connect', 'bind', 'associate']) {
15    // Check SOCKs command option.
16    if (!constants_1.SocksCommand[options.command]) {
17        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksCommand, options);
18    }
19    // Check SocksCommand for acceptable command.
20    if (acceptedCommands.indexOf(options.command) === -1) {
21        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksCommandForOperation, options);
22    }
23    // Check destination
24    if (!isValidSocksRemoteHost(options.destination)) {
25        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsDestination, options);
26    }
27    // Check SOCKS proxy to use
28    if (!isValidSocksProxy(options.proxy)) {
29        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsProxy, options);
30    }
31    // Validate custom auth (if set)
32    validateCustomProxyAuth(options.proxy, options);
33    // Check timeout
34    if (options.timeout && !isValidTimeoutValue(options.timeout)) {
35        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsTimeout, options);
36    }
37    // Check existing_socket (if provided)
38    if (options.existing_socket &&
39        !(options.existing_socket instanceof stream.Duplex)) {
40        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsExistingSocket, options);
41    }
42}
43exports.validateSocksClientOptions = validateSocksClientOptions;
44/**
45 * Validates the SocksClientChainOptions
46 * @param options { SocksClientChainOptions }
47 */
48function validateSocksClientChainOptions(options) {
49    // Only connect is supported when chaining.
50    if (options.command !== 'connect') {
51        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksCommandChain, options);
52    }
53    // Check destination
54    if (!isValidSocksRemoteHost(options.destination)) {
55        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsDestination, options);
56    }
57    // Validate proxies (length)
58    if (!(options.proxies &&
59        Array.isArray(options.proxies) &&
60        options.proxies.length >= 2)) {
61        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsProxiesLength, options);
62    }
63    // Validate proxies
64    options.proxies.forEach((proxy) => {
65        if (!isValidSocksProxy(proxy)) {
66            throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsProxy, options);
67        }
68        // Validate custom auth (if set)
69        validateCustomProxyAuth(proxy, options);
70    });
71    // Check timeout
72    if (options.timeout && !isValidTimeoutValue(options.timeout)) {
73        throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsTimeout, options);
74    }
75}
76exports.validateSocksClientChainOptions = validateSocksClientChainOptions;
77function validateCustomProxyAuth(proxy, options) {
78    if (proxy.custom_auth_method !== undefined) {
79        // Invalid auth method range
80        if (proxy.custom_auth_method < constants_1.SOCKS5_CUSTOM_AUTH_START ||
81            proxy.custom_auth_method > constants_1.SOCKS5_CUSTOM_AUTH_END) {
82            throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthRange, options);
83        }
84        // Missing custom_auth_request_handler
85        if (proxy.custom_auth_request_handler === undefined ||
86            typeof proxy.custom_auth_request_handler !== 'function') {
87            throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthOptions, options);
88        }
89        // Missing custom_auth_response_size
90        if (proxy.custom_auth_response_size === undefined) {
91            throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthOptions, options);
92        }
93        // Missing/invalid custom_auth_response_handler
94        if (proxy.custom_auth_response_handler === undefined ||
95            typeof proxy.custom_auth_response_handler !== 'function') {
96            throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthOptions, options);
97        }
98    }
99}
100/**
101 * Validates a SocksRemoteHost
102 * @param remoteHost { SocksRemoteHost }
103 */
104function isValidSocksRemoteHost(remoteHost) {
105    return (remoteHost &&
106        typeof remoteHost.host === 'string' &&
107        typeof remoteHost.port === 'number' &&
108        remoteHost.port >= 0 &&
109        remoteHost.port <= 65535);
110}
111/**
112 * Validates a SocksProxy
113 * @param proxy { SocksProxy }
114 */
115function isValidSocksProxy(proxy) {
116    return (proxy &&
117        (typeof proxy.host === 'string' || typeof proxy.ipaddress === 'string') &&
118        typeof proxy.port === 'number' &&
119        proxy.port >= 0 &&
120        proxy.port <= 65535 &&
121        (proxy.type === 4 || proxy.type === 5));
122}
123/**
124 * Validates a timeout value.
125 * @param value { Number }
126 */
127function isValidTimeoutValue(value) {
128    return typeof value === 'number' && value > 0;
129}
130function ipv4ToInt32(ip) {
131    const address = new ip_address_1.Address4(ip);
132    // Convert the IPv4 address parts to an integer
133    return address.toArray().reduce((acc, part) => (acc << 8) + part, 0);
134}
135exports.ipv4ToInt32 = ipv4ToInt32;
136function int32ToIpv4(int32) {
137    // Extract each byte (octet) from the 32-bit integer
138    const octet1 = (int32 >>> 24) & 0xff;
139    const octet2 = (int32 >>> 16) & 0xff;
140    const octet3 = (int32 >>> 8) & 0xff;
141    const octet4 = int32 & 0xff;
142    // Combine the octets into a string in IPv4 format
143    return [octet1, octet2, octet3, octet4].join('.');
144}
145exports.int32ToIpv4 = int32ToIpv4;
146function ipToBuffer(ip) {
147    if (net.isIPv4(ip)) {
148        // Handle IPv4 addresses
149        const address = new ip_address_1.Address4(ip);
150        return Buffer.from(address.toArray());
151    }
152    else if (net.isIPv6(ip)) {
153        // Handle IPv6 addresses
154        const address = new ip_address_1.Address6(ip);
155        return Buffer.from(address.toByteArray());
156    }
157    else {
158        throw new Error('Invalid IP address format');
159    }
160}
161exports.ipToBuffer = ipToBuffer;
162//# sourceMappingURL=helpers.js.map