// File: /workspace/github_c_makefile_star2_O3/FH0[P]tun_direct/lwip-2.1.2/src/core/tcp_in.c
// Function: tcp_listen_input
static void
tcp_listen_input(struct tcp_pcb_listen *pcb)
{
  struct tcp_pcb *npcb;
  u32_t iss;
  err_t rc;

  if (flags & TCP_RST) {
    /* An incoming RST should be ignored. Return. */
    return;
  }

  LWIP_ASSERT("tcp_listen_input: invalid pcb", pcb != NULL);

  /* In the LISTEN state, we check for incoming SYN segments,
     creates a new PCB, and responds with a SYN|ACK. */
  if (flags & TCP_ACK) {
    /* For incoming segments with the ACK flag set, respond with a
       RST. */
    LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
    tcp_rst((const struct tcp_pcb *)pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
            ip_current_src_addr(), tcphdr->dest, tcphdr->src);
  } else if (flags & TCP_SYN) {
    LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
#if TCP_LISTEN_BACKLOG
    if (pcb->accepts_pending >= pcb->backlog) {
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: listen backlog exceeded for port %"U16_F"\n", tcphdr->dest));
      return;
    }
#endif /* TCP_LISTEN_BACKLOG */
    npcb = tcp_alloc(pcb->prio);
    /* If a new PCB could not be created (probably due to lack of memory),
       we don't do anything, but rely on the sender will retransmit the
       SYN at a time when we have more memory available. */
    if (npcb == NULL) {
      err_t err;
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
      TCP_STATS_INC(tcp.memerr);
      TCP_EVENT_ACCEPT(pcb, NULL, pcb->callback_arg, ERR_MEM, err);
      LWIP_UNUSED_ARG(err); /* err not useful here */
      return;
    }
#if TCP_LISTEN_BACKLOG
    pcb->accepts_pending++;
    tcp_set_flags(npcb, TF_BACKLOGPEND);
#endif /* TCP_LISTEN_BACKLOG */
    /* Set up the new PCB. */
    ip_addr_copy(npcb->local_ip, *ip_current_dest_addr());
    ip_addr_copy(npcb->remote_ip, *ip_current_src_addr());
    npcb->local_port = pcb->local_port;

#if TUN2SOCKS
    // go-tun2socks logic
    // Always reset local port to the dest of the connection, because we are
    // accepting all incomming connections, regardless of there destination addresses,
    // as such, npcb is acting as the server socket that communicates with the
    // client socket.
    npcb->local_port = tcphdr->dest;
#endif /* TUN2SOCKS */

    npcb->remote_port = tcphdr->src;
    npcb->state = SYN_RCVD;
    npcb->rcv_nxt = seqno + 1;
    npcb->rcv_ann_right_edge = npcb->rcv_nxt;
    iss = tcp_next_iss(npcb);
    npcb->snd_wl2 = iss;
    npcb->snd_nxt = iss;
    npcb->lastack = iss;
    npcb->snd_lbb = iss;
    npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
    npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
    npcb->listener = pcb;
#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
    /* inherit socket options */
    npcb->so_options = pcb->so_options & SOF_INHERITED;
    npcb->netif_idx = pcb->netif_idx;
    /* Register the new PCB so that we can begin receiving segments
       for it. */
    TCP_REG_ACTIVE(npcb);

    /* Parse any options in the SYN. */
    tcp_parseopt(npcb);
    npcb->snd_wnd = tcphdr->wnd;
    npcb->snd_wnd_max = npcb->snd_wnd;

#if TCP_CALCULATE_EFF_SEND_MSS
    npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */

    MIB2_STATS_INC(mib2.tcppassiveopens);

#if LWIP_TCP_PCB_NUM_EXT_ARGS
    if (tcp_ext_arg_invoke_callbacks_passive_open(pcb, npcb) != ERR_OK) {
      tcp_abandon(npcb, 0);
      return;
    }
#endif

    /* Send a SYN|ACK together with the MSS option. */
    rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
    if (rc != ERR_OK) {
      tcp_abandon(npcb, 0);
      return;
    }
    tcp_output(npcb);
  }
  return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movzbl 0x13674(%rip), %eax     # 0x1c94c
testb $0x4, %al
jne 0x9370
movq %rdi, %r15
testb $0x10, %al
jne 0x9334
testb $0x2, %al
je 0x9370
movzbl 0x4c(%r15), %edi
callq 0x8251
testq %rax, %rax
je 0x937b
movq %rax, %r14
movq %rax, %rbx
leaq 0x13465(%rip), %rax     # 0x1c770
movb 0x50(%rax), %cl
movb %cl, 0x14(%r14)
movl 0x3c(%rax), %edx
movl %edx, (%r14)
cmpb $0x6, %cl
jne 0x939b
movl 0x40(%rax), %ecx
movl %ecx, 0x4(%rbx)
movl 0x44(%rax), %ecx
movl %ecx, 0x8(%rbx)
movl 0x48(%rax), %ecx
movl %ecx, 0xc(%rbx)
movb 0x4c(%rax), %cl
jmp 0x93ac
movzwl 0x13613(%rip), %edx     # 0x1c94e
addl 0x13603(%rip), %edx     # 0x1c944
movl 0x13601(%rip), %esi     # 0x1c948
movq 0x135da(%rip), %rax     # 0x1c928
movzwl 0x2(%rax), %r9d
movzwl (%rax), %eax
movl %eax, (%rsp)
leaq 0x13410(%rip), %r8      # 0x1c770
leaq 0x3c(%r8), %rcx
addq $0x24, %r8
movq %r15, %rdi
callq 0xc757
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq 0x50(%r15), %rax
testq %rax, %rax
je 0x9370
movq 0x40(%r15), %rdi
xorl %esi, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmpq *%rax
movl $0x0, 0xc(%rbx)
movq $0x0, 0x4(%rbx)
xorl %ecx, %ecx
movb %cl, 0x10(%rbx)
movb 0x38(%rax), %cl
movb %cl, 0x2c(%rbx)
movl 0x24(%rax), %edx
movl %edx, 0x18(%rbx)
cmpb $0x6, %cl
jne 0x93d7
movl 0x28(%rax), %ecx
movl %ecx, 0x1c(%rbx)
movl 0x2c(%rax), %ecx
movl %ecx, 0x20(%rbx)
movl 0x30(%rax), %ecx
movl %ecx, 0x24(%rbx)
movb 0x34(%rax), %al
jmp 0x93e8
movl $0x0, 0x24(%rbx)
movq $0x0, 0x1c(%rbx)
xorl %eax, %eax
addq $0x18, %r14
movb %al, 0x28(%rbx)
movq 0x13532(%rip), %rax     # 0x1c928
movd (%rax), %xmm0
pshuflw $0xe1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,2,3,4,5,6,7]
movd %xmm0, 0x4e(%rbx)
movl $0x3, 0x48(%rbx)
movl 0x13533(%rip), %eax     # 0x1c944
incl %eax
movl %eax, 0x5c(%rbx)
movl %eax, 0x64(%rbx)
movq %rbx, %rdi
callq 0x7da8
movl %eax, 0x90(%rbx)
movl %eax, 0x88(%rbx)
movl %eax, 0x7c(%rbx)
movl %eax, 0x94(%rbx)
movl 0x13508(%rip), %eax     # 0x1c944
decl %eax
movl %eax, 0x8c(%rbx)
movq 0x40(%r15), %rax
movq %rax, 0x40(%rbx)
movq %r15, 0xc8(%rbx)
movb 0x31(%r15), %al
andb $0xc, %al
movb %al, 0x31(%rbx)
movb 0x30(%r15), %al
movb %al, 0x30(%rbx)
leaq 0x1349e(%rip), %rax     # 0x1c908
movq (%rax), %rcx
movq %rcx, 0x38(%rbx)
movq %rbx, (%rax)
callq 0xcba0
leaq 0x13499(%rip), %rax     # 0x1c919
movb $0x1, (%rax)
movq %rbx, %rdi
callq 0x9b63
movq 0x13496(%rip), %rax     # 0x1c928
movzwl 0xe(%rax), %eax
movw %ax, 0x98(%rbx)
movw %ax, 0x9a(%rbx)
movzwl 0x6a(%rbx), %ebp
cmpb $0x6, 0x2c(%rbx)
jne 0x94bb
movq %rbx, %rdi
movq %r14, %rsi
callq 0xf744
jmp 0x94c3
movq %r14, %rdi
callq 0xe120
movzwl %bp, %edi
movq %rax, %rsi
movq %r14, %rdx
callq 0x7dee
movw %ax, 0x6a(%rbx)
movq %rbx, %rdi
movl $0x12, %esi
callq 0xbb78
movq %rbx, %rdi
testb %al, %al
je 0x94fa
xorl %esi, %esi
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x7153
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0xbd02