How to avoid SSL Handshake using OkHttp Android

371 Views Asked by At

Overview

I am using the below version of Okhttp com.squareup.okhttp3:okhttp:4.9.3

I need to execute multiple HttpRequests at one go when a transaction happens.

I have taken Singleton OkHttpClient to avoid creation of new client every time so I am reusing the same http client for all my http requests

Scenario

When I execute multiple http requests pararell using the same Singleton OkHttpClient, the SSL Handshake is happening for the 1st http request and it is not happening for the other http requests.

Problem Statement

If there is a delay of more than 30 seconds between 2 http requests then the SSL Handshake is happening every time .. I want to address this issue. SSL Handshake should happen only for the 1st http request. I may send a http request now and take some time and then send another http request. I dont want SSL handshake to happen for the 2nd httprequest. Right now it is happening if there is a delay of 30 seconds. If I execute multiple http requests without any time delay then it is working fine.

Is there any setting in OkttpClient where I can increase the idle time out between 2 http requests so that SSL Handshake wont happen every time.

public class OkHttpSingleton {

private static OkHttpSingleton singletonInstance;

// No need to be static; OkHttpSingleton is unique so is this.
private OkHttpClient httpClient;
int timeoutConnect = 45000;
int timeoutSocket = 45000;


// Private so that this cannot be instantiated.
private OkHttpSingleton() {
    try {
        String tlsVersion = "TLSv1.2";
        if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            tlsVersion = "TLSv1";
        }
        SSLContext sslContext = SSLContext.getInstance(tlsVersion);
        sslContext.init(null, null, null);
        SSLSocketFactory socketFactory = sslContext.getSocketFactory();

        httpClient = new OkHttpClient.Builder()
                .retryOnConnectionFailure(true)
                .connectTimeout(timeoutConnect, TimeUnit.SECONDS)
                .writeTimeout(timeoutSocket, TimeUnit.SECONDS)
                .readTimeout(timeoutSocket, TimeUnit.SECONDS)
                .sslSocketFactory(socketFactory, new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[0];
                    }
                })
                .build();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static OkHttpSingleton getInstance() {
    if (singletonInstance == null) {
        singletonInstance = new OkHttpSingleton();
    }
    return singletonInstance;
}

// In case you just need the unique OkHttpClient instance.
public OkHttpClient getClient() {
    return httpClient;
}

public void closeConnections() {
    httpClient.dispatcher().cancelAll();
}

}

Pls find the screenshot of WIRESHARK below . I want to avoid that Client Hello and HandShake

enter image description here

Pls find the RST ACK sent by server after 30 seconds of inactivity

enter image description here

2

There are 2 best solutions below

1
viethoang On

You can influence the idle time for connections, which indirectly affects the TLS handshake timeout. You do this by configuring the connection pool's eviction policy and the keep-alive duration.

// Increase the idle connection timeout to 10 minutes
ConnectionPool connectionPool = new ConnectionPool(
    /* maxIdleConnections */ 5,
    /* keepAliveDuration */ 10, TimeUnit.MINUTES
);

OkHttpClient client = new OkHttpClient.Builder()
    .connectionPool(connectionPool)
    .build();

In the code above, the keepAliveDuration parameter in the ConnectionPool constructor specifies how long connections can remain idle before they are considered for eviction and cleanup. By increasing this value, you can indirectly influence the timeout for the TLS handshake.

Hope it helps!

2
Hammad Ahmed khan On

try keepAliveDuration eg :

import okhttp3.OkHttpClient;

public class MyHttpClient {
    private static OkHttpClient client;

    public static OkHttpClient getClient() {
        if (client == null) {
            client = new OkHttpClient.Builder()
                .keepAliveDuration(60, TimeUnit.SECONDS) 
                .build();
        }
        return client;
    }
}

Use this in newer version :

OkHttpClient client = new OkHttpClient.Builder()
    .connectionPool(new ConnectionPool(5, 30, TimeUnit.SECONDS)) 
    .build();