Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a4475068f | ||
|
|
6f15bc6d3c |
@ -4,7 +4,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = 'com.sparrowwallet'
|
||||
version = '1.0.4'
|
||||
version = '1.0.6'
|
||||
|
||||
def secrets = new Properties()
|
||||
file("publish.properties").withInputStream {
|
||||
@ -24,7 +24,6 @@ dependencies {
|
||||
implementation('org.eclipse.jetty:jetty-client:9.4.54.v20240208')
|
||||
implementation('io.reactivex.rxjava2:rxjava:2.2.15')
|
||||
implementation('org.apache.commons:commons-lang3:3.7')
|
||||
implementation('com.google.guava:guava:33.0.0-jre')
|
||||
implementation('org.slf4j:slf4j-api:2.0.12')
|
||||
testImplementation platform('org.junit:junit-bom:5.10.0')
|
||||
testImplementation('org.junit.jupiter:junit-jupiter')
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
package com.sparrowwallet.tern.http.client;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class DefaultHttpProxySupplier implements IHttpProxySupplier {
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final HttpProxy httpProxy;
|
||||
|
||||
public DefaultHttpProxySupplier(String host, int port) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.httpProxy = computeHttpProxy(host, port);
|
||||
}
|
||||
|
||||
private HttpProxy computeHttpProxy(String host, int port) {
|
||||
if(host == null || host.isEmpty() || port < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new HttpProxy(HttpProxyProtocol.SOCKS, host, port);
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<HttpProxy> getHttpProxy(HttpUsage httpUsage) {
|
||||
return Optional.ofNullable(httpProxy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeIdentity() {
|
||||
//not implemented
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
package com.sparrowwallet.tern.http.client;
|
||||
|
||||
import com.google.common.net.HostAndPort;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
import java.util.Map;
|
||||
@ -17,8 +16,8 @@ public class HttpClientService extends JettyHttpClientService {
|
||||
this(requestTimeout, null);
|
||||
}
|
||||
|
||||
public HttpClientService(HostAndPort torProxy) {
|
||||
this(DEFAULT_REQUEST_TIMEOUT, new TorHttpProxySupplier(torProxy));
|
||||
public HttpClientService(String host, int port) {
|
||||
this(DEFAULT_REQUEST_TIMEOUT, new DefaultHttpProxySupplier(host, port));
|
||||
}
|
||||
|
||||
public HttpClientService(IHttpProxySupplier httpProxySupplier) {
|
||||
@ -41,20 +40,4 @@ public class HttpClientService extends JettyHttpClientService {
|
||||
IHttpClient httpClient = getHttpClient(HttpUsage.DEFAULT);
|
||||
return AsyncUtil.getInstance().blockingGet(httpClient.postString(url, headers, contentType, content)).get();
|
||||
}
|
||||
|
||||
public HostAndPort getTorProxy() {
|
||||
if(getHttpProxySupplier() instanceof TorHttpProxySupplier torHttpProxySupplier) {
|
||||
return torHttpProxySupplier.getTorProxy();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setTorProxy(HostAndPort torProxy) {
|
||||
if(getHttpProxySupplier() instanceof TorHttpProxySupplier torHttpProxySupplier) {
|
||||
//Ensure all http clients are shutdown first
|
||||
stop();
|
||||
torHttpProxySupplier._setTorProxy(torProxy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package com.sparrowwallet.tern.http.client;
|
||||
|
||||
import com.google.common.util.concurrent.RateLimiter;
|
||||
import com.sparrowwallet.tern.http.client.socks5.Socks5Proxy;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.ProxyConfiguration;
|
||||
import org.eclipse.jetty.client.Socks4Proxy;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
@ -23,7 +23,11 @@ public class JettyHttpClientService implements IHttpClientService {
|
||||
public static final long DEFAULT_TIMEOUT = 30000;
|
||||
|
||||
// limit changing Tor identity on network error every 4 minutes
|
||||
private static final double RATE_CHANGE_IDENTITY_ON_NETWORK_ERROR = 1.0 / 240;
|
||||
private static final int RATE_CHANGE_IDENTITY_ON_NETWORK_ERROR = 4 * 60 * 1000;
|
||||
|
||||
static {
|
||||
Log.getProperties().setProperty("org.eclipse.jetty.util.log.announce", "false");
|
||||
}
|
||||
|
||||
protected Map<HttpUsage, JettyHttpClient> httpClients; // used by Sparrow
|
||||
private final IHttpProxySupplier httpProxySupplier;
|
||||
@ -91,7 +95,7 @@ public class JettyHttpClientService implements IHttpClientService {
|
||||
}
|
||||
|
||||
protected Consumer<Exception> computeOnNetworkError() {
|
||||
RateLimiter rateLimiter = RateLimiter.create(RATE_CHANGE_IDENTITY_ON_NETWORK_ERROR);
|
||||
RateLimiter rateLimiter = new RateLimiter(1, RATE_CHANGE_IDENTITY_ON_NETWORK_ERROR);
|
||||
return e -> {
|
||||
if(!rateLimiter.tryAcquire()) {
|
||||
if(log.isDebugEnabled()) {
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
package com.sparrowwallet.tern.http.client;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class RateLimiter {
|
||||
private final int maxTokens;
|
||||
private final long refillIntervalMillis;
|
||||
private final AtomicInteger tokens;
|
||||
private long lastRefillTimestamp;
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public RateLimiter(int maxTokens, long refillIntervalMillis) {
|
||||
this.maxTokens = maxTokens;
|
||||
this.refillIntervalMillis = refillIntervalMillis;
|
||||
this.tokens = new AtomicInteger(maxTokens);
|
||||
this.lastRefillTimestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean tryAcquire() {
|
||||
refill();
|
||||
if (tokens.get() > 0) {
|
||||
tokens.decrementAndGet();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void refill() {
|
||||
lock.lock();
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
long elapsed = now - lastRefillTimestamp;
|
||||
if (elapsed > refillIntervalMillis) {
|
||||
int tokensToAdd = (int) (elapsed / refillIntervalMillis);
|
||||
tokens.set(Math.min(maxTokens, tokens.get() + tokensToAdd));
|
||||
lastRefillTimestamp = now;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
package com.sparrowwallet.tern.http.client;
|
||||
|
||||
import com.google.common.net.HostAndPort;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class TorHttpProxySupplier implements IHttpProxySupplier {
|
||||
private HostAndPort torProxy;
|
||||
private HttpProxy httpProxy;
|
||||
|
||||
public TorHttpProxySupplier(HostAndPort torProxy) {
|
||||
this.torProxy = torProxy;
|
||||
this.httpProxy = computeHttpProxy(torProxy);
|
||||
}
|
||||
|
||||
private HttpProxy computeHttpProxy(HostAndPort hostAndPort) {
|
||||
if (hostAndPort == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new HttpProxy(HttpProxyProtocol.SOCKS, hostAndPort.getHost(), hostAndPort.getPort());
|
||||
}
|
||||
|
||||
public HostAndPort getTorProxy() {
|
||||
return torProxy;
|
||||
}
|
||||
|
||||
// shouldnt call directly but use httpClientService.setTorProxy()
|
||||
public void _setTorProxy(HostAndPort hostAndPort) {
|
||||
// set proxy
|
||||
this.torProxy = hostAndPort;
|
||||
this.httpProxy = computeHttpProxy(hostAndPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<HttpProxy> getHttpProxy(HttpUsage httpUsage) {
|
||||
return Optional.ofNullable(httpProxy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeIdentity() {
|
||||
//unimplemented
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
module com.sparrowwallet.tern {
|
||||
requires java.management;
|
||||
requires com.google.common;
|
||||
requires io.reactivex.rxjava2;
|
||||
requires com.fasterxml.jackson.databind;
|
||||
requires org.eclipse.jetty.io;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user