5 #include <enet/types.h>
8 #define MS_VERSION "0.2"
10 #define MS_TIMEOUT 100
15 #define NET_MAXCLIENTS 64
17 #define NET_BUFSIZE 65536
19 #define NET_MSG_ADD 200
20 #define NET_MSG_RM 201
21 #define NET_MSG_LIST 202
23 #define LC_MS_INIT "D2DF master server starting on port %d...\n"
24 #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"
25 #define LC_MS_UPD "\nUpdated server #%d (%s:%d):\n%s\n%s (%d)\n%d/%d plrs\nproto: %d pw?: %d\n"
26 #define LC_MS_RM "\nRemoved server #%d (%s:%d) by request.\n"
27 #define LC_MS_TIME "\nServer #%d (%s:%d) timed out.\n"
28 #define LC_MS_LIST "\nSent server list to %x:%u (ver. %s).\n"
29 #define LC_MS_DIE "\nD2DF master server shutting down...\n"
30 #define LC_MS_CONN "\nIncoming connection from %x:%u...\n"
31 #define LC_MS_MOTD "\nMOTD: %s\n"
32 #define LC_MS_URGENT "\nURGENT: %s\n"
34 #define MS_URGENT_FILE "urgent.txt"
35 #define MS_MOTD_FILE "motd.txt"
46 enet_uint8 s_protocol
;
51 typedef struct ms_server_s ms_server
;
53 const char ms_game_ver
[] = "0.63";
54 char ms_motd
[255] = "";
55 char ms_urgent
[255] = "";
63 enet_uint8 b_send
[NET_BUFSIZE
];
65 ENetHost
*ms_host
= NULL
;
66 ENetPeer
*ms_peers
[NET_MAXCLIENTS
];
67 ms_server ms_srv
[MS_MAXSRVS
];
68 enet_uint8 ms_count
= 0;
70 // fake servers to show on old versions of the game
71 static const ms_server ms_fake_srv
[] = {
75 .s_name
= "! \xc2\xc0\xd8\xc0 \xca\xce\xcf\xc8\xdf \xc8\xc3\xd0\xdb "
76 "\xd3\xd1\xd2\xc0\xd0\xc5\xcb\xc0! "
77 "\xd1\xca\xc0\xd7\xc0\xc9\xd2\xc5 \xcd\xce\xc2\xd3\xde C "
79 .s_map
= "! Your game is outdated. "
80 "Get latest version at doom2d.org !",
86 .s_name
= "! \xcf\xd0\xce\xc1\xd0\xce\xd1\xdcTE \xcf\xce\xd0\xd2\xdb "
87 "25666 \xc8 57133 HA CEPBEPE \xcf\xc5\xd0\xc5\xc4 \xc8\xc3\xd0\xce\xc9 !",
88 .s_map
= "! Forward ports 25666 and 57133 before hosting !",
93 #define MS_FAKESRVS (sizeof(ms_fake_srv) / sizeof(ms_fake_srv[0]))
96 printf("Usage: d2df_master -p port_number [-t timeout_seconds]\n");
102 printf("Doom 2D Forever master server v%s\n", MS_VERSION
);
107 void d_error (const char *msg
, int fatal
) {
109 fprintf(stderr
, "FATAL ERROR: %s\n", msg
);
112 fprintf(stderr
, "ERROR: %s\n", msg
);
117 void d_getargs (int argc
, char *argv
[]) {
124 for (int i
= 1; i
< argc
; ++i
) {
125 if (!strcmp(argv
[i
], "-v")) {
129 } else if (!strcmp(argv
[i
], "-p")) {
131 d_error("Specify a port value!", 1);
134 ms_port
= atoi(argv
[++i
]);
136 } else if (!strcmp(argv
[i
], "-t") & (i
+ 1 < argc
)) {
137 ms_timeout
= atoi(argv
[++i
]);
143 int d_readtextfile (const char *fname
, char *buf
, size_t max
) {
144 FILE *f
= fopen(fname
, "r");
145 char *const end
= buf
+ max
- 1;
149 char *const lend
= ln
+ max
- 1;
150 while(p
< end
&& fgets(ln
, sizeof(ln
), f
)) {
151 for (char *n
= ln
; n
< lend
&& *n
&& *n
!= '\r' && *n
!= '\n'; ++n
) {
164 enet_uint8
b_read_uint8 (enet_uint8 buf
[], size_t *pos
) {
165 return buf
[(*pos
)++];
169 enet_uint16
b_read_uint16 (enet_uint8 buf
[], size_t *pos
) {
172 ret
= *(enet_uint16
*)(buf
+ *pos
);
173 *pos
+= sizeof(enet_uint16
);
179 char* b_read_dstring (enet_uint8 buf
[], size_t *pos
) {
182 size_t len
= b_read_uint8(buf
, pos
);
184 ret
= malloc(len
+ 1);
186 memmove(ret
, (char*)(buf
+ *pos
), len
);
194 void b_write_uint8 (enet_uint8 buf
[], size_t *pos
, enet_uint8 val
) {
199 void b_write_uint16 (enet_uint8 buf
[], size_t *pos
, enet_uint16 val
) {
200 *(enet_uint16
*)(buf
+ *pos
) = val
;
201 *pos
+= sizeof(enet_uint16
);
205 void b_write_dstring (enet_uint8 buf
[], size_t *pos
, const char* val
) {
206 enet_uint8 len
= strlen(val
);
207 b_write_uint8(buf
, pos
, len
);
209 memmove((char*)(buf
+ *pos
), val
, len
);
214 void b_write_server (enet_uint8 buf
[], size_t *pos
, ms_server s
) {
215 b_write_dstring(b_send
, pos
, s
.s_ip
);
216 b_write_uint16 (b_send
, pos
, s
.s_port
);
217 b_write_dstring(b_send
, pos
, s
.s_name
);
218 b_write_dstring(b_send
, pos
, s
.s_map
);
219 b_write_uint8 (b_send
, pos
, s
.s_mode
);
220 b_write_uint8 (b_send
, pos
, s
.s_plrs
);
221 b_write_uint8 (b_send
, pos
, s
.s_maxplrs
);
222 b_write_uint8 (b_send
, pos
, s
.s_protocol
);
223 b_write_uint8 (b_send
, pos
, s
.s_pw
);
227 int main (int argc
, char *argv
[]) {
228 d_getargs(argc
, argv
);
230 if (enet_initialize()) {
231 d_error("Could not init ENet!", 1);
235 printf(LC_MS_INIT
, ms_port
);
237 d_readtextfile(MS_MOTD_FILE
, ms_motd
, sizeof(ms_motd
));
238 d_readtextfile(MS_URGENT_FILE
, ms_urgent
, sizeof(ms_urgent
));
240 if (ms_motd
[0]) printf(LC_MS_MOTD
, ms_motd
);
241 if (ms_urgent
[0]) printf(LC_MS_URGENT
, ms_urgent
);
243 for (int i
= 0; i
< NET_MAXCLIENTS
; ++i
) ms_peers
[i
] = NULL
;
245 for (int i
= 0; i
< MS_MAXSRVS
; ++i
) {
247 ms_srv
[i
].s_ip
[0] = '\0';
248 ms_srv
[i
].s_name
[0] = '\0';
249 ms_srv
[i
].s_map
[0] = '\0';
250 ms_srv
[i
].deathtime
= 0;
254 addr
.host
= ENET_HOST_ANY
;
257 ms_host
= enet_host_create(&addr
, NET_MAXCLIENTS
, NET_CHANS
, 0, 0);
259 d_error("Could not create host on specified port!", 1);
263 atexit(enet_deinitialize
);
267 enet_uint8 msg
= 255;
270 enet_uint16 port
= 0;
274 char *clientver
= NULL
;
279 enet_uint8 proto
= 0;
282 while (enet_host_service(ms_host
, &event
, 5000) > 0) {
283 switch (event
.type
) {
284 case ENET_EVENT_TYPE_CONNECT
:
285 printf(LC_MS_CONN
, event
.peer
->address
.host
, event
.peer
->address
.port
);
287 case ENET_EVENT_TYPE_RECEIVE
:
288 if (!event
.peer
) continue;
290 msg
= b_read_uint8(event
.packet
->data
, &b_read
);
294 if (!event
.peer
) continue;
296 enet_address_get_host_ip(&(event
.peer
->address
), ip
, 17);
297 port
= b_read_uint16(event
.packet
->data
, &b_read
);
299 name
= b_read_dstring(event
.packet
->data
, &b_read
);
300 map
= b_read_dstring(event
.packet
->data
, &b_read
);
301 gm
= b_read_uint8(event
.packet
->data
, &b_read
);
303 pl
= b_read_uint8(event
.packet
->data
, &b_read
);
304 mpl
= b_read_uint8(event
.packet
->data
, &b_read
);
306 proto
= b_read_uint8(event
.packet
->data
, &b_read
);
307 pw
= b_read_uint8(event
.packet
->data
, &b_read
);
309 for (int i
= 0; i
< MS_MAXSRVS
; ++i
) {
310 if (ms_srv
[i
].used
) {
311 if ((strncmp(ip
, ms_srv
[i
].s_ip
, 16) == 0) && (ms_srv
[i
].s_port
== port
)) {
312 strncpy(ms_srv
[i
].s_map
, map
, sizeof(ms_srv
[i
].s_map
));
313 strncpy(ms_srv
[i
].s_name
, name
, sizeof(ms_srv
[i
].s_name
));
314 ms_srv
[i
].s_plrs
= pl
;
315 ms_srv
[i
].s_maxplrs
= mpl
;
317 ms_srv
[i
].s_mode
= gm
;
319 ms_srv
[i
].deathtime
= time(NULL
) + ms_timeout
;
321 printf(LC_MS_UPD
, i
, ip
, port
, name
, map
, gm
, pl
, mpl
, proto
, pw
);
325 strncpy(ms_srv
[i
].s_ip
, ip
, sizeof(ms_srv
[i
].s_ip
));
326 strncpy(ms_srv
[i
].s_map
, map
, sizeof(ms_srv
[i
].s_map
));
327 strncpy(ms_srv
[i
].s_name
, name
, sizeof(ms_srv
[i
].s_name
));
328 ms_srv
[i
].s_port
= port
;
329 ms_srv
[i
].s_plrs
= pl
;
330 ms_srv
[i
].s_maxplrs
= mpl
;
332 ms_srv
[i
].s_mode
= gm
;
333 ms_srv
[i
].s_protocol
= proto
;
334 ms_srv
[i
].deathtime
= time(NULL
) + ms_timeout
;
338 printf(LC_MS_ADD
, i
, ip
, port
, name
, map
, gm
, pl
, mpl
, proto
, pw
);
348 enet_address_get_host_ip(&(event
.peer
->address
), ip
, 17);
349 port
= b_read_uint16(event
.packet
->data
, &b_read
);
350 for (int i
= 0; i
< MS_MAXSRVS
; ++i
) {
351 if (ms_srv
[i
].used
) {
352 if ((strncmp(ip
, ms_srv
[i
].s_ip
, 16) == 0) && (ms_srv
[i
].s_port
== port
)) {
354 printf(LC_MS_RM
, i
, ip
, port
);
361 if (!event
.peer
) continue;
364 b_write_uint8(b_send
, &b_write
, NET_MSG_LIST
);
366 if (event
.packet
->dataLength
> 2) {
367 // holy shit a fresh client
368 clientver
= b_read_dstring(event
.packet
->data
, &b_read
);
369 b_write_uint8(b_send
, &b_write
, ms_count
);
371 // old client, feed them bullshit first
372 b_write_uint8(b_send
, &b_write
, ms_count
+ 2);
373 for (int i
= 0; i
< MS_FAKESRVS
; ++i
)
374 b_write_server(b_send
, &b_write
, ms_fake_srv
[i
]);
377 for (int i
= 0; i
< MS_MAXSRVS
; ++i
) {
378 if (ms_srv
[i
].used
) b_write_server(b_send
, &b_write
, ms_srv
[i
]);
382 // TODO: check if this client is outdated (?) and send back new verstring
383 // for now just write the same shit back
384 b_write_dstring(b_send
, &b_write
, clientver
);
385 // write the motd and urgent message
386 b_write_dstring(b_send
, &b_write
, ms_motd
);
387 b_write_dstring(b_send
, &b_write
, ms_urgent
);
390 ENetPacket
*p
= enet_packet_create(b_send
, b_write
, ENET_PACKET_FLAG_RELIABLE
);
391 enet_peer_send(event
.peer
, NET_CH_MAIN
, p
);
392 enet_host_flush(ms_host
);
394 printf(LC_MS_LIST
, event
.peer
->address
.host
, event
.peer
->address
.port
, clientver
? clientver
: "<old>");
400 enet_packet_destroy(event
.packet
);
408 time_t now
= time(NULL
);
409 for (int i
= 0; i
< MS_MAXSRVS
; ++i
) {
410 if (ms_srv
[i
].used
) {
411 if (ms_srv
[i
].deathtime
<= now
) {
413 printf(LC_MS_TIME
, i
, ms_srv
[i
].s_ip
, ms_srv
[i
].s_port
);