From ae7b06ff8ad775a945bd677effd72b7fafa13d8d Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Thu, 17 Apr 2014 16:10:11 -0700 Subject: Die sensibly, take 1 --- src/char/char.cpp | 81 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 31 deletions(-) (limited to 'src/char') diff --git a/src/char/char.cpp b/src/char/char.cpp index d7849af..7eb446a 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -185,6 +185,40 @@ TimeT update_online; // to update online files when we receiving infor static pid_t pid = 0; // For forked DB writes +static +void create_online_files(void); + +static +void on_delete(Session *sess) +{ + if (sess == login_session) + { + PRINTF("Char-server can't connect to login-server (connection #%d).\n", + sess); + login_session = nullptr; + } + else + { + auto it = std::find(server_session.begin(), server_session.end(), sess); + if (it != server_session.end()) + { + int id = it - server_session.begin(); + PRINTF("Map-server %d (session #%d) has disconnected.\n", id, + sess); + server[id] = mmo_map_server{}; + server_session[id] = nullptr; + for (Session *& oci : online_chars) + if (oci == sess) + oci = nullptr; + create_online_files(); // update online players files (to remove all online players of this server) + } + else + { + // normal player session + } + } +} + //------------------------------ // Writing function of logs file //------------------------------ @@ -1077,7 +1111,7 @@ int disconnect_player(int accound_id) { if (sd->account_id == accound_id) { - get_session(i)->eof = 1; + get_session(i)->set_eof(); return 1; } } @@ -1116,15 +1150,9 @@ void parse_tologin(Session *ls) { // only login-server can have an access to here. // so, if it isn't the login-server, we disconnect the session (fd != login_fd). - if (ls != login_session || ls->eof) + if (ls != login_session) { - if (ls == login_session) - { - PRINTF("Char-server can't connect to login-server (connection #%d).\n", - ls); - login_session = nullptr; - } - delete_session(ls); + ls->set_eof(); return; } @@ -1520,7 +1548,7 @@ void parse_tologin(Session *ls) break; default: - ls->eof = 1; + ls->set_eof(); return; } } @@ -1546,7 +1574,7 @@ void map_anti_freeze_system(TimerData *, tick_t) i); CHAR_LOG("Map-server anti-freeze system: char-server #%d is freezed -> disconnection.\n", i); - server_session[i]->eof = 1; + server_session[i]->set_eof(); } } } @@ -1559,20 +1587,9 @@ void parse_frommap(Session *ms) for (id = 0; id < MAX_MAP_SERVERS; id++) if (server_session[id] == ms) break; - if (id == MAX_MAP_SERVERS || ms->eof) + if (id == MAX_MAP_SERVERS) { - if (id < MAX_MAP_SERVERS) - { - PRINTF("Map-server %d (session #%d) has disconnected.\n", id, - ms); - server[id] = mmo_map_server{}; - server_session[id] = nullptr; - for (Session *& oci : online_chars) - if (oci == ms) - oci = nullptr; - create_online_files(); // update online players files (to remove all online players of this server) - } - delete_session(ms); + ms->set_eof(); return; } @@ -2057,7 +2074,7 @@ void parse_frommap(Session *ms) // inter server処理でもない場合は切断 PRINTF("char: unknown packet 0x%04x (%zu bytes to read in buffer)! (from map).\n", RFIFOW(ms, 0), RFIFOREST(ms)); - ms->eof = 1; + ms->set_eof(); return; } } @@ -2177,11 +2194,13 @@ void parse_char(Session *s) { IP4Address ip = s->client_ip; - if (!login_session || s->eof) - { // disconnect any player (already connected to char-server or coming back from map-server) if login-server is diconnected. + if (!login_session) + { + s->set_eof(); + + // I sure *hope* this doesn't happen ... if (s == login_session) login_session = nullptr; - delete_session(s); return; } @@ -2493,11 +2512,11 @@ void parse_char(Session *s) return; case 0x7532: // 接続の切断(defaultと処理は一緒だが明示的にするため) - s->eof = 1; + s->set_eof(); return; default: - s->eof = 1; + s->set_eof(); return; } } @@ -2906,7 +2925,7 @@ int do_init(Slice argv) create_online_files(); // update online players files at start of the server // set_termfunc (do_final); - set_defaultparse(parse_char); + set_defaultparse(parse_char, on_delete); char_session = make_listen_port(char_port); -- cgit v1.2.3-70-g09d2 From b0d3b261f454e921f90a3a2c748731d3379e2db7 Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Fri, 18 Apr 2014 08:38:18 -0700 Subject: Die sensibly, take 2 --- src/admin/ladmin.cpp | 7 ++--- src/char/char.cpp | 63 +++++++++++++++++++---------------------- src/login/login.cpp | 39 ++++++++++++------------- src/map/chrif.cpp | 13 +++++++-- src/map/clif.cpp | 36 +++++++++-------------- src/mmo/socket.cpp | 80 ++++++++++++++++++++++------------------------------ src/mmo/socket.hpp | 43 ++++++++++++++++++++-------- 7 files changed, 140 insertions(+), 141 deletions(-) (limited to 'src/char') diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp index 0d53ff4..9bbd710 100644 --- a/src/admin/ladmin.cpp +++ b/src/admin/ladmin.cpp @@ -286,7 +286,7 @@ void ladmin_log(XString line) } static -void on_delete(Session *) +void delete_fromlogin(Session *) { { PRINTF("Impossible to have a connection with the login-server [%s:%d] !\n", @@ -2785,7 +2785,8 @@ int Connect_login_server(void) Iprintf("Attempt to connect to login-server...\n"); LADMIN_LOG("Attempt to connect to login-server...\n"); - login_session = make_connection(login_ip, login_port); + login_session = make_connection(login_ip, login_port, SessionParsers{func_parse: parse_fromlogin, func_delete: delete_fromlogin}); + if (!login_session) return 0; @@ -2904,8 +2905,6 @@ int do_init(Slice argv) LADMIN_LOG(""); LADMIN_LOG("Configuration file readed.\n"); - set_defaultparse(parse_fromlogin, on_delete); - Iprintf("EAthena login-server administration tool.\n"); Version version = CURRENT_LOGIN_SERVER_VERSION; Iprintf("for tmwA version %hhu.%hhu.%hhu (dev? %hhu) (flags %hhx) (which %hhx) (vend %hu)\n", diff --git a/src/char/char.cpp b/src/char/char.cpp index 7eb446a..8a3397d 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -189,34 +189,32 @@ static void create_online_files(void); static -void on_delete(Session *sess) +void delete_tologin(Session *sess) { - if (sess == login_session) - { - PRINTF("Char-server can't connect to login-server (connection #%d).\n", - sess); - login_session = nullptr; - } - else - { - auto it = std::find(server_session.begin(), server_session.end(), sess); - if (it != server_session.end()) - { - int id = it - server_session.begin(); - PRINTF("Map-server %d (session #%d) has disconnected.\n", id, - sess); - server[id] = mmo_map_server{}; - server_session[id] = nullptr; - for (Session *& oci : online_chars) - if (oci == sess) - oci = nullptr; - create_online_files(); // update online players files (to remove all online players of this server) - } - else - { - // normal player session - } - } + assert (sess == login_session); + PRINTF("Char-server can't connect to login-server (connection #%d).\n", + sess); + login_session = nullptr; +} +static +void delete_char(Session *sess) +{ + (void)sess; +} +static +void delete_frommap(Session *sess) +{ + auto it = std::find(server_session.begin(), server_session.end(), sess); + assert (it != server_session.end()); + int id = it - server_session.begin(); + PRINTF("Map-server %d (session #%d) has disconnected.\n", id, + sess); + server[id] = mmo_map_server{}; + server_session[id] = nullptr; + for (Session *& oci : online_chars) + if (oci == sess) + oci = nullptr; + create_online_files(); // update online players files (to remove all online players of this server) } //------------------------------ @@ -2468,7 +2466,7 @@ void parse_char(Session *s) { int len; WFIFOB(s, 2) = 0; - s->func_parse = parse_frommap; + s->set_parsers(SessionParsers{func_parse: parse_frommap, func_delete: delete_frommap}); server_session[i] = s; if (anti_freeze_enable) server_freezeflag[i] = 5; // Map anti-freeze system. Counter. 5 ok, 4...0 freezed @@ -2605,10 +2603,10 @@ void check_connect_login_server(TimerData *, tick_t) if (!login_session) { PRINTF("Attempt to connect to login-server...\n"); - login_session = make_connection(login_ip, login_port); + login_session = make_connection(login_ip, login_port, + SessionParsers{func_parse: parse_tologin, func_delete: delete_tologin}); if (!login_session) return; - login_session->func_parse = parse_tologin; realloc_fifo(login_session, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); WFIFOW(login_session, 0) = 0x2710; WFIFO_ZERO(login_session, 2, 24); @@ -2924,10 +2922,7 @@ int do_init(Slice argv) update_online = TimeT::now(); create_online_files(); // update online players files at start of the server -// set_termfunc (do_final); - set_defaultparse(parse_char, on_delete); - - char_session = make_listen_port(char_port); + char_session = make_listen_port(char_port, SessionParsers{parse_char, delete_char}); Timer(gettick() + std::chrono::seconds(1), check_connect_login_server, diff --git a/src/login/login.cpp b/src/login/login.cpp index 966d7dc..a60b34e 100644 --- a/src/login/login.cpp +++ b/src/login/login.cpp @@ -257,28 +257,27 @@ void login_log(XString line) } static -void on_delete(Session *sess) +void delete_login(Session *sess) +{ + (void)sess; +} + +static +void delete_fromchar(Session *sess) { auto it = std::find(server_session.begin(), server_session.end(), sess); + assert (it != server_session.end()); + int id = it - server_session.begin(); IP4Address ip = sess->client_ip; - if (it != server_session.end()) - { - int id = it - server_session.begin(); - PRINTF("Char-server '%s' has disconnected.\n", server[id].name); - LOGIN_LOG("Char-server '%s' has disconnected (ip: %s).\n", - server[id].name, ip); - server_session[id] = nullptr; - server[id] = mmo_char_server{}; - } - else - { - // player session - ; - } + PRINTF("Char-server '%s' has disconnected.\n", server[id].name); + LOGIN_LOG("Char-server '%s' has disconnected (ip: %s).\n", + server[id].name, ip); + server_session[id] = nullptr; + server[id] = mmo_char_server{}; } static -void on_delete_admin(Session *s) +void delete_admin(Session *s) { PRINTF("Remote administration has disconnected (session #%d).\n", s); @@ -3015,7 +3014,7 @@ void parse_login(Session *s) WFIFOW(s, 0) = 0x2711; WFIFOB(s, 2) = 0; WFIFOSET(s, 3); - s->func_parse = parse_fromchar; + s->set_parsers(SessionParsers{func_parse: parse_fromchar, func_delete: delete_fromchar}); realloc_fifo(s, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); // send GM account to char-server len = 4; @@ -3089,8 +3088,7 @@ void parse_login(Session *s) password, ip); PRINTF("Connection of a remote administration accepted (non encrypted password).\n"); WFIFOB(s, 2) = 0; - s->func_parse = parse_admin; - s->func_delete = on_delete_admin; + s->set_parsers(SessionParsers{func_parse: parse_admin, func_delete: delete_admin}); } else if (admin_state != 1) LOGIN_LOG("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (non encrypted password: %s, ip: %s)\n", @@ -3912,8 +3910,7 @@ int do_init(Slice argv) read_gm_account(); mmo_auth_init(); // set_termfunc (mmo_auth_sync); - set_defaultparse(parse_login, on_delete); - login_session = make_listen_port(login_port); + login_session = make_listen_port(login_port, SessionParsers{func_parse: parse_login, func_delete: delete_login}); Timer(gettick() + std::chrono::minutes(5), diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index 86506b0..fa95be7 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -1037,6 +1037,15 @@ void ladmin_itemfrob(Session *s) } } +static +void chrif_delete(Session *s) +{ + assert (s == char_session); + PRINTF("Map-server can't connect to char-server (connection #%d).\n", + s); + char_session = nullptr; +} + /*========================================== * *------------------------------------------ @@ -1207,10 +1216,10 @@ void check_connect_char_server(TimerData *, tick_t) { PRINTF("Attempt to connect to char-server...\n"); chrif_state = 0; - char_session = make_connection(char_ip, char_port); + char_session = make_connection(char_ip, char_port, + SessionParsers{func_parse: chrif_parse, func_delete: chrif_delete}); if (!char_session) return; - char_session->func_parse = chrif_parse; realloc_fifo(char_session, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); chrif_connect(char_session); diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 8f9565e..eb008e4 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -149,29 +149,22 @@ static void clif_quitsave(Session *, dumb_ptr sd); static -void on_delete(Session *s) +void clif_delete(Session *s) { - if (s == char_session) - { - PRINTF("Map-server can't connect to char-server (connection #%d).\n", - s); - char_session = nullptr; - } - else + assert (s != char_session); + + dumb_ptr sd = dumb_ptr(static_cast(s->session_data.get())); + if (sd && sd->state.auth) { - dumb_ptr sd = dumb_ptr(static_cast(s->session_data.get())); - if (sd && sd->state.auth) - { - pc_logout(sd); - clif_quitsave(s, sd); + pc_logout(sd); + clif_quitsave(s, sd); - PRINTF("Player [%s] has logged off your server.\n", sd->status_key.name); // Player logout display [Valaris] - } - else if (sd) - { // not authentified! (refused by char-server or disconnect before to be authentified) - PRINTF("Player with account [%d] has logged off your server (not auth account).\n", sd->bl_id); // Player logout display [Yor] - map_deliddb(sd); // account_id has been included in the DB before auth answer - } + PRINTF("Player [%s] has logged off your server.\n", sd->status_key.name); // Player logout display [Valaris] + } + else if (sd) + { // not authentified! (refused by char-server or disconnect before to be authentified) + PRINTF("Player with account [%d] has logged off your server (not auth account).\n", sd->bl_id); // Player logout display [Yor] + map_deliddb(sd); // account_id has been included in the DB before auth answer } } @@ -5515,6 +5508,5 @@ void clif_parse(Session *s) void do_init_clif(void) { - set_defaultparse(clif_parse, on_delete); - make_listen_port(map_port); + make_listen_port(map_port, SessionParsers{func_parse: clif_parse, func_delete: clif_delete}); } diff --git a/src/mmo/socket.cpp b/src/mmo/socket.cpp index 322a1f4..53a891c 100644 --- a/src/mmo/socket.cpp +++ b/src/mmo/socket.cpp @@ -56,6 +56,23 @@ static std::array, FD_SETSIZE> session; #pragma GCC diagnostic pop +Session::Session(SessionIO io, SessionParsers p) +{ + set_io(io); + set_parsers(p); +} +void Session::set_io(SessionIO io) +{ + func_send = io.func_send; + func_recv = io.func_recv; +} +void Session::set_parsers(SessionParsers p) +{ + func_parse = p.func_parse; + func_delete = p.func_delete; +} + + void set_session(io::FD fd, std::unique_ptr sess) { int f = fd.uncast_dammit(); @@ -98,28 +115,10 @@ size_t RFIFOSPACE(Session *s) } -/// Discard all input -static -void null_parse(Session *s); -/// Default parser for new connections -static -void (*default_func_parse)(Session *) = null_parse; -static -void (*default_delete)(Session *) = nullptr; - -void set_defaultparse(void (*defaultparse)(Session *), void (*on_delete)(Session *)) -{ - default_func_parse = defaultparse; - default_delete = on_delete; -} - /// Read from socket to the queue static void recv_to_fifo(Session *s) { - if (s->private_is_eof()) - return; - ssize_t len = s->fd.read(&s->rdata[s->rdata_size], RFIFOSPACE(s)); @@ -137,9 +136,6 @@ void recv_to_fifo(Session *s) static void send_from_fifo(Session *s) { - if (s->private_is_eof()) - return; - ssize_t len = s->fd.write(&s->wdata[0], s->wdata_size); if (len > 0) @@ -158,13 +154,6 @@ void send_from_fifo(Session *s) } } -static -void null_parse(Session *s) -{ - PRINTF("null_parse : %d\n", s); - RFIFOSKIP(s, RFIFOREST(s)); -} - static void connect_client(Session *ls) @@ -214,24 +203,21 @@ void connect_client(Session *ls) fd.fcntl(F_SETFL, O_NONBLOCK); - set_session(fd, make_unique()); + set_session(fd, make_unique( + SessionIO{func_recv: recv_to_fifo, func_send: send_from_fifo}, + ls->for_inferior)); Session *s = get_session(fd); s->fd = fd; s->rdata.new_(RFIFO_SIZE); s->wdata.new_(WFIFO_SIZE); - s->max_rdata = RFIFO_SIZE; s->max_wdata = WFIFO_SIZE; - s->func_recv = recv_to_fifo; - s->func_send = send_from_fifo; - s->func_parse = default_func_parse; - s->func_delete = default_delete; s->client_ip = IP4Address(client_address.sin_addr); s->created = TimeT::now(); s->connected = 0; } -Session *make_listen_port(uint16_t port) +Session *make_listen_port(uint16_t port, SessionParsers inferior) { struct sockaddr_in server_address; io::FD fd = io::FD::socket(AF_INET, SOCK_STREAM, 0); @@ -280,18 +266,20 @@ Session *make_listen_port(uint16_t port) readfds.set(fd); - set_session(fd, make_unique()); + set_session(fd, make_unique( + SessionIO{func_recv: connect_client, func_send: nullptr}, + SessionParsers{func_parse: nullptr, func_delete: nullptr})); Session *s = get_session(fd); + s->for_inferior = inferior; s->fd = fd; - s->func_recv = connect_client; s->created = TimeT::now(); s->connected = 1; return s; } -Session *make_connection(IP4Address ip, uint16_t port) +Session *make_connection(IP4Address ip, uint16_t port, SessionParsers parsers) { struct sockaddr_in server_address; io::FD fd = io::FD::socket(AF_INET, SOCK_STREAM, 0); @@ -333,7 +321,9 @@ Session *make_connection(IP4Address ip, uint16_t port) readfds.set(fd); - set_session(fd, make_unique()); + set_session(fd, make_unique( + SessionIO{func_recv: recv_to_fifo, func_send: send_from_fifo}, + parsers)); Session *s = get_session(fd); s->fd = fd; s->rdata.new_(RFIFO_SIZE); @@ -341,10 +331,6 @@ Session *make_connection(IP4Address ip, uint16_t port) s->max_rdata = RFIFO_SIZE; s->max_wdata = WFIFO_SIZE; - s->func_recv = recv_to_fifo; - s->func_send = send_from_fifo; - s->func_parse = default_func_parse; - s->func_delete = default_delete; s->created = TimeT::now(); s->connected = 1; @@ -441,13 +427,13 @@ void do_sendrecv(interval_t next_ms) Session *s = get_session(i); if (!s) continue; - if (wfd.isset(i)) + if (wfd.isset(i) && !s->eof) { if (s->func_send) //send_from_fifo(i); s->func_send(s); } - if (rfd.isset(i)) + if (rfd.isset(i) && !s->eof) { if (s->func_recv) //recv_to_fifo(i); @@ -470,7 +456,7 @@ void do_parsepacket(void) PRINTF("Session #%d timed out\n", s); s->set_eof(); } - if (s->rdata_size && !s->private_is_eof() && s->func_parse) + if (s->rdata_size && !s->eof && s->func_parse) { s->func_parse(s); /// some func_parse may call delete_session @@ -479,7 +465,7 @@ void do_parsepacket(void) if (!s) continue; } - if (s->private_is_eof()) + if (s->eof) { delete_session(s); continue; diff --git a/src/mmo/socket.hpp b/src/mmo/socket.hpp index 53e0dfd..c166794 100644 --- a/src/mmo/socket.hpp +++ b/src/mmo/socket.hpp @@ -51,10 +51,28 @@ struct SessionDeleter void operator()(SessionData *sd); }; -// Struct declaration +struct Session; +struct SessionIO +{ + void (*func_recv)(Session *); + void (*func_send)(Session *); +}; + +struct SessionParsers +{ + void (*func_parse)(Session *); + void (*func_delete)(Session *); +}; struct Session { + Session(SessionIO, SessionParsers); + Session(Session&&) = delete; + Session& operator = (Session&&) = delete; + + void set_io(SessionIO); + void set_parsers(SessionParsers); + /// Checks whether a newly-connected socket actually does anything TimeT created; bool connected; @@ -64,8 +82,6 @@ private: bool eof; public: void set_eof() { eof = true; } - // not everything is a member yet ... - bool private_is_eof() { return eof; } /// Currently used by clif_setwaitclose Timer timed_close; @@ -82,6 +98,7 @@ public: IP4Address client_ip; +private: /// Send or recieve /// Only called when select() indicates the socket is ready /// If, after that, nothing is read, it sets eof @@ -91,14 +108,23 @@ public: /// This is the important one /// Set to different functions depending on whether the connection /// is a player or a server/ladmin - /// Can be set explicitly or via set_defaultparse void (*func_parse)(Session *); /// Cleanup function since we're not fully RAII yet void (*func_delete)(Session *); + +public: + // this really ought to be part of session_data, once that gets sane + SessionParsers for_inferior; + /// Server-specific data type + // (this really should include the deleter, but ...) std::unique_ptr session_data; io::FD fd; + + friend void do_sendrecv(interval_t next); + friend void do_parsepacket(void); + friend void delete_session(Session *); }; inline @@ -133,10 +159,10 @@ IteratorPair> iter_fds(); /// open a socket, bind, and listen. Return an fd, or -1 if socket() fails, /// but exit if bind() or listen() fails -Session *make_listen_port(uint16_t port); +Session *make_listen_port(uint16_t port, SessionParsers inferior); /// Connect to an address, return a connected socket or -1 // FIXME - this is IPv4 only! -Session *make_connection(IP4Address ip, uint16_t port); +Session *make_connection(IP4Address ip, uint16_t port, SessionParsers); /// free() the structure and close() the fd void delete_session(Session *); /// Make a the internal queues bigger @@ -146,11 +172,6 @@ void do_sendrecv(interval_t next); /// Call the parser function for every socket that has read data void do_parsepacket(void); -/// Change the default parser for newly connected clients -// typically called once per server, but individual clients may identify -// themselves as servers -void set_defaultparse(void(*defaultparse)(Session *), void(*defaultdelete)(Session *)); - template uint8_t *pod_addressof_m(T& structure) { -- cgit v1.2.3-70-g09d2