From fb9ae59816fa3b1a61c0359130631b4f99cf047b Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 31 Jul 2024 15:12:47 -0500 Subject: [PATCH 1/2] julian's patch love it --- .../test_monero_node_connection.dart | 139 +++++++----------- 1 file changed, 57 insertions(+), 82 deletions(-) diff --git a/lib/utilities/test_monero_node_connection.dart b/lib/utilities/test_monero_node_connection.dart index c47338227..92c4bc97e 100644 --- a/lib/utilities/test_monero_node_connection.dart +++ b/lib/utilities/test_monero_node_connection.dart @@ -38,34 +38,62 @@ Future testMoneroNodeConnection( int port, })? proxyInfo, }) async { - final httpClient = HttpClient(); - MoneroNodeConnectionResponse? badCertResponse; - - try { - if (proxyInfo != null) { - SocksTCPClient.assignToHttpClient(httpClient, [ - ProxySettings( - proxyInfo.host, - proxyInfo.port, - ), - ]); + if (uri.host.endsWith(".onion")) { + if (proxyInfo == null) { + // If the host ends in .onion, we can't access it without Tor. + return MoneroNodeConnectionResponse(null, null, null, false); } - httpClient.badCertificateCallback = (cert, url, port) { - if (allowBadX509Certificate) { - return true; + SOCKSSocket? socket; + try { + // An HttpClient cannot be used for onion nodes. + // + // The SOCKSSocket class from the tor_ffi_plugin package can be used to + // connect to .onion addresses. We'll do the same things as above but + // with SOCKSSocket instead of httpClient. + socket = await SOCKSSocket.create( + proxyHost: proxyInfo.host.address, + proxyPort: proxyInfo.port, + sslEnabled: false, + ); + await socket.connect(); + await socket.connectTo(uri.host, uri.port); + // assume success as connect did not fail + return MoneroNodeConnectionResponse(null, null, null, true); + } catch (e, s) { + Logging.instance.log("$e\n$s", level: LogLevel.Warning); + return MoneroNodeConnectionResponse(null, null, null, false); + } finally { + await socket?.close(); + } + } else { + final httpClient = HttpClient(); + MoneroNodeConnectionResponse? badCertResponse; + try { + if (proxyInfo != null) { + SocksTCPClient.assignToHttpClient(httpClient, [ + ProxySettings( + proxyInfo.host, + proxyInfo.port, + ), + ]); } - if (badCertResponse == null) { - badCertResponse = MoneroNodeConnectionResponse(cert, url, port, false); - } else { - return false; - } + httpClient.badCertificateCallback = (cert, url, port) { + if (allowBadX509Certificate) { + return true; + } - return false; - }; + if (badCertResponse == null) { + badCertResponse = + MoneroNodeConnectionResponse(cert, url, port, false); + } else { + return false; + } + + return false; + }; - if (!uri.host.endsWith(".onion")) { final request = await httpClient.postUrl(uri); final body = utf8.encode( @@ -94,69 +122,16 @@ Future testMoneroNodeConnection( // TODO: json decoded without error so assume connection exists? // or we can check for certain values in the response to decide return MoneroNodeConnectionResponse(null, null, null, true); - } else { - if (proxyInfo == null) { - // If the host ends in .onion, we can't access it without Tor. + } catch (e, s) { + if (badCertResponse != null) { + return badCertResponse!; + } else { + Logging.instance.log("$e\n$s", level: LogLevel.Warning); return MoneroNodeConnectionResponse(null, null, null, false); } - - // An HttpClient cannot be used for onion nodes. - // - // The SOCKSSocket class from the tor_ffi_plugin package can be used to - // connect to .onion addresses. We'll do the same things as above but - // with SOCKSSocket instead of httpClient. - final socket = await SOCKSSocket.create( - proxyHost: proxyInfo.host.address, - proxyPort: proxyInfo.port, - sslEnabled: false, - ); - await socket.connect(); - await socket.connectTo(uri.host, uri.port); - - final body = utf8.encode( - jsonEncode({ - "jsonrpc": "2.0", - "id": "0", - "method": "get_info", - }), - ); - - // Write the request body to the socket. - socket.write(body); - - // If this is an onion address and there are no errors yet, assume success. - if (uri.host.endsWith('.onion')) { - return MoneroNodeConnectionResponse(null, null, null, true); - } - - // Read the response. - final response = await socket.inputStream.first; - final result = utf8.decode(response); - - // Close the socket. - await socket.close(); - return MoneroNodeConnectionResponse(null, null, null, true); - - // Parse the response. - // - // This is commented because any issues should throw. - // final Map jsonResponse = jsonDecode(result); - // print(jsonResponse); - // if (jsonResponse.containsKey('result')) { - // return MoneroNodeConnectionResponse(null, null, null, true); - // } else { - // return MoneroNodeConnectionResponse(null, null, null, false); - // } - } - } catch (e, s) { - if (badCertResponse != null) { - return badCertResponse!; - } else { - Logging.instance.log("$e\n$s", level: LogLevel.Warning); - return MoneroNodeConnectionResponse(null, null, null, false); + } finally { + httpClient.close(force: true); } - } finally { - httpClient.close(force: true); } } From 4ea48890ace46f942dd69cf446949162699bfe8f Mon Sep 17 00:00:00 2001 From: sneurlax Date: Wed, 31 Jul 2024 15:18:15 -0500 Subject: [PATCH 2/2] fix monero onion node test --- .../test_monero_node_connection.dart | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/lib/utilities/test_monero_node_connection.dart b/lib/utilities/test_monero_node_connection.dart index 92c4bc97e..b1f590e41 100644 --- a/lib/utilities/test_monero_node_connection.dart +++ b/lib/utilities/test_monero_node_connection.dart @@ -58,8 +58,39 @@ Future testMoneroNodeConnection( ); await socket.connect(); await socket.connectTo(uri.host, uri.port); - // assume success as connect did not fail - return MoneroNodeConnectionResponse(null, null, null, true); + + final body = jsonEncode({ + "jsonrpc": "2.0", + "id": "0", + "method": "get_info", + }); + + final request = 'POST /json_rpc HTTP/1.1\r\n' + 'Host: ${uri.host}\r\n' + 'Content-Type: application/json\r\n' + 'Content-Length: ${body.length}\r\n' + '\r\n' + '$body'; + + socket.write(request); + print("Request sent: $request"); + + final buffer = StringBuffer(); + await for (var response in socket.inputStream) { + buffer.write(utf8.decode(response)); + if (buffer.toString().contains("\r\n\r\n")) { + break; + } + } + + final result = buffer.toString(); + print("Response received: $result"); + + // Check if the response contains "results" and does not contain "error" + final success = + result.contains('"result":') && !result.contains('"error"'); + + return MoneroNodeConnectionResponse(null, null, null, success); } catch (e, s) { Logging.instance.log("$e\n$s", level: LogLevel.Warning); return MoneroNodeConnectionResponse(null, null, null, false); @@ -119,9 +150,12 @@ Future testMoneroNodeConnection( final response = await request.close(); final result = await response.transform(utf8.decoder).join(); - // TODO: json decoded without error so assume connection exists? - // or we can check for certain values in the response to decide - return MoneroNodeConnectionResponse(null, null, null, true); + print("HTTP Response: $result"); + + final success = + result.contains('"result":') && !result.contains('"error"'); + + return MoneroNodeConnectionResponse(null, null, null, success); } catch (e, s) { if (badCertResponse != null) { return badCertResponse!;