// File: /workspace/github_c_makefile_star2_O3/wahern[P]cqueues/src/lib/socket.c
// Function: so_starttls
int so_starttls(struct socket *so, const struct so_starttls *cfg) {
	SSL_CTX *ctx, *tmp = NULL;
	SSL *ssl = NULL;
	const SSL_METHOD *method;
	int error;

	if (so->done & SO_S_STARTTLS)
		return 0;

	if (so->todo & SO_S_STARTTLS)
		goto check;

	cfg = (cfg)? cfg : &(struct so_starttls){ 0 };

	so_resetssl(so);

	/*
	 * NOTE: Commit to the SO_S_STARTTLS state at this point, no matter
	 * whether we can allocate the proper objects, so any errors will
	 * persist. so_starttls_() immediately returns if so->ssl.error is
	 * set. See NOTE at error label below.
	 */
	so->todo |= SO_S_STARTTLS;

	if (cfg->pushback.iov_len > 0) {
		if (!(so->bio.ahead.data = malloc(cfg->pushback.iov_len))) {
			error = errno;
			goto error;
		}

		memcpy(so->bio.ahead.data, cfg->pushback.iov_base, cfg->pushback.iov_len);
		so->bio.ahead.p = so->bio.ahead.data;
		so->bio.ahead.pe = so->bio.ahead.p + cfg->pushback.iov_len;
	}

	ERR_clear_error();

	if ((ssl = cfg->instance)) {
		SSL_up_ref(ssl);
	} else {
		if (!(ctx = cfg->context)) {
			if (!(method = cfg->method)) {
				if (so_isbool(cfg->accept)) {
					method = SSLv23_method();
				} else {
					method = SSLv23_client_method();
				}
			}

			if (!(ctx = tmp = SSL_CTX_new((SSL_METHOD *)method)))
				goto eossl;
		}

		if (!(ssl = SSL_new(ctx)))
			goto eossl;
	}

	if (so_isbool(cfg->accept)) {
		so->ssl.accept = so_tobool(cfg->accept);
	} else {
		/* NB: see WARNING at compat_SSL_is_server() */
		so->ssl.accept = SSL_is_server(ssl);
	}

	if (!so->ssl.accept && so->opts.tls_sendname && so->opts.tls_sendname != SO_OPTS_TLS_HOSTNAME) {
		if (!SSL_set_tlsext_host_name(ssl, so->opts.tls_sendname))
			goto eossl;
	}

	SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
	SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);

	so->ssl.ctx = ssl;
	ssl = NULL;

	if (tmp)
		SSL_CTX_free(tmp);

check:
	return so_exec(so);
eossl:
	error = SO_EOPENSSL;
error:
	/*
	 * NOTE: Store any error in so->ssl.error because callers expect to
	 * call-and-forget this routine, similar to so_connect() and
	 * so_listen(), but we still need to replay the error.
	 */
	so->ssl.error = error;

	if (ssl)
		SSL_free(ssl);

	if (tmp)
		SSL_CTX_free(tmp);

	return so->ssl.error;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
xorl %eax, %eax
testb $0x40, 0xb4(%rdi)
jne 0x24ba0
movq %rdi, %rbx
testb $0x40, 0xb8(%rdi)
jne 0x24b69
movq %rsi, %r14
testq %rsi, %rsi
je 0x249c3
leaq 0x18(%r14), %rbp
leaq 0x20(%r14), %r15
leaq 0x10(%r14), %r13
leaq 0x8(%r14), %rax
movq %rax, 0x8(%rsp)
leaq 0x28(%r14), %r12
jmp 0x249fd
xorl %eax, %eax
leaq 0x40(%rsp), %r14
movq %rax, (%r14)
leaq 0x38(%rsp), %rcx
movq %rcx, 0x8(%rsp)
movq %rax, (%rcx)
leaq 0x30(%rsp), %r13
movq %rax, (%r13)
leaq 0x28(%rsp), %rbp
movq %rax, (%rbp)
leaq 0x20(%rsp), %r15
movq %rax, (%r15)
leaq 0x18(%rsp), %r12
movq %rax, (%r12)
movq %rbx, %rdi
callq 0x24bd4
orb $0x40, 0xb8(%rbx)
movq (%r15), %r15
testq %r15, %r15
je 0x24a55
movq %r12, 0x10(%rsp)
movq %r15, %rdi
callq 0x10110
movq %rax, 0xf0(%rbx)
testq %rax, %rax
je 0x24a82
movq %rax, %r12
movq (%rbp), %rsi
movq %rax, %rdi
movq %r15, %rdx
callq 0xfa60
movq %r12, 0xf8(%rbx)
addq %r15, %r12
movq %r12, 0x100(%rbx)
movq 0x10(%rsp), %r12
callq 0x10130
movq (%r13), %r15
testq %r15, %r15
je 0x24a70
movq %r15, %rdi
callq 0xf100
xorl %r14d, %r14d
jmp 0x24ad4
movq 0x8(%rsp), %rax
movq (%rax), %rdi
testq %rdi, %rdi
je 0x24a91
xorl %r14d, %r14d
jmp 0x24ac3
callq 0xf0a0
movl (%rax), %eax
xorl %r14d, %r14d
jmp 0x24b84
movq (%r14), %rdi
testq %rdi, %rdi
jne 0x24aaf
cmpl $0x1, (%r12)
jne 0x24aa7
callq 0x10870
jmp 0x24aac
callq 0xf660
movq %rax, %rdi
callq 0x102d0
movq %rax, %rdi
movq %rax, %r14
testq %rax, %rax
je 0x24bca
callq 0xfd40
testq %rax, %rax
je 0x24b7f
movq %rax, %r15
movq (%r12), %rax
cmpl $0x1, %eax
jne 0x24af8
notq %rax
movabsq $0x100000001, %rcx      # imm = 0x100000001
testq %rcx, %rax
sete 0xd8(%rbx)
jne 0x24b0b
jmp 0x24b2d
movq %r15, %rdi
callq 0x10490
testl %eax, %eax
setne 0xd8(%rbx)
jne 0x24b2d
movq 0x40(%rbx), %rcx
cmpq $0x2, %rcx
jb 0x24b2d
movq %r15, %rdi
movl $0x37, %esi
xorl %edx, %edx
callq 0xf550
testq %rax, %rax
je 0x24baf
movl $0x2, %edx
movq %r15, %rdi
movl $0x21, %esi
xorl %ecx, %ecx
callq 0xf550
movl $0x1, %edx
movq %r15, %rdi
movl $0x21, %esi
xorl %ecx, %ecx
callq 0xf550
movq %r15, 0xc8(%rbx)
testq %r14, %r14
je 0x24b69
movq %r14, %rdi
callq 0xf0f0
movq %rbx, %rdi
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x23ff4
movl $0x8c9c94c7, %eax       # imm = 0x8C9C94C7
movl %eax, 0xd0(%rbx)
addq $0xd0, %rbx
testq %r14, %r14
je 0x24b9e
movq %r14, %rdi
callq 0xf0f0
movl (%rbx), %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x8c9c94c7, 0xd0(%rbx) # imm = 0x8C9C94C7
addq $0xd0, %rbx
movq %r15, %rdi
callq 0xf770
jmp 0x24b91
movl $0x8c9c94c7, %eax       # imm = 0x8C9C94C7
jmp 0x24a89