Update to OkHttp 3.12.3

This commit is contained in:
Cameron Gutman 2019-07-13 23:55:48 -07:00
parent 936834e396
commit 68040394fb
2 changed files with 64 additions and 66 deletions

View File

@ -23,8 +23,8 @@ android {
} }
dependencies { dependencies {
implementation 'com.squareup.okhttp:okhttp:2.7.5' implementation 'com.squareup.okhttp3:okhttp:3.12.3'
implementation 'com.squareup.okio:okio:1.13.0' implementation 'com.squareup.okio:okio:1.17.4'
// We expose an interface containing a jmDNS class // We expose an interface containing a jmDNS class
// so we need to expose the jmDNS library to users // so we need to expose the jmDNS library to users

View File

@ -10,6 +10,8 @@ import java.net.MalformedURLException;
import java.net.Socket; import java.net.Socket;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal; import java.security.Principal;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.SecureRandom; import java.security.SecureRandom;
@ -38,11 +40,12 @@ import com.limelight.LimeLog;
import com.limelight.nvstream.ConnectionContext; import com.limelight.nvstream.ConnectionContext;
import com.limelight.nvstream.http.PairingManager.PairState; import com.limelight.nvstream.http.PairingManager.PairState;
import com.moonlight_stream.moonlight_common.BuildConfig; import com.moonlight_stream.moonlight_common.BuildConfig;
import com.squareup.okhttp.ConnectionPool;
import com.squareup.okhttp.OkHttpClient; import okhttp3.ConnectionPool;
import com.squareup.okhttp.Request; import okhttp3.OkHttpClient;
import com.squareup.okhttp.Response; import okhttp3.Request;
import com.squareup.okhttp.ResponseBody; import okhttp3.Response;
import okhttp3.ResponseBody;
public class NvHTTP { public class NvHTTP {
@ -60,33 +63,31 @@ public class NvHTTP {
public String baseUrlHttps; public String baseUrlHttps;
public String baseUrlHttp; public String baseUrlHttp;
private OkHttpClient httpClient = new OkHttpClient(); private OkHttpClient httpClient;
private OkHttpClient httpClientWithReadTimeout; private OkHttpClient httpClientWithReadTimeout;
private TrustManager[] trustManager; private X509TrustManager trustManager;
private KeyManager[] keyManager; private X509KeyManager keyManager;
private X509Certificate serverCert; private X509Certificate serverCert;
void setServerCert(final X509Certificate serverCert) { void setServerCert(X509Certificate serverCert) {
this.serverCert = serverCert; this.serverCert = serverCert;
trustManager = new TrustManager[] { trustManager = new X509TrustManager() {
new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() {
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0];
return new X509Certificate[0]; }
public void checkClientTrusted(X509Certificate[] certs, String authType) {
throw new IllegalStateException("Should never be called");
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
if (certs.length != 1) {
throw new CertificateException("Invalid certificate chain length: "+certs.length);
} }
public void checkClientTrusted(X509Certificate[] certs, String authType) {
throw new IllegalStateException("Should never be called");
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
if (certs.length != 1) {
throw new CertificateException("Invalid certificate chain length: "+certs.length);
}
// Check the server certificate if we've paired to this host // Check the server certificate if we've paired to this host
if (!certs[0].equals(serverCert)) { if (!certs[0].equals(NvHTTP.this.serverCert)) {
throw new CertificateException("Certificate mismatch"); throw new CertificateException("Certificate mismatch");
}
} }
} }
}; };
@ -96,35 +97,36 @@ public class NvHTTP {
// Set up TrustManager // Set up TrustManager
setServerCert(serverCert); setServerCert(serverCert);
keyManager = new KeyManager[] { keyManager = new X509KeyManager() {
new X509KeyManager() { public String chooseClientAlias(String[] keyTypes,
public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) { return "Limelight-RSA"; }
Principal[] issuers, Socket socket) { return "Limelight-RSA"; } public String chooseServerAlias(String keyType, Principal[] issuers,
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { return null; }
Socket socket) { return null; } public X509Certificate[] getCertificateChain(String alias) {
public X509Certificate[] getCertificateChain(String alias) { return new X509Certificate[] {cryptoProvider.getClientCertificate()};
return new X509Certificate[] {cryptoProvider.getClientCertificate()}; }
} public String[] getClientAliases(String keyType, Principal[] issuers) { return null; }
public String[] getClientAliases(String keyType, Principal[] issuers) { return null; } public PrivateKey getPrivateKey(String alias) {
public PrivateKey getPrivateKey(String alias) { return cryptoProvider.getClientPrivateKey();
return cryptoProvider.getClientPrivateKey(); }
} public String[] getServerAliases(String keyType, Principal[] issuers) { return null; }
public String[] getServerAliases(String keyType, Principal[] issuers) { return null; }
}
}; };
// Ignore differences between given hostname and certificate hostname // Ignore differences between given hostname and certificate hostname
HostnameVerifier hv = new HostnameVerifier() { HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) { return true; } public boolean verify(String hostname, SSLSession session) { return true; }
}; };
httpClient = new OkHttpClient.Builder()
.connectionPool(new ConnectionPool(0, 1, TimeUnit.MILLISECONDS))
.hostnameVerifier(hv)
.readTimeout(0, TimeUnit.MILLISECONDS)
.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)
.build();
httpClient.setConnectionPool(new ConnectionPool(0, 1)); httpClientWithReadTimeout = httpClient.newBuilder()
httpClient.setHostnameVerifier(hv); .readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS)
httpClient.setReadTimeout(0, TimeUnit.MILLISECONDS); .build();
httpClient.setConnectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS);
httpClientWithReadTimeout = httpClient.clone();
httpClientWithReadTimeout.setReadTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS);
} }
public NvHTTP(String address, String uniqueId, X509Certificate serverCert, LimelightCryptoProvider cryptoProvider) throws IOException { public NvHTTP(String address, String uniqueId, X509Certificate serverCert, LimelightCryptoProvider cryptoProvider) throws IOException {
@ -271,23 +273,22 @@ public class NvHTTP {
return details; return details;
} }
// This hack is Android-specific but we do it on all platforms // This hack is Android-specific but we do it on all platforms
// because it doesn't really matter // because it doesn't really matter
private void performAndroidTlsHack(OkHttpClient client) { private OkHttpClient performAndroidTlsHack(OkHttpClient client) {
// Doing this each time we create a socket is required // Doing this each time we create a socket is required
// to avoid the SSLv3 fallback that causes connection failures // to avoid the SSLv3 fallback that causes connection failures
try { try {
SSLContext sc = SSLContext.getInstance("TLS"); SSLContext sc = SSLContext.getInstance("TLS");
sc.init(keyManager, trustManager, new SecureRandom()); sc.init(new KeyManager[] { keyManager }, new TrustManager[] { trustManager }, new SecureRandom());
return client.newBuilder().sslSocketFactory(sc.getSocketFactory(), trustManager).build();
client.setSslSocketFactory(sc.getSocketFactory()); } catch (NoSuchAlgorithmException | KeyManagementException e) {
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
// Read timeout should be enabled for any HTTP query that requires no outside action // Read timeout should be enabled for any HTTP query that requires no outside action
// on the GFE server. Examples of queries that DO require outside action are launch, resume, and quit. // on the GFE server. Examples of queries that DO require outside action are launch, resume, and quit.
// The initial pair query does require outside action (user entering a PIN) but subsequent pairing // The initial pair query does require outside action (user entering a PIN) but subsequent pairing
@ -299,16 +300,14 @@ public class NvHTTP {
if (serverCert == null && !url.startsWith(baseUrlHttp)) { if (serverCert == null && !url.startsWith(baseUrlHttp)) {
throw new IllegalStateException("Attempted HTTPS fetch without pinned cert"); throw new IllegalStateException("Attempted HTTPS fetch without pinned cert");
} }
if (enableReadTimeout) { if (enableReadTimeout) {
performAndroidTlsHack(httpClientWithReadTimeout); response = performAndroidTlsHack(httpClientWithReadTimeout).newCall(request).execute();
response = httpClientWithReadTimeout.newCall(request).execute();
} }
else { else {
performAndroidTlsHack(httpClient); response = performAndroidTlsHack(httpClient).newCall(request).execute();
response = httpClient.newCall(request).execute();
} }
ResponseBody body = response.body(); ResponseBody body = response.body();
if (response.isSuccessful()) { if (response.isSuccessful()) {
@ -316,11 +315,9 @@ public class NvHTTP {
} }
// Unsuccessful, so close the response body // Unsuccessful, so close the response body
try { if (body != null) {
if (body != null) { body.close();
body.close(); }
}
} catch (IOException e) {}
if (response.code() == 404) { if (response.code() == 404) {
throw new FileNotFoundException(url); throw new FileNotFoundException(url);
@ -338,6 +335,7 @@ public class NvHTTP {
ResponseBody resp = openHttpConnection(url, enableReadTimeout); ResponseBody resp = openHttpConnection(url, enableReadTimeout);
String respString = resp.string(); String respString = resp.string();
resp.close();
if (verbose) { if (verbose) {
LimeLog.info(url+" -> "+respString); LimeLog.info(url+" -> "+respString);