diff --git a/src/mastersrv/master.c b/src/mastersrv/master.c
index b344dac83894c7855f7b0dde3b25b40535fc2290..ca1c129895cb851f83c68d026288706b462bf011 100644 (file)
--- a/src/mastersrv/master.c
+++ b/src/mastersrv/master.c
#include <string.h>
#include <enet/enet.h>
#include <enet/types.h>
+#include <time.h>
-#define MS_VERSION "0.1"
-#define MS_MAXSRVS 32
+#define MS_VERSION "0.2"
+#define MS_MAXSRVS 128
#define MS_TIMEOUT 100
#define NET_CHANS 2
#define LC_MS_UPD "\nUpdated server #%d (%s:%d):\n%s\n%s (%d)\n%d/%d plrs\nproto: %d pw?: %d\n"
#define LC_MS_RM "\nRemoved server #%d (%s:%d) by request.\n"
#define LC_MS_TIME "\nServer #%d (%s:%d) timed out.\n"
-#define LC_MS_LIST "\nSent server list to %x:%u.\n"
+#define LC_MS_LIST "\nSent server list to %x:%u (ver. %s).\n"
#define LC_MS_DIE "\nD2DF master server shutting down...\n"
#define LC_MS_CONN "\nIncoming connection from %x:%u...\n"
+#define LC_MS_MOTD "\nMOTD: %s\n"
+#define LC_MS_URGENT "\nURGENT: %s\n"
+#define MS_URGENT_FILE "urgent.txt"
+#define MS_MOTD_FILE "motd.txt"
struct ms_server_s {
enet_uint8 used;
enet_uint8 s_mode;
enet_uint8 s_protocol;
enet_uint16 s_port;
- enet_uint32 ttl;
+ time_t deathtime;
};
typedef struct ms_server_s ms_server;
const char ms_game_ver[] = "0.63";
+char ms_motd[255] = "";
+char ms_urgent[255] = "";
+
int ms_port = 25660;
-int ms_timeout = 100000;
+int ms_timeout = 100;
size_t b_read = 0;
size_t b_write = 0;
ms_server ms_srv[MS_MAXSRVS];
enet_uint8 ms_count = 0;
+// fake servers to show on old versions of the game
+static const ms_server ms_fake_srv[] = {
+ {
+ .used = 1,
+ .s_ip = "0.0.0.0",
+ .s_name = "! \xc2\xc0\xd8\xc0 \xca\xce\xcf\xc8\xdf \xc8\xc3\xd0\xdb "
+ "\xd3\xd1\xd2\xc0\xd0\xc5\xcb\xc0! "
+ "\xd1\xca\xc0\xd7\xc0\xc9\xd2\xc5 \xcd\xce\xc2\xd3\xde C "
+ "doom2d.org !",
+ .s_map = "! Your game is outdated. "
+ "Get latest version at doom2d.org !",
+ .s_protocol = 255,
+ },
+ {
+ .used = 1,
+ .s_ip = "0.0.0.0",
+ .s_name = "! \xcf\xd0\xce\xc1\xd0\xce\xd1\xdcTE \xcf\xce\xd0\xd2\xdb "
+ "25666 \xc8 57133 HA CEPBEPE \xcf\xc5\xd0\xc5\xc4 \xc8\xc3\xd0\xce\xc9 !",
+ .s_map = "! Forward ports 25666 and 57133 before hosting !",
+ .s_protocol = 255,
+ },
+};
+
+#define MS_FAKESRVS (sizeof(ms_fake_srv) / sizeof(ms_fake_srv[0]))
void i_usage () {
printf("Usage: d2df_master -p port_number [-t timeout_seconds]\n");
ms_port = atoi(argv[++i]);
}
} else if (!strcmp(argv[i], "-t") & (i + 1 < argc)) {
- ms_timeout = atoi(argv[++i]) * 1000;
+ ms_timeout = atoi(argv[++i]);
+ }
+ }
+}
+
+
+int d_readtextfile (const char *fname, char *buf, size_t max) {
+ FILE *f = fopen(fname, "r");
+ char *const end = buf + max - 1;
+ char *p = buf;
+ if (f) {
+ char ln[max];
+ char *const lend = ln + max - 1;
+ while(p < end && fgets(ln, sizeof(ln), f)) {
+ for (char *n = ln; n < lend && *n && *n != '\r' && *n != '\n'; ++n) {
+ *(p++) = *n;
+ if (p == end) break;
+ }
}
+ *p = '\0';
+ fclose(f);
+ return 0;
}
+ return 1;
}
-enet_uint8 b_read_uint8 (enet_uint8 buf[], size_t *pos) {
+enet_uint8 b_read_uint8 (enet_uint8 buf[], size_t *pos) {
return buf[(*pos)++];
}
printf(LC_MS_INIT, ms_port);
+ d_readtextfile(MS_MOTD_FILE, ms_motd, sizeof(ms_motd));
+ d_readtextfile(MS_URGENT_FILE, ms_urgent, sizeof(ms_urgent));
+
+ if (ms_motd[0]) printf(LC_MS_MOTD, ms_motd);
+ if (ms_urgent[0]) printf(LC_MS_URGENT, ms_urgent);
+
for (int i = 0; i < NET_MAXCLIENTS; ++i) ms_peers[i] = NULL;
for (int i = 0; i < MS_MAXSRVS; ++i) {
ms_srv[i].s_ip[0] = '\0';
ms_srv[i].s_name[0] = '\0';
ms_srv[i].s_map[0] = '\0';
- ms_srv[i].ttl = 0;
+ ms_srv[i].deathtime = 0;
}
ENetAddress addr;
char *name = NULL;
char *map = NULL;
+ char *clientver = NULL;
enet_uint8 gm = 0;
enet_uint16 pl = 0;
enet_uint16 mpl = 0;
enet_uint8 proto = 0;
enet_uint8 pw = 0;
while (!shutdown) {
- while (enet_host_service(ms_host, &event, 1) > 0) {
+ while (enet_host_service(ms_host, &event, 5000) > 0) {
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT:
printf(LC_MS_CONN, event.peer->address.host, event.peer->address.port);
for (int i = 0; i < MS_MAXSRVS; ++i) {
if (ms_srv[i].used) {
if ((strncmp(ip, ms_srv[i].s_ip, 16) == 0) && (ms_srv[i].s_port == port)) {
- strncpy(ms_srv[i].s_map, map, 255);
- strncpy(ms_srv[i].s_name, name, 255);
+ strncpy(ms_srv[i].s_map, map, sizeof(ms_srv[i].s_map));
+ strncpy(ms_srv[i].s_name, name, sizeof(ms_srv[i].s_name));
ms_srv[i].s_plrs = pl;
ms_srv[i].s_maxplrs = mpl;
ms_srv[i].s_pw = pw;
ms_srv[i].s_mode = gm;
- ms_srv[i].ttl = ms_timeout;
+ ms_srv[i].deathtime = time(NULL) + ms_timeout;
printf(LC_MS_UPD, i, ip, port, name, map, gm, pl, mpl, proto, pw);
break;
}
} else {
- strncpy(ms_srv[i].s_ip, ip, 16);
- strncpy(ms_srv[i].s_map, map, 255);
- strncpy(ms_srv[i].s_name, name, 255);
+ strncpy(ms_srv[i].s_ip, ip, sizeof(ms_srv[i].s_ip));
+ strncpy(ms_srv[i].s_map, map, sizeof(ms_srv[i].s_map));
+ strncpy(ms_srv[i].s_name, name, sizeof(ms_srv[i].s_name));
ms_srv[i].s_port = port;
ms_srv[i].s_plrs = pl;
ms_srv[i].s_maxplrs = mpl;
ms_srv[i].s_pw = pw;
ms_srv[i].s_mode = gm;
ms_srv[i].s_protocol = proto;
- ms_srv[i].ttl = ms_timeout;
+ ms_srv[i].deathtime = time(NULL) + ms_timeout;
ms_srv[i].used = 1;
break;
case NET_MSG_LIST:
if (!event.peer) continue;
+
b_write = 0;
b_write_uint8(b_send, &b_write, NET_MSG_LIST);
- b_write_uint8(b_send, &b_write, ms_count);
+
+ if (event.packet->dataLength > 2) {
+ // holy shit a fresh client
+ clientver = b_read_dstring(event.packet->data, &b_read);
+ b_write_uint8(b_send, &b_write, ms_count);
+ } else {
+ // old client, feed them bullshit first
+ b_write_uint8(b_send, &b_write, ms_count + 2);
+ for (int i = 0; i < MS_FAKESRVS; ++i)
+ b_write_server(b_send, &b_write, ms_fake_srv[i]);
+ }
+
for (int i = 0; i < MS_MAXSRVS; ++i) {
if (ms_srv[i].used) b_write_server(b_send, &b_write, ms_srv[i]);
}
+ if (clientver) {
+ // TODO: check if this client is outdated (?) and send back new verstring
+ // for now just write the same shit back
+ b_write_dstring(b_send, &b_write, clientver);
+ // write the motd and urgent message
+ b_write_dstring(b_send, &b_write, ms_motd);
+ b_write_dstring(b_send, &b_write, ms_urgent);
+ }
+
ENetPacket *p = enet_packet_create(b_send, b_write, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(event.peer, NET_CH_MAIN, p);
enet_host_flush(ms_host);
- printf(LC_MS_LIST, event.peer->address.host, event.peer->address.port);
+ printf(LC_MS_LIST, event.peer->address.host, event.peer->address.port, clientver ? clientver : "<old>");
+ free(clientver);
+ clientver = NULL;
break;
}
}
}
+ time_t now = time(NULL);
for (int i = 0; i < MS_MAXSRVS; ++i) {
if (ms_srv[i].used) {
- if (--(ms_srv[i].ttl) == 0) {
+ if (ms_srv[i].deathtime <= now) {
ms_srv[i].used = 0;
printf(LC_MS_TIME, i, ms_srv[i].s_ip, ms_srv[i].s_port);
--ms_count;