// 
// Decompiled by Procyon v0.6.0
// 

package io.netty.handler.ssl;

import javax.net.ssl.SSLContext;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.SecureRandom;
import io.netty.handler.ssl.util.BouncyCastleUtil;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.util.function.BiFunction;
import javax.net.ssl.SSLParameters;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.EmptyArrays;
import java.util.List;
import javax.net.ssl.SSLEngine;
import java.lang.reflect.Method;
import io.netty.util.internal.logging.InternalLogger;

final class BouncyCastleAlpnSslUtils
{
    private static final InternalLogger logger;
    private static final Method SET_APPLICATION_PROTOCOLS;
    private static final Method GET_APPLICATION_PROTOCOL;
    private static final Method GET_HANDSHAKE_APPLICATION_PROTOCOL;
    private static final Method SET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR;
    private static final Method GET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR;
    private static final Class<?> BC_APPLICATION_PROTOCOL_SELECTOR;
    private static final Method BC_APPLICATION_PROTOCOL_SELECTOR_SELECT;
    private static final boolean SUPPORTED;
    
    private BouncyCastleAlpnSslUtils() {
    }
    
    static String getApplicationProtocol(final SSLEngine sslEngine) {
        try {
            return (String)BouncyCastleAlpnSslUtils.GET_APPLICATION_PROTOCOL.invoke(sslEngine, new Object[0]);
        }
        catch (final UnsupportedOperationException ex) {
            throw ex;
        }
        catch (final Exception ex2) {
            throw new IllegalStateException(ex2);
        }
    }
    
    static void setApplicationProtocols(final SSLEngine engine, final List<String> supportedProtocols) {
        final String[] protocolArray = supportedProtocols.toArray(EmptyArrays.EMPTY_STRINGS);
        try {
            final SSLParameters bcSslParameters = engine.getSSLParameters();
            BouncyCastleAlpnSslUtils.SET_APPLICATION_PROTOCOLS.invoke(bcSslParameters, protocolArray);
            engine.setSSLParameters(bcSslParameters);
        }
        catch (final UnsupportedOperationException ex) {
            throw ex;
        }
        catch (final Exception ex2) {
            throw new IllegalStateException(ex2);
        }
        if (PlatformDependent.javaVersion() >= 9) {
            JdkAlpnSslUtils.setApplicationProtocols(engine, supportedProtocols);
        }
    }
    
    static String getHandshakeApplicationProtocol(final SSLEngine sslEngine) {
        try {
            return (String)BouncyCastleAlpnSslUtils.GET_HANDSHAKE_APPLICATION_PROTOCOL.invoke(sslEngine, new Object[0]);
        }
        catch (final UnsupportedOperationException ex) {
            throw ex;
        }
        catch (final Exception ex2) {
            throw new IllegalStateException(ex2);
        }
    }
    
    static void setHandshakeApplicationProtocolSelector(final SSLEngine engine, final BiFunction<SSLEngine, List<String>, String> selector) {
        try {
            final Object selectorProxyInstance = Proxy.newProxyInstance(BouncyCastleAlpnSslUtils.class.getClassLoader(), new Class[] { BouncyCastleAlpnSslUtils.BC_APPLICATION_PROTOCOL_SELECTOR }, new InvocationHandler() {
                @Override
                public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
                    if (method.getName().equals("select")) {
                        try {
                            return selector.apply(args[0], args[1]);
                        }
                        catch (final ClassCastException e) {
                            throw new RuntimeException("BCApplicationProtocolSelector select method parameter of invalid type.", e);
                        }
                    }
                    throw new UnsupportedOperationException(String.format("Method '%s' not supported.", method.getName()));
                }
            });
            BouncyCastleAlpnSslUtils.SET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR.invoke(engine, selectorProxyInstance);
        }
        catch (final UnsupportedOperationException ex) {
            throw ex;
        }
        catch (final Exception ex2) {
            throw new IllegalStateException(ex2);
        }
    }
    
    static BiFunction<SSLEngine, List<String>, String> getHandshakeApplicationProtocolSelector(final SSLEngine engine) {
        try {
            final Object selector = BouncyCastleAlpnSslUtils.GET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR.invoke(engine, new Object[0]);
            return (BiFunction<SSLEngine, List<String>, String>)((sslEngine, strings) -> {
                try {
                    return (Object)BouncyCastleAlpnSslUtils.BC_APPLICATION_PROTOCOL_SELECTOR_SELECT.invoke(selector, sslEngine, strings);
                }
                catch (final Exception e) {
                    throw new RuntimeException("Could not call getHandshakeApplicationProtocolSelector", e);
                }
            });
        }
        catch (final UnsupportedOperationException ex) {
            throw ex;
        }
        catch (final Exception ex2) {
            throw new IllegalStateException(ex2);
        }
    }
    
    static boolean isAlpnSupported() {
        return BouncyCastleAlpnSslUtils.SUPPORTED;
    }
    
    static {
        logger = InternalLoggerFactory.getInstance(BouncyCastleAlpnSslUtils.class);
        Method setApplicationProtocols;
        Method getApplicationProtocol;
        Method getHandshakeApplicationProtocol;
        Class<?> bcApplicationProtocolSelector;
        Method bcApplicationProtocolSelectorSelect;
        Method setHandshakeApplicationProtocolSelector;
        Method getHandshakeApplicationProtocolSelector;
        boolean supported;
        try {
            if (!BouncyCastleUtil.isBcTlsAvailable()) {
                throw new IllegalStateException(BouncyCastleUtil.unavailabilityCauseBcTls());
            }
            final SSLContext context = SslUtils.getSSLContext(BouncyCastleUtil.getBcProviderJsse(), new SecureRandom());
            final SSLEngine engine = context.createSSLEngine();
            final Class<? extends SSLEngine> engineClass = engine.getClass();
            final Class<? extends SSLEngine> bcEngineClass = BouncyCastleUtil.getBcSSLEngineClass();
            if (bcEngineClass == null || !bcEngineClass.isAssignableFrom(engineClass)) {
                throw new IllegalStateException("Unexpected engine class: " + engineClass);
            }
            final SSLParameters bcSslParameters = engine.getSSLParameters();
            final Class<?> bCSslParametersClass = bcSslParameters.getClass();
            setApplicationProtocols = AccessController.doPrivileged((PrivilegedExceptionAction<Method>)new PrivilegedExceptionAction<Method>() {
                final /* synthetic */ Class val$bCSslParametersClass;
                
                @Override
                public Method run() throws Exception {
                    return this.val$bCSslParametersClass.getMethod("setApplicationProtocols", String[].class);
                }
            });
            setApplicationProtocols.invoke(bcSslParameters, EmptyArrays.EMPTY_STRINGS);
            getApplicationProtocol = AccessController.doPrivileged((PrivilegedExceptionAction<Method>)new PrivilegedExceptionAction<Method>() {
                final /* synthetic */ Class val$bcEngineClass;
                
                @Override
                public Method run() throws Exception {
                    return this.val$bcEngineClass.getMethod("getApplicationProtocol", (Class[])new Class[0]);
                }
            });
            getApplicationProtocol.invoke(engine, new Object[0]);
            getHandshakeApplicationProtocol = AccessController.doPrivileged((PrivilegedExceptionAction<Method>)new PrivilegedExceptionAction<Method>() {
                final /* synthetic */ Class val$bcEngineClass;
                
                @Override
                public Method run() throws Exception {
                    return this.val$bcEngineClass.getMethod("getHandshakeApplicationProtocol", (Class[])new Class[0]);
                }
            });
            getHandshakeApplicationProtocol.invoke(engine, new Object[0]);
            final Class<?> testBCApplicationProtocolSelector = bcApplicationProtocolSelector = Class.forName("org.bouncycastle.jsse.BCApplicationProtocolSelector", true, engineClass.getClassLoader());
            bcApplicationProtocolSelectorSelect = AccessController.doPrivileged((PrivilegedExceptionAction<Method>)new PrivilegedExceptionAction<Method>() {
                final /* synthetic */ Class val$testBCApplicationProtocolSelector;
                
                @Override
                public Method run() throws Exception {
                    return this.val$testBCApplicationProtocolSelector.getMethod("select", Object.class, List.class);
                }
            });
            setHandshakeApplicationProtocolSelector = AccessController.doPrivileged((PrivilegedExceptionAction<Method>)new PrivilegedExceptionAction<Method>() {
                final /* synthetic */ Class val$bcEngineClass;
                final /* synthetic */ Class val$testBCApplicationProtocolSelector = testBCApplicationProtocolSelector;
                
                @Override
                public Method run() throws Exception {
                    return this.val$bcEngineClass.getMethod("setBCHandshakeApplicationProtocolSelector", this.val$testBCApplicationProtocolSelector);
                }
            });
            getHandshakeApplicationProtocolSelector = AccessController.doPrivileged((PrivilegedExceptionAction<Method>)new PrivilegedExceptionAction<Method>() {
                final /* synthetic */ Class val$bcEngineClass;
                
                @Override
                public Method run() throws Exception {
                    return this.val$bcEngineClass.getMethod("getBCHandshakeApplicationProtocolSelector", (Class[])new Class[0]);
                }
            });
            getHandshakeApplicationProtocolSelector.invoke(engine, new Object[0]);
            supported = true;
        }
        catch (final Throwable t) {
            BouncyCastleAlpnSslUtils.logger.error("Unable to initialize BouncyCastleAlpnSslUtils.", t);
            setApplicationProtocols = null;
            getApplicationProtocol = null;
            getHandshakeApplicationProtocol = null;
            setHandshakeApplicationProtocolSelector = null;
            getHandshakeApplicationProtocolSelector = null;
            bcApplicationProtocolSelectorSelect = null;
            bcApplicationProtocolSelector = null;
            supported = false;
        }
        SET_APPLICATION_PROTOCOLS = setApplicationProtocols;
        GET_APPLICATION_PROTOCOL = getApplicationProtocol;
        GET_HANDSHAKE_APPLICATION_PROTOCOL = getHandshakeApplicationProtocol;
        SET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR = setHandshakeApplicationProtocolSelector;
        GET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR = getHandshakeApplicationProtocolSelector;
        BC_APPLICATION_PROTOCOL_SELECTOR_SELECT = bcApplicationProtocolSelectorSelect;
        BC_APPLICATION_PROTOCOL_SELECTOR = bcApplicationProtocolSelector;
        SUPPORTED = supported;
    }
}
