// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movq -0x10(%rbp), %rax
movl 0xb4(%rax), %eax
andl $0x40, %eax
cmpl $0x0, %eax
je 0x2e171
movl $0x0, -0x4(%rbp)
jmp 0x2e44c
movq -0x10(%rbp), %rax
movl 0xb8(%rax), %eax
andl $0x40, %eax
cmpl $0x0, %eax
je 0x2e188
jmp 0x2e3fd
cmpq $0x0, -0x18(%rbp)
je 0x2e199
movq -0x18(%rbp), %rax
movq %rax, -0x78(%rbp)
jmp 0x2e1b1
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0xf7d0
leaq -0x70(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rdi
callq 0x2e460
movq -0x10(%rbp), %rax
movl 0xb8(%rax), %ecx
orl $0x40, %ecx
movl %ecx, 0xb8(%rax)
movq -0x18(%rbp), %rax
cmpq $0x0, 0x20(%rax)
jbe 0x2e265
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x10260
movq -0x10(%rbp), %rcx
movq %rax, 0xf0(%rcx)
cmpq $0x0, %rax
jne 0x2e211
callq 0xf0a0
movl (%rax), %eax
movl %eax, -0x3c(%rbp)
jmp 0x2e412
movq -0x10(%rbp), %rax
movq 0xf0(%rax), %rdi
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rsi
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rdx
callq 0xfb40
movq -0x10(%rbp), %rax
movq 0xf0(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0xf8(%rax)
movq -0x10(%rbp), %rax
movq 0xf8(%rax), %rcx
movq -0x18(%rbp), %rax
addq 0x20(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x100(%rax)
callq 0x10280
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, %rax
je 0x2e28a
movq -0x30(%rbp), %rdi
callq 0xf120
jmp 0x2e30e
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
jne 0x2e2f4
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, %rax
jne 0x2e2d6
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x2e520
testb $0x1, %al
jne 0x2e2c0
jmp 0x2e2cb
callq 0x10a60
movq %rax, -0x38(%rbp)
jmp 0x2e2d4
callq 0xf6e0
movq %rax, -0x38(%rbp)
jmp 0x2e2d6
movq -0x38(%rbp), %rdi
callq 0x10430
movq %rax, -0x28(%rbp)
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
jne 0x2e2f2
jmp 0x2e40b
jmp 0x2e2f4
movq -0x20(%rbp), %rdi
callq 0xfe50
movq %rax, -0x30(%rbp)
cmpq $0x0, %rax
jne 0x2e30c
jmp 0x2e40b
jmp 0x2e30e
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x2e520
testb $0x1, %al
jne 0x2e321
jmp 0x2e33f
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x2e540
movb %al, %cl
movq -0x10(%rbp), %rax
andb $0x1, %cl
movb %cl, 0xd8(%rax)
jmp 0x2e35b
movq -0x30(%rbp), %rdi
callq 0x10610
cmpl $0x0, %eax
setne %cl
movq -0x10(%rbp), %rax
andb $0x1, %cl
movb %cl, 0xd8(%rax)
movq -0x10(%rbp), %rax
testb $0x1, 0xd8(%rax)
jne 0x2e3a6
movq -0x10(%rbp), %rax
cmpq $0x0, 0x40(%rax)
je 0x2e3a6
movq -0x10(%rbp), %rax
movl $0x1, %ecx
cmpq %rcx, 0x40(%rax)
je 0x2e3a6
movq -0x30(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rcx
movl $0x37, %esi
xorl %eax, %eax
movl %eax, %edx
callq 0xf5a0
cmpq $0x0, %rax
jne 0x2e3a4
jmp 0x2e40b
jmp 0x2e3a6
movq -0x30(%rbp), %rdi
movl $0x21, %esi
movl $0x2, %edx
xorl %eax, %eax
movl %eax, %ecx
callq 0xf5a0
movq -0x30(%rbp), %rdi
movl $0x21, %esi
movl $0x1, %edx
xorl %eax, %eax
movl %eax, %ecx
callq 0xf5a0
movq -0x30(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0xc8(%rax)
movq $0x0, -0x30(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0x2e3fb
movq -0x28(%rbp), %rdi
callq 0xf100
jmp 0x2e3fd
movq -0x10(%rbp), %rdi
callq 0x2dbb0
movl %eax, -0x4(%rbp)
jmp 0x2e44c
movl $0x8c9c94c7, -0x3c(%rbp) # imm = 0x8C9C94C7
movl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0xd0(%rax)
cmpq $0x0, -0x30(%rbp)
je 0x2e42f
movq -0x30(%rbp), %rdi
callq 0xf7f0
cmpq $0x0, -0x28(%rbp)
je 0x2e43f
movq -0x28(%rbp), %rdi
callq 0xf100
movq -0x10(%rbp), %rax
movl 0xd0(%rax), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x80, %rsp
popq %rbp
retq
nopl (%rax,%rax)