summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-04-17 16:10:11 -0700
committerBen Longbons <b.r.longbons@gmail.com>2014-04-17 16:10:11 -0700
commitae7b06ff8ad775a945bd677effd72b7fafa13d8d (patch)
tree3de2693f18a39e57008f63926fedf169da5b23ac
parent15dc4a8c51d0704bb82407c1dc79c751cda7fb42 (diff)
downloadtmwa-ae7b06ff8ad775a945bd677effd72b7fafa13d8d.tar.gz
tmwa-ae7b06ff8ad775a945bd677effd72b7fafa13d8d.tar.bz2
tmwa-ae7b06ff8ad775a945bd677effd72b7fafa13d8d.tar.xz
tmwa-ae7b06ff8ad775a945bd677effd72b7fafa13d8d.zip
Die sensibly, take 1
-rw-r--r--src/admin/ladmin.cpp28
-rw-r--r--src/char/char.cpp81
-rw-r--r--src/login/login.cpp70
-rw-r--r--src/map/chrif.cpp14
-rw-r--r--src/map/chrif.hpp1
-rw-r--r--src/map/clif.cpp64
-rw-r--r--src/mmo/socket.cpp34
-rw-r--r--src/mmo/socket.hpp10
8 files changed, 178 insertions, 124 deletions
diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp
index 5d772e3..0d53ff4 100644
--- a/src/admin/ladmin.cpp
+++ b/src/admin/ladmin.cpp
@@ -286,6 +286,18 @@ void ladmin_log(XString line)
}
static
+void on_delete(Session *)
+{
+ {
+ PRINTF("Impossible to have a connection with the login-server [%s:%d] !\n",
+ login_ip, login_port);
+ LADMIN_LOG("Impossible to have a connection with the login-server [%s:%d] !\n",
+ login_ip, login_port);
+ exit(0);
+ }
+}
+
+static
bool qsplit(ZString src)
{
return !src;
@@ -1940,16 +1952,6 @@ void prompt(void)
static
void parse_fromlogin(Session *s)
{
- if (s->eof)
- {
- PRINTF("Impossible to have a connection with the login-server [%s:%d] !\n",
- login_ip, login_port);
- LADMIN_LOG("Impossible to have a connection with the login-server [%s:%d] !\n",
- login_ip, login_port);
- delete_session(s);
- exit(0);
- }
-
// PRINTF("parse_fromlogin : %d %d %d\n", fd, RFIFOREST(fd), RFIFOW(fd,0));
while (RFIFOREST(s) >= 2)
@@ -1966,7 +1968,7 @@ void parse_fromlogin(Session *s)
PRINTF(" - administration system not activated, or\n");
PRINTF(" - unauthorised IP.\n");
LADMIN_LOG("Error at login: incorrect password, administration system not activated, or unauthorised IP.\n");
- s->eof = 1;
+ s->set_eof();
//bytes_to_read = 1; // not stop at prompt
}
else
@@ -2765,7 +2767,7 @@ void parse_fromlogin(Session *s)
default:
PRINTF("Remote administration has been disconnected (unknown packet).\n");
LADMIN_LOG("'End of connection, unknown packet.\n");
- s->eof = 1;
+ s->set_eof();
return;
}
}
@@ -2902,7 +2904,7 @@ int do_init(Slice<ZString> argv)
LADMIN_LOG("");
LADMIN_LOG("Configuration file readed.\n");
- set_defaultparse(parse_fromlogin);
+ set_defaultparse(parse_fromlogin, on_delete);
Iprintf("EAthena login-server administration tool.\n");
Version version = CURRENT_LOGIN_SERVER_VERSION;
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<ZString> 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);
diff --git a/src/login/login.cpp b/src/login/login.cpp
index f784c6a..966d7dc 100644
--- a/src/login/login.cpp
+++ b/src/login/login.cpp
@@ -256,6 +256,35 @@ void login_log(XString line)
log_with_timestamp(logfp, line);
}
+static
+void on_delete(Session *sess)
+{
+ auto it = std::find(server_session.begin(), server_session.end(), sess);
+ 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
+ ;
+ }
+}
+
+static
+void on_delete_admin(Session *s)
+{
+ PRINTF("Remote administration has disconnected (session #%d).\n",
+ s);
+}
+
+
//----------------------------------------------------------------------
// Determine if an account (id) is a GM account
// and returns its level (or 0 if it isn't a GM account or if not found)
@@ -948,7 +977,7 @@ void char_anti_freeze_system(TimerData *, tick_t)
i, server[i].name);
LOGIN_LOG("Char-server anti-freeze system: char-server #%d '%s' is freezed -> disconnection.\n",
i, server[i].name);
- server_session[i]->eof = 1;
+ server_session[i]->set_eof();
}
}
}
@@ -966,17 +995,9 @@ void parse_fromchar(Session *s)
for (id = 0; id < MAX_SERVERS; id++)
if (server_session[id] == s)
break;
- if (id == MAX_SERVERS || s->eof)
+ if (id == MAX_SERVERS)
{
- if (id < MAX_SERVERS)
- {
- 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{};
- }
- delete_session(s);
+ s->set_eof();
return;
}
@@ -1593,7 +1614,7 @@ void parse_fromchar(Session *s)
}
PRINTF("parse_fromchar: Unknown packet 0x%x (from a char-server)! -> disconnection.\n",
RFIFOW(s, 0));
- s->eof = 1;
+ s->set_eof();
PRINTF("Char-server has been disconnected (unknown packet).\n");
return;
}
@@ -1609,14 +1630,6 @@ void parse_admin(Session *s)
{
IP4Address ip = s->client_ip;
- if (s->eof)
- {
- delete_session(s);
- PRINTF("Remote administration has disconnected (session #%d).\n",
- s);
- return;
- }
-
while (RFIFOREST(s) >= 2)
{
if (display_parse_admin == 1)
@@ -1638,7 +1651,7 @@ void parse_admin(Session *s)
LOGIN_LOG("'ladmin': End of connection (ip: %s)\n",
ip);
RFIFOSKIP(s, 2);
- s->eof = 1;
+ s->set_eof();
break;
case 0x7920: // Request of an accounts list
@@ -2708,7 +2721,7 @@ void parse_admin(Session *s)
}
LOGIN_LOG("'ladmin': End of connection, unknown packet (ip: %s)\n",
ip);
- s->eof = 1;
+ s->set_eof();
PRINTF("Remote administration has been disconnected (unknown packet).\n");
return;
}
@@ -2742,12 +2755,6 @@ void parse_login(Session *s)
IP4Address ip = s->client_ip;
- if (s->eof)
- {
- delete_session(s);
- return;
- }
-
while (RFIFOREST(s) >= 2)
{
if (display_parse_login == 1)
@@ -3054,7 +3061,7 @@ void parse_login(Session *s)
case 0x7532: // Request to end connection
LOGIN_LOG("End of connection (ip: %s)\n", ip);
- s->eof = 1;
+ s->set_eof();
return;
case 0x7918: // Request for administation login
@@ -3083,6 +3090,7 @@ void parse_login(Session *s)
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;
}
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",
@@ -3157,7 +3165,7 @@ void parse_login(Session *s)
}
}
LOGIN_LOG("End of connection, unknown packet (ip: %s)\n", ip);
- s->eof = 1;
+ s->set_eof();
return;
}
}
@@ -3904,7 +3912,7 @@ int do_init(Slice<ZString> argv)
read_gm_account();
mmo_auth_init();
// set_termfunc (mmo_auth_sync);
- set_defaultparse(parse_login);
+ set_defaultparse(parse_login, on_delete);
login_session = make_listen_port(login_port);
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);
diff --git a/src/map/chrif.hpp b/src/map/chrif.hpp
index 5e8263d..afeba75 100644
--- a/src/map/chrif.hpp
+++ b/src/map/chrif.hpp
@@ -59,6 +59,7 @@ int chrif_send_divorce(int char_id);
void do_init_chrif(void);
// only used by intif.cpp
+// and clif.cpp for the new on_delete stuff ...
extern Session *char_session;
#endif // TMWA_MAP_CHRIF_HPP
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index ea92d15..8f9565e 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -145,6 +145,36 @@ int map_port = 5121;
static
int clif_changelook_towards(dumb_ptr<block_list> bl, LOOK type, int val,
dumb_ptr<map_session_data> dstsd);
+static
+void clif_quitsave(Session *, dumb_ptr<map_session_data> sd);
+
+static
+void on_delete(Session *s)
+{
+ if (s == char_session)
+ {
+ PRINTF("Map-server can't connect to char-server (connection #%d).\n",
+ s);
+ char_session = nullptr;
+ }
+ else
+ {
+ dumb_ptr<map_session_data> sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(s->session_data.get()));
+ if (sd && sd->state.auth)
+ {
+ 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
+ }
+ }
+}
+
/*==========================================
* map鯖のip設定
@@ -1099,7 +1129,7 @@ static
void clif_waitclose(TimerData *, tick_t, Session *s)
{
if (s)
- s->eof = 1;
+ s->set_eof();
}
/*==========================================
@@ -5203,7 +5233,7 @@ int clif_check_packet_flood(Session *s, int cmd)
PRINTF("packet flood detected from %s [0x%x]\n", sd->status_key.name, cmd);
if (battle_config.packet_spam_kick)
{
- s->eof = 1; // Kick
+ s->set_eof();
return 1;
}
sd->packet_flood_in = 0;
@@ -5338,32 +5368,18 @@ void clif_parse(Session *s)
{
if (RFIFOREST(s) < 2)
{ // too small a packet disconnect
- s->eof = 1;
+ s->set_eof();
}
if (RFIFOW(s, 0) != 0x72 && RFIFOW(s, 0) != 0x7530)
{
// first packet must be auth or finger
- s->eof = 1;
+ s->set_eof();
}
}
- // 接続が切れてるので後始末
- if (!chrif_isconnect() || s->eof)
- { // char鯖に繋がってない間は接続禁止 (!chrif_isconnect())
- if (sd && sd->state.auth)
- {
- 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
- }
- if (s)
- delete_session(s);
+ if (!chrif_isconnect())
+ {
+ s->set_eof();
return;
}
@@ -5384,7 +5400,7 @@ void clif_parse(Session *s)
RFIFOSKIP(s, 2);
break;
case 0x7532: // 接続の切断
- s->eof = 1;
+ s->set_eof();
break;
}
return;
@@ -5403,7 +5419,7 @@ void clif_parse(Session *s)
packet_len = RFIFOW(s, 2);
if (packet_len < 4 || packet_len > 32768)
{
- s->eof = 1;
+ s->set_eof();
return; // Runt packet (variable out of bounds)
}
}
@@ -5499,6 +5515,6 @@ void clif_parse(Session *s)
void do_init_clif(void)
{
- set_defaultparse(clif_parse);
+ set_defaultparse(clif_parse, on_delete);
make_listen_port(map_port);
}
diff --git a/src/mmo/socket.cpp b/src/mmo/socket.cpp
index 48cd149..322a1f4 100644
--- a/src/mmo/socket.cpp
+++ b/src/mmo/socket.cpp
@@ -104,17 +104,20 @@ 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 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->eof)
+ if (s->private_is_eof())
return;
ssize_t len = s->fd.read(&s->rdata[s->rdata_size],
@@ -127,14 +130,14 @@ void recv_to_fifo(Session *s)
}
else
{
- s->eof = 1;
+ s->set_eof();
}
}
static
void send_from_fifo(Session *s)
{
- if (s->eof)
+ if (s->private_is_eof())
return;
ssize_t len = s->fd.write(&s->wdata[0], s->wdata_size);
@@ -151,7 +154,7 @@ void send_from_fifo(Session *s)
}
else
{
- s->eof = 1;
+ s->set_eof();
}
}
@@ -222,6 +225,7 @@ void connect_client(Session *ls)
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;
@@ -340,6 +344,7 @@ Session *make_connection(IP4Address ip, uint16_t port)
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;
@@ -359,6 +364,8 @@ void delete_session(Session *s)
fd_max--;
readfds.clr(fd);
{
+ s->func_delete(s);
+
s->rdata.delete_();
s->wdata.delete_();
s->session_data.reset();
@@ -461,23 +468,22 @@ void do_parsepacket(void)
&& static_cast<time_t>(TimeT::now()) - static_cast<time_t>(s->created) > CONNECT_TIMEOUT)
{
PRINTF("Session #%d timed out\n", s);
- s->eof = 1;
+ s->set_eof();
}
- if (!s->rdata_size && !s->eof)
- continue;
- if (s->func_parse)
+ if (s->rdata_size && !s->private_is_eof() && s->func_parse)
{
s->func_parse(s);
/// some func_parse may call delete_session
+ // (that's kind of evil)
s = get_session(i);
- if (s && s->eof)
- {
- delete_session(s);
- s = nullptr;
- }
if (!s)
continue;
}
+ if (s->private_is_eof())
+ {
+ delete_session(s);
+ continue;
+ }
/// Reclaim buffer space for what was read
RFIFOFLUSH(s);
}
diff --git a/src/mmo/socket.hpp b/src/mmo/socket.hpp
index 256c08b..53e0dfd 100644
--- a/src/mmo/socket.hpp
+++ b/src/mmo/socket.hpp
@@ -59,8 +59,14 @@ struct Session
TimeT created;
bool connected;
+private:
/// Flag needed since structure must be freed in a server-dependent manner
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;
@@ -87,6 +93,8 @@ struct Session
/// 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 *);
/// Server-specific data type
std::unique_ptr<SessionData, SessionDeleter> session_data;
@@ -141,7 +149,7 @@ 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 set_defaultparse(void(*defaultparse)(Session *), void(*defaultdelete)(Session *));
template<class T>
uint8_t *pod_addressof_m(T& structure)