X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fmastersrv%2Fmaster.c;h=183d7454a8d2dc3601ddd2e3b2b9a9f1a1936e04;hb=5016bf24701d6c6b10c483a6c122afc0fecb3a9a;hp=e27cde1f9e57815cd012a47b20d5390213a47f4f;hpb=0e578925305a55462c9630370d6f0044728693ef;p=d2df-sdl.git diff --git a/src/mastersrv/master.c b/src/mastersrv/master.c index e27cde1..183d745 100644 --- a/src/mastersrv/master.c +++ b/src/mastersrv/master.c @@ -1,3 +1,18 @@ +/* Copyright (C) Doom 2D: Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License ONLY. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #include #include #include @@ -92,6 +107,7 @@ typedef struct server_s { char map[MAX_STRLEN + 2]; time_t death_time; time_t timestamp; + ENetPeer *peer; // who sent this server in } server_t; // real servers @@ -343,24 +359,32 @@ void b_write_server(enet_buf_t *buf, const server_t *s) { /* server functions */ -static void sv_remove(const enet_uint32 host, const enet_uint16 port) { - for (int i = 0; i < max_servers; ++i) { - if (servers[i].host == host && servers[i].port == port) { - servers[i].host = 0; - servers[i].port = 0; - --num_servers; +static inline void sv_remove(server_t *sv) { + if (sv->host) { + // drop the associated peer, if any + if (sv->peer && sv->peer->state == ENET_PEER_STATE_CONNECTED && sv->peer->data == sv) { + sv->peer->data = NULL; + enet_peer_reset(sv->peer); } + sv->host = 0; + sv->port = 0; + sv->peer = NULL; + --num_servers; + } +} + +static void sv_remove_by_addr(const enet_uint32 host, const enet_uint16 port) { + for (int i = 0; i < max_servers; ++i) { + if (servers[i].host == host && servers[i].port == port) + sv_remove(servers + i); } } static void sv_remove_by_host(enet_uint32 host, enet_uint32 mask) { host &= mask; for (int i = 0; i < max_servers; ++i) { - if (servers[i].host && (servers[i].host & mask) == host) { - servers[i].host = 0; - servers[i].port = 0; - --num_servers; - } + if (servers[i].host && (servers[i].host & mask) == host) + sv_remove(servers + i); } } @@ -398,6 +422,14 @@ static inline server_t *sv_find_or_add(const enet_uint32 host, const enet_uint32 return empty; } +static inline void sv_clear_peer(ENetPeer *peer) { + server_t *sv = peer->data; + if (sv) { + sv->peer = NULL; + peer->data = NULL; + } +} + /* ban list functions */ static inline time_t ban_get_time(const int cnt) { @@ -585,7 +617,7 @@ static void ban_add(const enet_uint32 host, const char *reason) { static inline void ban_peer(ENetPeer *peer, const char *reason) { if (peer) { ban_add(peer->address.host, reason); - peer->data = NULL; + sv_clear_peer(peer); enet_peer_reset(peer); } } @@ -656,6 +688,16 @@ static bool handle_msg(const enet_uint8 msgid, ENetPeer *peer) { // only then update the times sv->death_time = now + ms_sv_timeout; sv->timestamp = now; + // check if we're updating from a new peer + if (sv->peer != peer) { + // if there was an old one, kill it + if (sv->peer) { + sv->peer->data = NULL; + enet_peer_reset(sv->peer); + } + sv->peer = peer; + peer->data = sv; + } u_log(LOG_NOTE, "updated server #%d:", sv - servers); u_printsv(sv); } else { @@ -689,6 +731,8 @@ static bool handle_msg(const enet_uint8 msgid, ENetPeer *peer) { ban_peer(peer, "tripped sanity check"); return true; } + sv->peer = peer; + peer->data = sv; ++num_servers; u_log(LOG_NOTE, "added new server #%d:", sv - servers); u_printsv(sv); @@ -701,7 +745,10 @@ static bool handle_msg(const enet_uint8 msgid, ENetPeer *peer) { ban_peer(peer, "malformed MSG_RM"); return true; } - sv_remove(peer->address.host, tmpsv.port); + sv_remove_by_addr(peer->address.host, tmpsv.port); + // this peer can be disconnected pretty much immediately since he has no servers left, tell him to fuck off + sv_clear_peer(peer); + enet_peer_disconnect_later(peer, 0); return true; case NET_MSG_LIST: @@ -749,6 +796,10 @@ static bool handle_msg(const enet_uint8 msgid, ENetPeer *peer) { enet_peer_send(peer, NET_CH_MAIN, p); // enet_host_flush(ms_host); + // this peer can be disconnected pretty much immediately after receiving the server list, tell him to fuck off + sv_clear_peer(peer); + enet_peer_disconnect_later(peer, 0); + u_log(LOG_NOTE, "sent server list to %s:%d (ver %s)", u_iptostr(peer->address.host), peer->address.port, clientver[0] ? clientver : ""); return true; @@ -879,7 +930,7 @@ int main(int argc, char **argv) { ENetAddress addr; addr.host = 0; addr.port = ms_port; - ms_host = enet_host_create(&addr, MS_MAX_CLIENTS, NET_CH_COUNT, 0, 0); + ms_host = enet_host_create(&addr, MS_MAX_CLIENTS, NET_CH_COUNT + 1, 0, 0); if (!ms_host) u_fatal("could not create enet host on port %d", ms_port); @@ -891,12 +942,7 @@ int main(int argc, char **argv) { while (running) { while (enet_host_service(ms_host, &event, 10) > 0) { const time_t now = time(NULL); - bool filtered = !event.peer || (ms_spam_cap && spam_filter(event.peer, now)); - if (!filtered && event.peer->data) { - // kick people that have overstayed their welcome - const time_t timeout = (time_t)(intptr_t)event.peer->data; - if (timeout < now) filtered = true; - } + const bool filtered = !event.peer || (ms_spam_cap && spam_filter(event.peer, now)); if (!filtered) { switch (event.type) { @@ -904,8 +950,8 @@ int main(int argc, char **argv) { u_log(LOG_NOTE, "%s:%d connected", u_iptostr(event.peer->address.host), event.peer->address.port); if (event.peer->channelCount != NET_CH_COUNT) ban_peer(event.peer, "what is this"); - else // store timeout in the data field - event.peer->data = (void *)(intptr_t)(now + ms_cl_timeout); + else + enet_peer_timeout(event.peer, 0, 0, ms_cl_timeout * 1000); break; case ENET_EVENT_TYPE_RECEIVE: @@ -927,7 +973,8 @@ int main(int argc, char **argv) { break; case ENET_EVENT_TYPE_DISCONNECT: - event.peer->data = NULL; + + // u_log(LOG_NOTE, "%s:%d disconnected", u_iptostr(event.peer->address.host), event.peer->address.port); break; default: @@ -935,7 +982,7 @@ int main(int argc, char **argv) { } } else if (event.peer) { // u_log(LOG_WARN, "filtered event %d from %s", event.type, u_iptostr(event.peer->address.host)); - event.peer->data = NULL; + sv_clear_peer(event.peer); enet_peer_reset(event.peer); } @@ -946,14 +993,12 @@ int main(int argc, char **argv) { } const time_t now = time(NULL); + + // time out servers for (int i = 0; i < max_servers; ++i) { - if (servers[i].host) { - if (servers[i].death_time <= now) { - u_log(LOG_NOTE, "server #%d %s:%d timed out", i, u_iptostr(servers[i].host), servers[i].port); - servers[i].host = 0; - servers[i].port = 0; - --num_servers; - } + if (servers[i].host && servers[i].death_time <= now) { + u_log(LOG_NOTE, "server #%d %s:%d timed out", i, u_iptostr(servers[i].host), servers[i].port); + sv_remove(servers + i); } } }