From 84be7444dfc7f9f11ce0857b19bbd9401f30116e Mon Sep 17 00:00:00 2001 From: FlavioJS Date: Mon, 31 Dec 2007 19:23:34 +0000 Subject: * 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 --- src/map/chrif.c | 8 ++------ src/map/clif.c | 12 +++++++++++- src/map/map.c | 33 ++++++++++++++++++++++++++------- src/map/map.h | 3 ++- 4 files changed, 41 insertions(+), 15 deletions(-) (limited to 'src') 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 *); -- cgit v1.2.3-70-g09d2