summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-12-31 19:23:34 +0000
committerFlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-12-31 19:23:34 +0000
commit84be7444dfc7f9f11ce0857b19bbd9401f30116e (patch)
tree0441fe8346ef8a07929736792d6b8f1ab5b23b89 /src
parent0da3671876a62ff48b990990e2e1723865bc8cd7 (diff)
downloadhercules-84be7444dfc7f9f11ce0857b19bbd9401f30116e.tar.gz
hercules-84be7444dfc7f9f11ce0857b19bbd9401f30116e.tar.bz2
hercules-84be7444dfc7f9f11ce0857b19bbd9401f30116e.tar.xz
hercules-84be7444dfc7f9f11ce0857b19bbd9401f30116e.zip
* Added code to reject double logins in clif_parse_WantToConnection and added debug messages to detect possible double logins that escaped.
* Isolated accounts that are waiting for the quit ack. The rest of the game logic no longer has access to them though the id2sd/charid2sd dbs. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11998 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src')
-rw-r--r--src/map/chrif.c8
-rw-r--r--src/map/clif.c12
-rw-r--r--src/map/map.c33
-rw-r--r--src/map/map.h3
4 files changed, 41 insertions, 15 deletions
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 11ce53ae7..390c53966 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -273,11 +273,7 @@ int chrif_removemap(int fd)
// received after a character has been "final saved" on the char-server
int chrif_save_ack(int fd)
{
- struct map_session_data *sd;
- sd = map_id2sd(RFIFOL(fd,2));
-
- if (sd && sd->status.char_id == RFIFOL(fd,6))
- map_quit_ack(sd);
+ map_quit_ack(RFIFOL(fd,2), RFIFOL(fd,6));
return 0;
}
@@ -332,7 +328,7 @@ int chrif_changemapserverack(int account_id, int login_id1, int login_id2, int c
//Player has been saved already, remove him from memory. [Skotlex]
map_quit(sd);
- map_quit_ack(sd);
+ map_quit_ack(sd->status.account_id, sd->status.char_id);
return 0;
}
diff --git a/src/map/clif.c b/src/map/clif.c
index d2044a77e..9f1625b7a 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -7617,7 +7617,17 @@ void clif_parse_WantToConnection(int fd, TBL_PC* sd)
WFIFOSET(fd,packet_len(0x6a));
clif_setwaitclose(fd);
return;
- } else
+ } else if( map_knowsaccount(account_id) )
+ {// double login
+ ShowError("clif_parse_WantToConnection: double login attempt AID/CID: %d/%d, rejecting...\n", account_id, char_id);
+ WFIFOHEAD(fd,packet_len(0x6a));
+ WFIFOW(fd,0) = 0x6a;
+ WFIFOB(fd,2) = 3; // Rejected by server
+ WFIFOSET(fd,packet_len(0x6a));
+ clif_setwaitclose(fd);
+ return;
+ }
+ else
{// packet version accepted
struct block_list* bl;
if( (bl=map_id2bl(account_id)) != NULL && bl->type != BL_PC )
diff --git a/src/map/map.c b/src/map/map.c
index 4f8984041..c57f76987 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -101,6 +101,7 @@ static DBMap* mobid_db=NULL; // int id -> struct mob_data*
static DBMap* map_db=NULL; // unsigned int mapindex -> struct map_data*
static DBMap* nick_db=NULL; // int char_id -> struct charid2nick* (requested names of offline characters)
static DBMap* charid_db=NULL; // int char_id -> struct map_session_data*
+static DBMap* quit_db=NULL; // int account_id -> struct map_session_data* (players that are quitting or changing map-server)
static int map_users=0;
static struct block_list *objects[MAX_FLOORITEM];
@@ -1625,6 +1626,12 @@ void map_deliddb(struct block_list *bl)
idb_remove(id_db,bl->id);
}
+/// Returns true if the map server knows the account (to reject logins).
+bool map_knowsaccount(int account_id)
+{
+ return (map_id2sd(account_id) || idb_get(quit_db,account_id) ? true : false);
+}
+
/*==========================================
* PC‚Ěquit?—ť map.c?•Ş
*
@@ -1632,6 +1639,7 @@ void map_deliddb(struct block_list *bl)
*------------------------------------------*/
int map_quit(struct map_session_data *sd)
{
+ struct map_session_data* sd2;
if(!sd->state.auth) { //Removing a player that hasn't even finished loading
TBL_PC *sd2 = map_id2sd(sd->status.account_id);
if (sd->pd) unit_free(&sd->pd->bl,-1);
@@ -1661,7 +1669,12 @@ int map_quit(struct map_session_data *sd)
unit_remove_map(&sd->hd->bl, 0);
}
- idb_remove(id_db,sd->bl.id);
+ map_deliddb(&sd->bl);
+ if( (sd2=(struct map_session_data*)idb_put(quit_db, sd->status.account_id, sd)) )
+ {
+ ShowDebug("map_quit: Possible double login AID/CID: %d/%d AID/CID: %d/%d\n", sd2->status.account_id, sd2->status.char_id, sd->status.account_id, sd->status.char_id);
+ aFree(sd2);
+ }
if(sd->reg)
{ //Double logout already freed pointer fix... [Skotlex]
@@ -1695,12 +1708,15 @@ int map_quit(struct map_session_data *sd)
return 0;
}
-void map_quit_ack(struct map_session_data *sd)
+void map_quit_ack(int account_id, int char_id)
{
- if (sd && sd->state.finalsave) {
- idb_remove(pc_db,sd->status.account_id);
- idb_remove(charid_db,sd->status.char_id);
- aFree(sd);
+ struct map_session_data* sd = (struct map_session_data*)idb_get(quit_db,account_id);
+ if( sd )
+ {
+ if( sd->status.char_id != char_id )
+ ShowDebug("map_quit_ack: Possible double login AID/CID: %d/%d AID/CID: %d/%d\n", account_id, char_id, sd->status.account_id, sd->status.char_id);
+ else
+ idb_remove(quit_db,account_id);
}
}
@@ -1718,6 +1734,7 @@ static int do_reconnect_map_sub(DBKey key,void *data,va_list va)
void do_reconnect_map(void)
{
pc_db->foreach(pc_db,do_reconnect_map_sub);
+ pc_db->foreach(quit_db,do_reconnect_map_sub);//## FIXME possible loss of data [FlavioJS]
}
/*==========================================
@@ -3015,7 +3032,7 @@ static int cleanup_db_subpc(DBKey key,void *data,va_list va)
map_quit(sd); //Attempt force-save
}
//Force remove from memory...
- map_quit_ack(sd);
+ map_quit_ack(sd->status.account_id, sd->status.char_id);
return 1;
}
@@ -3093,6 +3110,7 @@ void do_final(void)
mobid_db->destroy(mobid_db, NULL);
nick_db->destroy(nick_db, nick_db_final);
charid_db->destroy(charid_db, NULL);
+ db_destroy(quit_db);
#ifndef TXT_ONLY
map_sql_close();
@@ -3273,6 +3291,7 @@ int do_init(int argc, char *argv[])
map_db = uidb_alloc(DB_OPT_BASE);
nick_db = idb_alloc(DB_OPT_BASE);
charid_db = idb_alloc(DB_OPT_BASE);
+ quit_db = idb_alloc(DB_OPT_RELEASE_DATA);
#ifndef TXT_ONLY
map_sql_init();
#endif /* not TXT_ONLY */
diff --git a/src/map/map.h b/src/map/map.h
index 24b6eb052..562c8b063 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -1300,8 +1300,9 @@ int map_delobjectnofree(int id);
void map_foreachobject(int (*)(struct block_list*,va_list),int,...);
int map_search_freecell(struct block_list *src, int m, short *x, short *y, int rx, int ry, int flag);
//
+bool map_knowsaccount(int account_id);
int map_quit(struct map_session_data *);
-void map_quit_ack(struct map_session_data *);
+void map_quit_ack(int account_id, int char_id);
// npc
int map_addnpc(int,struct npc_data *);