1aafef3ccSShuo Chen#include "InetAddress.h"
2aafef3ccSShuo Chen#include "Socket.h"
3aafef3ccSShuo Chen
4aafef3ccSShuo Chen#include <thread>
5aafef3ccSShuo Chen
6aafef3ccSShuo Chen#include <stdio.h>
7aafef3ccSShuo Chen#include <string.h>
8aafef3ccSShuo Chen#include <sys/time.h>
9aafef3ccSShuo Chen#include <unistd.h>
10aafef3ccSShuo Chen
11aafef3ccSShuo Chenconst int g_port = 3123;
12aafef3ccSShuo Chen
13aafef3ccSShuo Chenstruct Message
14aafef3ccSShuo Chen{
15aafef3ccSShuo Chen  int64_t request;
16aafef3ccSShuo Chen  int64_t response;
17aafef3ccSShuo Chen} __attribute__ ((__packed__));
18aafef3ccSShuo Chen
19aafef3ccSShuo Chenstatic_assert(sizeof(Message) == 16, "Message size should be 16 bytes");
20aafef3ccSShuo Chen
21aafef3ccSShuo Chenint64_t now()
22aafef3ccSShuo Chen{
23aafef3ccSShuo Chen  struct timeval tv = { 0, 0 };
24aafef3ccSShuo Chen  gettimeofday(&tv, NULL);
25aafef3ccSShuo Chen  return tv.tv_sec * int64_t(1000000) + tv.tv_usec;
26aafef3ccSShuo Chen}
27aafef3ccSShuo Chen
28eef48d84SShuo Chenvoid runServer(bool ipv6)
29aafef3ccSShuo Chen{
30eef48d84SShuo Chen  Socket sock(Socket::createUDP(ipv6 ? AF_INET6 : AF_INET));
31eef48d84SShuo Chen  sock.bindOrDie(InetAddress(g_port, ipv6));
32aafef3ccSShuo Chen
33aafef3ccSShuo Chen  while (true)
34aafef3ccSShuo Chen  {
35aafef3ccSShuo Chen    Message message = { 0, 0 };
36aafef3ccSShuo Chen
37eef48d84SShuo Chen    struct sockaddr_storage peerAddr;
38aafef3ccSShuo Chen    bzero(&peerAddr, sizeof peerAddr);
39aafef3ccSShuo Chen    socklen_t addrLen = sizeof peerAddr;
40eef48d84SShuo Chen    struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&peerAddr);
41eef48d84SShuo Chen
42eef48d84SShuo Chen    ssize_t nr = ::recvfrom(sock.fd(), &message, sizeof message, 0, addr, &addrLen);
43aafef3ccSShuo Chen    if (nr == sizeof message)
44aafef3ccSShuo Chen    {
45aafef3ccSShuo Chen      message.response = now();
46eef48d84SShuo Chen      ssize_t nw = ::sendto(sock.fd(), &message, sizeof message, 0, addr, addrLen);
47aafef3ccSShuo Chen      if (nw < 0)
48aafef3ccSShuo Chen      {
49aafef3ccSShuo Chen        perror("send Message");
50aafef3ccSShuo Chen      }
51aafef3ccSShuo Chen      else if (nw != sizeof message)
52aafef3ccSShuo Chen      {
53aafef3ccSShuo Chen        printf("sent message of %zd bytes, expect %zd bytes.\n", nw, sizeof message);
54aafef3ccSShuo Chen      }
55aafef3ccSShuo Chen    }
56aafef3ccSShuo Chen    else if (nr < 0)
57aafef3ccSShuo Chen    {
58aafef3ccSShuo Chen      perror("recv Message");
59aafef3ccSShuo Chen    }
60aafef3ccSShuo Chen    else
61aafef3ccSShuo Chen    {
62aafef3ccSShuo Chen      printf("received message of %zd bytes, expect %zd bytes.\n", nr, sizeof message);
63aafef3ccSShuo Chen    }
64aafef3ccSShuo Chen  }
65aafef3ccSShuo Chen}
66aafef3ccSShuo Chen
67aafef3ccSShuo Chenvoid runClient(const char* server_hostname)
68aafef3ccSShuo Chen{
6924ca08a8SShuo Chen  InetAddress serverAddr;
7024ca08a8SShuo Chen  if (!InetAddress::resolve(server_hostname, g_port, &serverAddr))
71f41285cfSShuo Chen  {
72f41285cfSShuo Chen    printf("Unable to resolve %s\n", server_hostname);
73f41285cfSShuo Chen    return;
74f41285cfSShuo Chen  }
75f41285cfSShuo Chen
7624ca08a8SShuo Chen  Socket sock(Socket::createUDP(serverAddr.family()));
7724ca08a8SShuo Chen
78f41285cfSShuo Chen  if (sock.connect(serverAddr) != 0)
79aafef3ccSShuo Chen  {
80aafef3ccSShuo Chen    perror("connect to server");
81aafef3ccSShuo Chen    return;
82aafef3ccSShuo Chen  }
83aafef3ccSShuo Chen
84aafef3ccSShuo Chen  std::thread thr([&sock] () {
85aafef3ccSShuo Chen    while (true)
86aafef3ccSShuo Chen    {
87aafef3ccSShuo Chen      Message message = { 0, 0 };
88aafef3ccSShuo Chen      message.request = now();
898bdf4aafSShuo Chen      int nw = sock.send(&message, sizeof message);
90aafef3ccSShuo Chen      if (nw < 0)
91aafef3ccSShuo Chen      {
92aafef3ccSShuo Chen        perror("send Message");
93aafef3ccSShuo Chen      }
94aafef3ccSShuo Chen      else if (nw != sizeof message)
95aafef3ccSShuo Chen      {
96aafef3ccSShuo Chen        printf("sent message of %d bytes, expect %zd bytes.\n", nw, sizeof message);
97aafef3ccSShuo Chen      }
98aafef3ccSShuo Chen
99aafef3ccSShuo Chen      ::usleep(200*1000);
100aafef3ccSShuo Chen    }
101aafef3ccSShuo Chen  });
102aafef3ccSShuo Chen
103aafef3ccSShuo Chen  while (true)
104aafef3ccSShuo Chen  {
105aafef3ccSShuo Chen    Message message = { 0, 0 };
1068bdf4aafSShuo Chen    int nr = sock.recv(&message, sizeof message);
107aafef3ccSShuo Chen    if (nr == sizeof message)
108aafef3ccSShuo Chen    {
109aafef3ccSShuo Chen      int64_t back = now();
110aafef3ccSShuo Chen      int64_t mine = (back + message.request) / 2;
111eef48d84SShuo Chen      printf("now %jd, round trip time %jd us, clock error %jd us\n",
112f41285cfSShuo Chen             back, back - message.request, message.response - mine);
113aafef3ccSShuo Chen    }
114aafef3ccSShuo Chen    else if (nr < 0)
115aafef3ccSShuo Chen    {
1168bdf4aafSShuo Chen      perror("recv Message");
117aafef3ccSShuo Chen    }
118f41285cfSShuo Chen    else
119aafef3ccSShuo Chen    {
120aafef3ccSShuo Chen      printf("received message of %d bytes, expect %zd bytes.\n", nr, sizeof message);
121aafef3ccSShuo Chen    }
122aafef3ccSShuo Chen  }
123aafef3ccSShuo Chen}
124aafef3ccSShuo Chen
125aafef3ccSShuo Chenint main(int argc, const char* argv[])
126aafef3ccSShuo Chen{
127aafef3ccSShuo Chen  if (argc < 2)
128aafef3ccSShuo Chen  {
129eef48d84SShuo Chen    printf("Usage:\nServer: %s -s [-6]\nClient: %s server_hostname\n", argv[0], argv[0]);
130aafef3ccSShuo Chen    return 0;
131aafef3ccSShuo Chen  }
132aafef3ccSShuo Chen
133aafef3ccSShuo Chen  if (strcmp(argv[1], "-s") == 0)
134aafef3ccSShuo Chen  {
135eef48d84SShuo Chen    bool ipv6 = argc > 2 ? strcmp(argv[2], "-6") == 0 : false;
136eef48d84SShuo Chen    runServer(ipv6);
137aafef3ccSShuo Chen  }
138aafef3ccSShuo Chen  else
139aafef3ccSShuo Chen  {
140aafef3ccSShuo Chen    runClient(argv[1]);
141aafef3ccSShuo Chen  }
142aafef3ccSShuo Chen}
143