DEADSOFTWARE

b344dac83894c7855f7b0dde3b25b40535fc2290
[d2df-sdl.git] / src / mastersrv / master.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <enet/enet.h>
5 #include <enet/types.h>
7 #define MS_VERSION "0.1"
8 #define MS_MAXSRVS 32
9 #define MS_TIMEOUT 100
11 #define NET_CHANS 2
12 #define NET_CH_MAIN 0
13 #define NET_CH_UPD 1
14 #define NET_MAXCLIENTS 64
16 #define NET_BUFSIZE 65536
18 #define NET_MSG_ADD 200
19 #define NET_MSG_RM 201
20 #define NET_MSG_LIST 202
22 #define LC_MS_INIT "D2DF master server starting on port %d...\n"
23 #define LC_MS_ADD "\nAdded server in slot #%d:\n%s:%d\n%s\n%s (%d)\n%d/%d plrs\nproto: %d pw?: %d\n"
24 #define LC_MS_UPD "\nUpdated server #%d (%s:%d):\n%s\n%s (%d)\n%d/%d plrs\nproto: %d pw?: %d\n"
25 #define LC_MS_RM "\nRemoved server #%d (%s:%d) by request.\n"
26 #define LC_MS_TIME "\nServer #%d (%s:%d) timed out.\n"
27 #define LC_MS_LIST "\nSent server list to %x:%u.\n"
28 #define LC_MS_DIE "\nD2DF master server shutting down...\n"
29 #define LC_MS_CONN "\nIncoming connection from %x:%u...\n"
32 struct ms_server_s {
33 enet_uint8 used;
34 char s_ip[17];
35 char s_name[256];
36 char s_map[256];
37 enet_uint8 s_pw;
38 enet_uint8 s_plrs;
39 enet_uint8 s_maxplrs;
40 enet_uint8 s_mode;
41 enet_uint8 s_protocol;
42 enet_uint16 s_port;
43 enet_uint32 ttl;
44 };
46 typedef struct ms_server_s ms_server;
48 const char ms_game_ver[] = "0.63";
49 int ms_port = 25660;
50 int ms_timeout = 100000;
52 size_t b_read = 0;
53 size_t b_write = 0;
55 enet_uint8 b_send[NET_BUFSIZE];
57 ENetHost *ms_host = NULL;
58 ENetPeer *ms_peers[NET_MAXCLIENTS];
59 ms_server ms_srv[MS_MAXSRVS];
60 enet_uint8 ms_count = 0;
63 void i_usage () {
64 printf("Usage: d2df_master -p port_number [-t timeout_seconds]\n");
65 fflush(stdout);
66 }
69 void i_version () {
70 printf("Doom 2D Forever master server v%s\n", MS_VERSION);
71 fflush(stdout);
72 }
75 void d_error (const char *msg, int fatal) {
76 if (fatal) {
77 fprintf(stderr, "FATAL ERROR: %s\n", msg);
78 exit(EXIT_FAILURE);
79 } else {
80 fprintf(stderr, "ERROR: %s\n", msg);
81 }
82 }
85 void d_getargs (int argc, char *argv[]) {
86 if (argc < 2) {
87 i_usage();
88 exit(0);
89 return;
90 }
92 for (int i = 1; i < argc; ++i) {
93 if (!strcmp(argv[i], "-v")) {
94 i_version();
95 exit(0);
96 return;
97 } else if (!strcmp(argv[i], "-p")) {
98 if (i + 1 >= argc) {
99 d_error("Specify a port value!", 1);
100 return;
101 } else {
102 ms_port = atoi(argv[++i]);
104 } else if (!strcmp(argv[i], "-t") & (i + 1 < argc)) {
105 ms_timeout = atoi(argv[++i]) * 1000;
111 enet_uint8 b_read_uint8 (enet_uint8 buf[], size_t *pos) {
112 return buf[(*pos)++];
116 enet_uint16 b_read_uint16 (enet_uint8 buf[], size_t *pos) {
117 enet_uint16 ret = 0;
119 ret = *(enet_uint16*)(buf + *pos);
120 *pos += sizeof(enet_uint16);
122 return ret;
126 char* b_read_dstring (enet_uint8 buf[], size_t *pos) {
127 char *ret = NULL;
129 size_t len = b_read_uint8(buf, pos);
131 ret = malloc(len + 1);
133 memmove(ret, (char*)(buf + *pos), len);
134 ret[len] = '\0';
135 *pos += len;
137 return ret;
141 void b_write_uint8 (enet_uint8 buf[], size_t *pos, enet_uint8 val) {
142 buf[(*pos)++] = val;
146 void b_write_uint16 (enet_uint8 buf[], size_t *pos, enet_uint16 val) {
147 *(enet_uint16*)(buf + *pos) = val;
148 *pos += sizeof(enet_uint16);
152 void b_write_dstring (enet_uint8 buf[], size_t *pos, const char* val) {
153 enet_uint8 len = strlen(val);
154 b_write_uint8(buf, pos, len);
156 memmove((char*)(buf + *pos), val, len);
157 *pos += len;
161 void b_write_server (enet_uint8 buf[], size_t *pos, ms_server s) {
162 b_write_dstring(b_send, pos, s.s_ip);
163 b_write_uint16 (b_send, pos, s.s_port);
164 b_write_dstring(b_send, pos, s.s_name);
165 b_write_dstring(b_send, pos, s.s_map);
166 b_write_uint8 (b_send, pos, s.s_mode);
167 b_write_uint8 (b_send, pos, s.s_plrs);
168 b_write_uint8 (b_send, pos, s.s_maxplrs);
169 b_write_uint8 (b_send, pos, s.s_protocol);
170 b_write_uint8 (b_send, pos, s.s_pw);
174 int main (int argc, char *argv[]) {
175 d_getargs(argc, argv);
177 if (enet_initialize()) {
178 d_error("Could not init ENet!", 1);
179 return EXIT_FAILURE;
182 printf(LC_MS_INIT, ms_port);
184 for (int i = 0; i < NET_MAXCLIENTS; ++i) ms_peers[i] = NULL;
186 for (int i = 0; i < MS_MAXSRVS; ++i) {
187 ms_srv[i].used = 0;
188 ms_srv[i].s_ip[0] = '\0';
189 ms_srv[i].s_name[0] = '\0';
190 ms_srv[i].s_map[0] = '\0';
191 ms_srv[i].ttl = 0;
194 ENetAddress addr;
195 addr.host = ENET_HOST_ANY;
196 addr.port = ms_port;
198 ms_host = enet_host_create(&addr, NET_MAXCLIENTS, NET_CHANS, 0, 0);
199 if (!ms_host) {
200 d_error("Could not create host on specified port!", 1);
201 return EXIT_FAILURE;
204 atexit(enet_deinitialize);
206 ENetEvent event;
207 int shutdown = 0;
208 enet_uint8 msg = 255;
210 char ip[17];
211 enet_uint16 port = 0;
213 char *name = NULL;
214 char *map = NULL;
215 enet_uint8 gm = 0;
216 enet_uint16 pl = 0;
217 enet_uint16 mpl = 0;
219 enet_uint8 proto = 0;
220 enet_uint8 pw = 0;
221 while (!shutdown) {
222 while (enet_host_service(ms_host, &event, 1) > 0) {
223 switch (event.type) {
224 case ENET_EVENT_TYPE_CONNECT:
225 printf(LC_MS_CONN, event.peer->address.host, event.peer->address.port);
226 break;
227 case ENET_EVENT_TYPE_RECEIVE:
228 if (!event.peer) continue;
229 b_read = 0;
230 msg = b_read_uint8(event.packet->data, &b_read);
232 switch (msg) {
233 case NET_MSG_ADD:
234 if (!event.peer) continue;
236 enet_address_get_host_ip(&(event.peer->address), ip, 17);
237 port = b_read_uint16(event.packet->data, &b_read);
239 name = b_read_dstring(event.packet->data, &b_read);
240 map = b_read_dstring(event.packet->data, &b_read);
241 gm = b_read_uint8(event.packet->data, &b_read);
243 pl = b_read_uint8(event.packet->data, &b_read);
244 mpl = b_read_uint8(event.packet->data, &b_read);
246 proto = b_read_uint8(event.packet->data, &b_read);
247 pw = b_read_uint8(event.packet->data, &b_read);
249 for (int i = 0; i < MS_MAXSRVS; ++i) {
250 if (ms_srv[i].used) {
251 if ((strncmp(ip, ms_srv[i].s_ip, 16) == 0) && (ms_srv[i].s_port == port)) {
252 strncpy(ms_srv[i].s_map, map, 255);
253 strncpy(ms_srv[i].s_name, name, 255);
254 ms_srv[i].s_plrs = pl;
255 ms_srv[i].s_maxplrs = mpl;
256 ms_srv[i].s_pw = pw;
257 ms_srv[i].s_mode = gm;
259 ms_srv[i].ttl = ms_timeout;
261 printf(LC_MS_UPD, i, ip, port, name, map, gm, pl, mpl, proto, pw);
262 break;
264 } else {
265 strncpy(ms_srv[i].s_ip, ip, 16);
266 strncpy(ms_srv[i].s_map, map, 255);
267 strncpy(ms_srv[i].s_name, name, 255);
268 ms_srv[i].s_port = port;
269 ms_srv[i].s_plrs = pl;
270 ms_srv[i].s_maxplrs = mpl;
271 ms_srv[i].s_pw = pw;
272 ms_srv[i].s_mode = gm;
273 ms_srv[i].s_protocol = proto;
274 ms_srv[i].ttl = ms_timeout;
276 ms_srv[i].used = 1;
278 printf(LC_MS_ADD, i, ip, port, name, map, gm, pl, mpl, proto, pw);
280 ++ms_count;
281 break;
284 free(name);
285 free(map);
286 break;
287 case NET_MSG_RM:
288 enet_address_get_host_ip(&(event.peer->address), ip, 17);
289 port = b_read_uint16(event.packet->data, &b_read);
290 for (int i = 0; i < MS_MAXSRVS; ++i) {
291 if (ms_srv[i].used) {
292 if ((strncmp(ip, ms_srv[i].s_ip, 16) == 0) && (ms_srv[i].s_port == port)) {
293 ms_srv[i].used = 0;
294 printf(LC_MS_RM, i, ip, port);
295 --ms_count;
299 break;
300 case NET_MSG_LIST:
301 if (!event.peer) continue;
302 b_write = 0;
303 b_write_uint8(b_send, &b_write, NET_MSG_LIST);
304 b_write_uint8(b_send, &b_write, ms_count);
305 for (int i = 0; i < MS_MAXSRVS; ++i) {
306 if (ms_srv[i].used) b_write_server(b_send, &b_write, ms_srv[i]);
309 ENetPacket *p = enet_packet_create(b_send, b_write, ENET_PACKET_FLAG_RELIABLE);
310 enet_peer_send(event.peer, NET_CH_MAIN, p);
311 enet_host_flush(ms_host);
313 printf(LC_MS_LIST, event.peer->address.host, event.peer->address.port);
314 break;
317 enet_packet_destroy(event.packet);
318 break;
320 default:
321 break;
325 for (int i = 0; i < MS_MAXSRVS; ++i) {
326 if (ms_srv[i].used) {
327 if (--(ms_srv[i].ttl) == 0) {
328 ms_srv[i].used = 0;
329 printf(LC_MS_TIME, i, ms_srv[i].s_ip, ms_srv[i].s_port);
330 --ms_count;
336 printf(LC_MS_DIE);
338 return EXIT_SUCCESS;