mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-02-02 03:06:29 +00:00
fix v0l/socks5/master/lib/socks5.dart for dart 3
and Android Studio IDE warnings
This commit is contained in:
parent
cfce22fa73
commit
7c3c41ae5e
1 changed files with 100 additions and 85 deletions
|
@ -1,4 +1,6 @@
|
||||||
library socks;
|
// https://github.com/v0l/socks5 https://pub.dev/packages/socks5 for Dart 3
|
||||||
|
|
||||||
|
// library socks;
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
@ -7,42 +9,44 @@ import 'dart:typed_data';
|
||||||
|
|
||||||
/// https://tools.ietf.org/html/rfc1928
|
/// https://tools.ietf.org/html/rfc1928
|
||||||
/// https://tools.ietf.org/html/rfc1929
|
/// https://tools.ietf.org/html/rfc1929
|
||||||
///
|
|
||||||
|
|
||||||
const SOCKSVersion = 0x05;
|
const SOCKSVersion = 0x05;
|
||||||
const RFC1929Version = 0x01;
|
const RFC1929Version = 0x01;
|
||||||
|
|
||||||
class AuthMethods {
|
class AuthMethods {
|
||||||
static const NoAuth = const AuthMethods._(0x00);
|
static const NoAuth = AuthMethods._(0x00);
|
||||||
static const GSSApi = const AuthMethods._(0x01);
|
static const GSSApi = AuthMethods._(0x01);
|
||||||
static const UsernamePassword = const AuthMethods._(0x02);
|
static const UsernamePassword = AuthMethods._(0x02);
|
||||||
static const NoAcceptableMethods = const AuthMethods._(0xFF);
|
static const NoAcceptableMethods = AuthMethods._(0xFF);
|
||||||
|
|
||||||
final int _value;
|
final int _value;
|
||||||
|
|
||||||
const AuthMethods._(this._value);
|
const AuthMethods._(this._value);
|
||||||
|
|
||||||
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return const {
|
return const {
|
||||||
0x00: 'AuthMethods.NoAuth',
|
0x00: 'AuthMethods.NoAuth',
|
||||||
0x01: 'AuthMethods.GSSApi',
|
0x01: 'AuthMethods.GSSApi',
|
||||||
0x02: 'AuthMethods.UsernamePassword',
|
0x02: 'AuthMethods.UsernamePassword',
|
||||||
0xFF: 'AuthMethods.NoAcceptableMethods'
|
0xFF: 'AuthMethods.NoAcceptableMethods'
|
||||||
}[_value];
|
}[_value] ??
|
||||||
|
'Unknown AuthMethod';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SOCKSState {
|
class SOCKSState {
|
||||||
static const Starting = const SOCKSState._(0x00);
|
static const Starting = SOCKSState._(0x00);
|
||||||
static const Auth = const SOCKSState._(0x01);
|
static const Auth = SOCKSState._(0x01);
|
||||||
static const RequestReady = const SOCKSState._(0x02);
|
static const RequestReady = SOCKSState._(0x02);
|
||||||
static const Connected = const SOCKSState._(0x03);
|
static const Connected = SOCKSState._(0x03);
|
||||||
static const AuthStarted = const SOCKSState._(0x04);
|
static const AuthStarted = SOCKSState._(0x04);
|
||||||
|
|
||||||
final int _value;
|
final int _value;
|
||||||
|
|
||||||
const SOCKSState._(this._value);
|
const SOCKSState._(this._value);
|
||||||
|
|
||||||
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return const [
|
return const [
|
||||||
'SOCKSState.Starting',
|
'SOCKSState.Starting',
|
||||||
|
@ -55,14 +59,15 @@ class SOCKSState {
|
||||||
}
|
}
|
||||||
|
|
||||||
class SOCKSAddressType {
|
class SOCKSAddressType {
|
||||||
static const IPv4 = const SOCKSAddressType._(0x01);
|
static const IPv4 = SOCKSAddressType._(0x01);
|
||||||
static const Domain = const SOCKSAddressType._(0x03);
|
static const Domain = SOCKSAddressType._(0x03);
|
||||||
static const IPv6 = const SOCKSAddressType._(0x04);
|
static const IPv6 = SOCKSAddressType._(0x04);
|
||||||
|
|
||||||
final int _value;
|
final int _value;
|
||||||
|
|
||||||
const SOCKSAddressType._(this._value);
|
const SOCKSAddressType._(this._value);
|
||||||
|
|
||||||
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return const [
|
return const [
|
||||||
null,
|
null,
|
||||||
|
@ -70,44 +75,48 @@ class SOCKSAddressType {
|
||||||
null,
|
null,
|
||||||
'SOCKSAddressType.Domain',
|
'SOCKSAddressType.Domain',
|
||||||
'SOCKSAddressType.IPv6',
|
'SOCKSAddressType.IPv6',
|
||||||
][_value];
|
][_value] ??
|
||||||
|
'Unknown SOCKSAddressType';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SOCKSCommand {
|
class SOCKSCommand {
|
||||||
static const Connect = const SOCKSCommand._(0x01);
|
static const Connect = SOCKSCommand._(0x01);
|
||||||
static const Bind = const SOCKSCommand._(0x02);
|
static const Bind = SOCKSCommand._(0x02);
|
||||||
static const UDPAssociate = const SOCKSCommand._(0x03);
|
static const UDPAssociate = SOCKSCommand._(0x03);
|
||||||
|
|
||||||
final int _value;
|
final int _value;
|
||||||
|
|
||||||
const SOCKSCommand._(this._value);
|
const SOCKSCommand._(this._value);
|
||||||
|
|
||||||
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return const [
|
return const [
|
||||||
null,
|
null,
|
||||||
'SOCKSCommand.Connect',
|
'SOCKSCommand.Connect',
|
||||||
'SOCKSCommand.Bind',
|
'SOCKSCommand.Bind',
|
||||||
'SOCKSCommand.UDPAssociate',
|
'SOCKSCommand.UDPAssociate',
|
||||||
][_value];
|
][_value] ??
|
||||||
|
'Unknown SOCKSCommand';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SOCKSReply {
|
class SOCKSReply {
|
||||||
static const Success = const SOCKSReply._(0x00);
|
static const Success = SOCKSReply._(0x00);
|
||||||
static const GeneralFailure = const SOCKSReply._(0x01);
|
static const GeneralFailure = SOCKSReply._(0x01);
|
||||||
static const ConnectionNotAllowedByRuleset = const SOCKSReply._(0x02);
|
static const ConnectionNotAllowedByRuleset = SOCKSReply._(0x02);
|
||||||
static const NetworkUnreachable = const SOCKSReply._(0x03);
|
static const NetworkUnreachable = SOCKSReply._(0x03);
|
||||||
static const HostUnreachable = const SOCKSReply._(0x04);
|
static const HostUnreachable = SOCKSReply._(0x04);
|
||||||
static const ConnectionRefused = const SOCKSReply._(0x05);
|
static const ConnectionRefused = SOCKSReply._(0x05);
|
||||||
static const TTLExpired = const SOCKSReply._(0x06);
|
static const TTLExpired = SOCKSReply._(0x06);
|
||||||
static const CommandNotSupported = const SOCKSReply._(0x07);
|
static const CommandNotSupported = SOCKSReply._(0x07);
|
||||||
static const AddressTypeNotSupported = const SOCKSReply._(0x08);
|
static const AddressTypeNotSupported = SOCKSReply._(0x08);
|
||||||
|
|
||||||
final int _value;
|
final int _value;
|
||||||
|
|
||||||
const SOCKSReply._(this._value);
|
const SOCKSReply._(this._value);
|
||||||
|
|
||||||
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return const [
|
return const [
|
||||||
'SOCKSReply.Success',
|
'SOCKSReply.Success',
|
||||||
|
@ -130,13 +139,13 @@ class SOCKSRequest {
|
||||||
final Uint8List address;
|
final Uint8List address;
|
||||||
final int port;
|
final int port;
|
||||||
|
|
||||||
String getAddressString() {
|
String? getAddressString() {
|
||||||
if (addressType == SOCKSAddressType.Domain) {
|
if (addressType == SOCKSAddressType.Domain) {
|
||||||
return AsciiDecoder().convert(address);
|
return const AsciiDecoder().convert(address);
|
||||||
} else if (addressType == SOCKSAddressType.IPv4) {
|
} else if (addressType == SOCKSAddressType.IPv4) {
|
||||||
return address.join(".");
|
return address.join(".");
|
||||||
} else if (addressType == SOCKSAddressType.IPv6) {
|
} else if (addressType == SOCKSAddressType.IPv6) {
|
||||||
var ret = List<String>();
|
var ret = <String>[];
|
||||||
for (var x = 0; x < address.length; x += 2) {
|
for (var x = 0; x < address.length; x += 2) {
|
||||||
ret.add(
|
ret.add(
|
||||||
"${address[x].toRadixString(16).padLeft(2, "0")}${address[x + 1].toRadixString(16).padLeft(2, "0")}");
|
"${address[x].toRadixString(16).padLeft(2, "0")}${address[x + 1].toRadixString(16).padLeft(2, "0")}");
|
||||||
|
@ -147,30 +156,30 @@ class SOCKSRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
SOCKSRequest({
|
SOCKSRequest({
|
||||||
this.command,
|
required this.command,
|
||||||
this.addressType,
|
required this.addressType,
|
||||||
this.address,
|
required this.address,
|
||||||
this.port,
|
required this.port,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class SOCKSSocket {
|
class SOCKSSocket {
|
||||||
List<AuthMethods> _auth;
|
late List<AuthMethods> _auth;
|
||||||
RawSocket _sock;
|
late RawSocket _sock;
|
||||||
SOCKSRequest _request;
|
late SOCKSRequest _request;
|
||||||
|
|
||||||
StreamSubscription<RawSocketEvent> _sockSub;
|
late StreamSubscription<RawSocketEvent> _sockSub;
|
||||||
StreamSubscription<RawSocketEvent> get subscription => _sockSub;
|
StreamSubscription<RawSocketEvent> get subscription => _sockSub;
|
||||||
|
|
||||||
SOCKSState _state;
|
late SOCKSState _state;
|
||||||
final StreamController<SOCKSState> _stateStream =
|
final StreamController<SOCKSState> _stateStream =
|
||||||
StreamController<SOCKSState>();
|
StreamController<SOCKSState>();
|
||||||
SOCKSState get state => _state;
|
SOCKSState get state => _state;
|
||||||
Stream<SOCKSState> get stateStream => _stateStream?.stream;
|
Stream<SOCKSState> get stateStream => _stateStream.stream;
|
||||||
|
|
||||||
/// For username:password auth
|
/// For username:password auth
|
||||||
final String username;
|
final String? username;
|
||||||
final String password;
|
final String? password;
|
||||||
|
|
||||||
/// Waits for state to change to [SOCKSState.Connected]
|
/// Waits for state to change to [SOCKSState.Connected]
|
||||||
/// If the connection request returns an error from the
|
/// If the connection request returns an error from the
|
||||||
|
@ -198,21 +207,21 @@ class SOCKSSocket {
|
||||||
|
|
||||||
/// Issue connect command to proxy
|
/// Issue connect command to proxy
|
||||||
///
|
///
|
||||||
Future connect(String domain) async {
|
Future<void> connect(String domain) async {
|
||||||
final ds = domain.split(':');
|
final ds = domain.split(':');
|
||||||
assert(ds.length == 2, "Domain must contain port, example.com:80");
|
assert(ds.length == 2, "Domain must contain port, example.com:80");
|
||||||
|
|
||||||
_request = SOCKSRequest(
|
_request = SOCKSRequest(
|
||||||
command: SOCKSCommand.Connect,
|
command: SOCKSCommand.Connect,
|
||||||
addressType: SOCKSAddressType.Domain,
|
addressType: SOCKSAddressType.Domain,
|
||||||
address: AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length),
|
address: const AsciiEncoder().convert(ds[0]).sublist(0, ds[0].length),
|
||||||
port: int.tryParse(ds[1]) ?? 80,
|
port: int.tryParse(ds[1]) ?? 80,
|
||||||
);
|
);
|
||||||
await _start();
|
await _start();
|
||||||
await _waitForConnect;
|
await _waitForConnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future connectIp(InternetAddress ip, int port) async {
|
Future<void> connectIp(InternetAddress ip, int port) async {
|
||||||
_request = SOCKSRequest(
|
_request = SOCKSRequest(
|
||||||
command: SOCKSCommand.Connect,
|
command: SOCKSCommand.Connect,
|
||||||
addressType: ip.type == InternetAddressType.IPv4
|
addressType: ip.type == InternetAddressType.IPv4
|
||||||
|
@ -225,14 +234,14 @@ class SOCKSSocket {
|
||||||
await _waitForConnect;
|
await _waitForConnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future close({bool keepOpen = true}) async {
|
Future<void> close({bool keepOpen = true}) async {
|
||||||
await _stateStream.close();
|
await _stateStream.close();
|
||||||
if (!keepOpen) {
|
if (!keepOpen) {
|
||||||
await _sock.close();
|
await _sock.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _start() async {
|
Future<void> _start() async {
|
||||||
// send auth methods
|
// send auth methods
|
||||||
_setState(SOCKSState.Auth);
|
_setState(SOCKSState.Auth);
|
||||||
//print(">> Version: 5, AuthMethods: $_auth");
|
//print(">> Version: 5, AuthMethods: $_auth");
|
||||||
|
@ -248,7 +257,7 @@ class SOCKSSocket {
|
||||||
{
|
{
|
||||||
final have = _sock.available();
|
final have = _sock.available();
|
||||||
final data = _sock.read(have);
|
final data = _sock.read(have);
|
||||||
_handleRead(data);
|
if (data != null) _handleRead(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RawSocketEvent.closed:
|
case RawSocketEvent.closed:
|
||||||
|
@ -256,6 +265,12 @@ class SOCKSSocket {
|
||||||
_sockSub.cancel();
|
_sockSub.cancel();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case RawSocketEvent.readClosed:
|
||||||
|
// TODO: Handle this case.
|
||||||
|
break;
|
||||||
|
case RawSocketEvent.write:
|
||||||
|
// TODO: Handle this case.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -268,9 +283,9 @@ class SOCKSSocket {
|
||||||
final data = [
|
final data = [
|
||||||
RFC1929Version,
|
RFC1929Version,
|
||||||
uname.length,
|
uname.length,
|
||||||
...AsciiEncoder().convert(uname),
|
...const AsciiEncoder().convert(uname),
|
||||||
password.length,
|
password.length,
|
||||||
...AsciiEncoder().convert(password)
|
...const AsciiEncoder().convert(password)
|
||||||
];
|
];
|
||||||
|
|
||||||
//print(">> Sending $username:$password");
|
//print(">> Sending $username:$password");
|
||||||
|
@ -280,14 +295,14 @@ class SOCKSSocket {
|
||||||
void _handleRead(Uint8List data) async {
|
void _handleRead(Uint8List data) async {
|
||||||
if (state == SOCKSState.Auth) {
|
if (state == SOCKSState.Auth) {
|
||||||
if (data.length == 2) {
|
if (data.length == 2) {
|
||||||
final version = data[0];
|
// final version = data[0];
|
||||||
final auth = AuthMethods._(data[1]);
|
|
||||||
|
|
||||||
//print("<< Version: $version, Auth: $auth");
|
//print("<< Version: $version, Auth: $auth");
|
||||||
|
final auth = AuthMethods._(data[1]);
|
||||||
|
|
||||||
if (auth._value == AuthMethods.UsernamePassword._value) {
|
if (auth._value == AuthMethods.UsernamePassword._value) {
|
||||||
_setState(SOCKSState.AuthStarted);
|
_setState(SOCKSState.AuthStarted);
|
||||||
_sendUsernamePassword(username, password);
|
_sendUsernamePassword(username ?? '', password ?? '');
|
||||||
|
// TODO check that passing an empty string is valid (vs. null previously)
|
||||||
} else if (auth._value == AuthMethods.NoAuth._value) {
|
} else if (auth._value == AuthMethods.NoAuth._value) {
|
||||||
_setState(SOCKSState.RequestReady);
|
_setState(SOCKSState.RequestReady);
|
||||||
_writeRequest(_request);
|
_writeRequest(_request);
|
||||||
|
@ -311,26 +326,26 @@ class SOCKSSocket {
|
||||||
}
|
}
|
||||||
} else if (_state == SOCKSState.RequestReady) {
|
} else if (_state == SOCKSState.RequestReady) {
|
||||||
if (data.length >= 10) {
|
if (data.length >= 10) {
|
||||||
final version = data[0];
|
|
||||||
final reply = SOCKSReply._(data[1]);
|
final reply = SOCKSReply._(data[1]);
|
||||||
//data[2] reserved
|
//data[2] reserved
|
||||||
final addrType = SOCKSAddressType._(data[3]);
|
|
||||||
Uint8List addr;
|
|
||||||
var port = 0;
|
|
||||||
|
|
||||||
if (addrType == SOCKSAddressType.Domain) {
|
|
||||||
final len = data[4];
|
|
||||||
addr = data.sublist(5, 5 + len);
|
|
||||||
port = data[5 + len] << 8 | data[6 + len];
|
|
||||||
} else if (addrType == SOCKSAddressType.IPv4) {
|
|
||||||
addr = data.sublist(5, 9);
|
|
||||||
port = data[9] << 8 | data[10];
|
|
||||||
} else if (addrType == SOCKSAddressType.IPv6) {
|
|
||||||
addr = data.sublist(5, 21);
|
|
||||||
port = data[21] << 8 | data[22];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// final version = data[0];
|
||||||
|
// final addrType = SOCKSAddressType._(data[3]);
|
||||||
|
// Uint8List addr;
|
||||||
|
// var port = 0;
|
||||||
|
// if (addrType == SOCKSAddressType.Domain) {
|
||||||
|
// final len = data[4];
|
||||||
|
// addr = data.sublist(5, 5 + len);
|
||||||
|
// port = data[5 + len] << 8 | data[6 + len];
|
||||||
|
// } else if (addrType == SOCKSAddressType.IPv4) {
|
||||||
|
// addr = data.sublist(5, 9);
|
||||||
|
// port = data[9] << 8 | data[10];
|
||||||
|
// } else if (addrType == SOCKSAddressType.IPv6) {
|
||||||
|
// addr = data.sublist(5, 21);
|
||||||
|
// port = data[21] << 8 | data[22];
|
||||||
|
// }
|
||||||
// print("<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port");
|
// print("<< Version: $version, Reply: $reply, AddrType: $addrType, Addr: $addr, Port: $port");
|
||||||
|
|
||||||
if (reply._value == SOCKSReply.Success._value) {
|
if (reply._value == SOCKSReply.Success._value) {
|
||||||
_setState(SOCKSState.Connected);
|
_setState(SOCKSState.Connected);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue