mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
refactor transport and speedup private server delay on connection failure
This commit is contained in:
parent
04917c45b6
commit
258fe34101
5 changed files with 53 additions and 28 deletions
|
@ -73,9 +73,11 @@ public class AppServices {
|
||||||
|
|
||||||
private static final int SERVER_PING_PERIOD_SECS = 60;
|
private static final int SERVER_PING_PERIOD_SECS = 60;
|
||||||
private static final int PUBLIC_SERVER_RETRY_PERIOD_SECS = 3;
|
private static final int PUBLIC_SERVER_RETRY_PERIOD_SECS = 3;
|
||||||
|
private static final int PRIVATE_SERVER_RETRY_PERIOD_SECS = 15;
|
||||||
public static final int ENUMERATE_HW_PERIOD_SECS = 30;
|
public static final int ENUMERATE_HW_PERIOD_SECS = 30;
|
||||||
private static final int RATES_PERIOD_SECS = 5 * 60;
|
private static final int RATES_PERIOD_SECS = 5 * 60;
|
||||||
private static final int VERSION_CHECK_PERIOD_HOURS = 24;
|
private static final int VERSION_CHECK_PERIOD_HOURS = 24;
|
||||||
|
private static final int CONNECTION_DELAY_SECS = 2;
|
||||||
private static final ExchangeSource DEFAULT_EXCHANGE_SOURCE = ExchangeSource.COINGECKO;
|
private static final ExchangeSource DEFAULT_EXCHANGE_SOURCE = ExchangeSource.COINGECKO;
|
||||||
private static final Currency DEFAULT_FIAT_CURRENCY = Currency.getInstance("USD");
|
private static final Currency DEFAULT_FIAT_CURRENCY = Currency.getInstance("USD");
|
||||||
private static final String TOR_DEFAULT_PROXY_CIRCUIT_ID = "default";
|
private static final String TOR_DEFAULT_PROXY_CIRCUIT_ID = "default";
|
||||||
|
@ -251,7 +253,7 @@ public class AppServices {
|
||||||
private ElectrumServer.ConnectionService createConnectionService() {
|
private ElectrumServer.ConnectionService createConnectionService() {
|
||||||
ElectrumServer.ConnectionService connectionService = new ElectrumServer.ConnectionService();
|
ElectrumServer.ConnectionService connectionService = new ElectrumServer.ConnectionService();
|
||||||
//Delay startup on first connection to Bitcoin Core to allow any unencrypted wallets to open first
|
//Delay startup on first connection to Bitcoin Core to allow any unencrypted wallets to open first
|
||||||
connectionService.setDelay(Config.get().getServerType() == ServerType.BITCOIN_CORE ? Duration.seconds(2) : Duration.ZERO);
|
connectionService.setDelay(Config.get().getServerType() == ServerType.BITCOIN_CORE ? Duration.seconds(CONNECTION_DELAY_SECS) : Duration.ZERO);
|
||||||
connectionService.setPeriod(Duration.seconds(SERVER_PING_PERIOD_SECS));
|
connectionService.setPeriod(Duration.seconds(SERVER_PING_PERIOD_SECS));
|
||||||
connectionService.setRestartOnFailure(true);
|
connectionService.setRestartOnFailure(true);
|
||||||
EventManager.get().register(connectionService);
|
EventManager.get().register(connectionService);
|
||||||
|
@ -323,6 +325,8 @@ public class AppServices {
|
||||||
if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER) {
|
if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER) {
|
||||||
Config.get().changePublicServer();
|
Config.get().changePublicServer();
|
||||||
connectionService.setPeriod(Duration.seconds(PUBLIC_SERVER_RETRY_PERIOD_SECS));
|
connectionService.setPeriod(Duration.seconds(PUBLIC_SERVER_RETRY_PERIOD_SECS));
|
||||||
|
} else {
|
||||||
|
connectionService.setPeriod(Duration.seconds(PRIVATE_SERVER_RETRY_PERIOD_SECS));
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("Connection failed", failEvent.getSource().getException());
|
log.debug("Connection failed", failEvent.getSource().getException());
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.sparrowwallet.sparrow.net;
|
||||||
|
|
||||||
|
import com.github.arteam.simplejsonrpc.client.Transport;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
|
||||||
|
public interface CloseableTransport extends Transport, Closeable {
|
||||||
|
void connect() throws ServerException;
|
||||||
|
boolean isConnected();
|
||||||
|
boolean isClosed();
|
||||||
|
}
|
|
@ -47,7 +47,7 @@ public class ElectrumServer {
|
||||||
|
|
||||||
public static final BlockTransaction UNFETCHABLE_BLOCK_TRANSACTION = new BlockTransaction(Sha256Hash.ZERO_HASH, 0, null, null, null);
|
public static final BlockTransaction UNFETCHABLE_BLOCK_TRANSACTION = new BlockTransaction(Sha256Hash.ZERO_HASH, 0, null, null, null);
|
||||||
|
|
||||||
private static Transport transport;
|
private static CloseableTransport transport;
|
||||||
|
|
||||||
private static final Map<String, List<String>> subscribedScriptHashes = Collections.synchronizedMap(new HashMap<>());
|
private static final Map<String, List<String>> subscribedScriptHashes = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class ElectrumServer {
|
||||||
|
|
||||||
private static final Pattern RPC_WALLET_LOADING_PATTERN = Pattern.compile(".*\"(Wallet loading failed:[^\"]*)\".*");
|
private static final Pattern RPC_WALLET_LOADING_PATTERN = Pattern.compile(".*\"(Wallet loading failed:[^\"]*)\".*");
|
||||||
|
|
||||||
private static synchronized Transport getTransport() throws ServerException {
|
private static synchronized CloseableTransport getTransport() throws ServerException {
|
||||||
if(transport == null) {
|
if(transport == null) {
|
||||||
try {
|
try {
|
||||||
String electrumServer = null;
|
String electrumServer = null;
|
||||||
|
@ -133,8 +133,8 @@ public class ElectrumServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connect() throws ServerException {
|
public void connect() throws ServerException {
|
||||||
TcpTransport tcpTransport = (TcpTransport)getTransport();
|
CloseableTransport closeableTransport = getTransport();
|
||||||
tcpTransport.connect();
|
closeableTransport.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ping() throws ServerException {
|
public void ping() throws ServerException {
|
||||||
|
@ -163,12 +163,15 @@ public class ElectrumServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void closeActiveConnection() throws ServerException {
|
public static synchronized void closeActiveConnection() throws ServerException {
|
||||||
|
if(transport != null) {
|
||||||
|
closeConnection(transport);
|
||||||
|
transport = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void closeConnection(Closeable closeableTransport) throws ServerException {
|
||||||
try {
|
try {
|
||||||
if(transport != null) {
|
closeableTransport.close();
|
||||||
Closeable closeableTransport = (Closeable)transport;
|
|
||||||
closeableTransport.close();
|
|
||||||
transport = null;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ServerException(e);
|
throw new ServerException(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import java.security.cert.CertificateException;
|
||||||
public enum Protocol {
|
public enum Protocol {
|
||||||
TCP {
|
TCP {
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server) {
|
public CloseableTransport getTransport(HostAndPort server) {
|
||||||
if(isOnionAddress(server)) {
|
if(isOnionAddress(server)) {
|
||||||
return new TorTcpTransport(server);
|
return new TorTcpTransport(server);
|
||||||
}
|
}
|
||||||
|
@ -22,24 +22,24 @@ public enum Protocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server, File serverCert) {
|
public CloseableTransport getTransport(HostAndPort server, File serverCert) {
|
||||||
return getTransport(server);
|
return getTransport(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server, HostAndPort proxy) {
|
public CloseableTransport getTransport(HostAndPort server, HostAndPort proxy) {
|
||||||
//Avoid using a TorSocket if a proxy is specified, even if a .onion address
|
//Avoid using a TorSocket if a proxy is specified, even if a .onion address
|
||||||
return new TcpTransport(server, proxy);
|
return new TcpTransport(server, proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server, File serverCert, HostAndPort proxy) {
|
public CloseableTransport getTransport(HostAndPort server, File serverCert, HostAndPort proxy) {
|
||||||
return getTransport(server, proxy);
|
return getTransport(server, proxy);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SSL {
|
SSL {
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
public CloseableTransport getTransport(HostAndPort server) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||||
if(isOnionAddress(server)) {
|
if(isOnionAddress(server)) {
|
||||||
return new TorTcpOverTlsTransport(server);
|
return new TorTcpOverTlsTransport(server);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public enum Protocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server, File serverCert) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
public CloseableTransport getTransport(HostAndPort server, File serverCert) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||||
if(isOnionAddress(server)) {
|
if(isOnionAddress(server)) {
|
||||||
return new TorTcpOverTlsTransport(server, serverCert);
|
return new TorTcpOverTlsTransport(server, serverCert);
|
||||||
}
|
}
|
||||||
|
@ -57,44 +57,44 @@ public enum Protocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server, HostAndPort proxy) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
public CloseableTransport getTransport(HostAndPort server, HostAndPort proxy) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||||
return new ProxyTcpOverTlsTransport(server, proxy);
|
return new ProxyTcpOverTlsTransport(server, proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server, File serverCert, HostAndPort proxy) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
public CloseableTransport getTransport(HostAndPort server, File serverCert, HostAndPort proxy) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||||
return new ProxyTcpOverTlsTransport(server, serverCert, proxy);
|
return new ProxyTcpOverTlsTransport(server, serverCert, proxy);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
HTTP {
|
HTTP {
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server) {
|
public CloseableTransport getTransport(HostAndPort server) {
|
||||||
throw new UnsupportedOperationException("No transport supported for HTTP");
|
throw new UnsupportedOperationException("No transport supported for HTTP");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server, File serverCert) {
|
public CloseableTransport getTransport(HostAndPort server, File serverCert) {
|
||||||
throw new UnsupportedOperationException("No transport supported for HTTP");
|
throw new UnsupportedOperationException("No transport supported for HTTP");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server, HostAndPort proxy) {
|
public CloseableTransport getTransport(HostAndPort server, HostAndPort proxy) {
|
||||||
throw new UnsupportedOperationException("No transport supported for HTTP");
|
throw new UnsupportedOperationException("No transport supported for HTTP");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Transport getTransport(HostAndPort server, File serverCert, HostAndPort proxy) {
|
public CloseableTransport getTransport(HostAndPort server, File serverCert, HostAndPort proxy) {
|
||||||
throw new UnsupportedOperationException("No transport supported for HTTP");
|
throw new UnsupportedOperationException("No transport supported for HTTP");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public abstract Transport getTransport(HostAndPort server) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException;
|
public abstract CloseableTransport getTransport(HostAndPort server) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException;
|
||||||
|
|
||||||
public abstract Transport getTransport(HostAndPort server, File serverCert) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException;
|
public abstract CloseableTransport getTransport(HostAndPort server, File serverCert) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException;
|
||||||
|
|
||||||
public abstract Transport getTransport(HostAndPort server, HostAndPort proxy) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException;
|
public abstract CloseableTransport getTransport(HostAndPort server, HostAndPort proxy) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException;
|
||||||
|
|
||||||
public abstract Transport getTransport(HostAndPort server, File serverCert, HostAndPort proxy) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException;
|
public abstract CloseableTransport getTransport(HostAndPort server, File serverCert, HostAndPort proxy) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException;
|
||||||
|
|
||||||
public HostAndPort getServerHostAndPort(String url) {
|
public HostAndPort getServerHostAndPort(String url) {
|
||||||
return HostAndPort.fromString(url.substring(this.toUrlString().length()));
|
return HostAndPort.fromString(url.substring(this.toUrlString().length()));
|
||||||
|
|
|
@ -22,7 +22,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
public class TcpTransport implements Transport, Closeable, TimeoutCounter {
|
public class TcpTransport implements CloseableTransport, TimeoutCounter {
|
||||||
private static final Logger log = LoggerFactory.getLogger(TcpTransport.class);
|
private static final Logger log = LoggerFactory.getLogger(TcpTransport.class);
|
||||||
|
|
||||||
public static final int DEFAULT_PORT = 50001;
|
public static final int DEFAULT_PORT = 50001;
|
||||||
|
@ -46,6 +46,7 @@ public class TcpTransport implements Transport, Closeable, TimeoutCounter {
|
||||||
private final ReentrantLock clientRequestLock = new ReentrantLock();
|
private final ReentrantLock clientRequestLock = new ReentrantLock();
|
||||||
private boolean running = false;
|
private boolean running = false;
|
||||||
private volatile boolean reading = true;
|
private volatile boolean reading = true;
|
||||||
|
private boolean closed = false;
|
||||||
private boolean firstRead = true;
|
private boolean firstRead = true;
|
||||||
private int readTimeoutIndex;
|
private int readTimeoutIndex;
|
||||||
private int requestIdCount = 1;
|
private int requestIdCount = 1;
|
||||||
|
@ -223,6 +224,7 @@ public class TcpTransport implements Transport, Closeable, TimeoutCounter {
|
||||||
public void connect() throws ServerException {
|
public void connect() throws ServerException {
|
||||||
try {
|
try {
|
||||||
socket = createSocket();
|
socket = createSocket();
|
||||||
|
log.debug("Created " + socket);
|
||||||
socket.setSoTimeout(SOCKET_READ_TIMEOUT_MILLIS);
|
socket.setSoTimeout(SOCKET_READ_TIMEOUT_MILLIS);
|
||||||
running = true;
|
running = true;
|
||||||
} catch(SSLHandshakeException e) {
|
} catch(SSLHandshakeException e) {
|
||||||
|
@ -237,18 +239,23 @@ public class TcpTransport implements Transport, Closeable, TimeoutCounter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConnected() {
|
public boolean isConnected() {
|
||||||
return socket != null && running;
|
return socket != null && running && !closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Socket createSocket() throws IOException {
|
protected Socket createSocket() throws IOException {
|
||||||
return socketFactory.createSocket(server.getHost(), server.getPortOrDefault(DEFAULT_PORT));
|
return socketFactory.createSocket(server.getHost(), server.getPortOrDefault(DEFAULT_PORT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClosed() {
|
||||||
|
return closed;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if(socket != null) {
|
if(socket != null) {
|
||||||
socket.close();
|
socket.close();
|
||||||
}
|
}
|
||||||
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue