// File: /workspace/github_cpp_makefile_star2_O1/romkatv[P]hcproxy/src/hcproxy.cc
// Function: hcproxy::(anonymous namespace)::RunProxy(hcproxy::(anonymous namespace)::Options const&)
void RunProxy(const Options& opt) {
  auto IsAllowedPort = [&](std::string_view host_port) {
    auto sep = host_port.find(':');
    if (sep == std::string_view::npos) return false;
    std::string_view port = host_port.substr(sep + 1);
    return opt.allowed_ports.empty() || opt.allowed_ports.count(port);
  };

  signal(SIGPIPE, SIG_IGN);

  if (opt.max_num_open_files > 0) {
    struct rlimit lim;
    CHECK(getrlimit(RLIMIT_NOFILE, &lim) == 0) << Errno();
    lim.rlim_cur = opt.max_num_open_files;
    // It'll fail if opt.max_num_open_files is greater than lim.rlim_max.
    CHECK(setrlimit(RLIMIT_NOFILE, &lim) == 0) << Errno();
  }

  auto& acceptor = *new Acceptor(opt);
  auto& parser = *new Parser(opt);
  auto& dns_resolver = *new DnsResolver(opt);
  auto& connector = *new Connector(opt);
  auto& forwarder = *new Forwarder(opt);

  while (true) {
    int client_fd = acceptor.Accept();
    parser.ParseRequest(client_fd, [&, client_fd](std::string_view host_port) {
      if (host_port.empty() || !IsAllowedPort(host_port)) {
        CHECK(close(client_fd) == 0) << Errno();
        return;
      }
      dns_resolver.Resolve(host_port, [&, client_fd](std::shared_ptr<const addrinfo> addr) {
        if (!addr) {
          LOG(WARN) << "[" << client_fd << "] DNS error: " << host_port;
          CHECK(close(client_fd) == 0) << Errno();
          return;
        }
        LOG(INFO) << "[" << client_fd << "] tunnel to " << IpPort(*addr);
        connector.Connect(*addr, [&, client_fd](int server_fd) {
          if (server_fd < 0) {
            CHECK(close(client_fd) == 0) << Errno();
            return;
          }
          forwarder.Forward(client_fd, server_fd);
        });
      });
    });
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rdi, %r15
movq %rdi, 0x70(%rsp)
movl $0x1, %esi
movl $0xd, %edi
callq 0x155a0
cmpq $0x0, 0xb8(%r15)
jne 0x1d4c2
movl $0x4, %edi
callq 0x22210
movq %rax, %r14
movq %rax, %rdi
movq %r15, %rsi
callq 0x196b4
movl $0x18, %edi
callq 0x22210
movq %rax, %rbx
movq 0x30(%r15), %rsi
movq 0x38(%r15), %rdx
movq %rax, %rdi
callq 0x18ac8
movl $0x148, %edi            # imm = 0x148
callq 0x22210
movq %rax, %r12
movups 0x40(%r15), %xmm0
movups 0x50(%r15), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movq %rax, %rdi
callq 0x1a6c4
movl $0x8, %edi
callq 0x22210
movq %rax, %r13
leaq 0x60(%r15), %rsi
movq %rax, %rdi
callq 0x19f0c
movl $0x20, %edi
callq 0x22210
movq %rax, %rbp
movq 0x78(%r15), %rax
movq %rax, 0x10(%rsp)
movups 0x68(%r15), %xmm0
movups %xmm0, (%rsp)
movq %rbp, %rdi
callq 0x1e4ac
movq %rbp, 0x68(%rsp)
movq %r12, %rbp
movq %rbx, %r12
leaq 0x40(%rsp), %r15
movq %r14, %rbx
movq %r14, %rdi
callq 0x19b86
movl %eax, %r14d
xorps %xmm0, %xmm0
movaps %xmm0, 0x40(%rsp)
movaps %xmm0, 0x50(%rsp)
movl $0x28, %edi
callq 0x22210
movl %r14d, (%rax)
leaq 0x70(%rsp), %rcx
movq %rcx, 0x8(%rax)
movq %rbp, 0x10(%rax)
movq %r13, 0x18(%rax)
movq 0x68(%rsp), %rcx
movq %rcx, 0x20(%rax)
movq %rax, 0x40(%rsp)
leaq 0x1d2(%rip), %rax       # 0x1d656
movq %rax, 0x58(%rsp)
leaq 0x3aa(%rip), %rax       # 0x1d83a
movq %rax, 0x50(%rsp)
movq %r12, %rdi
movl %r14d, %esi
movq %r15, %rdx
callq 0x18b14
movq 0x50(%rsp), %rax
testq %rax, %rax
movq %rbx, %r14
je 0x1d436
movq %r15, %rdi
movq %r15, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x1d436
leaq 0x78(%rsp), %rsi
movl $0x7, %edi
callq 0x15760
testl %eax, %eax
jne 0x1d552
movq 0xb8(%r15), %rax
leaq 0x78(%rsp), %rsi
movq %rax, (%rsi)
movl $0x7, %edi
callq 0x15190
testl %eax, %eax
je 0x1d389
leaq 0xb279c(%rip), %rsi     # 0xcfc99
leaq 0x20(%rsp), %rbx
movq %rbx, %rdi
movl $0x43, %edx
movl $0x3, %ecx
callq 0x2019c
movq 0x18(%rbx), %rdi
leaq 0xb27c5(%rip), %rsi     # 0xcfce4
movl $0x23, %edx
callq 0x8bab0
movq 0x38(%rsp), %rdi
leaq 0xb6dd6(%rip), %rsi     # 0xd430b
movl $0x2, %edx
callq 0x8bab0
movl 0x20(%rsp), %esi
movq 0x38(%rsp), %rdi
callq 0x2023b
jmp 0x1d609
leaq 0xb2740(%rip), %rsi     # 0xcfc99
leaq 0x20(%rsp), %rbx
movq %rbx, %rdi
movl $0x40, %edx
movl $0x3, %ecx
callq 0x2019c
movq 0x18(%rbx), %rdi
leaq 0xb2745(%rip), %rsi     # 0xcfcc0
movl $0x23, %edx
callq 0x8bab0
movq 0x38(%rsp), %rdi
leaq 0xb6d7a(%rip), %rsi     # 0xd430b
movl $0x2, %edx
callq 0x8bab0
movl 0x20(%rsp), %esi
movq 0x38(%rsp), %rdi
callq 0x2023b
jmp 0x1d609
jmp 0x1d5cb
movq %rax, %r15
movq 0x50(%rsp), %rax
testq %rax, %rax
je 0x1d623
leaq 0x40(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x1d623
movq %rax, %rdi
callq 0x18abd
movq %rax, %r15
movl $0x20, %esi
movq %rbp, %rdi
jmp 0x1d61e
movq %rax, %r15
movl $0x8, %esi
movq %r13, %rdi
jmp 0x1d61e
movq %rax, %r15
movl $0x148, %esi            # imm = 0x148
movq %r12, %rdi
jmp 0x1d61e
jmp 0x1d609
movq %rax, %r15
movl $0x18, %esi
movq %rbx, %rdi
jmp 0x1d61e
leaq 0x20(%rsp), %rdi
callq 0x18aaa
movq %rax, %r15
movl $0x4, %esi
movq %r14, %rdi
callq 0x21280
movq %r15, %rdi
callq 0xcc900
nop