Skip to content

Commit

Permalink
Merge pull request #390 from Chainfire/https-proxy
Browse files Browse the repository at this point in the history
HTTPS proxy support
  • Loading branch information
devgianlu committed Aug 18, 2021
2 parents 56c7a2c + 5af8a38 commit 9628376
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 4 deletions.
75 changes: 71 additions & 4 deletions lib/src/main/java/xyz/gianlu/librespot/core/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
Expand Down Expand Up @@ -156,6 +158,10 @@ public Request authenticate(Route route, @NotNull Response response) {
}
});
}
if (conf.proxyType == Proxy.Type.HTTP && conf.proxySSL) {
// builder.socketFactory(SSLSocketFactory.getDefault()) throws an error on some okhttp versions
builder.socketFactory(new DelegatingSocketFactory(SSLSocketFactory.getDefault()));
}
}

builder.addInterceptor(chain -> {
Expand Down Expand Up @@ -1029,6 +1035,7 @@ public final static class Configuration {
// Proxy
public final boolean proxyEnabled;
public final Proxy.Type proxyType;
public final boolean proxySSL;
public final String proxyAddress;
public final int proxyPort;
public final boolean proxyAuth;
Expand All @@ -1054,13 +1061,15 @@ public final static class Configuration {
// Network
public final int connectionTimeout;

private Configuration(boolean proxyEnabled, Proxy.Type proxyType, String proxyAddress, int proxyPort, boolean proxyAuth, String proxyUsername, String proxyPassword,
private Configuration(boolean proxyEnabled, Proxy.Type proxyType, boolean proxySSL, String proxyAddress,
int proxyPort, boolean proxyAuth, String proxyUsername, String proxyPassword,
TimeProvider.Method timeSynchronizationMethod, int timeManualCorrection,
boolean cacheEnabled, File cacheDir, boolean doCacheCleanUp,
boolean storeCredentials, File storedCredentialsFile,
boolean retryOnChunkError, int connectionTimeout) {
this.proxyEnabled = proxyEnabled;
this.proxyType = proxyType;
this.proxySSL = proxySSL;
this.proxyAddress = proxyAddress;
this.proxyPort = proxyPort;
this.proxyAuth = proxyAuth;
Expand All @@ -1081,6 +1090,7 @@ public static final class Builder {
// Proxy
private boolean proxyEnabled = false;
private Proxy.Type proxyType;
private boolean proxySSL = false;
private String proxyAddress;
private int proxyPort;
private boolean proxyAuth;
Expand Down Expand Up @@ -1119,6 +1129,11 @@ public Builder setProxyType(Proxy.Type proxyType) {
return this;
}

public Builder setProxySSL(boolean proxySSL) {
this.proxySSL = proxySSL;
return this;
}

public Builder setProxyAddress(String proxyAddress) {
this.proxyAddress = proxyAddress;
return this;
Expand Down Expand Up @@ -1191,7 +1206,8 @@ public Builder setConnectionTimeout(int connectionTimeout) {

@NotNull
public Configuration build() {
return new Configuration(proxyEnabled, proxyType, proxyAddress, proxyPort, proxyAuth, proxyUsername, proxyPassword,
return new Configuration(proxyEnabled, proxyType, proxySSL, proxyAddress, proxyPort, proxyAuth,
proxyUsername, proxyPassword,
timeSynchronizationMethod, timeManualCorrection,
cacheEnabled, cacheDir, doCacheCleanUp,
storeCredentials, storedCredentialsFile,
Expand Down Expand Up @@ -1245,7 +1261,12 @@ static ConnectionHolder create(@NotNull String addr, @NotNull Configuration conf

switch (conf.proxyType) {
case HTTP:
Socket sock = new Socket(conf.proxyAddress, conf.proxyPort);
Socket sock;
if (conf.proxySSL) {
sock = SSLSocketFactory.getDefault().createSocket(conf.proxyAddress, conf.proxyPort);
} else{
sock = new Socket(conf.proxyAddress, conf.proxyPort);
}
OutputStream out = sock.getOutputStream();
DataInputStream in = new DataInputStream(sock.getInputStream());

Expand All @@ -1264,7 +1285,7 @@ static ConnectionHolder create(@NotNull String addr, @NotNull Configuration conf
// Read all headers
}

LOGGER.info("Successfully connected to the HTTP proxy.");
LOGGER.info(String.format("Successfully connected to the %s proxy.", conf.proxySSL ? "HTTPS" : "HTTP"));
return new ConnectionHolder(sock);
case SOCKS:
if (conf.proxyAuth) {
Expand Down Expand Up @@ -1399,4 +1420,50 @@ public void run() {
LOGGER.trace("Session.Receiver stopped");
}
}

/**
* A {@link SocketFactory} that delegates calls. Sockets can be configured after creation by
* overriding {@link #configureSocket(java.net.Socket)}.
*
* Copy/pasted from okhttp3 tests sources for HTTPS proxy support
*/
public static class DelegatingSocketFactory extends SocketFactory {
private final SocketFactory delegate;

public DelegatingSocketFactory(SocketFactory delegate) {
this.delegate = delegate;
}

@Override public Socket createSocket() throws IOException {
Socket socket = delegate.createSocket();
return configureSocket(socket);
}

@Override public Socket createSocket(String host, int port) throws IOException {
Socket socket = delegate.createSocket(host, port);
return configureSocket(socket);
}

@Override public Socket createSocket(String host, int port, InetAddress localAddress,
int localPort) throws IOException {
Socket socket = delegate.createSocket(host, port, localAddress, localPort);
return configureSocket(socket);
}

@Override public Socket createSocket(InetAddress host, int port) throws IOException {
Socket socket = delegate.createSocket(host, port);
return configureSocket(socket);
}

@Override public Socket createSocket(InetAddress host, int port, InetAddress localAddress,
int localPort) throws IOException {
Socket socket = delegate.createSocket(host, port, localAddress, localPort);
return configureSocket(socket);
}

protected Socket configureSocket(Socket socket) throws IOException {
// No-op by default.
return socket;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ public Session.Configuration toSession() {
.setTimeManualCorrection(config.get("time.manualCorrection"))
.setProxyEnabled(config.get("proxy.enabled"))
.setProxyType(config.getEnum("proxy.type", Proxy.Type.class))
.setProxySSL(config.get("proxy.ssl"))
.setProxyAddress(config.get("proxy.address"))
.setProxyPort(config.get("proxy.port"))
.setProxyAuth(config.get("proxy.auth"))
Expand Down
1 change: 1 addition & 0 deletions player/src/main/resources/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ host = "0.0.0.0" # API listen interface (`api` module only)
[proxy] ### Proxy ###
enabled = false # Whether the proxy is enabled
type = "HTTP" # The proxy type (HTTP, SOCKS)
ssl = false # Connect to proxy using SSL (HTTP only)
address = "" # The proxy hostname
port = 0 # The proxy port
auth = false # Whether authentication is enabled on the server
Expand Down

0 comments on commit 9628376

Please sign in to comment.