duplicate send, resend, ack
The 'software' renderer is now explicitly requested.
This commit is contained in:
parent
16eaa08244
commit
8c1c1e97f6
2
Makefile
2
Makefile
@ -43,7 +43,7 @@ serial_forwarder: $(SERIAL_FORWARDER_OBJS)
|
|||||||
$(CC) $^ -o $@
|
$(CC) $^ -o $@
|
||||||
|
|
||||||
time_display: $(TIME_DISPLAY_OBJS)
|
time_display: $(TIME_DISPLAY_OBJS)
|
||||||
$(CC) $(LDFLAGS) $^ -o $@
|
$(CC) $^ -o $@ $(LDFLAGS)
|
||||||
|
|
||||||
-include $(shell find -type f -name '*.d')
|
-include $(shell find -type f -name '*.d')
|
||||||
|
|
||||||
|
10
gpio.c
10
gpio.c
@ -66,13 +66,13 @@ void gpio_set_values_from_link_state(struct gpio_state * gpio_state,
|
|||||||
|
|
||||||
struct timespec delta = timespec_sub(&now, &link_state->last_pong);
|
struct timespec delta = timespec_sub(&now, &link_state->last_pong);
|
||||||
if (delta.tv_sec >= LAST_PONG_TIMEOUT) {
|
if (delta.tv_sec >= LAST_PONG_TIMEOUT) {
|
||||||
printf("pong timeout %ld\n", delta.tv_sec);
|
printf("gpio pong timeout %ld\n", delta.tv_sec);
|
||||||
if (gpio_state->chip_fd != -1)
|
|
||||||
gpio_set_values(gpio_state, GREEN);
|
|
||||||
} else {
|
|
||||||
printf("pong ok %ld\n", delta.tv_sec);
|
|
||||||
if (gpio_state->chip_fd != -1)
|
if (gpio_state->chip_fd != -1)
|
||||||
gpio_set_values(gpio_state, RED);
|
gpio_set_values(gpio_state, RED);
|
||||||
|
} else {
|
||||||
|
printf("gpio pong ok %ld\n", delta.tv_sec);
|
||||||
|
if (gpio_state->chip_fd != -1)
|
||||||
|
gpio_set_values(gpio_state, GREEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
51
packet.c
51
packet.c
@ -5,6 +5,9 @@
|
|||||||
#include "link.h"
|
#include "link.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
|
#include "timespec.h"
|
||||||
|
|
||||||
|
#define DUPLICATE_SEND 3
|
||||||
|
|
||||||
int packet_send_ping(int sockfd,
|
int packet_send_ping(int sockfd,
|
||||||
struct sockaddr_in6 * dest_addr)
|
struct sockaddr_in6 * dest_addr)
|
||||||
@ -56,12 +59,12 @@ int packet_send_pong(int sockfd,
|
|||||||
|
|
||||||
int packet_send_average_rtt(int sockfd,
|
int packet_send_average_rtt(int sockfd,
|
||||||
struct sockaddr_in6 * dest_addr,
|
struct sockaddr_in6 * dest_addr,
|
||||||
struct timespec * time)
|
struct timespec * offset)
|
||||||
{
|
{
|
||||||
struct packet_ping_pong pkt;
|
struct packet_average_rtt pkt;
|
||||||
pkt.event.type = EVENT_TYPE__AVERAGE_RTT;
|
pkt.event.type = EVENT_TYPE__AVERAGE_RTT;
|
||||||
pkt.event.sequence = 0;
|
pkt.event.sequence = 0;
|
||||||
memcpy(&pkt.time, time, (sizeof (struct timespec)));
|
memcpy(&pkt.offset, offset, (sizeof (struct timespec)));
|
||||||
|
|
||||||
int ret = sendto(sockfd,
|
int ret = sendto(sockfd,
|
||||||
&pkt, (sizeof (pkt)),
|
&pkt, (sizeof (pkt)),
|
||||||
@ -83,8 +86,9 @@ int packet_send_start_event(int sockfd,
|
|||||||
{
|
{
|
||||||
struct packet_start pkt;
|
struct packet_start pkt;
|
||||||
pkt.event.type = EVENT_TYPE__TIME_START;
|
pkt.event.type = EVENT_TYPE__TIME_START;
|
||||||
pkt.event.sequence = link_state->send_sequence++;
|
pkt.event.sequence = ++link_state->send_sequence;
|
||||||
|
|
||||||
|
for (int i = 0; i < DUPLICATE_SEND; i++) {
|
||||||
int ret = sendto(sockfd,
|
int ret = sendto(sockfd,
|
||||||
&pkt, (sizeof (pkt)),
|
&pkt, (sizeof (pkt)),
|
||||||
0,
|
0,
|
||||||
@ -94,18 +98,26 @@ int packet_send_start_event(int sockfd,
|
|||||||
perror("packet_send_start_event sendto");
|
perror("packet_send_start_event sendto");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int packet_send_resume_event(int sockfd,
|
int packet_send_resume_event(int sockfd,
|
||||||
struct sockaddr_in6 * dest_addr,
|
struct sockaddr_in6 * dest_addr,
|
||||||
|
struct timer_state * timer_state,
|
||||||
struct link_state * link_state)
|
struct link_state * link_state)
|
||||||
{
|
{
|
||||||
struct packet_start pkt;
|
struct packet_resume pkt;
|
||||||
pkt.event.type = EVENT_TYPE__TIME_RESUME;
|
pkt.event.type = EVENT_TYPE__TIME_RESUME;
|
||||||
pkt.event.sequence = link_state->send_sequence++;
|
pkt.event.sequence = ++link_state->send_sequence;
|
||||||
|
struct timespec now;
|
||||||
|
int ret = clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
||||||
|
assert(ret != -1);
|
||||||
|
pkt.offset = timespec_sub(&now, &timer_state->counter.start);
|
||||||
|
printf("resume offset %ld.%09ld\n", pkt.offset.tv_sec, pkt.offset.tv_nsec);
|
||||||
|
|
||||||
|
for (int i = 0; i < DUPLICATE_SEND; i++) {
|
||||||
int ret = sendto(sockfd,
|
int ret = sendto(sockfd,
|
||||||
&pkt, (sizeof (pkt)),
|
&pkt, (sizeof (pkt)),
|
||||||
0,
|
0,
|
||||||
@ -115,6 +127,7 @@ int packet_send_resume_event(int sockfd,
|
|||||||
perror("packet_send_resume_event sendto");
|
perror("packet_send_resume_event sendto");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -126,9 +139,10 @@ int packet_send_stopwatch_event(int sockfd,
|
|||||||
{
|
{
|
||||||
struct packet_stopwatch pkt;
|
struct packet_stopwatch pkt;
|
||||||
pkt.event.type = EVENT_TYPE__TIME_STOP;
|
pkt.event.type = EVENT_TYPE__TIME_STOP;
|
||||||
pkt.event.sequence = link_state->send_sequence++;
|
pkt.event.sequence = ++link_state->send_sequence;
|
||||||
memcpy(&pkt.stopwatch_time, &timer_state->time, (sizeof (struct stopwatch_time)));
|
memcpy(&pkt.stopwatch_time, &timer_state->time, (sizeof (struct stopwatch_time)));
|
||||||
|
|
||||||
|
for (int i = 0; i < DUPLICATE_SEND; i++) {
|
||||||
int ret = sendto(sockfd,
|
int ret = sendto(sockfd,
|
||||||
&pkt, (sizeof (pkt)),
|
&pkt, (sizeof (pkt)),
|
||||||
0,
|
0,
|
||||||
@ -138,6 +152,29 @@ int packet_send_stopwatch_event(int sockfd,
|
|||||||
perror("packet_send_stopwatch_event sendto");
|
perror("packet_send_stopwatch_event sendto");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int packet_send_ack(int sockfd,
|
||||||
|
struct sockaddr_in6 * dest_addr,
|
||||||
|
uint32_t sequence)
|
||||||
|
{
|
||||||
|
struct packet_ack pkt;
|
||||||
|
pkt.event.type = EVENT_TYPE__ACK;
|
||||||
|
pkt.event.sequence = sequence;
|
||||||
|
|
||||||
|
int ret = sendto(sockfd,
|
||||||
|
&pkt, (sizeof (pkt)),
|
||||||
|
0,
|
||||||
|
(struct sockaddr *)dest_addr,
|
||||||
|
(sizeof (struct sockaddr_in6)));
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("packet_send_pong sendto");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
18
packet.h
18
packet.h
@ -38,18 +38,26 @@ struct packet_start {
|
|||||||
|
|
||||||
static_assert((sizeof (struct packet_start)) == (sizeof (struct event)));
|
static_assert((sizeof (struct packet_start)) == (sizeof (struct event)));
|
||||||
|
|
||||||
|
struct packet_resume {
|
||||||
|
struct event event;
|
||||||
|
struct timespec offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert((sizeof (struct packet_resume)) ==
|
||||||
|
(sizeof (struct event)) + (sizeof (struct timespec)));
|
||||||
|
|
||||||
struct packet_ack {
|
struct packet_ack {
|
||||||
struct event event;
|
struct event event;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert((sizeof (struct packet_ack)) == (sizeof (struct event)));
|
static_assert((sizeof (struct packet_ack)) == (sizeof (struct event)));
|
||||||
|
|
||||||
struct packet_rtt_delay {
|
struct packet_average_rtt {
|
||||||
struct event event;
|
struct event event;
|
||||||
struct timespec offset;
|
struct timespec offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert((sizeof (struct packet_rtt_delay)) == (sizeof (struct event)) + (sizeof (struct timespec)));
|
static_assert((sizeof (struct packet_average_rtt)) == (sizeof (struct event)) + (sizeof (struct timespec)));
|
||||||
|
|
||||||
struct packet_ping_pong {
|
struct packet_ping_pong {
|
||||||
struct event event;
|
struct event event;
|
||||||
@ -63,15 +71,19 @@ int packet_send_pong(int sockfd,
|
|||||||
struct timespec * time);
|
struct timespec * time);
|
||||||
int packet_send_average_rtt(int sockfd,
|
int packet_send_average_rtt(int sockfd,
|
||||||
struct sockaddr_in6 * dest_addr,
|
struct sockaddr_in6 * dest_addr,
|
||||||
struct timespec * time);
|
struct timespec * offset);
|
||||||
|
|
||||||
int packet_send_start_event(int sockfd,
|
int packet_send_start_event(int sockfd,
|
||||||
struct sockaddr_in6 * dest_addr,
|
struct sockaddr_in6 * dest_addr,
|
||||||
struct link_state * link_state);
|
struct link_state * link_state);
|
||||||
int packet_send_resume_event(int sockfd,
|
int packet_send_resume_event(int sockfd,
|
||||||
struct sockaddr_in6 * dest_addr,
|
struct sockaddr_in6 * dest_addr,
|
||||||
|
struct timer_state * timer_state,
|
||||||
struct link_state * link_state);
|
struct link_state * link_state);
|
||||||
int packet_send_stopwatch_event(int sockfd,
|
int packet_send_stopwatch_event(int sockfd,
|
||||||
struct sockaddr_in6 * dest_addr,
|
struct sockaddr_in6 * dest_addr,
|
||||||
struct timer_state * timer_state,
|
struct timer_state * timer_state,
|
||||||
struct link_state * link_state);
|
struct link_state * link_state);
|
||||||
|
int packet_send_ack(int sockfd,
|
||||||
|
struct sockaddr_in6 * dest_addr,
|
||||||
|
uint32_t sequence);
|
||||||
|
@ -94,7 +94,7 @@ uint32_t handle_line(uint8_t const * const buf, int length,
|
|||||||
return EVENT_TYPE__TIME_START;
|
return EVENT_TYPE__TIME_START;
|
||||||
} else if (is_timer_resume(buf, length)) {
|
} else if (is_timer_resume(buf, length)) {
|
||||||
timer_state->status = TIMER_RUNNING;
|
timer_state->status = TIMER_RUNNING;
|
||||||
return EVENT_TYPE__TIME_START;
|
return EVENT_TYPE__TIME_RESUME;
|
||||||
} else {
|
} else {
|
||||||
int ret = parse_time(buf, length, &timer_state->time);
|
int ret = parse_time(buf, length, &timer_state->time);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
|
10
ping_pong.c
10
ping_pong.c
@ -55,13 +55,15 @@ int handle_ping_pong(int sockfd,
|
|||||||
break;
|
break;
|
||||||
case EVENT_TYPE__AVERAGE_RTT:
|
case EVENT_TYPE__AVERAGE_RTT:
|
||||||
{
|
{
|
||||||
if (length != (sizeof (struct packet_ping_pong))) {
|
if (length != (sizeof (struct packet_average_rtt))) {
|
||||||
printf("handle_ping_pong: average_rtt: invalid length\n");
|
printf("handle_average_rtt: average_rtt: invalid length\n");
|
||||||
return 0; // recoverable
|
return 0; // recoverable
|
||||||
}
|
}
|
||||||
struct packet_ping_pong * ping_pkt = (struct packet_ping_pong *)buf;
|
struct packet_average_rtt * ping_pkt = (struct packet_average_rtt *)buf;
|
||||||
|
|
||||||
printf("recv average_rtt: %ld.%09ld\n", ping_pkt->time.tv_sec, ping_pkt->time.tv_nsec);
|
printf("recv average_rtt: %ld.%09ld\n", ping_pkt->offset.tv_sec, ping_pkt->offset.tv_nsec);
|
||||||
|
|
||||||
|
link_state->remote_average_rtt = ping_pkt->offset;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
|
|
||||||
#define PING_INTERVAL 5
|
#define PING_INTERVAL 1
|
||||||
|
|
||||||
int handle_ping_pong(int sockfd,
|
int handle_ping_pong(int sockfd,
|
||||||
struct sockaddr_in6 * dest_addr,
|
struct sockaddr_in6 * dest_addr,
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "link.h"
|
#include "link.h"
|
||||||
#include "timespec.h"
|
#include "timespec.h"
|
||||||
#include "ping_pong.h"
|
#include "ping_pong.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
#define PORT 4321
|
#define PORT 4321
|
||||||
//#define SERIALPORT "/dev/ttyS0"
|
//#define SERIALPORT "/dev/ttyS0"
|
||||||
@ -47,6 +48,10 @@ int handle_buf(int sockfd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EVENT_TYPE__ACK:
|
||||||
|
printf("recv ack %d\n", evt->sequence);
|
||||||
|
link_state->recv_sequence = evt->sequence;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("unhandled event %d\n", evt->type);
|
printf("unhandled event %d\n", evt->type);
|
||||||
break;
|
break;
|
||||||
@ -108,10 +113,76 @@ int rearm_timer(int timerfd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int handle_event(int sockfd,
|
||||||
|
struct sockaddr_in6 * dest_addr,
|
||||||
|
struct timer_state * timer_state,
|
||||||
|
struct link_state * link_state,
|
||||||
|
uint32_t type)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
switch (type) {
|
||||||
|
case EVENT_TYPE__TIME_STOP:
|
||||||
|
printf("event time stop\n");
|
||||||
|
ret = packet_send_stopwatch_event(sockfd, dest_addr, timer_state, link_state);
|
||||||
|
if (ret == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EVENT_TYPE__TIME_START:
|
||||||
|
printf("event time start\n");
|
||||||
|
ret = packet_send_start_event(sockfd, dest_addr, link_state);
|
||||||
|
if (ret == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EVENT_TYPE__TIME_RESUME:
|
||||||
|
printf("event time resume\n");
|
||||||
|
ret = packet_send_resume_event(sockfd, dest_addr, timer_state, link_state);
|
||||||
|
if (ret == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_sequence(int sockfd,
|
||||||
|
struct sockaddr_in6 * dest_addr,
|
||||||
|
struct timer_state * timer_state,
|
||||||
|
struct link_state * link_state)
|
||||||
|
{
|
||||||
|
printf("check_sequence send %ld recv: %ld\n", link_state->send_sequence, link_state->recv_sequence);
|
||||||
|
|
||||||
|
if (link_state->send_sequence != link_state->recv_sequence) {
|
||||||
|
switch (timer_state->status) {
|
||||||
|
case TIMER_STOPPED:
|
||||||
|
handle_event(sockfd,
|
||||||
|
dest_addr,
|
||||||
|
timer_state,
|
||||||
|
link_state,
|
||||||
|
EVENT_TYPE__TIME_STOP);
|
||||||
|
break;
|
||||||
|
case TIMER_RUNNING:
|
||||||
|
handle_event(sockfd,
|
||||||
|
dest_addr,
|
||||||
|
timer_state,
|
||||||
|
link_state,
|
||||||
|
EVENT_TYPE__TIME_RESUME);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int handle_timerfd(int timerfd,
|
int handle_timerfd(int timerfd,
|
||||||
int sockfd,
|
int sockfd,
|
||||||
struct sockaddr_in6 * dest_addr,
|
struct sockaddr_in6 * dest_addr,
|
||||||
struct link_state * link_state)
|
struct timer_state * timer_state,
|
||||||
|
struct link_state * link_state,
|
||||||
|
struct gpio_state * gpio_state)
|
||||||
{
|
{
|
||||||
uint64_t expired_count = 0;
|
uint64_t expired_count = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -130,11 +201,23 @@ int handle_timerfd(int timerfd,
|
|||||||
|
|
||||||
rearm_timer(timerfd);
|
rearm_timer(timerfd);
|
||||||
|
|
||||||
int ret = packet_send_ping(sockfd, dest_addr);
|
int ret;
|
||||||
|
ret = packet_send_ping(sockfd, dest_addr);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = check_sequence(sockfd,
|
||||||
|
dest_addr,
|
||||||
|
timer_state,
|
||||||
|
link_state);
|
||||||
|
if (ret == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_set_values_from_link_state(gpio_state,
|
||||||
|
link_state);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,29 +251,14 @@ int handle_serialfd(int serialfd,
|
|||||||
uint32_t type = handle_parse(buf, len,
|
uint32_t type = handle_parse(buf, len,
|
||||||
parser_state,
|
parser_state,
|
||||||
timer_state);
|
timer_state);
|
||||||
int ret;
|
int ret = handle_event(sockfd,
|
||||||
switch (type) {
|
dest_addr,
|
||||||
case EVENT_TYPE__TIME_STOP:
|
timer_state,
|
||||||
ret = packet_send_stopwatch_event(sockfd, dest_addr, timer_state, link_state);
|
link_state,
|
||||||
|
type);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case EVENT_TYPE__TIME_START:
|
|
||||||
ret = packet_send_start_event(sockfd, dest_addr, link_state);
|
|
||||||
if (ret == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EVENT_TYPE__TIME_RESUME:
|
|
||||||
ret = packet_send_resume_event(sockfd, dest_addr, link_state);
|
|
||||||
if (ret == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -291,6 +359,10 @@ int main(void)
|
|||||||
struct parser_state parser_state = {0};
|
struct parser_state parser_state = {0};
|
||||||
struct timer_state timer_state = {0};
|
struct timer_state timer_state = {0};
|
||||||
struct link_state link_state = {0};
|
struct link_state link_state = {0};
|
||||||
|
struct gpio_state gpio_state = {0};
|
||||||
|
|
||||||
|
gpio_open("/dev/gpiochip0", &gpio_state);
|
||||||
|
// ignored gpio_open error
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
|
int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
|
||||||
@ -308,7 +380,9 @@ int main(void)
|
|||||||
ret = handle_timerfd(timerfd,
|
ret = handle_timerfd(timerfd,
|
||||||
sockfd,
|
sockfd,
|
||||||
&dest_addr,
|
&dest_addr,
|
||||||
&link_state);
|
&timer_state,
|
||||||
|
&link_state,
|
||||||
|
&gpio_state);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return -1;
|
return -1;
|
||||||
} else if (events[n].data.fd == serialfd) {
|
} else if (events[n].data.fd == serialfd) {
|
||||||
|
@ -172,8 +172,20 @@ int handle_buf(int sockfd,
|
|||||||
struct link_state * link_state)
|
struct link_state * link_state)
|
||||||
{
|
{
|
||||||
struct event * evt = (struct event *)buf;
|
struct event * evt = (struct event *)buf;
|
||||||
|
|
||||||
|
if (evt->sequence != 0) {
|
||||||
|
if (evt->sequence == link_state->recv_sequence) {
|
||||||
|
printf("ignore duplicate seq %d; recv %ld type %d\n", evt->sequence, link_state->recv_sequence, evt->type);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
printf("type %d seq %d\n", evt->sequence, evt->type);
|
||||||
|
link_state->recv_sequence = evt->sequence;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (evt->type) {
|
switch (evt->type) {
|
||||||
case EVENT_TYPE__TIME_STOP:
|
case EVENT_TYPE__TIME_STOP:
|
||||||
|
{
|
||||||
if (length != (sizeof (struct packet_stopwatch))) {
|
if (length != (sizeof (struct packet_stopwatch))) {
|
||||||
printf("handle_buf: packet_stopwatch: invalid length\n");
|
printf("handle_buf: packet_stopwatch: invalid length\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -182,26 +194,40 @@ int handle_buf(int sockfd,
|
|||||||
struct packet_stopwatch * time_pkt = (struct packet_stopwatch *)buf;
|
struct packet_stopwatch * time_pkt = (struct packet_stopwatch *)buf;
|
||||||
memcpy(&timer_state->time, &time_pkt->stopwatch_time, (sizeof (struct stopwatch_time)));
|
memcpy(&timer_state->time, &time_pkt->stopwatch_time, (sizeof (struct stopwatch_time)));
|
||||||
timer_state->status = TIMER_STOPPED;
|
timer_state->status = TIMER_STOPPED;
|
||||||
|
packet_send_ack(sockfd, dest_addr, evt->sequence);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_TYPE__TIME_START:
|
case EVENT_TYPE__TIME_START:
|
||||||
if (length != (sizeof (struct event))) {
|
{
|
||||||
|
if (length != (sizeof (struct packet_start))) {
|
||||||
printf("handle_buf: time start: invalid length\n");
|
printf("handle_buf: time start: invalid length\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = clock_gettime(CLOCK_MONOTONIC_RAW, &timer_state->counter.start);
|
int ret = clock_gettime(CLOCK_MONOTONIC_RAW, &timer_state->counter.start);
|
||||||
assert(ret != -1);
|
assert(ret != -1);
|
||||||
timer_state->counter.offset.tv_sec = 0;
|
timer_state->counter.offset = timespec_div(&link_state->remote_average_rtt, 2);
|
||||||
timer_state->counter.offset.tv_nsec = 0;
|
printf("counter_offset %ld.%09ld\n", timer_state->counter.offset.tv_sec, timer_state->counter.offset.tv_nsec);
|
||||||
timer_state->status = TIMER_RUNNING;
|
timer_state->status = TIMER_RUNNING;
|
||||||
|
packet_send_ack(sockfd, dest_addr, evt->sequence);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_TYPE__TIME_RESUME:
|
case EVENT_TYPE__TIME_RESUME:
|
||||||
if (length != (sizeof (struct event))) {
|
{
|
||||||
|
if (length != (sizeof (struct packet_resume))) {
|
||||||
printf("handle_buf: time resume: invalid length\n");
|
printf("handle_buf: time resume: invalid length\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
struct packet_resume * resume_pkt = (struct packet_resume *)buf;
|
||||||
|
printf("resume offset %ld.%09ld\n", resume_pkt->offset.tv_sec, resume_pkt->offset.tv_nsec);
|
||||||
|
int ret = clock_gettime(CLOCK_MONOTONIC_RAW, &timer_state->counter.start);
|
||||||
|
assert(ret != -1);
|
||||||
|
timer_state->counter.offset = timespec_div(&link_state->remote_average_rtt, 2);
|
||||||
|
timer_state->counter.offset = timespec_add(&timer_state->counter.offset, &resume_pkt->offset);
|
||||||
|
printf("counter offset %ld.%09ld\n", timer_state->counter.offset.tv_sec, timer_state->counter.offset.tv_nsec);
|
||||||
timer_state->status = TIMER_RUNNING;
|
timer_state->status = TIMER_RUNNING;
|
||||||
|
packet_send_ack(sockfd, dest_addr, evt->sequence);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_TYPE__PING: [[fallthrough]];
|
case EVENT_TYPE__PING: [[fallthrough]];
|
||||||
case EVENT_TYPE__PONG: [[fallthrough]];
|
case EVENT_TYPE__PONG: [[fallthrough]];
|
||||||
@ -294,7 +320,13 @@ int main()
|
|||||||
512, // h
|
512, // h
|
||||||
SDL_WINDOW_RESIZABLE);// | SDL_WINDOW_MAXIMIZED);
|
SDL_WINDOW_RESIZABLE);// | SDL_WINDOW_MAXIMIZED);
|
||||||
|
|
||||||
renderer = SDL_CreateRenderer(window, NULL);
|
int num_drivers = SDL_GetNumRenderDrivers();
|
||||||
|
printf("available drivers:\n");
|
||||||
|
for (int i = 0; i < num_drivers; i++) {
|
||||||
|
const char * s = SDL_GetRenderDriver(i);
|
||||||
|
printf(" %s\n", s);
|
||||||
|
}
|
||||||
|
renderer = SDL_CreateRenderer(window, "software");
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
|
|
||||||
SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
|
SDL_PropertiesID props = SDL_GetRendererProperties(renderer);
|
||||||
@ -376,10 +408,11 @@ int main()
|
|||||||
int ret = clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
int ret = clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
||||||
assert(ret != -1);
|
assert(ret != -1);
|
||||||
|
|
||||||
struct timespec duration = timespec_sub(&now, &timer_state.counter.start);
|
struct timespec real_start = timespec_sub(&timer_state.counter.start, &timer_state.counter.offset);
|
||||||
|
struct timespec duration = timespec_sub(&now, &real_start);
|
||||||
|
|
||||||
snprintf(str_buf, (sizeof (str_buf)) - 1,
|
snprintf(str_buf, (sizeof (str_buf)) - 1,
|
||||||
"%ld.%ld",
|
"%ld.%02ld",
|
||||||
duration.tv_sec,
|
duration.tv_sec,
|
||||||
duration.tv_nsec / (1000000000 / 100)); // 2 digits
|
duration.tv_nsec / (1000000000 / 100)); // 2 digits
|
||||||
}
|
}
|
||||||
@ -390,6 +423,7 @@ int main()
|
|||||||
}
|
}
|
||||||
int length = strlen(str_buf);
|
int length = strlen(str_buf);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
int window_width;
|
int window_width;
|
||||||
int window_height;
|
int window_height;
|
||||||
@ -433,8 +467,6 @@ int main()
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
timer.h
1
timer.h
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
enum timer_status {
|
enum timer_status {
|
||||||
TIMER_STOPPED,
|
TIMER_STOPPED,
|
||||||
|
21
timespec.c
21
timespec.c
@ -31,6 +31,18 @@ struct timespec timespec_add(const struct timespec * a,
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct timespec timespec_div(const struct timespec * a,
|
||||||
|
int n)
|
||||||
|
{
|
||||||
|
int64_t rem = a->tv_sec % n;
|
||||||
|
struct timespec c = {
|
||||||
|
.tv_sec = a->tv_sec / n,
|
||||||
|
.tv_nsec = (a->tv_nsec / n) + (rem * 1000000000 / n)
|
||||||
|
};
|
||||||
|
assert(c.tv_nsec < 1000000000);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
struct timespec timespec_average(const struct timespec * ts,
|
struct timespec timespec_average(const struct timespec * ts,
|
||||||
int length)
|
int length)
|
||||||
{
|
{
|
||||||
@ -39,10 +51,7 @@ struct timespec timespec_average(const struct timespec * ts,
|
|||||||
c = timespec_add(&c, &ts[i]);
|
c = timespec_add(&c, &ts[i]);
|
||||||
//printf("rtt[%d]: %ld.%09ld\n", i, ts[i].tv_sec, ts[i].tv_nsec);
|
//printf("rtt[%d]: %ld.%09ld\n", i, ts[i].tv_sec, ts[i].tv_nsec);
|
||||||
}
|
}
|
||||||
int64_t rem = c.tv_sec % length;
|
struct timespec d = timespec_div(&c, length);
|
||||||
c.tv_sec /= length;
|
//printf("average: %ld.%09ld\n", d.tv_sec, d.tv_nsec);
|
||||||
c.tv_nsec = (c.tv_nsec / length) + (rem * 1000000000 / length);
|
return d;
|
||||||
assert(c.tv_nsec < 1000000000);
|
|
||||||
//printf("average: %ld.%09ld\n", c.tv_sec, c.tv_nsec);
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,8 @@ struct timespec timespec_sub(const struct timespec * a,
|
|||||||
struct timespec timespec_add(const struct timespec * a,
|
struct timespec timespec_add(const struct timespec * a,
|
||||||
const struct timespec * b);
|
const struct timespec * b);
|
||||||
|
|
||||||
|
struct timespec timespec_div(const struct timespec * a,
|
||||||
|
int n);
|
||||||
|
|
||||||
struct timespec timespec_average(const struct timespec * ts,
|
struct timespec timespec_average(const struct timespec * ts,
|
||||||
int length);
|
int length);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user