// File: /workspace/github_c_makefile_star2_O2/ddrown[P]pretend-ntp/ntp-query.c
// Function: main
int main(int argc, char *argv[]) {
  struct ntp_msg bufs;
  struct timespec t[3];
  int status[6];
  int sock, opt;
  struct sockaddr_in addr;
  struct msghdr msg;
  struct iovec iovec;
  uint8_t cmsgbuf[256];
  struct pollfd readfd;

  if(argc < 3) {
    printf("%s [ip] [port]\n", argv[0]);
    exit(1);
  }
  if(inet_aton(argv[1], &addr.sin_addr) == INADDR_NONE) {
    printf("invalid ip %s\n", argv[1]);
    exit(1);
  }
  addr.sin_port = htons(strtoul(argv[2], NULL, 10));
  addr.sin_family = AF_INET;

  memset(&bufs, 0, sizeof(bufs));
  bufs.version = NTP_VERS_4;
  bufs.mode = NTP_MODE_CLIENT;
  clock_gettime(CLOCK_REALTIME, &t[0]);
  bufs.trans_time = unixtime_to_ntp_s(t[0].tv_sec);
  bufs.trans_time_fb = ns_to_ntp_frac(t[0].tv_nsec);
  printf("=== request ===\n");
  print_ntp(&bufs, NULL, NULL);

  sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (sock == -1) {
    perror_exit("socket");
  }
  opt = 1;
  if(setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) < 0) {
    perror_exit("setsockopt(IP_PKTINFO)");
  }

  memset(&msg, 0, sizeof(msg));
  iovec.iov_base          = &bufs;
  iovec.iov_len           = sizeof(bufs);
  msg.msg_iov     = &iovec;
  msg.msg_iovlen  = 1;
  msg.msg_name    = &addr;
  msg.msg_namelen = sizeof(addr);
  msg.msg_control = cmsgbuf;
  msg.msg_controllen = sizeof(cmsgbuf);

  readfd.fd = sock;
  readfd.events = POLLIN;

  status[0] = clock_gettime(CLOCK_REALTIME, &t[0]);
  status[1] = sendto(sock, &bufs, sizeof(bufs), 0, &addr, sizeof(addr));
  status[2] = clock_gettime(CLOCK_REALTIME, &t[1]);
  status[3] = poll(&readfd, 1, DEFAULT_TIMEOUT_MS);
  status[4] = clock_gettime(CLOCK_REALTIME, &t[2]);
  status[5] = recvmsg(sock, &msg, MSG_DONTWAIT);
  if((status[5] < 0) && (errno != EAGAIN)) {
    perror_exit("recvmsg");
  }
  if(status[4] != 0) {
    perror_exit("clock_gettime #3");
  }
  if(status[3] < 0) {
    perror_exit("poll");
  }
  if(status[2] != 0) {
    perror_exit("clock_gettime #2");
  }
  if(status[1] < 0) {
    perror_exit("sendto");
  }
  if(status[0] != 0) {
    perror_exit("clock_gettime #1");
  }

  printf("=== %d packet(s) received ===\n=== response ===\n", status[3]);
  if(status[5] > 0) {
    printf("rtt = ");
    print_diff_ts(&t[2], &t[1]);
    printf("\n");

    printf("source = ");
    print_addr(&addr);
    for(struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
      if(cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
        print_pktinfo((struct in_pktinfo *)CMSG_DATA(cmsg));
      }
    }
    printf("len = %u\n", status[5]);
    print_ntp(&bufs, &t[1], &t[2]);
  }

  printf("before sendto = ");
  print_t(&t[0]);
  printf("\n");
  printf("after sendto = ");
  print_t(&t[1]);
  printf(" ");
  print_diff_ts(&t[1], &t[0]);
  printf("\n");
  printf("after recvmmsg = ");
  print_t(&t[2]);
  printf(" ");
  print_diff_ts(&t[2], &t[1]);
  printf("\n");
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1d8, %rsp            # imm = 0x1D8
movq %rsi, %rbx
cmpl $0x2, %edi
jle 0x163e
movq 0x8(%rbx), %rdi
leaq 0x10(%rsp), %rsi
callq 0x10b0
cmpl $-0x1, %eax
je 0x164a
movq 0x10(%rbx), %rdi
pushq $0xa
popq %rdx
xorl %esi, %esi
callq 0x10f0
rolw $0x8, %ax
movw %ax, 0xe(%rsp)
movw $0x2, 0xc(%rsp)
xorps %xmm0, %xmm0
leaq 0xa0(%rsp), %rbx
movaps %xmm0, (%rbx)
movaps %xmm0, 0x10(%rbx)
andq $0x0, 0x20(%rbx)
movb $0x23, (%rbx)
leaq 0x20(%rsp), %r14
xorl %edi, %edi
movq %r14, %rsi
callq 0x1070
movl (%r14), %edi
callq 0x1673
movl %eax, 0x28(%rbx)
movl 0x8(%r14), %edi
callq 0x167c
movl %eax, 0x2c(%rbx)
leaq 0xdf3(%rip), %rdi       # 0x2128
callq 0x1050
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x16ae
pushq $0x2
popq %rdi
movl %edi, %esi
xorl %edx, %edx
callq 0x1120
movl %eax, %r15d
cmpl $-0x1, %eax
jne 0x1366
leaq 0xce4(%rip), %rdi       # 0x2045
callq 0x1cbc
leaq 0x1c(%rsp), %rcx
movl $0x1, (%rcx)
pushq $0x8
popq %rdx
pushq $0x4
popq %r8
movl %r15d, %edi
xorl %esi, %esi
callq 0x1060
testl %eax, %eax
jns 0x1392
leaq 0xcbf(%rip), %rdi       # 0x204c
callq 0x1cbc
xorps %xmm0, %xmm0
leaq 0x58(%rsp), %rbp
movups %xmm0, 0x8(%rbp)
movups %xmm0, 0x18(%rbp)
movups %xmm0, 0x28(%rbp)
leaq 0x90(%rsp), %rax
movq %rbx, (%rax)
movq $0x30, 0x8(%rax)
movq %rax, 0x10(%rbp)
movq $0x1, 0x18(%rbp)
leaq 0xc(%rsp), %r14
movq %r14, (%rbp)
movl $0x10, 0x8(%rbp)
leaq 0xd0(%rsp), %rax
movq %rax, 0x20(%rbp)
movq $0x100, 0x28(%rbp)      # imm = 0x100
leaq 0x50(%rsp), %r12
movl %r15d, (%r12)
movw $0x1, 0x4(%r12)
leaq 0x20(%rsp), %rsi
xorl %edi, %edi
callq 0x1070
movl %eax, 0x8(%rsp)
pushq $0x30
popq %rdx
pushq $0x10
popq %r9
movl %r15d, %edi
movq %rbx, %rsi
xorl %ecx, %ecx
movq %r14, %r8
callq 0x10a0
movq %rax, %r13
leaq 0x30(%rsp), %rsi
xorl %edi, %edi
callq 0x1070
movl %eax, %r14d
pushq $0x1
popq %rsi
movq %r12, %rdi
movl $0x1f4, %edx            # imm = 0x1F4
callq 0x10d0
movl %eax, %r12d
leaq 0x40(%rsp), %rsi
xorl %edi, %edi
callq 0x1070
movl %eax, %ebx
pushq $0x40
popq %rdx
movl %r15d, %edi
movq %rbp, %rsi
callq 0x10c0
movq %rax, %r15
testl %r15d, %r15d
jns 0x1480
callq 0x1040
cmpl $0xb, (%rax)
je 0x1480
leaq 0xbe8(%rip), %rdi       # 0x2063
callq 0x1cbc
testl %ebx, %ebx
je 0x1490
leaq 0xbe0(%rip), %rdi       # 0x206b
callq 0x1cbc
testl %r12d, %r12d
leaq 0x40(%rsp), %rbx
jns 0x14a6
leaq 0xbdb(%rip), %rdi       # 0x207c
callq 0x1cbc
testl %r14d, %r14d
je 0x14b7
leaq 0xbcf(%rip), %rdi       # 0x2081
callq 0x1cbc
testl %r13d, %r13d
jns 0x14c8
leaq 0xbcf(%rip), %rdi       # 0x2092
callq 0x1cbc
cmpl $0x0, 0x8(%rsp)
leaq 0x30(%rsp), %r13
je 0x14e0
leaq 0xbbe(%rip), %rdi       # 0x2099
callq 0x1cbc
leaq 0xbc3(%rip), %rdi       # 0x20aa
movl %r12d, %esi
xorl %eax, %eax
callq 0x1090
testl %r15d, %r15d
jle 0x159e
leaq 0xbd9(%rip), %rdi       # 0x20da
xorl %r12d, %r12d
xorl %eax, %eax
callq 0x1090
movq %rbx, %rdi
movq %r13, %rsi
callq 0x1c5b
pushq $0xa
popq %rdi
callq 0x1030
leaq 0xbbc(%rip), %rdi       # 0x20e1
xorl %eax, %eax
callq 0x1090
leaq 0xc(%rsp), %rdi
callq 0x122c
cmpq $0x10, 0x80(%rsp)
jb 0x1546
movq 0x78(%rsp), %r12
leaq 0x58(%rsp), %r14
testq %r12, %r12
je 0x157a
cmpl $0x0, 0x8(%r12)
jne 0x156a
cmpl $0x8, 0xc(%r12)
jne 0x156a
leaq 0x10(%r12), %rdi
callq 0x1255
movq %r14, %rdi
movq %r12, %rsi
callq 0x1110
movq %rax, %r12
jmp 0x154b
leaq 0xb6a(%rip), %rdi       # 0x20eb
movl %r15d, %esi
xorl %eax, %eax
callq 0x1090
leaq 0xa0(%rsp), %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x16ae
leaq 0xb50(%rip), %rdi       # 0x20f5
xorl %eax, %eax
callq 0x1090
movq %rbx, %r15
leaq 0x20(%rsp), %rbx
movq %rbx, %rdi
callq 0x1bd4
pushq $0xa
popq %rbp
movl %ebp, %edi
callq 0x1030
leaq 0xb39(%rip), %rdi       # 0x2106
xorl %eax, %eax
callq 0x1090
movq %r13, %rdi
callq 0x1bd4
pushq $0x20
popq %r14
movl %r14d, %edi
callq 0x1030
movq %r13, %rdi
movq %rbx, %rsi
callq 0x1c5b
movl %ebp, %edi
callq 0x1030
leaq 0xb15(%rip), %rdi       # 0x2116
xorl %eax, %eax
callq 0x1090
movq %r15, %rdi
callq 0x1bd4
movl %r14d, %edi
callq 0x1030
movq %r15, %rdi
movq %r13, %rsi
callq 0x1c5b
movl %ebp, %edi
callq 0x1030
xorl %eax, %eax
addq $0x1d8, %rsp            # imm = 0x1D8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%rbx), %rsi
leaq 0x9de(%rip), %rdi       # 0x2026
jmp 0x1655
movq 0x8(%rbx), %rsi
leaq 0x9e1(%rip), %rdi       # 0x2036
xorl %eax, %eax
callq 0x1090
pushq $0x1
popq %rdi
callq 0x1100