Uploaded image for project: 'HttpComponents HttpAsyncClient'
  1. HttpComponents HttpAsyncClient
  2. HTTPASYNC-134

Getting error with httpclient5 with HTTP2 & SSL (java.io.IOException: An existing connection was forcibly closed by the remote host)

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Blocker
    • Resolution: Invalid
    • None
    • None
    • None
    • JDK 1.8, org.apache.httpcomponents.client5 5.0-beta1

    Description

      Hi

      Getting following error when I configure CloseableHttpAsyncClient to use HTTP2 over SSL.

       

      java.io.IOException: An existing connection was forcibly closed by the remote host
      at sun.nio.ch.SocketDispatcher.read0(Native Method)
      at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
      at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
      at sun.nio.ch.IOUtil.read(IOUtil.java:197)
      at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
      at org.apache.hc.core5.reactor.ssl.SSLIOSession.receiveEncryptedData(SSLIOSession.java:443)
      at org.apache.hc.core5.reactor.ssl.SSLIOSession.isAppInputReady(SSLIOSession.java:498)
      at org.apache.hc.core5.reactor.InternalDataChannel.onIOEvent(InternalDataChannel.java:112)
      at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:50)
      at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:173)
      at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:123)
      at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:80)
      at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)
      at java.lang.Thread.run(Thread.java:745)

       

       

      Could you help, please? The complete code is provided in code section. Thanks.

       

       

      Regards

       

      Rajan

      // App.java
      
      public static void main( String[] args ) throws Exception
      {
      final CountDownLatch countDownLatch = new CountDownLatch(1);
      String trustStorePath = "C:\\cert\\keystore.jks";
      String trustStorePassword = "password";
      // SSLProvider should be used for all SSL related config like building a SSL context
      SSLProvider provider = new SSLProvider();
      SSLContext sslContext = provider.buildSSLContext(null, null, trustStorePath, trustStorePassword);
      final TlsStrategy tlsStrategy = new H2TlsStrategy(
      sslContext,
      H2TlsStrategy.getDefaultHostnameVerifier()) {
      };
      
      final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create()
      .setTlsStrategy(tlsStrategy)
      .build();
      CloseableHttpAsyncClient client = HttpAsyncClients.custom().setConnectionManager(cm).setVersionPolicy(HttpVersionPolicy.FORCE_HTTP_2).build();
      client.start(); 
      
      final HttpHost target = new HttpHost("localhost", 1090, "https");
      
      final String requestUri = "/rest/rest/helloWorld";
      final HttpClientContext clientContext = HttpClientContext.create();
      
      final SimpleHttpRequest request = SimpleHttpRequest.get(target, requestUri);
      final Future<SimpleHttpResponse> future = client.execute(
      SimpleRequestProducer.create(request),
      SimpleResponseConsumer.create(),
      new FutureCallback<SimpleHttpResponse>() {
      
      public void completed(final SimpleHttpResponse response) {
      System.out.println(requestUri + "->" + response.getCode());
      System.out.println(response.getBody());
      final SSLSession sslSession = clientContext.getSSLSession();
      if (sslSession != null) {
      System.out.println("SSL protocol " + sslSession.getProtocol());
      System.out.println("SSL cipher suite " + sslSession.getCipherSuite());
      }
      countDownLatch.countDown();
      }
      
      public void failed(final Exception ex) {
      ex.printStackTrace();
      System.out.println(requestUri + "->" + ex);
      }
      
      public void cancelled() {
      System.out.println(requestUri + " cancelled");
      }
      
      });
      countDownLatch.await();
      System.out.println("Shutting down");
      client.shutdown(ShutdownType.GRACEFUL);
      
      }
      
      
      //SSLProvider.java
      
      public class SSLProvider
      {
      
      public SSLContext buildSSLContext(String keyStorePath, String keyStorePassword, String trustStorePath, String trustStorePassword)
      throws Exception
      {
      
      TrustManager trustManagers[] = null;
      KeyManager keyManagers[] = null;
      
      if(null != trustStorePath && !"".equalsIgnoreCase(trustStorePath))
      {
      trustManagers = new TrustManager[] {new MyX509TrustManager(trustStorePath, trustStorePassword.toCharArray())};
      }
      
      if(null != keyStorePath && !"".equalsIgnoreCase(keyStorePath))
      {
      keyManagers = new KeyManager[] {new MyX509KeyManager(keyStorePath, keyStorePassword.toCharArray())};
      }
      
      SSLContext context = SSLContext.getInstance("TLS");
      context.init(keyManagers, trustManagers, null);
      
      return context;
      
      }
      
      static class MyX509TrustManager implements X509TrustManager
      {
      
      /*
      * The default PKIX X509TrustManager9. We'll delegate decisions to it, and fall back to the logic in this class if the default
      * X509TrustManager doesn't trust it.
      */
      X509TrustManager pkixTrustManager;
      
      MyX509TrustManager(String trustStore, char[] password) throws Exception
      {
      this(new File(trustStore), password);
      }
      
      MyX509TrustManager(File trustStore, char[] password) throws Exception
      {
      // create a "default" JSSE X509TrustManager.
      
      KeyStore ks = KeyStore.getInstance("JKS");
      
      ks.load(new FileInputStream(trustStore), password);
      
      TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
      tmf.init(ks);
      
      TrustManager tms[] = tmf.getTrustManagers();
      
      /*
      * Iterate over the returned trustmanagers, look for an instance of X509TrustManager. If found, use that as our "default" trust
      * manager.
      */
      for(int i = 0; i < tms.length; i++)
      {
      if(tms[i] instanceof X509TrustManager)
      {
      pkixTrustManager = (X509TrustManager) tms[i];
      return;
      }
      }
      
      /*
      * Find some other way to initialize, or else we have to fail the constructor.
      */
      throw new Exception("Couldn't initialize");
      }
      
      /*
      * Delegate to the default trust manager.
      */
      public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException
      {
      
      pkixTrustManager.checkClientTrusted(chain, authType);
      
      }
      
      /*
      * Delegate to the default trust manager.
      */
      public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException
      {
      
      pkixTrustManager.checkServerTrusted(chain, authType);
      
      }
      
      /*
      * Merely pass this through.
      */
      public X509Certificate[] getAcceptedIssuers()
      {
      return pkixTrustManager.getAcceptedIssuers();
      }
      }
      
      /**
      * Inspired from http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html
      * 
      */
      static class MyX509KeyManager implements X509KeyManager
      {
      
      /*
      * The default PKIX X509KeyManager. We'll delegate decisions to it, and fall back to the logic in this class if the default
      * X509KeyManager doesn't trust it.
      */
      X509KeyManager pkixKeyManager;
      
      MyX509KeyManager(String keyStore, char[] password) throws Exception
      {
      this(new File(keyStore), password);
      }
      
      MyX509KeyManager(File keyStore, char[] password) throws Exception
      {
      // create a "default" JSSE X509KeyManager.
      
      KeyStore ks = KeyStore.getInstance("JKS");
      ks.load(new FileInputStream(keyStore), password);
      
      KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509", "SunJSSE");
      kmf.init(ks, password);
      
      KeyManager kms[] = kmf.getKeyManagers();
      
      /*
      * Iterate over the returned keymanagers, look for an instance of X509KeyManager. If found, use that as our "default" key
      * manager.
      */
      for(int i = 0; i < kms.length; i++)
      {
      if(kms[i] instanceof X509KeyManager)
      {
      pkixKeyManager = (X509KeyManager) kms[i];
      return;
      }
      }
      
      /*
      * Find some other way to initialize, or else we have to fail the constructor.
      */
      throw new Exception("Couldn't initialize");
      }
      
      public PrivateKey getPrivateKey(String arg0)
      {
      return pkixKeyManager.getPrivateKey(arg0);
      }
      
      public X509Certificate[] getCertificateChain(String arg0)
      {
      return pkixKeyManager.getCertificateChain(arg0);
      }
      
      public String[] getClientAliases(String arg0, Principal[] arg1)
      {
      return pkixKeyManager.getClientAliases(arg0, arg1);
      }
      
      public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2)
      {
      return pkixKeyManager.chooseClientAlias(arg0, arg1, arg2);
      }
      
      public String[] getServerAliases(String arg0, Principal[] arg1)
      {
      return pkixKeyManager.getServerAliases(arg0, arg1);
      }
      
      public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2)
      {
      return pkixKeyManager.chooseServerAlias(arg0, arg1, arg2);
      }
      
      }
      
      public HostnameVerifier getHostNameVerfier()
      {
      
      return new HostnameVerifier()
      {
      
      
      public boolean verify(String arg0, SSLSession arg1)
      {
      // a host can be termed as blocked or non-verified through some logic here;by returning false
      return true;
      }
      };
      }
      }

       

      Attachments

        Activity

          People

            Unassigned Unassigned
            rajan.saini Rajan
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: