-
Notifications
You must be signed in to change notification settings - Fork 2
/
xelflut.c
115 lines (98 loc) · 2.98 KB
/
xelflut.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "xelflut.h"
int usage(char* fn){
printf("%s - Multiplayer X11 canvas\n", XELFLUT_VERSION);
printf("Recognized parameters:\n");
printf("-b <bindhost>\tInterface to bind to (Default ::)\n");
printf("-p <port>\tPort to listen for connections on (Default 3141)\n");
printf("-l <limit>\tPixels a client may set per frame (Default 50)\n");
printf("-f <framerate>\tMaximum framerate (Default 25)\n");
printf("-d <width>x<height>\tThe canvas size (Default 800x600)\n");
printf("-e <enforcer>\tSelect a limit enforcing handler (limit (Default), ignore, disconnect or none)\n");
printf("-u\t\tUnsafe mode - disregard client checks and limits\n");
printf("-x\t\tOnly accept IPv4/6 clients as indicated by bindhost\n");
printf("-w\t\tDo not fullscreen the window\n");
printf("-s\t\tForce uniform scaling (square pixels)\n");
printf("-c\t\tCenter the image (only useful with uniform scaling)\n");
printf("-q\t\tQuiet mode (suppress status output)\n");
return EXIT_FAILURE;
}
void signal_handler(int signum){
abort_signaled = 1;
}
int main(int argc, char** argv){
int listen_fd = -1, maxfd, error;
struct timespec current_time;
struct timeval select_timeout;
int delta_nanos;
fd_set readfds;
//parse arguments
if(args_parse(argc, argv)){
return usage(argv[0]);
}
//handle SIGINT
signal(SIGINT, signal_handler);
//create sockets
listen_fd = tcp_listener(config.bindhost, config.port);
if(listen_fd < 0){
fprintf(stderr, "Failed to create listening socket\n");
return usage(argv[0]);
}
//create window
if(x11_init()){
abort_signaled = 1;
}
else{
//handle initial events
x11_handle();
}
//wait for events
while(!abort_signaled){
//reset fd set
FD_ZERO(&readfds);
//add listen fd
FD_SET(listen_fd, &readfds);
maxfd = listen_fd;
//add all clients
clients_add(&readfds, &maxfd);
//add all x fds
xfds_select(&x11.xfds, &readfds, &maxfd);
//set up timeout
select_timeout.tv_sec = 0;
select_timeout.tv_usec = (1e6 / config.frame_rate) / 2;
//wait for events
error = select(maxfd + 1, &readfds, NULL, NULL, &select_timeout);
if(error < 0){
perror("select");
break;
}
if(error > 0){
//handle events
x11_handle();
if(FD_ISSET(listen_fd, &readfds)){
client_accept(listen_fd);
}
}
clients_handle(&readfds);
//if frame time elapsed, draw and reset the limits
clock_gettime(CLOCK_MONOTONIC_RAW, ¤t_time);
delta_nanos = current_time.tv_nsec - x11.last_render.tv_nsec;
delta_nanos = (delta_nanos < 0) ? 1e9 + delta_nanos:delta_nanos;
if(delta_nanos > 1e9 / config.frame_rate){
if(current_time.tv_sec != x11.last_render.tv_sec){
if(!config.quiet){
fprintf(stderr, "Drawing at %f fps, %f updates per frame from %u clients\n", 1e9/delta_nanos, (config.pixels/(1e9/delta_nanos)), config.clients);
}
//reset the statistic
config.pixels = 0;
}
x11_redraw();
clients_relimit();
x11.last_render = current_time;
}
}
//cleanup
x11_cleanup();
clients_cleanup();
close(listen_fd);
return EXIT_SUCCESS;
}