// File: /workspace/github_cpp_makefile_star2_O3/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 0x1d374
movl $0x4, %edi
callq 0x22050
movq %rax, %r14
movq %rax, %rdi
movq %r15, %rsi
callq 0x195c8
movl $0x18, %edi
callq 0x22050
movq %rax, %rbx
movq 0x30(%r15), %rsi
movq 0x38(%r15), %rdx
movq %rax, %rdi
callq 0x18a44
movl $0x148, %edi            # imm = 0x148
callq 0x22050
movq %rax, %r12
movups 0x40(%r15), %xmm0
movups 0x50(%r15), %xmm1
movups %xmm1, 0x10(%rsp)
movups %xmm0, (%rsp)
movq %rax, %rdi
callq 0x1a610
movl $0x8, %edi
callq 0x22050
movq %rax, %r13
leaq 0x60(%r15), %rsi
movq %rax, %rdi
callq 0x19e60
movl $0x20, %edi
callq 0x22050
movq %rax, %rbp
movq 0x78(%r15), %rax
movq %rax, 0x10(%rsp)
movups 0x68(%r15), %xmm0
movups %xmm0, (%rsp)
movq %rbp, %rdi
callq 0x1e31c
movq %rbp, 0x48(%rsp)
movq %r12, %rbp
movq %rbx, %r12
leaq 0x50(%rsp), %r15
movq %r14, %rbx
movq %r14, %rdi
callq 0x19ab2
movl %eax, %r14d
movq $0x0, 0x58(%rsp)
movl $0x28, %edi
callq 0x22050
movl %r14d, (%rax)
leaq 0x70(%rsp), %rcx
movq %rcx, 0x8(%rax)
movq %rbp, 0x10(%rax)
movq %r13, 0x18(%rax)
movq 0x48(%rsp), %rcx
movq %rcx, 0x20(%rax)
movq %rax, 0x50(%rsp)
leaq 0x1d2(%rip), %rax       # 0x1d508
movq %rax, 0x68(%rsp)
leaq 0x3a0(%rip), %rax       # 0x1d6e2
movq %rax, 0x60(%rsp)
movq %r12, %rdi
movl %r14d, %esi
movq %r15, %rdx
callq 0x18a90
movq 0x60(%rsp), %rax
testq %rax, %rax
movq %rbx, %r14
je 0x1d2ec
movq %r15, %rdi
movq %r15, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x1d2ec
leaq 0x78(%rsp), %rsi
movl $0x7, %edi
callq 0x15760
testl %eax, %eax
jne 0x1d404
movq 0xb8(%r15), %rax
leaq 0x78(%rsp), %rsi
movq %rax, (%rsi)
movl $0x7, %edi
callq 0x15190
testl %eax, %eax
je 0x1d23f
leaq 0xb28da(%rip), %rsi     # 0xcfc89
leaq 0x28(%rsp), %rbx
movq %rbx, %rdi
movl $0x43, %edx
movl $0x3, %ecx
callq 0x2003c
movq 0x18(%rbx), %rdi
leaq 0xb2903(%rip), %rsi     # 0xcfcd4
movl $0x23, %edx
callq 0x8b8f0
movq 0x40(%rsp), %rdi
leaq 0xb6ee4(%rip), %rsi     # 0xd42cb
movl $0x2, %edx
callq 0x8b8f0
movl 0x28(%rsp), %esi
movq 0x40(%rsp), %rdi
callq 0x200db
jmp 0x1d4bb
leaq 0xb287e(%rip), %rsi     # 0xcfc89
leaq 0x28(%rsp), %rbx
movq %rbx, %rdi
movl $0x40, %edx
movl $0x3, %ecx
callq 0x2003c
movq 0x18(%rbx), %rdi
leaq 0xb2883(%rip), %rsi     # 0xcfcb0
movl $0x23, %edx
callq 0x8b8f0
movq 0x40(%rsp), %rdi
leaq 0xb6e88(%rip), %rsi     # 0xd42cb
movl $0x2, %edx
callq 0x8b8f0
movl 0x28(%rsp), %esi
movq 0x40(%rsp), %rdi
callq 0x200db
jmp 0x1d4bb
jmp 0x1d47d
movq %rax, %r15
movq 0x60(%rsp), %rax
testq %rax, %rax
je 0x1d4d5
leaq 0x50(%rsp), %rdi
movq %rdi, %rsi
movl $0x3, %edx
callq *%rax
jmp 0x1d4d5
movq %rax, %rdi
callq 0x18a37
movq %rax, %r15
movl $0x20, %esi
movq %rbp, %rdi
jmp 0x1d4d0
movq %rax, %r15
movl $0x8, %esi
movq %r13, %rdi
jmp 0x1d4d0
movq %rax, %r15
movl $0x148, %esi            # imm = 0x148
movq %r12, %rdi
jmp 0x1d4d0
jmp 0x1d4bb
movq %rax, %r15
movl $0x18, %esi
movq %rbx, %rdi
jmp 0x1d4d0
leaq 0x28(%rsp), %rdi
callq 0x18a24
movq %rax, %r15
movl $0x4, %esi
movq %r14, %rdi
callq 0x210c0
movq %r15, %rdi
callq 0xcc750
nop