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

package io.netty.handler.codec.quic;

import io.netty.handler.ssl.util.LazyX509Certificate;
import java.security.cert.X509Certificate;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.io.ByteArrayOutputStream;
import org.jetbrains.annotations.Nullable;

final class BoringSSL
{
    static final int SSL_VERIFY_NONE;
    static final int SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
    static final int SSL_VERIFY_PEER;
    static final int X509_V_OK;
    static final int X509_V_ERR_CERT_HAS_EXPIRED;
    static final int X509_V_ERR_CERT_NOT_YET_VALID;
    static final int X509_V_ERR_CERT_REVOKED;
    static final int X509_V_ERR_UNSPECIFIED;
    
    static long SSLContext_new(final boolean server, final String[] applicationProtocols, final BoringSSLHandshakeCompleteCallback handshakeCompleteCallback, final BoringSSLCertificateCallback certificateCallback, final BoringSSLCertificateVerifyCallback verifyCallback, @Nullable final BoringSSLTlsextServernameCallback servernameCallback, @Nullable final BoringSSLKeylogCallback keylogCallback, @Nullable final BoringSSLSessionCallback sessionCallback, @Nullable final BoringSSLPrivateKeyMethod privateKeyMethod, final BoringSSLSessionTicketCallback sessionTicketCallback, final int verifyMode, final byte[][] subjectNames) {
        return SSLContext_new0(server, toWireFormat(applicationProtocols), handshakeCompleteCallback, certificateCallback, verifyCallback, servernameCallback, keylogCallback, sessionCallback, privateKeyMethod, sessionTicketCallback, verifyMode, subjectNames);
    }
    
    private static byte[] toWireFormat(final String[] applicationProtocols) {
        if (applicationProtocols == null) {
            return null;
        }
        try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            for (final String p : applicationProtocols) {
                final byte[] bytes = p.getBytes(StandardCharsets.US_ASCII);
                out.write(bytes.length);
                out.write(bytes);
            }
            return out.toByteArray();
        }
        catch (final IOException e) {
            throw new IllegalStateException(e);
        }
    }
    
    static native long SSLContext_new();
    
    private static native long SSLContext_new0(final boolean p0, final byte[] p1, final Object p2, final Object p3, final Object p4, @Nullable final Object p5, @Nullable final Object p6, @Nullable final Object p7, @Nullable final Object p8, final Object p9, final int p10, final byte[][] p11);
    
    static native void SSLContext_set_early_data_enabled(final long p0, final boolean p1);
    
    static native long SSLContext_setSessionCacheSize(final long p0, final long p1);
    
    static native long SSLContext_setSessionCacheTimeout(final long p0, final long p1);
    
    static native void SSLContext_setSessionTicketKeys(final long p0, final boolean p1);
    
    static int SSLContext_set1_groups_list(final long ctx, final String... groups) {
        if (groups == null) {
            throw new NullPointerException("curves");
        }
        if (groups.length == 0) {
            throw new IllegalArgumentException();
        }
        final StringBuilder sb = new StringBuilder();
        for (final String group : groups) {
            sb.append(group);
            sb.append(':');
        }
        sb.setLength();
        return SSLContext_set1_groups_list(ctx, sb.toString());
    }
    
    static int SSLContext_set1_sigalgs_list(final long ctx, final String... sigalgs) {
        if (sigalgs.length == 0) {
            throw new IllegalArgumentException();
        }
        final StringBuilder sb = new StringBuilder();
        for (final String sigalg : sigalgs) {
            sb.append(sigalg);
            sb.append(':');
        }
        sb.setLength();
        return SSLContext_set1_sigalgs_list(ctx, sb.toString());
    }
    
    private static native int SSLContext_set1_sigalgs_list(final long p0, final String p1);
    
    private static native int SSLContext_set1_groups_list(final long p0, final String p1);
    
    static native void SSLContext_free(final long p0);
    
    static long SSL_new(final long context, final boolean server, final String hostname) {
        return SSL_new0(context, server, tlsExtHostName(hostname));
    }
    
    static native long SSL_new0(final long p0, final boolean p1, @Nullable final String p2);
    
    static native void SSL_free(final long p0);
    
    static native Runnable SSL_getTask(final long p0);
    
    static native void SSL_cleanup(final long p0);
    
    static native long EVP_PKEY_parse(final byte[] p0, final String p1);
    
    static native void EVP_PKEY_free(final long p0);
    
    static native long CRYPTO_BUFFER_stack_new(final long p0, final byte[][] p1);
    
    static native void CRYPTO_BUFFER_stack_free(final long p0);
    
    @Nullable
    static native String ERR_last_error();
    
    @Nullable
    private static String tlsExtHostName(@Nullable String hostname) {
        if (hostname != null && hostname.endsWith(".")) {
            hostname = hostname.substring(0, hostname.length() - 1);
        }
        return hostname;
    }
    
    static X509Certificate[] certificates(final byte[][] chain) {
        final X509Certificate[] peerCerts = new X509Certificate[chain.length];
        for (int i = 0; i < peerCerts.length; ++i) {
            peerCerts[i] = new LazyX509Certificate(chain[i]);
        }
        return peerCerts;
    }
    
    static byte[][] subjectNames(final X509Certificate[] certificates) {
        final byte[][] subjectNames = new byte[certificates.length][];
        for (int i = 0; i < certificates.length; ++i) {
            subjectNames[i] = certificates[i].getSubjectX500Principal().getEncoded();
        }
        return subjectNames;
    }
    
    private BoringSSL() {
    }
    
    static {
        SSL_VERIFY_NONE = BoringSSLNativeStaticallyReferencedJniMethods.ssl_verify_none();
        SSL_VERIFY_FAIL_IF_NO_PEER_CERT = BoringSSLNativeStaticallyReferencedJniMethods.ssl_verify_fail_if_no_peer_cert();
        SSL_VERIFY_PEER = BoringSSLNativeStaticallyReferencedJniMethods.ssl_verify_peer();
        X509_V_OK = BoringSSLNativeStaticallyReferencedJniMethods.x509_v_ok();
        X509_V_ERR_CERT_HAS_EXPIRED = BoringSSLNativeStaticallyReferencedJniMethods.x509_v_err_cert_has_expired();
        X509_V_ERR_CERT_NOT_YET_VALID = BoringSSLNativeStaticallyReferencedJniMethods.x509_v_err_cert_not_yet_valid();
        X509_V_ERR_CERT_REVOKED = BoringSSLNativeStaticallyReferencedJniMethods.x509_v_err_cert_revoked();
        X509_V_ERR_UNSPECIFIED = BoringSSLNativeStaticallyReferencedJniMethods.x509_v_err_unspecified();
    }
}
