// File: /workspace/github_c_makefile_star2_O3/FH0[P]tun_direct/tcp.c
// Function: tun_tcp_accept
err_t tun_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
  ELOG(__FUNCTION__);

  if (err != ERR_OK || newpcb == NULL) {
    ELOG("err != ERR_OK || newpcb == NULL");
    return ERR_VAL;
  }

  if (newpcb->local_ip.type != IPADDR_TYPE_V4 &&
      newpcb->local_ip.type != IPADDR_TYPE_V6) {
    ELOG("unsupport ip type");
    tcp_close(newpcb);
  }

  tun_data_t *data;
  extern int errno;

  /* filled struct */
  data = MALLOC(sizeof(tun_data_t));
  data->type = TUN_TCP;
  data->tpcb = newpcb;
  data->client_buf = MALLOC(TUN_TCP_SIZE);
  data->server_buf = MALLOC(TUN_TCP_SIZE);
  data->client_buf_len = 0;
  data->server_buf_len = 0;
  data->type = TUN_TCP;
  data->client_status = TUN_CONNECTED;
  data->server_status = TUN_CONNECTING;

  /* add event to epoll */
  if (newpcb->local_ip.type == IPADDR_TYPE_V4) {
    struct sockaddr_in sai;

    sai.sin_family = AF_INET;
    memcpy(&sai.sin_addr, &newpcb->local_ip.u_addr, 4);
    sai.sin_port = htons(newpcb->local_port);

    data->fd = socket(AF_INET, SOCK_STREAM, 0);
    ASSERT(data->fd != -1);
    epoll_ET_add(data, epollfd, EPOLLIN | EPOLLOUT);
    if (connect(data->fd, (struct sockaddr *)&sai, sizeof(sai)) == -1 &&
        errno != EINPROGRESS) {
      ELOG("connect()");
      tun_tcp_close(data);
    }
  } else if (newpcb->local_ip.type == IPADDR_TYPE_V6) {
    struct sockaddr_in6 sai;

    sai.sin6_family = AF_INET6;
    memcpy(&sai.sin6_addr, &newpcb->local_ip.u_addr, 16);
    sai.sin6_port = htons(newpcb->local_port);

    data->fd = socket(AF_INET6, SOCK_STREAM, 0);
    ASSERT(data->fd != -1);
    epoll_ET_add(data, epollfd, EPOLLIN | EPOLLOUT);
    if (connect(data->fd, (struct sockaddr *)&sai, sizeof(sai)) == -1 &&
        errno != EINPROGRESS) {
      ELOG("connect()");
      tun_tcp_close(data);
    }
  }

  /* lwip callback */
  tcp_arg(newpcb, data);
  tcp_err(newpcb, tun_tcp_error);
  tcp_recv(newpcb, tun_tcp_recv);
  tcp_sent(newpcb, tun_tcp_send);

  return ERR_OK;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x28, %rsp
movl %edx, %ebp
movq %rsi, %rbx
movq 0x19a35(%rip), %r15     # 0x1bff0
movq (%r15), %rdi
leaq 0x11aa5(%rip), %rsi     # 0x1406a
leaq 0x126d0(%rip), %rdx     # 0x14c9c
leaq 0x11b2a(%rip), %r8      # 0x140fd
pushq $0xd
popq %rcx
xorl %eax, %eax
callq 0x2170
testq %rbx, %rbx
je 0x2797
testb %bpl, %bpl
jne 0x2797
movzbl 0x14(%rbx), %eax
testl %eax, %eax
je 0x2600
cmpl $0x6, %eax
jne 0x27bd
pushq $0x38
popq %rdi
callq 0x3b24
movq %rax, %r14
pushq $0x3
popq %rbp
movl %ebp, (%rax)
movq %rbx, 0x8(%rax)
movl $0xffff, %edi           # imm = 0xFFFF
callq 0x3b24
movq %rax, 0x18(%r14)
movl $0xffff, %edi           # imm = 0xFFFF
callq 0x3b24
movq %rax, 0x20(%r14)
andq $0x0, 0x28(%r14)
movl %ebp, (%r14)
movq $0x1, 0x10(%r14)
movzbl 0x14(%rbx), %eax
cmpl $0x6, %eax
je 0x26e4
testl %eax, %eax
jne 0x2752
movw $0x2, 0xc(%rsp)
movl (%rbx), %eax
movl %eax, 0x10(%rsp)
movzwl 0x4e(%rbx), %eax
rolw $0x8, %ax
movw %ax, 0xe(%rsp)
pushq $0x2
popq %rdi
pushq $0x1
popq %rsi
xorl %edx, %edx
callq 0x2260
movl %eax, 0x4(%r14)
cmpl $-0x1, %eax
je 0x281b
leaq 0x19ae0(%rip), %rax     # 0x1c170
movl (%rax), %esi
pushq $0x5
popq %rdx
movq %r14, %rdi
callq 0x3a3a
movl 0x4(%r14), %edi
leaq 0xc(%rsp), %rsi
pushq $0x10
popq %rdx
callq 0x2210
cmpl $-0x1, %eax
jne 0x2752
callq 0x2060
cmpl $0x73, (%rax)
je 0x2752
movq (%r15), %rdi
leaq 0x1199b(%rip), %rsi     # 0x1406a
leaq 0x125c6(%rip), %rdx     # 0x14c9c
leaq 0x11a61(%rip), %r8      # 0x1413e
pushq $0x36
jmp 0x2806
movw $0xa, 0xc(%rsp)
movups (%rbx), %xmm0
movups %xmm0, 0x14(%rsp)
movzwl 0x4e(%rbx), %eax
rolw $0x8, %ax
movw %ax, 0xe(%rsp)
pushq $0xa
popq %rdi
pushq $0x1
popq %rsi
xorl %edx, %edx
callq 0x2260
movl %eax, 0x4(%r14)
cmpl $-0x1, %eax
je 0x283c
leaq 0x19a4f(%rip), %rax     # 0x1c170
movl (%rax), %esi
pushq $0x5
popq %rdx
movq %r14, %rdi
callq 0x3a3a
movl 0x4(%r14), %edi
leaq 0xc(%rsp), %rsi
pushq $0x1c
popq %rdx
callq 0x2210
cmpl $-0x1, %eax
jne 0x2752
callq 0x2060
cmpl $0x73, (%rax)
jne 0x27ec
movq %rbx, %rdi
movq %r14, %rsi
callq 0x84d4
leaq 0x17f(%rip), %rsi       # 0x28e3
movq %rbx, %rdi
callq 0x8560
leaq 0x1cc(%rip), %rsi       # 0x293f
movq %rbx, %rdi
callq 0x84de
leaq 0x30e(%rip), %rsi       # 0x2a90
movq %rbx, %rdi
callq 0x851f
xorl %eax, %eax
addq $0x28, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq (%r15), %rdi
leaq 0x118c9(%rip), %rsi     # 0x1406a
leaq 0x124f4(%rip), %rdx     # 0x14c9c
leaq 0x1195d(%rip), %r8      # 0x1410c
pushq $0x10
popq %rcx
xorl %eax, %eax
callq 0x2170
movb $-0x6, %al
jmp 0x278c
movq (%r15), %rdi
leaq 0x118a3(%rip), %rsi     # 0x1406a
leaq 0x124ce(%rip), %rdx     # 0x14c9c
leaq 0x11957(%rip), %r8      # 0x1412c
pushq $0x16
popq %rcx
xorl %eax, %eax
callq 0x2170
movq %rbx, %rdi
callq 0x6e77
jmp 0x2600
movq (%r15), %rdi
leaq 0x11874(%rip), %rsi     # 0x1406a
leaq 0x1249f(%rip), %rdx     # 0x14c9c
leaq 0x1193a(%rip), %r8      # 0x1413e
pushq $0x45
popq %rcx
xorl %eax, %eax
callq 0x2170
movq %r14, %rdi
callq 0x286e
jmp 0x2752
movq (%r15), %rbx
callq 0x2060
movl (%rax), %edi
callq 0x2220
leaq 0x117d3(%rip), %rsi     # 0x14004
leaq 0x12464(%rip), %rdx     # 0x14c9c
pushq $0x32
jmp 0x285b
movq (%r15), %rbx
callq 0x2060
movl (%rax), %edi
callq 0x2220
leaq 0x117b2(%rip), %rsi     # 0x14004
leaq 0x12443(%rip), %rdx     # 0x14c9c
pushq $0x41
popq %rcx
movq %rbx, %rdi
movq %rax, %r8
xorl %eax, %eax
callq 0x2170
callq 0x2050