Add pve http proxy

This commit is contained in:
leganck
2024-05-30 23:30:45 +08:00
parent fbabd8c351
commit 9e308792aa
2 changed files with 70 additions and 37 deletions

View File

@@ -10,20 +10,24 @@ import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/data/model/app/error.dart'; import 'package:toolbox/data/model/app/error.dart';
import 'package:toolbox/data/model/server/pve.dart'; import 'package:toolbox/data/model/server/pve.dart';
import 'package:toolbox/data/model/server/server_private_info.dart'; import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:dartssh2/dartssh2.dart';
typedef PveCtrlFunc = Future<bool> Function(String node, String id); typedef PveCtrlFunc = Future<bool> Function(String node, String id);
final class PveProvider extends ChangeNotifier { final class PveProvider extends ChangeNotifier {
final ServerPrivateInfo spi; final ServerPrivateInfo spi;
late final String addr; late String addr;
//late final SSHClient _client; late final SSHClient _client;
late final ServerSocket _serverSocket;
final List<SSHForwardChannel> _forwards = [];
int _localPort = 0;
PveProvider({required this.spi}) { PveProvider({required this.spi}) {
// final client = _spi.server?.client; final client = spi.server?.client;
// if (client == null) { if (client == null) {
// throw Exception('Server client is null'); throw Exception('Server client is null');
// } }
// _client = client; _client = client;
final addr = spi.custom?.pveAddr; final addr = spi.custom?.pveAddr;
if (addr == null) { if (addr == null) {
err.value = 'PVE address is null'; err.value = 'PVE address is null';
@@ -36,11 +40,12 @@ final class PveProvider extends ChangeNotifier {
final err = ValueNotifier<String?>(null); final err = ValueNotifier<String?>(null);
final connected = Completer<void>(); final connected = Completer<void>();
late final _ignoreCert = spi.custom?.pveIgnoreCert ?? false; late bool _ignoreCert = spi.custom?.pveIgnoreCert ?? false;
late final session = Dio() late final session = Dio()
..httpClientAdapter = IOHttpClientAdapter( ..httpClientAdapter = IOHttpClientAdapter(
createHttpClient: () { createHttpClient: () {
final client = HttpClient(); final client = HttpClient();
client.connectionFactory = cf;
if (_ignoreCert) { if (_ignoreCert) {
client.badCertificateCallback = (_, __, ___) => true; client.badCertificateCallback = (_, __, ___) => true;
} }
@@ -50,16 +55,14 @@ final class PveProvider extends ChangeNotifier {
); );
final data = ValueNotifier<PveRes?>(null); final data = ValueNotifier<PveRes?>(null);
bool get onlyOneNode => data.value?.nodes.length == 1; bool get onlyOneNode => data.value?.nodes.length == 1;
String? release; String? release;
bool isBusy = false; bool isBusy = false;
// int _localPort = 0;
// String get addr => 'http://127.0.0.1:$_localPort';
Future<void> _init() async { Future<void> _init() async {
try { try {
//await _forward(); await _forward();
await _login(); await _login();
await _release; await _release;
} on PveErr { } on PveErr {
@@ -72,33 +75,53 @@ final class PveProvider extends ChangeNotifier {
} }
} }
// Future<void> _forward() async { Future<void> _forward() async {
// var retries = 0; final url = Uri.parse(addr);
// while (retries < 3) { if (_localPort == 0) {
// try { _serverSocket = await ServerSocket.bind('localhost', 0);
// _localPort = Random().nextInt(1000) + 37000; _localPort = _serverSocket.port;
// print('Forwarding local port $_localPort'); _serverSocket.listen((socket) async {
// final serverSocket = await ServerSocket.bind('localhost', _localPort); final forward = await _client.forwardLocal(url.host, url.port);
// final forward = await _client.forwardLocal('127.0.0.1', 8006); _forwards.add(forward);
// serverSocket.listen((socket) { forward.stream.cast<List<int>>().pipe(socket);
// forward.stream.cast<List<int>>().pipe(socket); socket.cast<List<int>>().pipe(forward.sink);
// socket.pipe(forward.sink); });
// }); final newUrl = Uri.parse(addr)
// return; .replace(host: 'localhost', port: _localPort)
// } on SocketException { .toString();
// retries++; print('Forwarding $newUrl to $addr');
// } }
// } }
// throw Exception('Failed to bind local port');
// } Future<ConnectionTask<Socket>> cf(
Uri url, String? proxyHost, int? proxyPort) async {
/* final serverSocket = await ServerSocket.bind(InternetAddress.anyIPv4, 0);
final _localPort = serverSocket.port;
serverSocket.listen((socket) async {
final forward = await _client.forwardLocal(url.host, url.port);
forwards.add(forward);
forward.stream.cast<List<int>>().pipe(socket);
socket.cast<List<int>>().pipe(forward.sink);
});*/
if (url.isScheme("https")) {
return SecureSocket.startConnect('localhost', _localPort,
onBadCertificate: (_) => true);
} else {
return Socket.startConnect('localhost', _localPort);
}
}
Future<void> _login() async { Future<void> _login() async {
final resp = await session.post('$addr/api2/extjs/access/ticket', data: { final resp = await session.post('$addr/api2/extjs/access/ticket',
data: {
'username': spi.user, 'username': spi.user,
'password': spi.pwd, 'password': spi.pwd,
'realm': 'pam', 'realm': 'pam',
'new-format': '1' 'new-format': '1'
}); },
options: Options(
headers: {HttpHeaders.contentTypeHeader: Headers.jsonContentType}));
try { try {
final ticket = resp.data['data']['ticket']; final ticket = resp.data['data']['ticket'];
session.options.headers['CSRFPreventionToken'] = session.options.headers['CSRFPreventionToken'] =
@@ -167,4 +190,13 @@ final class PveProvider extends ChangeNotifier {
bool _isCtrlSuc(Response resp) { bool _isCtrlSuc(Response resp) {
return resp.statusCode == 200; return resp.statusCode == 200;
} }
@override
Future<void> dispose() async {
super.dispose();
await _serverSocket.close();
for (final forward in _forwards) {
forward.close();
}
}
} }

View File

@@ -46,6 +46,7 @@ final class _PvePageState extends State<PvePage> {
void dispose() { void dispose() {
super.dispose(); super.dispose();
_timer?.cancel(); _timer?.cancel();
_pve.dispose();
} }
@override @override