// File: /workspace/github_c_makefile_star2_O1/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 0x1aa35(%rip), %r15     # 0x1cff0
movq (%r15), %rdi
leaq 0x12aa5(%rip), %rsi     # 0x1506a
leaq 0x136e7(%rip), %rdx     # 0x15cb3
leaq 0x12b2a(%rip), %r8      # 0x150fd
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 0x3b54
movq %rax, %r14
pushq $0x3
popq %rbp
movl %ebp, (%rax)
movq %rbx, 0x8(%rax)
movl $0xffff, %edi           # imm = 0xFFFF
callq 0x3b54
movq %rax, 0x18(%r14)
movl $0xffff, %edi           # imm = 0xFFFF
callq 0x3b54
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 0x1aae0(%rip), %rax     # 0x1d170
movl (%rax), %esi
pushq $0x5
popq %rdx
movq %r14, %rdi
callq 0x3a69
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 0x1299b(%rip), %rsi     # 0x1506a
leaq 0x135dd(%rip), %rdx     # 0x15cb3
leaq 0x12a61(%rip), %r8      # 0x1513e
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 0x1aa4f(%rip), %rax     # 0x1d170
movl (%rax), %esi
pushq $0x5
popq %rdx
movq %r14, %rdi
callq 0x3a69
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 0x85e0
leaq 0x17f(%rip), %rsi       # 0x28e3
movq %rbx, %rdi
callq 0x866c
leaq 0x1cc(%rip), %rsi       # 0x293f
movq %rbx, %rdi
callq 0x85ea
leaq 0x30c(%rip), %rsi       # 0x2a8e
movq %rbx, %rdi
callq 0x862b
xorl %eax, %eax
addq $0x28, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq (%r15), %rdi
leaq 0x128c9(%rip), %rsi     # 0x1506a
leaq 0x1350b(%rip), %rdx     # 0x15cb3
leaq 0x1295d(%rip), %r8      # 0x1510c
pushq $0x10
popq %rcx
xorl %eax, %eax
callq 0x2170
movb $-0x6, %al
jmp 0x278c
movq (%r15), %rdi
leaq 0x128a3(%rip), %rsi     # 0x1506a
leaq 0x134e5(%rip), %rdx     # 0x15cb3
leaq 0x12957(%rip), %r8      # 0x1512c
pushq $0x16
popq %rcx
xorl %eax, %eax
callq 0x2170
movq %rbx, %rdi
callq 0x6f63
jmp 0x2600
movq (%r15), %rdi
leaq 0x12874(%rip), %rsi     # 0x1506a
leaq 0x134b6(%rip), %rdx     # 0x15cb3
leaq 0x1293a(%rip), %r8      # 0x1513e
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 0x127d3(%rip), %rsi     # 0x15004
leaq 0x1347b(%rip), %rdx     # 0x15cb3
pushq $0x32
jmp 0x285b
movq (%r15), %rbx
callq 0x2060
movl (%rax), %edi
callq 0x2220
leaq 0x127b2(%rip), %rsi     # 0x15004
leaq 0x1345a(%rip), %rdx     # 0x15cb3
pushq $0x41
popq %rcx
movq %rbx, %rdi
movq %rax, %r8
xorl %eax, %eax
callq 0x2170
callq 0x2050