mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-25 13:16:44 +00:00
close connecting sockets and interrupt read thread on shutdown
This commit is contained in:
parent
a05fcba6d9
commit
0260a12663
10 changed files with 61 additions and 32 deletions
|
@ -944,6 +944,8 @@ public class AppController implements Initializable {
|
||||||
if(AppServices.isConnected()) {
|
if(AppServices.isConnected()) {
|
||||||
return "Connected to " + Config.get().getServerDisplayName() + (currentBlockHeight != null ? " at height " + currentBlockHeight : "") +
|
return "Connected to " + Config.get().getServerDisplayName() + (currentBlockHeight != null ? " at height " + currentBlockHeight : "") +
|
||||||
(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? "\nWarning! You are connected to a public server and sharing your transaction data with it.\nFor better privacy, consider using your own Bitcoin Core node or private Electrum server." : "");
|
(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? "\nWarning! You are connected to a public server and sharing your transaction data with it.\nFor better privacy, consider using your own Bitcoin Core node or private Electrum server." : "");
|
||||||
|
} else if(AppServices.isConnecting()) {
|
||||||
|
return "Connecting...";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Disconnected";
|
return "Disconnected";
|
||||||
|
|
|
@ -1139,10 +1139,12 @@ public class AppServices {
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void requestDisconnect(RequestDisconnectEvent event) {
|
public void requestDisconnect(RequestDisconnectEvent event) {
|
||||||
onlineProperty.set(false);
|
onlineProperty.set(false);
|
||||||
//Ensure services don't try to reconnect
|
//Ensure services don't try to reconnect later
|
||||||
|
Platform.runLater(() -> {
|
||||||
connectionService.cancel();
|
connectionService.cancel();
|
||||||
ratesService.cancel();
|
ratesService.cancel();
|
||||||
versionCheckService.cancel();
|
versionCheckService.cancel();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
|
|
@ -1063,6 +1063,7 @@ public class ElectrumServer {
|
||||||
private final ReentrantLock bwtStartLock = new ReentrantLock();
|
private final ReentrantLock bwtStartLock = new ReentrantLock();
|
||||||
private final Condition bwtStartCondition = bwtStartLock.newCondition();
|
private final Condition bwtStartCondition = bwtStartLock.newCondition();
|
||||||
private Throwable bwtStartException;
|
private Throwable bwtStartException;
|
||||||
|
private boolean shutdown;
|
||||||
|
|
||||||
public ConnectionService() {
|
public ConnectionService() {
|
||||||
this(true);
|
this(true);
|
||||||
|
@ -1195,7 +1196,7 @@ public class ElectrumServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnecting() {
|
public boolean isConnecting() {
|
||||||
return isRunning() && Config.get().getServerType() == ServerType.BITCOIN_CORE && bwt.isRunning() && !bwt.isReady();
|
return isRunning() && firstCall && (Config.get().getServerType() != ServerType.BITCOIN_CORE || (bwt.isRunning() && !bwt.isReady()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnectionRunning() {
|
public boolean isConnectionRunning() {
|
||||||
|
@ -1203,7 +1204,11 @@ public class ElectrumServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnected() {
|
public boolean isConnected() {
|
||||||
return isRunning() && (Config.get().getServerType() != ServerType.BITCOIN_CORE || (bwt.isRunning() && bwt.isReady()));
|
return isRunning() && !firstCall && (Config.get().getServerType() != ServerType.BITCOIN_CORE || (bwt.isRunning() && bwt.isReady()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isShutdown() {
|
||||||
|
return shutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1219,6 +1224,11 @@ public class ElectrumServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shutdown() {
|
private void shutdown() {
|
||||||
|
shutdown = true;
|
||||||
|
if(reader != null && reader.isAlive()) {
|
||||||
|
reader.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
if(Config.get().getServerType() == ServerType.BITCOIN_CORE && bwt.isRunning()) {
|
if(Config.get().getServerType() == ServerType.BITCOIN_CORE && bwt.isRunning()) {
|
||||||
Bwt.DisconnectionService disconnectionService = bwt.getDisconnectionService();
|
Bwt.DisconnectionService disconnectionService = bwt.getDisconnectionService();
|
||||||
disconnectionService.setOnSucceeded(workerStateEvent -> {
|
disconnectionService.setOnSucceeded(workerStateEvent -> {
|
||||||
|
|
|
@ -29,13 +29,11 @@ public class ProxyTcpOverTlsTransport extends TcpOverTlsTransport {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Socket createSocket() throws IOException {
|
protected void createSocket() throws IOException {
|
||||||
InetSocketAddress proxyAddr = new InetSocketAddress(proxy.getHost(), proxy.getPortOrDefault(DEFAULT_PROXY_PORT));
|
InetSocketAddress proxyAddr = new InetSocketAddress(proxy.getHost(), proxy.getPortOrDefault(DEFAULT_PROXY_PORT));
|
||||||
Socket underlying = new Socket(new Proxy(Proxy.Type.SOCKS, proxyAddr));
|
socket = new Socket(new Proxy(Proxy.Type.SOCKS, proxyAddr));
|
||||||
underlying.connect(new InetSocketAddress(server.getHost(), server.getPortOrDefault(DEFAULT_PORT)));
|
socket.connect(new InetSocketAddress(server.getHost(), server.getPortOrDefault(DEFAULT_PORT)));
|
||||||
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(underlying, proxy.getHost(), proxy.getPortOrDefault(DEFAULT_PROXY_PORT), true);
|
socket = sslSocketFactory.createSocket(socket, proxy.getHost(), proxy.getPortOrDefault(DEFAULT_PROXY_PORT), true);
|
||||||
startHandshake(sslSocket);
|
startHandshake((SSLSocket)socket);
|
||||||
|
|
||||||
return sslSocket;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import javax.net.ssl.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Socket;
|
import java.net.InetSocketAddress;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.cert.*;
|
import java.security.cert.*;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
|
@ -86,10 +86,10 @@ public class TcpOverTlsTransport extends TcpTransport {
|
||||||
return trustManagerFactory.getTrustManagers();
|
return trustManagerFactory.getTrustManagers();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Socket createSocket() throws IOException {
|
protected void createSocket() throws IOException {
|
||||||
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(server.getHost(), server.getPortOrDefault(DEFAULT_PORT));
|
socket = sslSocketFactory.createSocket();
|
||||||
startHandshake(sslSocket);
|
socket.connect(new InetSocketAddress(server.getHost(), server.getPortOrDefault(DEFAULT_PORT)));
|
||||||
return sslSocket;
|
startHandshake((SSLSocket)socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void startHandshake(SSLSocket sslSocket) throws IOException {
|
protected void startHandshake(SSLSocket sslSocket) throws IOException {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory;
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
@ -36,7 +37,7 @@ public class TcpTransport implements CloseableTransport, TimeoutCounter {
|
||||||
protected final SocketFactory socketFactory;
|
protected final SocketFactory socketFactory;
|
||||||
protected final int[] readTimeouts;
|
protected final int[] readTimeouts;
|
||||||
|
|
||||||
private Socket socket;
|
protected Socket socket;
|
||||||
|
|
||||||
private String response;
|
private String response;
|
||||||
|
|
||||||
|
@ -231,7 +232,7 @@ public class TcpTransport implements CloseableTransport, TimeoutCounter {
|
||||||
|
|
||||||
public void connect() throws ServerException {
|
public void connect() throws ServerException {
|
||||||
try {
|
try {
|
||||||
socket = createSocket();
|
createSocket();
|
||||||
log.debug("Created " + socket);
|
log.debug("Created " + socket);
|
||||||
socket.setSoTimeout(SOCKET_READ_TIMEOUT_MILLIS);
|
socket.setSoTimeout(SOCKET_READ_TIMEOUT_MILLIS);
|
||||||
running = true;
|
running = true;
|
||||||
|
@ -250,8 +251,9 @@ public class TcpTransport implements CloseableTransport, TimeoutCounter {
|
||||||
return socket != null && running && !closed;
|
return socket != null && running && !closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Socket createSocket() throws IOException {
|
protected void createSocket() throws IOException {
|
||||||
return socketFactory.createSocket(server.getHost(), server.getPortOrDefault(DEFAULT_PORT));
|
socket = socketFactory.createSocket();
|
||||||
|
socket.connect(new InetSocketAddress(server.getHost(), server.getPortOrDefault(DEFAULT_PORT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
|
|
|
@ -26,9 +26,10 @@ public class TorTcpOverTlsTransport extends TcpOverTlsTransport {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Socket createSocket() throws IOException {
|
protected void createSocket() throws IOException {
|
||||||
TorTcpTransport torTcpTransport = new TorTcpTransport(server);
|
TorTcpTransport torTcpTransport = new TorTcpTransport(server);
|
||||||
Socket socket = torTcpTransport.createSocket();
|
torTcpTransport.createSocket();
|
||||||
|
socket = torTcpTransport.socket;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Field socketField = socket.getClass().getDeclaredField("socket");
|
Field socketField = socket.getClass().getDeclaredField("socket");
|
||||||
|
@ -41,9 +42,7 @@ public class TorTcpOverTlsTransport extends TcpOverTlsTransport {
|
||||||
log.error("Could not set socket connected status", e);
|
log.error("Could not set socket connected status", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(socket, server.getHost(), server.getPortOrDefault(DEFAULT_PORT), true);
|
socket = sslSocketFactory.createSocket(socket, server.getHost(), server.getPortOrDefault(DEFAULT_PORT), true);
|
||||||
startHandshake(sslSocket);
|
startHandshake((SSLSocket)socket);
|
||||||
|
|
||||||
return sslSocket;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,11 @@ public class TorTcpTransport extends TcpTransport {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Socket createSocket() throws IOException {
|
protected void createSocket() throws IOException {
|
||||||
if(!AppServices.isTorRunning()) {
|
if(!AppServices.isTorRunning()) {
|
||||||
throw new IllegalStateException("Can't create Tor socket, Tor is not running");
|
throw new IllegalStateException("Can't create Tor socket, Tor is not running");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TorSocket(server.getHost(), server.getPort(), "sparrow");
|
socket = new TorSocket(server.getHost(), server.getPort(), "sparrow");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,6 +175,9 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
EventManager.get().register(this);
|
EventManager.get().register(this);
|
||||||
getMasterController().closingProperty().addListener((observable, oldValue, newValue) -> {
|
getMasterController().closingProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
EventManager.get().unregister(this);
|
EventManager.get().unregister(this);
|
||||||
|
if(connectionService != null && connectionService.isRunning()) {
|
||||||
|
connectionService.cancel();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Platform.runLater(this::setupValidation);
|
Platform.runLater(this::setupValidation);
|
||||||
|
@ -360,7 +363,7 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
|
|
||||||
boolean isConnected = AppServices.isConnecting() || AppServices.isConnected();
|
boolean isConnected = AppServices.isConnecting() || AppServices.isConnected();
|
||||||
|
|
||||||
if(AppServices.isConnecting()) {
|
if(Config.get().getServerType() == ServerType.BITCOIN_CORE && AppServices.isConnecting()) {
|
||||||
testResults.appendText("Connecting to server, please wait...");
|
testResults.appendText("Connecting to server, please wait...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +383,7 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
|
|
||||||
editConnection.managedProperty().bind(editConnection.visibleProperty());
|
editConnection.managedProperty().bind(editConnection.visibleProperty());
|
||||||
editConnection.setVisible(isConnected);
|
editConnection.setVisible(isConnected);
|
||||||
editConnection.setDisable(AppServices.isConnecting());
|
editConnection.setDisable(Config.get().getServerType() == ServerType.BITCOIN_CORE && AppServices.isConnecting());
|
||||||
editConnection.setOnAction(event -> {
|
editConnection.setOnAction(event -> {
|
||||||
EventManager.get().post(new RequestDisconnectEvent());
|
EventManager.get().post(new RequestDisconnectEvent());
|
||||||
setFieldsEditable(true);
|
setFieldsEditable(true);
|
||||||
|
@ -536,6 +539,11 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
});
|
});
|
||||||
connectionService.setOnFailed(workerStateEvent -> {
|
connectionService.setOnFailed(workerStateEvent -> {
|
||||||
EventManager.get().unregister(connectionService);
|
EventManager.get().unregister(connectionService);
|
||||||
|
if(connectionService.isShutdown()) {
|
||||||
|
connectionService.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
showConnectionFailure(workerStateEvent.getSource().getException());
|
showConnectionFailure(workerStateEvent.getSource().getException());
|
||||||
connectionService.cancel();
|
connectionService.cancel();
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,9 @@ public class ServerTestDialog extends DialogWindow {
|
||||||
close();
|
close();
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
|
if(connectionService != null && connectionService.isRunning()) {
|
||||||
|
connectionService.cancel();
|
||||||
|
}
|
||||||
if(Config.get().getMode() == Mode.ONLINE && !(AppServices.isConnecting() || AppServices.isConnected())) {
|
if(Config.get().getMode() == Mode.ONLINE && !(AppServices.isConnecting() || AppServices.isConnected())) {
|
||||||
EventManager.get().post(new RequestConnectEvent());
|
EventManager.get().post(new RequestConnectEvent());
|
||||||
}
|
}
|
||||||
|
@ -145,6 +148,11 @@ public class ServerTestDialog extends DialogWindow {
|
||||||
});
|
});
|
||||||
connectionService.setOnFailed(workerStateEvent -> {
|
connectionService.setOnFailed(workerStateEvent -> {
|
||||||
EventManager.get().unregister(connectionService);
|
EventManager.get().unregister(connectionService);
|
||||||
|
if(connectionService.isShutdown()) {
|
||||||
|
connectionService.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
showConnectionFailure(workerStateEvent.getSource().getException());
|
showConnectionFailure(workerStateEvent.getSource().getException());
|
||||||
connectionService.cancel();
|
connectionService.cancel();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue