// File: /workspace/github_c_makefile_star2_O1/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 $0x1e8, %rsp            # imm = 0x1E8
movq %rsi, %rbx
cmpl $0x2, %edi
jle 0x167f
movq 0x8(%rbx), %rdi
leaq 0x10(%rsp), %rsi
callq 0x10b0
cmpl $-0x1, %eax
je 0x168b
movq 0x10(%rbx), %rdi
xorl %esi, %esi
movl $0xa, %edx
callq 0x10f0
rolw $0x8, %ax
movw %ax, 0xe(%rsp)
movw $0x2, 0xc(%rsp)
xorps %xmm0, %xmm0
leaq 0xb0(%rsp), %rbx
movaps %xmm0, (%rbx)
movaps %xmm0, 0x10(%rbx)
movaps %xmm0, 0x20(%rbx)
movb $0x23, (%rbx)
leaq 0x20(%rsp), %r14
xorl %edi, %edi
movq %r14, %rsi
callq 0x1070
movl (%r14), %edi
callq 0x16b7
movl %eax, 0x28(%rbx)
movl 0x8(%r14), %edi
callq 0x16c0
movl %eax, 0x2c(%rbx)
leaq 0xdf2(%rip), %rdi       # 0x2128
callq 0x1050
movq %rbx, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x16fc
movl $0x2, %edi
movl $0x2, %esi
xorl %edx, %edx
callq 0x1120
movl %eax, %r15d
cmpl $-0x1, %eax
jne 0x136c
leaq 0xcde(%rip), %rdi       # 0x2045
callq 0x1d1c
leaq 0x1c(%rsp), %rcx
movl $0x1, (%rcx)
movl %r15d, %edi
xorl %esi, %esi
movl $0x8, %edx
movl $0x4, %r8d
callq 0x1060
testl %eax, %eax
jns 0x139c
leaq 0xcb5(%rip), %rdi       # 0x204c
callq 0x1d1c
xorps %xmm0, %xmm0
leaq 0x60(%rsp), %rbp
movaps %xmm0, 0x10(%rbp)
movaps %xmm0, (%rbp)
movaps %xmm0, 0x20(%rbp)
movq $0x0, 0x30(%rbp)
leaq 0xa0(%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 0xe0(%rsp), %rax
movq %rax, 0x20(%rbp)
movq $0x100, 0x28(%rbp)      # imm = 0x100
leaq 0x58(%rsp), %r12
movl %r15d, (%r12)
movw $0x1, 0x4(%r12)
leaq 0x20(%rsp), %rsi
xorl %edi, %edi
callq 0x1070
movl %eax, 0x8(%rsp)
movl $0x30, %edx
movl %r15d, %edi
movq %rbx, %rsi
xorl %ecx, %ecx
movq %r14, %r8
movl $0x10, %r9d
callq 0x10a0
movq %rax, %r13
leaq 0x30(%rsp), %rsi
xorl %edi, %edi
callq 0x1070
movl %eax, %r14d
movl $0x1, %esi
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
movl %r15d, %edi
movq %rbp, %rsi
movl $0x40, %edx
callq 0x10c0
movq %rax, %r15
testl %r15d, %r15d
jns 0x149a
callq 0x1040
cmpl $0xb, (%rax)
je 0x149a
leaq 0xbce(%rip), %rdi       # 0x2063
callq 0x1d1c
testl %ebx, %ebx
je 0x14aa
leaq 0xbc6(%rip), %rdi       # 0x206b
callq 0x1d1c
testl %r12d, %r12d
leaq 0x40(%rsp), %rbp
jns 0x14c0
leaq 0xbc1(%rip), %rdi       # 0x207c
callq 0x1d1c
testl %r14d, %r14d
je 0x14d1
leaq 0xbb5(%rip), %rdi       # 0x2081
callq 0x1d1c
testl %r13d, %r13d
jns 0x14e2
leaq 0xbb5(%rip), %rdi       # 0x2092
callq 0x1d1c
cmpl $0x0, 0x8(%rsp)
leaq 0x30(%rsp), %r13
je 0x14fa
leaq 0xba4(%rip), %rdi       # 0x2099
callq 0x1d1c
leaq 0xba9(%rip), %rdi       # 0x20aa
movl %r12d, %esi
xorl %eax, %eax
callq 0x1090
testl %r15d, %r15d
jle 0x15dc
leaq 0xbbf(%rip), %rdi       # 0x20da
xorl %eax, %eax
callq 0x1090
movq %rbp, %rdi
movq %r13, %rsi
callq 0x1cbe
movl $0xa, %edi
callq 0x1030
leaq 0xba3(%rip), %rdi       # 0x20e1
xorl %eax, %eax
callq 0x1090
movl 0x10(%rsp), %edi
callq 0x1080
movzwl 0xe(%rsp), %ecx
rolw $0x8, %cx
movzwl %cx, %edx
leaq 0xaa3(%rip), %rdi       # 0x2004
movq %rax, %rsi
xorl %eax, %eax
callq 0x1090
movq 0x80(%rsp), %r14
cmpq $0x10, 0x88(%rsp)
setb %al
testq %r14, %r14
sete %cl
orb %al, %cl
jne 0x15b8
leaq 0x60(%rsp), %r12
cmpl $0x0, 0x8(%r14)
jne 0x15a5
cmpl $0x8, 0xc(%r14)
jne 0x15a5
leaq 0x10(%r14), %rdi
callq 0x1255
movq %r12, %rdi
movq %r14, %rsi
callq 0x1110
movq %rax, %r14
testq %rax, %rax
jne 0x158e
leaq 0xb2c(%rip), %rdi       # 0x20eb
movl %r15d, %esi
xorl %eax, %eax
callq 0x1090
leaq 0xb0(%rsp), %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x16fc
leaq 0xb12(%rip), %rdi       # 0x20f5
xorl %eax, %eax
callq 0x1090
leaq 0x20(%rsp), %rbx
movq %rbx, %rdi
callq 0x1c40
movl $0xa, %edi
callq 0x1030
leaq 0xafe(%rip), %rdi       # 0x2106
xorl %eax, %eax
callq 0x1090
movq %r13, %rdi
callq 0x1c40
movl $0x20, %edi
callq 0x1030
movq %r13, %rdi
movq %rbx, %rsi
callq 0x1cbe
movl $0xa, %edi
callq 0x1030
leaq 0xad9(%rip), %rdi       # 0x2116
xorl %eax, %eax
callq 0x1090
movq %rbp, %rdi
callq 0x1c40
movl $0x20, %edi
callq 0x1030
movq %rbp, %rdi
movq %r13, %rsi
callq 0x1cbe
movl $0xa, %edi
callq 0x1030
xorl %eax, %eax
addq $0x1e8, %rsp            # imm = 0x1E8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%rbx), %rsi
leaq 0x99d(%rip), %rdi       # 0x2026
jmp 0x1696
movq 0x8(%rbx), %rsi
leaq 0x9a0(%rip), %rdi       # 0x2036
xorl %eax, %eax
callq 0x1090
movl $0x1, %edi
callq 0x1100
nop