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/map/chrif.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src/map/chrif.cpp') diff --git a/src/map/chrif.cpp b/src/map/chrif.cpp index 9a70d63..86506b0 100644 --- a/src/map/chrif.cpp +++ b/src/map/chrif.cpp @@ -1048,15 +1048,9 @@ void chrif_parse(Session *s) // only char-server can have an access to here. // so, if it isn't the char-server, we disconnect the session (fd != char_fd). - if (s != char_session || s->eof) + if (s != char_session) { - if (s == char_session) - { - PRINTF("Map-server can't connect to char-server (connection #%d).\n", - s); - char_session = nullptr; - } - delete_session(s); + s->set_eof(); return; } @@ -1077,7 +1071,7 @@ void chrif_parse(Session *s) if (r == 2) return; // intifで処理したが、データが足りない - s->eof = 1; + s->set_eof(); return; } packet_len = packet_len_table[cmd - 0x2af8]; @@ -1160,7 +1154,7 @@ void chrif_parse(Session *s) if (battle_config.error_log) PRINTF("chrif_parse : unknown packet %d %d\n", s, RFIFOW(s, 0)); - s->eof = 1; + s->set_eof(); return; } RFIFOSKIP(s, packet_len); -- cgit v1.2.3-60-g2f50 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/map/chrif.cpp') 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-60-g2f50