Skip to content

Commit c278ccf

Browse files
committed
feat(cw_bitcoin): support socks proxy and CakeTor
1 parent 5a316b3 commit c278ccf

File tree

16 files changed

+288
-55
lines changed

16 files changed

+288
-55
lines changed

cw_bitcoin/lib/electrum.dart

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import 'dart:typed_data';
55
import 'package:bitcoin_base/bitcoin_base.dart';
66
import 'package:cw_bitcoin/bitcoin_amount_format.dart';
77
import 'package:cw_core/utils/print_verbose.dart';
8+
import 'package:cw_core/utils/proxy_socket/abstract.dart';
9+
import 'package:cw_core/utils/proxy_wrapper.dart';
810
import 'package:flutter/foundation.dart';
911
import 'package:rxdart/rxdart.dart';
1012

@@ -42,7 +44,7 @@ class ElectrumClient {
4244
static const aliveTimerDuration = Duration(seconds: 4);
4345

4446
bool get isConnected => _isConnected;
45-
Socket? socket;
47+
ProxySocket? socket;
4648
void Function(ConnectionStatus)? onConnectionStatusChange;
4749
int _id;
4850
final Map<String, SocketTask> _tasks;
@@ -73,17 +75,9 @@ class ElectrumClient {
7375
socket = null;
7476

7577
try {
76-
if (useSSL == false || (useSSL == null && uri.toString().contains("btc-electrum"))) {
77-
socket = await Socket.connect(host, port, timeout: connectionTimeout);
78-
} else {
79-
socket = await SecureSocket.connect(
80-
host,
81-
port,
82-
timeout: connectionTimeout,
83-
onBadCertificate: (_) => true,
84-
);
85-
}
78+
socket = await ProxyWrapper().getSocksSocket(useSSL ?? false, host, port, connectionTimeout: connectionTimeout);
8679
} catch (e) {
80+
printV("connect: $e");
8781
if (e is HandshakeException) {
8882
useSSL = !(useSSL ?? false);
8983
}

cw_bitcoin/pubspec.lock

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -902,11 +902,21 @@ packages:
902902
socks5_proxy:
903903
dependency: transitive
904904
description:
905-
name: socks5_proxy
906-
sha256: "616818a0ea1064a4823b53c9f7eaf8da64ed82dcd51ed71371c7e54751ed5053"
907-
url: "https://pub.dev"
908-
source: hosted
909-
version: "1.0.6"
905+
path: "."
906+
ref: d304fcfcc97cb7212bcd347aeb5d96792c128ff3
907+
resolved-ref: d304fcfcc97cb7212bcd347aeb5d96792c128ff3
908+
url: "https://github.com/cake-tech/socks_dart.git"
909+
source: git
910+
version: "1.0.4"
911+
socks_socket:
912+
dependency: "direct main"
913+
description:
914+
path: "."
915+
ref: e6232c53c1595469931ababa878759a067c02e94
916+
resolved-ref: e6232c53c1595469931ababa878759a067c02e94
917+
url: "https://github.com/sneurlax/socks_socket"
918+
source: git
919+
version: "1.1.1"
910920
source_gen:
911921
dependency: transitive
912922
description:
@@ -992,7 +1002,7 @@ packages:
9921002
dependency: transitive
9931003
description:
9941004
name: timing
995-
sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
1005+
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
9961006
url: "https://pub.dev"
9971007
source: hosted
9981008
version: "1.0.1"

cw_bitcoin/pubspec.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ dependencies:
4949
git:
5050
url: https://github.com/cake-tech/ledger-flutter-plus-plugins
5151
path: packages/ledger-litecoin
52+
socks_socket:
53+
git:
54+
url: https://github.com/sneurlax/socks_socket
55+
ref: e6232c53c1595469931ababa878759a067c02e94
5256

5357
dev_dependencies:
5458
flutter_test:

cw_core/lib/node.dart

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:io';
22
import 'package:cw_core/keyable.dart';
3+
import 'package:cw_core/utils/proxy_socket/abstract.dart';
34
import 'package:cw_core/utils/proxy_wrapper.dart';
45
import 'package:cw_core/utils/print_verbose.dart';
56
import 'dart:convert';
@@ -303,13 +304,9 @@ class Node extends HiveObject with Keyable {
303304
// you try to communicate with it
304305
Future<bool> requestElectrumServer() async {
305306
try {
306-
final Socket socket;
307-
if (useSSL == true) {
308-
socket = await SecureSocket.connect(uri.host, uri.port,
309-
timeout: Duration(seconds: 5), onBadCertificate: (_) => true);
310-
} else {
311-
socket = await Socket.connect(uri.host, uri.port, timeout: Duration(seconds: 5));
312-
}
307+
final ProxySocket socket;
308+
socket = await ProxyWrapper().getSocksSocket(useSSL ?? false, uri.host, uri.port);
309+
313310

314311
socket.destroy();
315312
return true;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import 'dart:async';
2+
import 'dart:io';
3+
import 'dart:typed_data';
4+
5+
import 'package:cw_core/utils/proxy_socket/insecure.dart';
6+
import 'package:cw_core/utils/proxy_socket/secure.dart';
7+
import 'package:cw_core/utils/proxy_socket/socks.dart';
8+
import 'package:cw_core/utils/proxy_wrapper.dart';
9+
import 'package:socks_socket/socks_socket.dart';
10+
11+
class ProxyAddress {
12+
final String host;
13+
final int port;
14+
15+
ProxyAddress({required this.host, required this.port});
16+
}
17+
18+
abstract class ProxySocket {
19+
static Future<ProxySocket> connect(bool sslEnabled, ProxyAddress address, {Duration? connectionTimeout}) async {
20+
if (CakeTor.instance.started) {
21+
var socksSocket = await SOCKSSocket.create(
22+
proxyHost: InternetAddress.loopbackIPv4.address,
23+
proxyPort: CakeTor.instance.port,
24+
sslEnabled: sslEnabled,
25+
);
26+
await socksSocket.connect();
27+
await socksSocket.connectTo(address.host, address.port);
28+
return ProxySocketSocks(socksSocket);
29+
}
30+
if (sslEnabled == false) {
31+
return ProxySocketInsecure(await Socket.connect(address.host, address.port, timeout: connectionTimeout));
32+
} else {
33+
return ProxySocketSecure(await SecureSocket.connect(
34+
address.host,
35+
address.port,
36+
timeout: connectionTimeout,
37+
onBadCertificate: (_) => true,
38+
));
39+
}
40+
}
41+
42+
Future<void> close();
43+
Future<void> destroy();
44+
Future<void> write(String data);
45+
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function (Object error)? onError, Function ()? onDone, bool cancelOnError = true});
46+
ProxyAddress get address;
47+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
import 'package:cw_core/utils/proxy_socket/abstract.dart';
3+
import 'dart:async';
4+
import 'dart:typed_data';
5+
import 'dart:io';
6+
7+
class ProxySocketInsecure implements ProxySocket {
8+
final Socket socket;
9+
10+
ProxySocketInsecure(this.socket);
11+
12+
ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
13+
14+
@override
15+
Future<void> close() => socket.close();
16+
17+
@override
18+
Future<void> destroy() async => socket.destroy();
19+
20+
@override
21+
Future<void> write(String data) async => socket.write(data);
22+
23+
@override
24+
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
25+
return socket.listen(
26+
(data) {
27+
onData(Uint8List.fromList(data));
28+
},
29+
onError: onError,
30+
onDone: onDone,
31+
cancelOnError: cancelOnError,
32+
);
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import 'dart:async';
2+
import 'dart:io';
3+
import 'dart:typed_data';
4+
5+
import 'package:cw_core/utils/proxy_socket/abstract.dart';
6+
7+
class ProxySocketSecure implements ProxySocket {
8+
final SecureSocket socket;
9+
10+
ProxySocketSecure(this.socket);
11+
12+
ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
13+
14+
@override
15+
Future<void> close() => socket.close();
16+
17+
@override
18+
Future<void> destroy() async => socket.destroy();
19+
20+
@override
21+
Future<void> write(String data) async => socket.write(data);
22+
23+
@override
24+
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
25+
return socket.listen(
26+
(data) {
27+
onData(Uint8List.fromList(data));
28+
},
29+
onError: onError,
30+
onDone: onDone,
31+
cancelOnError: cancelOnError,
32+
);
33+
}
34+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import 'dart:async';
2+
import 'dart:typed_data';
3+
4+
import 'package:cw_core/utils/proxy_socket/abstract.dart';
5+
import 'package:socks_socket/socks_socket.dart';
6+
7+
class ProxySocketSocks implements ProxySocket {
8+
final SOCKSSocket socket;
9+
10+
ProxySocketSocks(this.socket);
11+
12+
@override
13+
ProxyAddress get address => ProxyAddress(host: socket.proxyHost, port: socket.proxyPort);
14+
15+
@override
16+
Future<void> close() => socket.close();
17+
18+
@override
19+
Future<void> destroy() => close();
20+
21+
@override
22+
Future<void> write(String data) async => socket.write(data);
23+
24+
@override
25+
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
26+
return socket.listen(
27+
(data) {
28+
onData(Uint8List.fromList(data));
29+
},
30+
onError: onError,
31+
onDone: onDone,
32+
cancelOnError: cancelOnError,
33+
);
34+
}
35+
}
36+

cw_core/lib/utils/proxy_wrapper.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
1+
import 'dart:async';
12
import 'dart:convert';
23
import 'dart:io';
4+
import 'dart:typed_data';
5+
import 'package:cw_core/utils/proxy_socket/abstract.dart';
36
import 'package:socks5_proxy/socks_client.dart';
7+
import 'package:socks_socket/socks_socket.dart';
48
import 'package:tor/tor.dart';
59
import 'package:http/io_client.dart' as ioc;
610

7-
8-
911
class ProxyWrapper {
1012
ProxyWrapper();
1113

14+
Future<ProxySocket> getSocksSocket(bool sslEnabled, String host, int port, {Duration? connectionTimeout}) async {
15+
return ProxySocket.connect(sslEnabled, ProxyAddress(host: host, port: port), connectionTimeout: connectionTimeout);
16+
}
17+
1218
ioc.IOClient getHttpIOClient() {
1319
final httpClient = ProxyWrapper().getHttpClient();
1420
return ioc.IOClient(httpClient);

cw_core/pubspec.lock

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,15 @@ packages:
641641
url: "https://github.com/cake-tech/socks_dart.git"
642642
source: git
643643
version: "1.0.4"
644+
socks_socket:
645+
dependency: "direct main"
646+
description:
647+
path: "."
648+
ref: e6232c53c1595469931ababa878759a067c02e94
649+
resolved-ref: e6232c53c1595469931ababa878759a067c02e94
650+
url: "https://github.com/sneurlax/socks_socket"
651+
source: git
652+
version: "1.1.1"
644653
source_gen:
645654
dependency: transitive
646655
description:
@@ -717,7 +726,7 @@ packages:
717726
dependency: transitive
718727
description:
719728
name: timing
720-
sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe"
729+
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
721730
url: "https://pub.dev"
722731
source: hosted
723732
version: "1.0.1"

cw_core/pubspec.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ dependencies:
3535
url: https://github.com/cake-tech/on_chain.git
3636
ref: cake-update-v2
3737
tor: any
38+
socks_socket:
39+
git:
40+
url: https://github.com/sneurlax/socks_socket
41+
ref: e6232c53c1595469931ababa878759a067c02e94
3842

3943
dev_dependencies:
4044
flutter_test:

cw_decred/pubspec.lock

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -666,11 +666,21 @@ packages:
666666
socks5_proxy:
667667
dependency: transitive
668668
description:
669-
name: socks5_proxy
670-
sha256: "616818a0ea1064a4823b53c9f7eaf8da64ed82dcd51ed71371c7e54751ed5053"
671-
url: "https://pub.dev"
672-
source: hosted
673-
version: "1.0.6"
669+
path: "."
670+
ref: d304fcfcc97cb7212bcd347aeb5d96792c128ff3
671+
resolved-ref: d304fcfcc97cb7212bcd347aeb5d96792c128ff3
672+
url: "https://github.com/cake-tech/socks_dart.git"
673+
source: git
674+
version: "1.0.4"
675+
socks_socket:
676+
dependency: transitive
677+
description:
678+
path: "."
679+
ref: e6232c53c1595469931ababa878759a067c02e94
680+
resolved-ref: e6232c53c1595469931ababa878759a067c02e94
681+
url: "https://github.com/sneurlax/socks_socket"
682+
source: git
683+
version: "1.1.1"
674684
source_gen:
675685
dependency: transitive
676686
description:
@@ -751,6 +761,14 @@ packages:
751761
url: "https://pub.dev"
752762
source: hosted
753763
version: "1.0.2"
764+
tor:
765+
dependency: transitive
766+
description:
767+
name: tor
768+
sha256: eeed80e5c912a1806c2f81825c12e84f4dc5a0b50aebedea59e3a8ba53df3142
769+
url: "https://pub.dev"
770+
source: hosted
771+
version: "0.0.8"
754772
tuple:
755773
dependency: transitive
756774
description:

0 commit comments

Comments
 (0)