// File: /workspace/github_c_makefile_star2_O1/TimeToogo[P]ff-proxy/src/http.c
// Function: ff_http_send_request_tls
bool ff_http_send_request_tls(struct ff_request *request, char *host_name)
{
    bool ret;
    long res = 1;

    SSL_CTX *ctx = NULL;
    BIO *web = NULL;
    SSL *ssl = NULL;
    char error_string[256] = {0};

    int chunk = 0;
    int sent = 0;
    int received = 0;
    char response[FF_HTTP_RESPONSE_BUFF_SIZE] = {0};

    const SSL_METHOD *method = SSLv23_method();
    if (method == NULL)
    {
        ff_log(FF_ERROR, "Failed to initialise OpenSSL method");
        goto error;
    }

    ctx = SSL_CTX_new(method);
    if (ctx == NULL)
    {
        ff_log(FF_ERROR, "Failed to initialise OpenSSL context");
        goto error;
    }

    SSL_CTX_set_default_verify_paths(ctx);

    web = BIO_new_ssl_connect(ctx);

    if (web == NULL)
    {
        ff_log(FF_ERROR, "Failed to initialise OpenSSL connection");
        goto error;
    }

    res = BIO_set_conn_hostname(web, host_name);
    res = BIO_set_conn_port(web, "443");
    if (res != 1)
    {
        ff_log(FF_ERROR, "Failed to set OpenSSL connection host name");
        goto error;
    }

    BIO_get_ssl(web, &ssl);
    if (ssl == NULL)
    {
        ff_log(FF_ERROR, "Failed to set OpenSSL ssl");
        goto error;
    }

    const char *const PREFERRED_CIPHERS = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
    res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);
    if (res != 1)
    {
        ff_log(FF_ERROR, "Failed to set OpenSSL preferred ciphers");
        goto error;
    }

    res = SSL_set_tlsext_host_name(ssl, host_name);
    if (res != 1)
    {
        ff_log(FF_ERROR, "Failed to set OpenSSL TLS host name");
        goto error;
    }

#ifndef OPENSSL_SKIP_HOST_VALIDATION
    {
        X509_VERIFY_PARAM *param = SSL_get0_param(ssl);

        res = X509_VERIFY_PARAM_set1_host(param, host_name, strlen(host_name));
        if (res != 1)
        {
            ff_log(FF_ERROR, "Failed to set OpenSSL param host name");
            goto error;
        }
    }
#endif

    SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);

    res = BIO_do_connect(web);
    if (res != 1)
    {
        ERR_error_string(ERR_get_error(), error_string);
        ff_log(FF_WARNING, "Failed to perform OpenSSL request connection: %s", error_string);
        goto error;
    }

    res = BIO_do_handshake(web);
    if (res != 1)
    {
        ERR_error_string(ERR_get_error(), error_string);
        ff_log(FF_WARNING, "Failed to perform OpenSSL request handshake: %s", error_string);
        goto error;
    }

    X509 *cert = SSL_get_peer_certificate(ssl);
    if (cert)
    {
        X509_free(cert);
    }
    if (cert == NULL)
    {
        ff_log(FF_WARNING, "Server did not present a certificate");
        goto error;
    }

    res = SSL_get_verify_result(ssl);
    if (res != X509_V_OK)
    {
        ERR_error_string(ERR_get_error(), error_string);
        ff_log(FF_WARNING, "Server certificate could not be validated against CA: %s", error_string);
        goto error;
    }

    do
    {
        chunk = BIO_write(web, request->payload->value + sent, request->payload_length - sent);
        sent += chunk;
    } while (chunk > 0);

    ff_log(FF_DEBUG, "Finished sending request to %s over HTTPS (%d bytes sent)", host_name, sent);

    do
    {
        chunk = BIO_read(web, response + received, sizeof(response) - received);

        received += chunk;

        if (received > 5 && strncasecmp(response, "http/", 5) == 0)
        {
            break;
        }
    } while (chunk > 0 || BIO_should_retry(web));

    ff_log(FF_DEBUG, "Finished receiving response from %s (%d bytes received)", host_name, received);
    size_t response_header_length = strchr((char *)response, '\n') - response;
    ff_log(FF_DEBUG, "Response: %.*s", response_header_length > 100l ? 100 : response_header_length, response);
    goto done;

error:
    ret = false;
    goto cleanup;

done:
    ret = true;
    goto cleanup;

cleanup:
    if (web != NULL)
    {
        BIO_free_all(web);
    }

    if (ctx != NULL)
    {
        SSL_CTX_free(ctx);
    }

    return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1108, %rsp           # imm = 0x1108
movq %rsi, %r15
movq %rdi, %r12
movq $0x0, -0x30(%rbp)
leaq -0x130(%rbp), %rdi
movl $0x100, %edx            # imm = 0x100
xorl %esi, %esi
callq 0x2190
leaq -0x1130(%rbp), %rdi
movl $0x1000, %edx           # imm = 0x1000
xorl %esi, %esi
callq 0x2190
callq 0x2490
testq %rax, %rax
je 0x3bc9
movq %rax, %rdi
callq 0x23d0
testq %rax, %rax
je 0x3bd2
movq %rax, %rbx
movq %rax, %rdi
callq 0x22f0
movq %rbx, %rdi
callq 0x2300
testq %rax, %rax
je 0x3bef
movq %rax, %r14
movq %rax, %rdi
movl $0x64, %esi
xorl %edx, %edx
movq %r15, %rcx
callq 0x20a0
leaq 0x2f46(%rip), %rcx      # 0x69de
movl $0x1, %edx
movq %r14, %rdi
movl $0x64, %esi
callq 0x20a0
cmpq $0x1, %rax
jne 0x3c07
leaq -0x30(%rbp), %r13
movq %r14, %rdi
movl $0x6e, %esi
xorl %edx, %edx
movq %r13, %rcx
callq 0x20a0
movq (%r13), %rdi
testq %rdi, %rdi
je 0x3c10
leaq 0x2f49(%rip), %rsi      # 0x6a27
callq 0x21d0
cmpl $0x1, %eax
jne 0x3c19
movq -0x30(%rbp), %rdi
movl $0x37, %esi
xorl %edx, %edx
movq %r15, %rcx
callq 0x2110
cmpq $0x1, %rax
jne 0x3c22
movq -0x30(%rbp), %rdi
callq 0x2030
movq %rax, %r13
movq %r15, %rdi
callq 0x2130
movq %r13, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0x24d0
cmpl $0x1, %eax
jne 0x3c2b
movq -0x30(%rbp), %rdi
movl $0x1, %esi
xorl %edx, %edx
callq 0x2200
movq %r14, %rdi
movl $0x65, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x20a0
cmpq $0x1, %rax
jne 0x3c70
movq %r14, %rdi
movl $0x65, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x20a0
cmpq $0x1, %rax
jne 0x3c90
movq -0x30(%rbp), %rdi
callq 0x24b0
testq %rax, %rax
je 0x3cc5
movq %rax, %rdi
callq 0x2180
movq -0x30(%rbp), %rdi
callq 0x2100
testq %rax, %rax
je 0x3cd9
callq 0x23b0
leaq -0x130(%rbp), %r12
movq %rax, %rdi
movq %r12, %rsi
callq 0x20b0
leaq 0x2f81(%rip), %rsi      # 0x6b45
jmp 0x3cae
leaq 0x2d9d(%rip), %rsi      # 0x696d
jmp 0x3bd9
leaq 0x2db8(%rip), %rsi      # 0x6991
xorl %r14d, %r14d
movl $0x4, %edi
xorl %eax, %eax
callq 0x4100
xorl %ebx, %ebx
xorl %r15d, %r15d
jmp 0x3c41
leaq 0x2dc0(%rip), %rsi      # 0x69b6
xorl %r14d, %r14d
movl $0x4, %edi
xorl %eax, %eax
callq 0x4100
jmp 0x3bea
leaq 0x2dd4(%rip), %rsi      # 0x69e2
jmp 0x3c32
leaq 0x2df6(%rip), %rsi      # 0x6a0d
jmp 0x3c32
leaq 0x2e2d(%rip), %rsi      # 0x6a4d
jmp 0x3c32
leaq 0x2e4c(%rip), %rsi      # 0x6a75
jmp 0x3c32
leaq 0x2e67(%rip), %rsi      # 0x6a99
xorl %r15d, %r15d
movl $0x4, %edi
xorl %eax, %eax
callq 0x4100
testq %r14, %r14
je 0x3c4e
movq %r14, %rdi
callq 0x2120
testq %rbx, %rbx
je 0x3c5b
movq %rbx, %rdi
callq 0x2060
movl %r15d, %eax
addq $0x1108, %rsp           # imm = 0x1108
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x23b0
leaq -0x130(%rbp), %r12
movq %rax, %rdi
movq %r12, %rsi
callq 0x20b0
leaq 0x2e31(%rip), %rsi      # 0x6abf
jmp 0x3cae
callq 0x23b0
leaq -0x130(%rbp), %r12
movq %rax, %rdi
movq %r12, %rsi
callq 0x20b0
leaq 0x2e42(%rip), %rsi      # 0x6af0
xorl %r15d, %r15d
movl $0x3, %edi
movq %r12, %rdx
xorl %eax, %eax
callq 0x4100
jmp 0x3c41
leaq 0x2e54(%rip), %rsi      # 0x6b20
xorl %r15d, %r15d
movl $0x3, %edi
jmp 0x3c3a
xorl %r13d, %r13d
movq 0x50(%r12), %rax
movslq %r13d, %r13
movq 0x8(%rax), %rsi
addq %r13, %rsi
movl 0x40(%r12), %edx
subl %r13d, %edx
movq %r14, %rdi
callq 0x22e0
addl %eax, %r13d
testl %eax, %eax
jg 0x3cdc
leaq 0x2e75(%rip), %rsi      # 0x6b7e
xorl %r12d, %r12d
movl $0x1, %edi
movq %r15, %rdx
movl %r13d, %ecx
xorl %eax, %eax
callq 0x4100
movslq %r12d, %r12
leaq (%r12,%rbp), %rsi
addq $-0x1130, %rsi          # imm = 0xEED0
movl $0x1000, %edx           # imm = 0x1000
subl %r12d, %edx
movq %r14, %rdi
callq 0x2320
movl %eax, %r13d
addl %eax, %r12d
cmpl $0x6, %r12d
jl 0x3d64
movl $0x5, %edx
leaq -0x1130(%rbp), %rdi
leaq 0x2e5d(%rip), %rsi      # 0x6bb8
callq 0x2380
testl %eax, %eax
je 0x3d7a
testl %r13d, %r13d
jg 0x3d1e
movq %r14, %rdi
movl $0x8, %esi
callq 0x23f0
testl %eax, %eax
jne 0x3d1e
leaq 0x2ba5(%rip), %rsi      # 0x6926
movl $0x1, %edi
movq %r15, %rdx
movl %r12d, %ecx
xorl %eax, %eax
callq 0x4100
leaq -0x1130(%rbp), %r15
movq %r15, %rdi
movl $0xa, %esi
callq 0x20f0
subq %r15, %rax
cmpq $0x64, %rax
movl $0x64, %edx
cmovbq %rax, %rdx
leaq 0x2ba0(%rip), %rsi      # 0x695e
movl $0x1, %edi
movq %r15, %rcx
xorl %eax, %eax
callq 0x4100
movb $0x1, %r15b
jmp 0x3c41