From e06b88411d56b76522f5796356a65c91f26da609 Mon Sep 17 00:00:00 2001 From: gumi Date: Thu, 5 Apr 2018 20:48:38 -0400 Subject: make sessions expire after 5 minutes of being unreachable --- src/net/socket.cpp | 35 ++++++++++++++++++++++++++++------- src/net/socket.hpp | 14 +++++++++++--- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/net/socket.cpp b/src/net/socket.cpp index 7f71310..786f085 100644 --- a/src/net/socket.cpp +++ b/src/net/socket.cpp @@ -34,6 +34,10 @@ #include "../io/cxxstdio.hpp" +#include "../proto2/map-user.hpp" + +#include "../wire/packets.hpp" + #include "timer.hpp" #include "../poison.hpp" @@ -59,8 +63,8 @@ DIAG_POP(); Session::Session(SessionIO io, SessionParsers p) : created() +, last_tick() , connected() -, eof() , timed_close() , rdata(), wdata() , max_rdata(), max_wdata() @@ -75,6 +79,8 @@ Session::Session(SessionIO io, SessionParsers p) , session_data() , fd() { + flag.eof = 0; + flag.server = 0; set_io(io); set_parsers(p); } @@ -143,6 +149,7 @@ void recv_to_fifo(Session *s) { s->rdata_size += len; s->connected = 1; + s->last_tick = TimeT::now(); } else { @@ -164,6 +171,7 @@ void send_from_fifo(Session *s) s->wdata_size); } s->connected = 1; + s->last_tick = TimeT::now(); } else { @@ -295,6 +303,7 @@ Session *make_listen_port(uint16_t port, SessionParsers inferior) s->created = TimeT::now(); s->connected = 1; + s->set_server(); return s; } @@ -351,6 +360,7 @@ Session *make_connection(IP4Address ip, uint16_t port, SessionParsers parsers) s->max_wdata = WFIFO_SIZE; s->created = TimeT::now(); s->connected = 1; + s->set_server(); return s; } @@ -433,13 +443,13 @@ bool do_sendrecv(interval_t next_ms) Session *s = get_session(i); if (!s) continue; - if (wfd.isset(i) && !s->eof) + if (wfd.isset(i) && s->flag.eof != 1) { if (s->func_send) //send_from_fifo(i); s->func_send(s); } - if (rfd.isset(i) && !s->eof) + if (rfd.isset(i) && s->flag.eof != 1) { if (s->func_recv) //recv_to_fifo(i); @@ -457,13 +467,24 @@ bool do_parsepacket(void) Session *s = get_session(i); if (!s) continue; - if (!s->connected - && static_cast(TimeT::now()) - static_cast(s->created) > CONNECT_TIMEOUT) + if (s->connected && s->flag.server != 1 + && static_cast(TimeT::now()) - static_cast(s->last_tick) > STALL_TIMEOUT / 2) + { + // send a keepalive packet + Packet_Fixed<0x007f> fixed_7f; + fixed_7f.tick = gettick(); + send_fpacket<0x007f, 6>(s, fixed_7f); + // if this fails it will auto-eof + } + if ((!s->connected + && static_cast(TimeT::now()) - static_cast(s->created) > CONNECT_TIMEOUT) || + (s->connected && s->flag.server != 1 + && static_cast(TimeT::now()) - static_cast(s->last_tick) > STALL_TIMEOUT)) { PRINTF("Session #%d timed out\n"_fmt, s); s->set_eof(); } - if (s->rdata_size && !s->eof && s->func_parse) + if (s->rdata_size && s->flag.eof != 1 && s->func_parse) { s->func_parse(s); /// some func_parse may call delete_session @@ -472,7 +493,7 @@ bool do_parsepacket(void) if (!s) continue; } - if (s->eof) + if (s->flag.eof == 1) { delete_session(s); continue; diff --git a/src/net/socket.hpp b/src/net/socket.hpp index d6caefd..6115d70 100644 --- a/src/net/socket.hpp +++ b/src/net/socket.hpp @@ -78,12 +78,17 @@ struct Session /// Checks whether a newly-connected socket actually does anything TimeT created; bool connected; + TimeT last_tick; private: - /// Flag needed since structure must be freed in a server-dependent manner - bool eof; + struct { + unsigned char eof : 1; /// Flag needed since structure must be freed in a server-dependent manner + unsigned char server : 1; + } flag; + public: - void set_eof() { eof = true; } + void set_eof() { flag.eof = 1; } + void set_server() { flag.server = 1; } /// Currently used by clif_setwaitclose Timer timed_close; @@ -141,6 +146,9 @@ constexpr int SOFT_LIMIT = FD_SETSIZE - 50; // socket timeout to establish a full connection in seconds constexpr int CONNECT_TIMEOUT = 15; +// socket timeout (no activity at all) in seconds +// the server will try to contact the session halfway through +constexpr int STALL_TIMEOUT = 300; // 5 minutes void set_session(io::FD fd, std::unique_ptr sess); Session *get_session(io::FD fd); -- cgit v1.2.3-70-g09d2