// File: /workspace/github_c_makefile_star2_O2/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 0x1a266(%rip), %r15     # 0x1cff0
movq (%r15), %rdi
leaq 0x112d6(%rip), %rsi     # 0x1406a
leaq 0x11f18(%rip), %rdx     # 0x14cb3
leaq 0x1135b(%rip), %r8      # 0x140fd
pushq $0xd
popq %rcx
xorl %eax, %eax
callq 0x2170
testq %rbx, %rbx
je 0x2f66
testb %bpl, %bpl
jne 0x2f66
movzbl 0x14(%rbx), %eax
testl %eax, %eax
je 0x2dcf
cmpl $0x6, %eax
jne 0x2f8c
pushq $0x38
popq %rdi
callq 0x2d3c
movq %rax, %r14
pushq $0x3
popq %rbp
movl %ebp, (%rax)
movq %rbx, 0x8(%rax)
movl $0xffff, %edi           # imm = 0xFFFF
callq 0x2d3c
movq %rax, 0x18(%r14)
movl $0xffff, %edi           # imm = 0xFFFF
callq 0x2d3c
movq %rax, 0x20(%r14)
andq $0x0, 0x28(%r14)
movl %ebp, (%r14)
movq $0x1, 0x10(%r14)
movzbl 0x14(%rbx), %eax
cmpl $0x6, %eax
je 0x2eb3
testl %eax, %eax
jne 0x2f21
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 0x2fea
leaq 0x1a311(%rip), %rax     # 0x1d170
movl (%rax), %esi
pushq $0x5
popq %rdx
movq %r14, %rdi
callq 0x2bba
movl 0x4(%r14), %edi
leaq 0xc(%rsp), %rsi
pushq $0x10
popq %rdx
callq 0x2210
cmpl $-0x1, %eax
jne 0x2f21
callq 0x2060
cmpl $0x73, (%rax)
je 0x2f21
movq (%r15), %rdi
leaq 0x111cc(%rip), %rsi     # 0x1406a
leaq 0x11e0e(%rip), %rdx     # 0x14cb3
leaq 0x11292(%rip), %r8      # 0x1413e
pushq $0x36
jmp 0x2fd5
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 0x300b
leaq 0x1a280(%rip), %rax     # 0x1d170
movl (%rax), %esi
pushq $0x5
popq %rdx
movq %r14, %rdi
callq 0x2bba
movl 0x4(%r14), %edi
leaq 0xc(%rsp), %rsi
pushq $0x1c
popq %rdx
callq 0x2210
cmpl $-0x1, %eax
jne 0x2f21
callq 0x2060
cmpl $0x73, (%rax)
jne 0x2fbb
movq %rbx, %rdi
movq %r14, %rsi
callq 0x8161
leaq 0x17f(%rip), %rsi       # 0x30b2
movq %rbx, %rdi
callq 0x81ed
leaq 0x1cc(%rip), %rsi       # 0x310e
movq %rbx, %rdi
callq 0x816b
leaq 0x30d(%rip), %rsi       # 0x325e
movq %rbx, %rdi
callq 0x81ac
xorl %eax, %eax
addq $0x28, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq (%r15), %rdi
leaq 0x110fa(%rip), %rsi     # 0x1406a
leaq 0x11d3c(%rip), %rdx     # 0x14cb3
leaq 0x1118e(%rip), %r8      # 0x1410c
pushq $0x10
popq %rcx
xorl %eax, %eax
callq 0x2170
movb $-0x6, %al
jmp 0x2f5b
movq (%r15), %rdi
leaq 0x110d4(%rip), %rsi     # 0x1406a
leaq 0x11d16(%rip), %rdx     # 0x14cb3
leaq 0x11188(%rip), %r8      # 0x1412c
pushq $0x16
popq %rcx
xorl %eax, %eax
callq 0x2170
movq %rbx, %rdi
callq 0x6c1b
jmp 0x2dcf
movq (%r15), %rdi
leaq 0x110a5(%rip), %rsi     # 0x1406a
leaq 0x11ce7(%rip), %rdx     # 0x14cb3
leaq 0x1116b(%rip), %r8      # 0x1413e
pushq $0x45
popq %rcx
xorl %eax, %eax
callq 0x2170
movq %r14, %rdi
callq 0x303d
jmp 0x2f21
movq (%r15), %rbx
callq 0x2060
movl (%rax), %edi
callq 0x2220
leaq 0x11004(%rip), %rsi     # 0x14004
leaq 0x11cac(%rip), %rdx     # 0x14cb3
pushq $0x32
jmp 0x302a
movq (%r15), %rbx
callq 0x2060
movl (%rax), %edi
callq 0x2220
leaq 0x10fe3(%rip), %rsi     # 0x14004
leaq 0x11c8b(%rip), %rdx     # 0x14cb3
pushq $0x41
popq %rcx
movq %rbx, %rdi
movq %rax, %r8
xorl %eax, %eax
callq 0x2170
callq 0x2050