@mtkruto/browser 0.133.0 → 0.135.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/0_deps.d.ts +1 -0
- package/esm/0_deps.d.ts.map +1 -1
- package/esm/0_deps.js +1 -0
- package/esm/1_utilities.d.ts +1 -0
- package/esm/1_utilities.d.ts.map +1 -1
- package/esm/1_utilities.js +1 -0
- package/esm/2_connection.d.ts +1 -0
- package/esm/2_connection.d.ts.map +1 -1
- package/esm/2_connection.js +1 -0
- package/esm/3_transport.d.ts +1 -0
- package/esm/3_transport.d.ts.map +1 -1
- package/esm/3_transport.js +1 -0
- package/esm/3_types.d.ts +1 -0
- package/esm/3_types.d.ts.map +1 -1
- package/esm/3_types.js +1 -0
- package/esm/client/0_params.d.ts +24 -2
- package/esm/client/0_params.d.ts.map +1 -1
- package/esm/client/0_utilities.d.ts +1 -1
- package/esm/client/0_utilities.d.ts.map +1 -1
- package/esm/client/1_client_generic.d.ts +11 -3
- package/esm/client/1_client_generic.d.ts.map +1 -1
- package/esm/client/3_message_manager.d.ts.map +1 -1
- package/esm/client/3_message_manager.js +13 -9
- package/esm/client/4_gift_manager.d.ts +3 -2
- package/esm/client/4_gift_manager.d.ts.map +1 -1
- package/esm/client/4_gift_manager.js +9 -0
- package/esm/client/4_poll_manager.js +1 -1
- package/esm/client/6_client.d.ts +11 -3
- package/esm/client/6_client.d.ts.map +1 -1
- package/esm/client/6_client.js +11 -1
- package/esm/client/6_client_dispatcher.d.ts +11 -3
- package/esm/client/6_client_dispatcher.d.ts.map +1 -1
- package/esm/client/6_client_dispatcher.js +11 -1
- package/esm/connection/1_connection_socks5.d.ts +36 -0
- package/esm/connection/1_connection_socks5.d.ts.map +1 -0
- package/esm/connection/1_connection_socks5.js +192 -0
- package/esm/connection/1_connection_socks5.node.d.ts +35 -0
- package/esm/connection/1_connection_socks5.node.d.ts.map +1 -0
- package/esm/connection/1_connection_socks5.node.js +214 -0
- package/esm/connection/1_connection_tcp.d.ts.map +1 -1
- package/esm/connection/1_connection_tcp.js +0 -1
- package/esm/deps/jsr.io/@std/net/1.0.6/unstable_ip.d.ts +103 -0
- package/esm/deps/jsr.io/@std/net/1.0.6/unstable_ip.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/net/1.0.6/unstable_ip.js +296 -0
- package/esm/tl/1_telegram_api.d.ts +1616 -10
- package/esm/tl/1_telegram_api.d.ts.map +1 -1
- package/esm/tl/1_telegram_api.js +333 -48
- package/esm/transport/2_transport_provider_mtproxy.d.ts +1 -1
- package/esm/transport/2_transport_provider_mtproxy.d.ts.map +1 -1
- package/esm/transport/2_transport_provider_mtproxy.js +3 -3
- package/esm/transport/2_transport_provider_socks5.d.ts +27 -0
- package/esm/transport/2_transport_provider_socks5.d.ts.map +1 -0
- package/esm/transport/2_transport_provider_socks5.js +45 -0
- package/esm/types/0_premium_subscription_duration.d.ts +21 -0
- package/esm/types/0_premium_subscription_duration.d.ts.map +1 -0
- package/esm/types/0_premium_subscription_duration.js +20 -0
- package/esm/types/3_poll_option.d.ts +1 -1
- package/esm/types/3_poll_option.d.ts.map +1 -1
- package/esm/types/3_poll_option.js +2 -1
- package/esm/types/4_poll.d.ts +3 -3
- package/esm/types/4_poll.d.ts.map +1 -1
- package/esm/types/4_poll.js +5 -3
- package/esm/types/5_star_transaction.js +2 -2
- package/esm/utilities/0_ip.d.ts +22 -0
- package/esm/utilities/0_ip.d.ts.map +1 -0
- package/esm/utilities/0_ip.js +73 -0
- package/package.json +1 -1
- package/script/0_deps.d.ts +1 -0
- package/script/0_deps.d.ts.map +1 -1
- package/script/0_deps.js +4 -1
- package/script/1_utilities.d.ts +1 -0
- package/script/1_utilities.d.ts.map +1 -1
- package/script/1_utilities.js +1 -0
- package/script/2_connection.d.ts +1 -0
- package/script/2_connection.d.ts.map +1 -1
- package/script/2_connection.js +1 -0
- package/script/3_transport.d.ts +1 -0
- package/script/3_transport.d.ts.map +1 -1
- package/script/3_transport.js +1 -0
- package/script/3_types.d.ts +1 -0
- package/script/3_types.d.ts.map +1 -1
- package/script/3_types.js +1 -0
- package/script/client/0_params.d.ts +24 -2
- package/script/client/0_params.d.ts.map +1 -1
- package/script/client/0_utilities.d.ts +1 -1
- package/script/client/0_utilities.d.ts.map +1 -1
- package/script/client/1_client_generic.d.ts +11 -3
- package/script/client/1_client_generic.d.ts.map +1 -1
- package/script/client/3_message_manager.d.ts.map +1 -1
- package/script/client/3_message_manager.js +13 -9
- package/script/client/4_gift_manager.d.ts +3 -2
- package/script/client/4_gift_manager.d.ts.map +1 -1
- package/script/client/4_gift_manager.js +9 -0
- package/script/client/4_poll_manager.js +1 -1
- package/script/client/6_client.d.ts +11 -3
- package/script/client/6_client.d.ts.map +1 -1
- package/script/client/6_client.js +11 -1
- package/script/client/6_client_dispatcher.d.ts +11 -3
- package/script/client/6_client_dispatcher.d.ts.map +1 -1
- package/script/client/6_client_dispatcher.js +11 -1
- package/script/connection/1_connection_socks5.d.ts +36 -0
- package/script/connection/1_connection_socks5.d.ts.map +1 -0
- package/script/connection/1_connection_socks5.js +196 -0
- package/script/connection/1_connection_socks5.node.d.ts +35 -0
- package/script/connection/1_connection_socks5.node.d.ts.map +1 -0
- package/script/connection/1_connection_socks5.node.js +218 -0
- package/script/connection/1_connection_tcp.d.ts.map +1 -1
- package/script/connection/1_connection_tcp.js +0 -1
- package/script/deps/jsr.io/@std/net/1.0.6/unstable_ip.d.ts +103 -0
- package/script/deps/jsr.io/@std/net/1.0.6/unstable_ip.d.ts.map +1 -0
- package/script/deps/jsr.io/@std/net/1.0.6/unstable_ip.js +303 -0
- package/script/tl/1_telegram_api.d.ts +1616 -10
- package/script/tl/1_telegram_api.d.ts.map +1 -1
- package/script/tl/1_telegram_api.js +333 -48
- package/script/transport/2_transport_provider_mtproxy.d.ts +1 -1
- package/script/transport/2_transport_provider_mtproxy.d.ts.map +1 -1
- package/script/transport/2_transport_provider_mtproxy.js +3 -3
- package/script/transport/2_transport_provider_socks5.d.ts +27 -0
- package/script/transport/2_transport_provider_socks5.d.ts.map +1 -0
- package/script/transport/2_transport_provider_socks5.js +48 -0
- package/script/types/0_premium_subscription_duration.d.ts +21 -0
- package/script/types/0_premium_subscription_duration.d.ts.map +1 -0
- package/script/types/0_premium_subscription_duration.js +21 -0
- package/script/types/3_poll_option.d.ts +1 -1
- package/script/types/3_poll_option.d.ts.map +1 -1
- package/script/types/3_poll_option.js +2 -1
- package/script/types/4_poll.d.ts +3 -3
- package/script/types/4_poll.d.ts.map +1 -1
- package/script/types/4_poll.js +5 -3
- package/script/types/5_star_transaction.js +1 -1
- package/script/utilities/0_ip.d.ts +22 -0
- package/script/utilities/0_ip.d.ts.map +1 -0
- package/script/utilities/0_ip.js +77 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MTKruto - Cross-runtime JavaScript library for building Telegram clients
|
|
4
|
+
* Copyright (C) 2023-2026 Roj <https://roj.im/>
|
|
5
|
+
*
|
|
6
|
+
* This file is part of MTKruto.
|
|
7
|
+
*
|
|
8
|
+
* This program is free software: you can redistribute it and/or modify
|
|
9
|
+
* it under the terms of the GNU Lesser General Public License as published by
|
|
10
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
11
|
+
* (at your option) any later version.
|
|
12
|
+
*
|
|
13
|
+
* This program is distributed in the hope that it will be useful,
|
|
14
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
* GNU Lesser General Public License for more details.
|
|
17
|
+
*
|
|
18
|
+
* You should have received a copy of the GNU Lesser General Public License
|
|
19
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.ConnectionSocks5 = void 0;
|
|
23
|
+
const _0_deps_js_1 = require("../0_deps.js");
|
|
24
|
+
const _0_errors_js_1 = require("../0_errors.js");
|
|
25
|
+
const _1_utilities_js_1 = require("../1_utilities.js");
|
|
26
|
+
const VERSION_SOCKS = 5;
|
|
27
|
+
const VERSION_USERNAME_PASSWORD_AUTH = 1;
|
|
28
|
+
const AUTH_MEHTOD_NONE = 0;
|
|
29
|
+
const AUTH_METHOD_USERNAME_PASSWORD = 2;
|
|
30
|
+
const RESULT_SUCCESS = 0;
|
|
31
|
+
const COMMAND_CONNECT = 1;
|
|
32
|
+
const ADDRESS_TYPE_4 = 1;
|
|
33
|
+
const ADDRESS_TYPE_DOMAIN_NAME = 3;
|
|
34
|
+
const ADDRESS_TYPE_6 = 4;
|
|
35
|
+
const L = (0, _1_utilities_js_1.getLogger)("ConnectionSocks5");
|
|
36
|
+
class ConnectionSocks5 {
|
|
37
|
+
#hostname;
|
|
38
|
+
#port;
|
|
39
|
+
#socks5Hostname;
|
|
40
|
+
#socks5Port;
|
|
41
|
+
#credentials;
|
|
42
|
+
#connection;
|
|
43
|
+
#rMutex = new _1_utilities_js_1.Mutex();
|
|
44
|
+
#wMutex = new _1_utilities_js_1.Mutex();
|
|
45
|
+
#canRead = false;
|
|
46
|
+
#canWrite = false;
|
|
47
|
+
stateChangeHandler;
|
|
48
|
+
callback;
|
|
49
|
+
constructor(hostname, port, socks5Hostname, socks5Port, params) {
|
|
50
|
+
this.#hostname = hostname.slice(0, 255);
|
|
51
|
+
this.#port = port;
|
|
52
|
+
this.#socks5Hostname = socks5Hostname;
|
|
53
|
+
this.#socks5Port = socks5Port;
|
|
54
|
+
this.#credentials = params?.username && params.password ? { username: params.username.slice(0, 255), password: params.password.slice(0, 255) } : undefined;
|
|
55
|
+
}
|
|
56
|
+
get isConnected() {
|
|
57
|
+
return !!this.#connection && this.#canRead && this.#canWrite;
|
|
58
|
+
}
|
|
59
|
+
#assertConnected() {
|
|
60
|
+
if (!this.isConnected) {
|
|
61
|
+
throw new _0_errors_js_1.ConnectionError("The connection is not open.");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async open() {
|
|
65
|
+
if (this.isConnected) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const connection = await Deno.connect({
|
|
69
|
+
hostname: this.#socks5Hostname,
|
|
70
|
+
port: this.#socks5Port,
|
|
71
|
+
});
|
|
72
|
+
connection.setNoDelay(true);
|
|
73
|
+
connection.setKeepAlive(true);
|
|
74
|
+
this.#canRead = this.#canWrite = true;
|
|
75
|
+
this.#connection = connection;
|
|
76
|
+
const header = new Uint8Array([VERSION_SOCKS, 2, AUTH_MEHTOD_NONE, AUTH_METHOD_USERNAME_PASSWORD]);
|
|
77
|
+
await this.write(header);
|
|
78
|
+
const negotiation = new Uint8Array(2);
|
|
79
|
+
await this.read(negotiation);
|
|
80
|
+
if (negotiation[0] !== VERSION_SOCKS || (negotiation[1] !== AUTH_MEHTOD_NONE && negotiation[1] !== AUTH_METHOD_USERNAME_PASSWORD)) {
|
|
81
|
+
throw new _0_errors_js_1.ConnectionError("Negotiation with SOCKS5 server failed.");
|
|
82
|
+
}
|
|
83
|
+
if (negotiation[1] === AUTH_METHOD_USERNAME_PASSWORD && !this.#credentials) {
|
|
84
|
+
throw new _0_errors_js_1.ConnectionError("Username and password are required for connecting to SOCKS5 server.");
|
|
85
|
+
}
|
|
86
|
+
else if (this.#credentials) {
|
|
87
|
+
await this.write((0, _0_deps_js_1.concat)([new Uint8Array([VERSION_USERNAME_PASSWORD_AUTH, this.#credentials.username.length]), (0, _1_utilities_js_1.encodeText)(this.#credentials.username), new Uint8Array([this.#credentials.password.length]), (0, _1_utilities_js_1.encodeText)(this.#credentials.password)]));
|
|
88
|
+
const status = new Uint8Array(2);
|
|
89
|
+
await this.read(status);
|
|
90
|
+
if (status[0] !== VERSION_USERNAME_PASSWORD_AUTH || status[1] !== RESULT_SUCCESS) {
|
|
91
|
+
throw new _0_errors_js_1.ConnectionError("SOCKS5 username and password authentication failed.");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
let hostnameType;
|
|
95
|
+
let hostname;
|
|
96
|
+
if ((0, _0_deps_js_1.isIPv4)(this.#hostname)) {
|
|
97
|
+
hostnameType = ADDRESS_TYPE_4;
|
|
98
|
+
hostname = new Uint8Array((0, _1_utilities_js_1.ipv4ToBytes)(this.#hostname));
|
|
99
|
+
}
|
|
100
|
+
else if ((0, _0_deps_js_1.isIPv6)(this.#hostname)) {
|
|
101
|
+
hostnameType = ADDRESS_TYPE_6;
|
|
102
|
+
hostname = new Uint8Array((0, _1_utilities_js_1.ipv6ToBytes)(this.#hostname));
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
hostnameType = ADDRESS_TYPE_DOMAIN_NAME;
|
|
106
|
+
hostname = (0, _0_deps_js_1.concat)([new Uint8Array([this.#hostname.length]), (0, _1_utilities_js_1.encodeText)(this.#hostname)]);
|
|
107
|
+
}
|
|
108
|
+
const address = (0, _0_deps_js_1.concat)([new Uint8Array([hostnameType]), hostname, new Uint8Array(2)]);
|
|
109
|
+
new DataView(address.buffer).setUint16(hostname.byteLength + 1, this.#port);
|
|
110
|
+
await this.write((0, _0_deps_js_1.concat)([new Uint8Array([VERSION_SOCKS, COMMAND_CONNECT, 0]), address]));
|
|
111
|
+
const status = new Uint8Array(3);
|
|
112
|
+
await this.read(status);
|
|
113
|
+
if (status[0] !== VERSION_SOCKS || status[1] !== RESULT_SUCCESS) {
|
|
114
|
+
throw new _0_errors_js_1.ConnectionError("Connection with SOCKS5 server failed.");
|
|
115
|
+
}
|
|
116
|
+
const addressType = new Uint8Array(1);
|
|
117
|
+
await this.read(addressType);
|
|
118
|
+
switch (addressType[0]) {
|
|
119
|
+
case ADDRESS_TYPE_4: {
|
|
120
|
+
const ipv4 = new Uint8Array(4);
|
|
121
|
+
await this.read(ipv4);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
case ADDRESS_TYPE_6: {
|
|
125
|
+
const ipv4 = new Uint8Array(16);
|
|
126
|
+
await this.read(ipv4);
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
case ADDRESS_TYPE_DOMAIN_NAME: {
|
|
130
|
+
const length = new Uint8Array(1);
|
|
131
|
+
await this.read(length);
|
|
132
|
+
const domainName = new Uint8Array(length[0]);
|
|
133
|
+
await this.read(domainName);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const port = new Uint8Array(2);
|
|
138
|
+
await this.read(port);
|
|
139
|
+
this.stateChangeHandler?.(true);
|
|
140
|
+
L.debug("connected to", this.#hostname, "port", this.#port, "through socks5 server", this.#socks5Hostname, "port", this.#socks5Port);
|
|
141
|
+
}
|
|
142
|
+
async read(p) {
|
|
143
|
+
this.#assertConnected();
|
|
144
|
+
const unlock = await this.#rMutex.lock();
|
|
145
|
+
let offset = 0;
|
|
146
|
+
try {
|
|
147
|
+
do {
|
|
148
|
+
const read = await this.#connection.read(p.subarray(offset));
|
|
149
|
+
if (read === null) {
|
|
150
|
+
this.#canRead = false;
|
|
151
|
+
this.stateChangeHandler?.(false);
|
|
152
|
+
throw new _0_errors_js_1.ConnectionError("The connection was closed.");
|
|
153
|
+
}
|
|
154
|
+
offset += read;
|
|
155
|
+
} while (offset < p.byteLength);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
this.#canRead = false;
|
|
159
|
+
this.stateChangeHandler?.(false);
|
|
160
|
+
throw new _0_errors_js_1.ConnectionError("The connection was closed.");
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
unlock();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
async write(p) {
|
|
167
|
+
this.#assertConnected();
|
|
168
|
+
const unlock = await this.#wMutex.lock();
|
|
169
|
+
try {
|
|
170
|
+
this.#assertConnected();
|
|
171
|
+
let written = 0;
|
|
172
|
+
while (written < p.byteLength) {
|
|
173
|
+
try {
|
|
174
|
+
const wrote = await this.#connection.write(p.subarray(written));
|
|
175
|
+
this.callback?.write(wrote);
|
|
176
|
+
written += wrote;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
this.#canWrite = false;
|
|
180
|
+
this.stateChangeHandler?.(false);
|
|
181
|
+
throw new _0_errors_js_1.ConnectionError("The connection was closed.");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
unlock();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
close() {
|
|
190
|
+
this.#assertConnected();
|
|
191
|
+
this.#connection.close();
|
|
192
|
+
this.#canRead = this.#canWrite = false;
|
|
193
|
+
this.#connection = undefined;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
exports.ConnectionSocks5 = ConnectionSocks5;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MTKruto - Cross-runtime JavaScript library for building Telegram clients
|
|
3
|
+
* Copyright (C) 2023-2026 Roj <https://roj.im/>
|
|
4
|
+
*
|
|
5
|
+
* This file is part of MTKruto.
|
|
6
|
+
*
|
|
7
|
+
* This program is free software: you can redistribute it and/or modify
|
|
8
|
+
* it under the terms of the GNU Lesser General Public License as published by
|
|
9
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
* (at your option) any later version.
|
|
11
|
+
*
|
|
12
|
+
* This program is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
* GNU Lesser General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU Lesser General Public License
|
|
18
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
19
|
+
*/
|
|
20
|
+
import type { Connection } from "./0_connection.js";
|
|
21
|
+
export interface ConnectionSocks5Params {
|
|
22
|
+
username: string;
|
|
23
|
+
password: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class ConnectionSocks5 implements Connection {
|
|
26
|
+
#private;
|
|
27
|
+
stateChangeHandler?: Connection["stateChangeHandler"];
|
|
28
|
+
constructor(hostname: string, port: number, socks5Hostname: string, socks5Port: number, params?: ConnectionSocks5Params);
|
|
29
|
+
open(): Promise<void> | undefined;
|
|
30
|
+
get isConnected(): boolean;
|
|
31
|
+
read(p: Uint8Array): Promise<void>;
|
|
32
|
+
write(p: Uint8Array): Promise<void>;
|
|
33
|
+
close(): void;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=1_connection_socks5.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"1_connection_socks5.node.d.ts","sourceRoot":"","sources":["../../src/connection/1_connection_socks5.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAkBpD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,gBAAiB,YAAW,UAAU;;IAejD,kBAAkB,CAAC,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC;gBAE1C,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,sBAAsB;IAevH,IAAI;IAoHJ,IAAI,WAAW,YAEd;IAQK,IAAI,CAAC,CAAC,EAAE,UAAU;IAclB,KAAK,CAAC,CAAC,EAAE,UAAU;IA0BzB,KAAK;CAKN"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MTKruto - Cross-runtime JavaScript library for building Telegram clients
|
|
4
|
+
* Copyright (C) 2023-2026 Roj <https://roj.im/>
|
|
5
|
+
*
|
|
6
|
+
* This file is part of MTKruto.
|
|
7
|
+
*
|
|
8
|
+
* This program is free software: you can redistribute it and/or modify
|
|
9
|
+
* it under the terms of the GNU Lesser General Public License as published by
|
|
10
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
11
|
+
* (at your option) any later version.
|
|
12
|
+
*
|
|
13
|
+
* This program is distributed in the hope that it will be useful,
|
|
14
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
* GNU Lesser General Public License for more details.
|
|
17
|
+
*
|
|
18
|
+
* You should have received a copy of the GNU Lesser General Public License
|
|
19
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.ConnectionSocks5 = void 0;
|
|
23
|
+
const node_net_1 = require("node:net");
|
|
24
|
+
const _0_deps_js_1 = require("../0_deps.js");
|
|
25
|
+
const _0_errors_js_1 = require("../0_errors.js");
|
|
26
|
+
const _1_utilities_js_1 = require("../1_utilities.js");
|
|
27
|
+
const VERSION_SOCKS = 5;
|
|
28
|
+
const VERSION_USERNAME_PASSWORD_AUTH = 1;
|
|
29
|
+
const AUTH_MEHTOD_NONE = 0;
|
|
30
|
+
const AUTH_METHOD_USERNAME_PASSWORD = 2;
|
|
31
|
+
const RESULT_SUCCESS = 0;
|
|
32
|
+
const COMMAND_CONNECT = 1;
|
|
33
|
+
const ADDRESS_TYPE_4 = 1;
|
|
34
|
+
const ADDRESS_TYPE_DOMAIN_NAME = 3;
|
|
35
|
+
const ADDRESS_TYPE_6 = 4;
|
|
36
|
+
const L = (0, _1_utilities_js_1.getLogger)("ConnectionTCP");
|
|
37
|
+
const errConnectionNotOpen = new _0_errors_js_1.ConnectionError("The connection is not open.");
|
|
38
|
+
class ConnectionSocks5 {
|
|
39
|
+
#hostname;
|
|
40
|
+
#port;
|
|
41
|
+
#socks5Hostname;
|
|
42
|
+
#socks5Port;
|
|
43
|
+
#credentials;
|
|
44
|
+
#socket;
|
|
45
|
+
#rMutex = new _1_utilities_js_1.Mutex();
|
|
46
|
+
#wMutex = new _1_utilities_js_1.Mutex();
|
|
47
|
+
#buffer = new Array();
|
|
48
|
+
#nextResolve = null;
|
|
49
|
+
stateChangeHandler;
|
|
50
|
+
constructor(hostname, port, socks5Hostname, socks5Port, params) {
|
|
51
|
+
this.#hostname = hostname.slice(0, 255);
|
|
52
|
+
this.#port = port;
|
|
53
|
+
this.#socks5Hostname = socks5Hostname;
|
|
54
|
+
this.#socks5Port = socks5Port;
|
|
55
|
+
this.#credentials = params?.username && params.password ? { username: params.username.slice(0, 255), password: params.password.slice(0, 255) } : undefined;
|
|
56
|
+
}
|
|
57
|
+
#rejectRead() {
|
|
58
|
+
if (this.#nextResolve !== null) {
|
|
59
|
+
this.#nextResolve[1].reject(errConnectionNotOpen);
|
|
60
|
+
this.#nextResolve = null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
open() {
|
|
64
|
+
if (this.isConnected) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
this.#socket = new node_net_1.Socket();
|
|
68
|
+
this.#socket.on("close", () => {
|
|
69
|
+
this.#rejectRead();
|
|
70
|
+
this.stateChangeHandler?.(false);
|
|
71
|
+
});
|
|
72
|
+
this.#socket.on("data", (data) => {
|
|
73
|
+
if (typeof data === "string") {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
for (const byte of data) {
|
|
77
|
+
this.#buffer.push(byte);
|
|
78
|
+
}
|
|
79
|
+
if (this.#nextResolve !== null && this.#buffer.length >= this.#nextResolve[0]) {
|
|
80
|
+
const resolve = this.#nextResolve[1].resolve;
|
|
81
|
+
this.#nextResolve = null;
|
|
82
|
+
resolve();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
this.#socket.connect(this.#socks5Port, this.#socks5Hostname);
|
|
87
|
+
this.#socket.once("error", reject);
|
|
88
|
+
this.#socket.once("connect", async () => {
|
|
89
|
+
this.#socket.off("error", reject);
|
|
90
|
+
try {
|
|
91
|
+
const header = new Uint8Array([VERSION_SOCKS, 2, AUTH_MEHTOD_NONE, AUTH_METHOD_USERNAME_PASSWORD]);
|
|
92
|
+
await this.write(header);
|
|
93
|
+
const negotiation = new Uint8Array(2);
|
|
94
|
+
await this.read(negotiation);
|
|
95
|
+
if (negotiation[0] !== VERSION_SOCKS || (negotiation[1] !== AUTH_MEHTOD_NONE && negotiation[1] !== AUTH_METHOD_USERNAME_PASSWORD)) {
|
|
96
|
+
throw new _0_errors_js_1.ConnectionError("Negotiation with SOCKS5 server failed.");
|
|
97
|
+
}
|
|
98
|
+
if (negotiation[1] === AUTH_METHOD_USERNAME_PASSWORD && !this.#credentials) {
|
|
99
|
+
throw new _0_errors_js_1.ConnectionError("Username and password are required for connecting to SOCKS5 server.");
|
|
100
|
+
}
|
|
101
|
+
else if (this.#credentials) {
|
|
102
|
+
await this.write((0, _0_deps_js_1.concat)([new Uint8Array([VERSION_USERNAME_PASSWORD_AUTH, this.#credentials.username.length]), (0, _1_utilities_js_1.encodeText)(this.#credentials.username), new Uint8Array([this.#credentials.password.length]), (0, _1_utilities_js_1.encodeText)(this.#credentials.password)]));
|
|
103
|
+
const status = new Uint8Array(2);
|
|
104
|
+
await this.read(status);
|
|
105
|
+
if (status[0] !== VERSION_USERNAME_PASSWORD_AUTH || status[1] !== RESULT_SUCCESS) {
|
|
106
|
+
throw new _0_errors_js_1.ConnectionError("SOCKS5 username and password authentication failed.");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
let hostnameType;
|
|
110
|
+
let hostname;
|
|
111
|
+
if ((0, _0_deps_js_1.isIPv4)(this.#hostname)) {
|
|
112
|
+
hostnameType = ADDRESS_TYPE_4;
|
|
113
|
+
hostname = new Uint8Array((0, _1_utilities_js_1.ipv4ToBytes)(this.#hostname));
|
|
114
|
+
}
|
|
115
|
+
else if ((0, _0_deps_js_1.isIPv6)(this.#hostname)) {
|
|
116
|
+
hostnameType = ADDRESS_TYPE_6;
|
|
117
|
+
hostname = new Uint8Array((0, _1_utilities_js_1.ipv6ToBytes)(this.#hostname));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
hostnameType = ADDRESS_TYPE_DOMAIN_NAME;
|
|
121
|
+
hostname = (0, _0_deps_js_1.concat)([new Uint8Array([this.#hostname.length]), (0, _1_utilities_js_1.encodeText)(this.#hostname)]);
|
|
122
|
+
}
|
|
123
|
+
const address = (0, _0_deps_js_1.concat)([new Uint8Array([hostnameType]), hostname, new Uint8Array(2)]);
|
|
124
|
+
new DataView(address.buffer).setUint16(hostname.byteLength + 1, this.#port);
|
|
125
|
+
await this.write((0, _0_deps_js_1.concat)([new Uint8Array([VERSION_SOCKS, COMMAND_CONNECT, 0]), address]));
|
|
126
|
+
const status = new Uint8Array(3);
|
|
127
|
+
await this.read(status);
|
|
128
|
+
if (status[0] !== VERSION_SOCKS || status[1] !== RESULT_SUCCESS) {
|
|
129
|
+
throw new _0_errors_js_1.ConnectionError("Connection with SOCKS5 server failed.");
|
|
130
|
+
}
|
|
131
|
+
const addressType = new Uint8Array(1);
|
|
132
|
+
await this.read(addressType);
|
|
133
|
+
switch (addressType[0]) {
|
|
134
|
+
case ADDRESS_TYPE_4: {
|
|
135
|
+
const ipv4 = new Uint8Array(4);
|
|
136
|
+
await this.read(ipv4);
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
case ADDRESS_TYPE_6: {
|
|
140
|
+
const ipv4 = new Uint8Array(16);
|
|
141
|
+
await this.read(ipv4);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
case ADDRESS_TYPE_DOMAIN_NAME: {
|
|
145
|
+
const length = new Uint8Array(1);
|
|
146
|
+
await this.read(length);
|
|
147
|
+
const domainName = new Uint8Array(length[0]);
|
|
148
|
+
await this.read(domainName);
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const port = new Uint8Array(2);
|
|
153
|
+
await this.read(port);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
reject(err);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
resolve();
|
|
160
|
+
this.stateChangeHandler?.(true);
|
|
161
|
+
L.debug("connected to", this.#hostname, "port", this.#port, "through socks5 server", this.#socks5Hostname, "port", this.#socks5Port);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
get isConnected() {
|
|
166
|
+
return this.#socket?.readyState === "open";
|
|
167
|
+
}
|
|
168
|
+
#assertConnected() {
|
|
169
|
+
if (!this.isConnected) {
|
|
170
|
+
throw errConnectionNotOpen;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async read(p) {
|
|
174
|
+
this.#assertConnected();
|
|
175
|
+
const unlock = await this.#rMutex.lock();
|
|
176
|
+
try {
|
|
177
|
+
this.#assertConnected();
|
|
178
|
+
if (this.#buffer.length < p.length) {
|
|
179
|
+
await new Promise((resolve, reject) => this.#nextResolve = [p.length, { resolve, reject }]);
|
|
180
|
+
}
|
|
181
|
+
p.set(this.#buffer.splice(0, p.length));
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
unlock();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async write(p) {
|
|
188
|
+
this.#assertConnected();
|
|
189
|
+
const unlock = await this.#wMutex.lock();
|
|
190
|
+
try {
|
|
191
|
+
this.#assertConnected();
|
|
192
|
+
try {
|
|
193
|
+
await new Promise((resolve, reject) => {
|
|
194
|
+
this.#socket.write(p, (err) => {
|
|
195
|
+
(err === undefined || err === null) ? resolve() : reject(err);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
catch (err) {
|
|
200
|
+
if (!this.isConnected) {
|
|
201
|
+
throw errConnectionNotOpen;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
throw err;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
finally {
|
|
209
|
+
unlock();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
close() {
|
|
213
|
+
this.#assertConnected();
|
|
214
|
+
this.#socket.destroy();
|
|
215
|
+
this.#socket = undefined;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
exports.ConnectionSocks5 = ConnectionSocks5;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"1_connection_tcp.d.ts","sourceRoot":"","sources":["../../src/connection/1_connection_tcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,qBAAa,aAAc,YAAW,UAAU;;IAQ9C,OAAO,EAAE,OAAO,IAAI,CAAC,OAAO,CAAgB;IAC5C,kBAAkB,CAAC,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC;IACtD,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;gBAEtB,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAK1C,IAAI,WAAW,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"1_connection_tcp.d.ts","sourceRoot":"","sources":["../../src/connection/1_connection_tcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,qBAAa,aAAc,YAAW,UAAU;;IAQ9C,OAAO,EAAE,OAAO,IAAI,CAAC,OAAO,CAAgB;IAC5C,kBAAkB,CAAC,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC;IACtD,QAAQ,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;gBAEtB,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAK1C,IAAI,WAAW,IAAI,OAAO,CAEzB;IAQK,IAAI;IAiBJ,IAAI,CAAC,CAAC,EAAE,UAAU;IAyBlB,KAAK,CAAC,CAAC,EAAE,UAAU;IAsBzB,KAAK;CAMN"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates whether a given string is a valid IPv4 address.
|
|
3
|
+
*
|
|
4
|
+
* @experimental **UNSTABLE**: New API, yet to be vetted.
|
|
5
|
+
*
|
|
6
|
+
* @param addr IPv4 address in a string format (e.g., "192.168.0.1").
|
|
7
|
+
* @returns A boolean indicating if the string is a valid IPv4 address.
|
|
8
|
+
*
|
|
9
|
+
* @example Check if the address is a IPv4
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { isIPv4 } from "@std/net/unstable-ip"
|
|
12
|
+
* import { assert, assertFalse } from "@std/assert"
|
|
13
|
+
*
|
|
14
|
+
* const correctIp = "192.168.0.1"
|
|
15
|
+
* const incorrectIp = "192.168.0.256"
|
|
16
|
+
*
|
|
17
|
+
* assert(isIPv4(correctIp))
|
|
18
|
+
* assertFalse(isIPv4(incorrectIp))
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function isIPv4(addr: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Validates whether a given string is a IPv6 address.
|
|
24
|
+
*
|
|
25
|
+
* @experimental **UNSTABLE**: New API, yet to be vetted.
|
|
26
|
+
*
|
|
27
|
+
* @param addr IPv6 address in a string format (e.g., "2001:db8::1").
|
|
28
|
+
* @returns A boolean indicating if the string is a valid IPv6 address.
|
|
29
|
+
*
|
|
30
|
+
* @example Check if the address is a IPv6
|
|
31
|
+
* ```ts
|
|
32
|
+
* import { isIPv6 } from "@std/net/unstable-ip"
|
|
33
|
+
* import { assert, assertFalse } from "@std/assert"
|
|
34
|
+
*
|
|
35
|
+
* const correctIp = "2001::db8:0:1"
|
|
36
|
+
* const incorrectIp = "2001::db8::1"
|
|
37
|
+
*
|
|
38
|
+
* assert(isIPv6(correctIp))
|
|
39
|
+
* assertFalse(isIPv6(incorrectIp))
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function isIPv6(addr: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Checks if an IP address matches a subnet or specific IP address.
|
|
45
|
+
*
|
|
46
|
+
* @experimental **UNSTABLE**: New API, yet to be vetted.
|
|
47
|
+
*
|
|
48
|
+
* @param addr The IP address to check (IPv4 or IPv6)
|
|
49
|
+
* @param subnetOrIps The subnet in CIDR notation (e.g., "192.168.1.0/24") or a specific IP address
|
|
50
|
+
* @returns true if the IP address matches the subnet or IP, false otherwise
|
|
51
|
+
* @example Check if the address is a IPv6
|
|
52
|
+
*
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { matchSubnets } from "@std/net/unstable-ip"
|
|
55
|
+
* import { assert, assertFalse } from "@std/assert"
|
|
56
|
+
*
|
|
57
|
+
* assert(matchSubnets("192.168.1.10", ["192.168.1.0/24"]));
|
|
58
|
+
* assertFalse(matchSubnets("192.168.2.10", ["192.168.1.0/24"]));
|
|
59
|
+
*
|
|
60
|
+
* assert(matchSubnets("2001:db8::ffff", ["2001:db8::/64"]));
|
|
61
|
+
* assertFalse(matchSubnets("2001:db9::1", ["2001:db8::/64"]));
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function matchSubnets(addr: string, subnetOrIps: string[]): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Checks if an IPv4 address matches a subnet or specific IPv4 address.
|
|
67
|
+
*
|
|
68
|
+
* @experimental **UNSTABLE**: New API, yet to be vetted.
|
|
69
|
+
*
|
|
70
|
+
* @param addr The IP address to check (IPv4)
|
|
71
|
+
* @param subnet The subnet in CIDR notation (e.g., "192.168.1.0/24") or a specific IP address
|
|
72
|
+
* @returns true if the IP address matches the subnet or IP, false otherwise
|
|
73
|
+
* @example Check if the address is a IPv6
|
|
74
|
+
*
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { matchIPv4Subnet } from "@std/net/unstable-ip"
|
|
77
|
+
* import { assert, assertFalse } from "@std/assert"
|
|
78
|
+
*
|
|
79
|
+
* assert(matchIPv4Subnet("192.168.1.10", "192.168.1.0/24"));
|
|
80
|
+
* assertFalse(matchIPv4Subnet("192.168.2.10", "192.168.1.0/24"));
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function matchIPv4Subnet(addr: string, subnet: string): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Checks if an IPv6 address matches a subnet or specific IPv6 address.
|
|
86
|
+
*
|
|
87
|
+
* @experimental **UNSTABLE**: New API, yet to be vetted.
|
|
88
|
+
*
|
|
89
|
+
* @param addr The IP address to check (IPv6)
|
|
90
|
+
* @param subnet The subnet in CIDR notation (e.g., "2001:db8::/64") or a specific IP address
|
|
91
|
+
* @returns true if the IP address matches the subnet or IP, false otherwise
|
|
92
|
+
* @example Check if the address is a IPv6
|
|
93
|
+
*
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { matchIPv6Subnet } from "@std/net/unstable-ip"
|
|
96
|
+
* import { assert, assertFalse } from "@std/assert"
|
|
97
|
+
*
|
|
98
|
+
* assert(matchIPv6Subnet("2001:db8::ffff", "2001:db8::/64"));
|
|
99
|
+
* assertFalse(matchIPv6Subnet("2001:db9::1", "2001:db8::/64"));
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function matchIPv6Subnet(addr: string, subnet: string): boolean;
|
|
103
|
+
//# sourceMappingURL=unstable_ip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unstable_ip.d.ts","sourceRoot":"","sources":["../../../../../../src/deps/jsr.io/@std/net/1.0.6/unstable_ip.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAU5C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAiC5C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAYzE;AAwCD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CA6CrE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAoDrE"}
|