summaryrefslogtreecommitdiff
path: root/src/map/clif.c
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-02-21 00:13:56 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-02-21 00:13:56 +0000
commitfd665092bbcd4be32f9d8319ffbb4aad30b40d08 (patch)
tree96fbf399d2704c89a5254a91994dd07a40fdfe39 /src/map/clif.c
parent5870b45487fde3bc3fef54062aab5fcce4ce39ca (diff)
downloadhercules-fd665092bbcd4be32f9d8319ffbb4aad30b40d08.tar.gz
hercules-fd665092bbcd4be32f9d8319ffbb4aad30b40d08.tar.bz2
hercules-fd665092bbcd4be32f9d8319ffbb4aad30b40d08.tar.xz
hercules-fd665092bbcd4be32f9d8319ffbb4aad30b40d08.zip
- Fixed new guilds displaying online-connect member count at 0 rather than 1, and the guild master not knowing it is one (eg: it cannot edit the guild notice of a newly created guild until relogging).
- Fixed acc_reg2 parsing screwing up the char_id and subtracting 2 from it rather than passing it as it is. - Extended the auth_node/auth_db system in chrif.c to handle log in/out and mapserver-change procedures. This way players are not in the main dbs when they are not "active", which blocks potential invalid accesses to them. - Replaced states auth, waiting_disconnect and finalsave with active. - Cleaned some the party/guild login and creation procedures, removed the party_sent/guild_sent states. - Removed a redundant guild_check_member call which is beyond not-needed and into the realm of wasting resources. - clif_parse will no longer process packets from !sd->state.active players, this also makes checking for finalsave uneccessary (since players re already removed from the maps and dbs by this point, so you can't access them in any other way) - Separated the roles of unit_free and map_quit, the former will handle cleaning structures from the player so it can be free'd safely, while the latter performs additional routines which are unique to characters logging out normally (map-server changes will invoke unit_free and bypass map_quit). - Removed pc_isplaying, quit_db, map_knowsaccount, MAPIT_PCISPLAYING among other functions/defines which are no longer needed due to the new login scheme. - Cleand up a bit some code in the clif_send(_sub) functions. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@12223 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/clif.c')
-rw-r--r--src/map/clif.c183
1 files changed, 90 insertions, 93 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index ed5e46bbd..5d6daaa26 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -175,7 +175,7 @@ int clif_countusers(void)
for(i = 0; i < fd_max; i++) {
if (session[i] && session[i]->func_parse == clif_parse &&
(sd = (struct map_session_data*)session[i]->session_data) &&
- sd->state.auth && !(battle_config.hide_GM_session && pc_isGM(sd)))
+ sd->state.active && !(battle_config.hide_GM_session && pc_isGM(sd)))
users++;
}
return users;
@@ -195,7 +195,7 @@ int clif_foreachclient(int (*func)(struct map_session_data*, va_list),...) //rec
for(i = 0; i < fd_max; i++) {
if ( session[i] && session[i]->func_parse == clif_parse) {
sd = (struct map_session_data*)session[i]->session_data;
- if ( sd && sd->state.auth && !sd->state.waitingdisconnect )
+ if ( sd && sd->state.active )
func(sd, ap);
}
}
@@ -246,20 +246,23 @@ int clif_send_sub(struct block_list *bl, va_list ap)
break;
}
- if (session[fd] != NULL) {
- WFIFOHEAD(fd, len);
- if (WFIFOP(fd,0) == buf) {
- ShowError("WARNING: Invalid use of clif_send function\n");
- ShowError(" Packet x%4x use a WFIFO of a player instead of to use a buffer.\n", WBUFW(buf,0));
- ShowError(" Please correct your code.\n");
- // don't send to not move the pointer of the packet for next sessions in the loop
- WFIFOSET(fd,0);//## TODO is this ok?
- } else {
- if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd,len);
- }
- }
+ if (session[fd] == NULL)
+ return 0;
+
+ WFIFOHEAD(fd, len);
+ if (WFIFOP(fd,0) == buf) {
+ ShowError("WARNING: Invalid use of clif_send function\n");
+ ShowError(" Packet x%4x use a WFIFO of a player instead of to use a buffer.\n", WBUFW(buf,0));
+ ShowError(" Please correct your code.\n");
+ // don't send to not move the pointer of the packet for next sessions in the loop
+ //WFIFOSET(fd,0);//## TODO is this ok?
+ //NO. It is not ok. There is the chance WFIFOSET actually sends the buffer data, and shifts elements around, which will corrupt the buffer.
+ return 0;
+ }
+
+ if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
+ memcpy(WFIFOP(fd,0), buf, len);
+ WFIFOSET(fd,len);
}
return 0;
@@ -285,13 +288,13 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
case ALL_CLIENT: //All player clients.
for (i = 0; i < fd_max; i++) {
if (session[i] && session[i]->func_parse == clif_parse &&
- (sd = (struct map_session_data *)session[i]->session_data) != NULL&&
- sd->state.auth) {
- if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
- WFIFOHEAD(i, len);
- memcpy(WFIFOP(i,0), buf, len);
- WFIFOSET(i,len);
- }
+ (sd = (struct map_session_data *)session[i]->session_data) != NULL &&
+ sd->state.active &&
+ packet_db[sd->packet_ver][RBUFW(buf,0)].len)
+ { // packet must exist for the client version
+ WFIFOHEAD(i, len);
+ memcpy(WFIFOP(i,0), buf, len);
+ WFIFOSET(i,len);
}
}
break;
@@ -299,12 +302,12 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
for(i = 0; i < fd_max; i++) {
if (session[i] && session[i]->func_parse == clif_parse &&
(sd = (struct map_session_data*)session[i]->session_data) != NULL &&
- sd->state.auth && sd->bl.m == bl->m) {
- if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
- WFIFOHEAD(i,len);
- memcpy(WFIFOP(i,0), buf, len);
- WFIFOSET(i,len);
- }
+ sd->state.active && sd->bl.m == bl->m &&
+ packet_db[sd->packet_ver][RBUFW(buf,0)].len)
+ { // packet must exist for the client version
+ WFIFOHEAD(i,len);
+ memcpy(WFIFOP(i,0), buf, len);
+ WFIFOSET(i,len);
}
}
break;
@@ -350,11 +353,11 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
for(i=1; i<fd_max; i++) {
if (session[i] && session[i]->func_parse == clif_parse &&
(sd = (struct map_session_data*)session[i]->session_data) != NULL &&
- sd->state.mainchat && !sd->chatID && (fd=sd->fd))
+ sd->state.active && sd->state.mainchat && !sd->chatID)
{
- WFIFOHEAD(fd,len);
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd, len);
+ WFIFOHEAD(i,len);
+ memcpy(WFIFOP(i,0), buf, len);
+ WFIFOSET(i, len);
}
}
break;
@@ -376,12 +379,9 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
if( (sd = p->data[i].sd) == NULL )
continue;
- if( !(fd=sd->fd) || fd <= 0 || fd >= fd_max )
+ if( !(fd=sd->fd) )
continue;
- if( session[fd] == NULL || sd->state.auth == 0 || session[fd]->session_data == NULL || sd->packet_ver > MAX_PACKET_VER )
- continue;
-
if( sd->bl.id == bl->id && (type == PARTY_WOS || type == PARTY_SAMEMAP_WOS || type == PARTY_AREA_WOS) )
continue;
@@ -404,13 +404,12 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
if (session[i] && session[i]->func_parse == clif_parse &&
(sd = (struct map_session_data*)session[i]->session_data) != NULL &&
- sd->state.auth && (fd=sd->fd) && sd->partyspy == p->party.party_id)
- {
- if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
- WFIFOHEAD(fd,len);
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd,len);
- }
+ sd->state.active && sd->partyspy == p->party.party_id &&
+ packet_db[sd->packet_ver][RBUFW(buf,0)].len)
+ { // packet must exist for the client version
+ WFIFOHEAD(i,len);
+ memcpy(WFIFOP(i,0), buf, len);
+ WFIFOSET(i,len);
}
}
}
@@ -423,7 +422,7 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
for (i = 0; i < fd_max; i++) {
if (session[i] && session[i]->func_parse == clif_parse &&
(sd = (struct map_session_data *)session[i]->session_data) != NULL &&
- sd->state.auth && sd->duel_group == x0) {
+ sd->state.active && sd->duel_group == x0) {
if (type == DUEL_WOS && bl->id == sd->bl.id)
continue;
if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) {
@@ -460,10 +459,7 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
for(i = 0; i < g->max_member; i++) {
if( (sd = g->member[i].sd) != NULL )
{
- if( !(fd=sd->fd) || fd <= 0 || fd >= fd_max )
- continue;
-
- if( session[fd] == NULL || sd->state.auth == 0 || session[fd]->session_data == NULL || sd->packet_ver > MAX_PACKET_VER )
+ if( !(fd=sd->fd) )
continue;
if( sd->bl.id == bl->id && (type == GUILD_WOS || type == GUILD_SAMEMAP_WOS || type == GUILD_AREA_WOS) )
@@ -488,12 +484,12 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
for (i = 1; i < fd_max; i++){ // guildspy [Syrus22]
if (session[i] && session[i]->func_parse == clif_parse &&
(sd = (struct map_session_data*)session[i]->session_data) != NULL &&
- sd->state.auth && (fd=sd->fd) && sd->guildspy == g->guild_id) {
- if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version
- WFIFOHEAD(fd,len);
- memcpy(WFIFOP(fd,0), buf, len);
- WFIFOSET(fd,len);
- }
+ sd->state.active && sd->guildspy == g->guild_id &&
+ packet_db[sd->packet_ver][RBUFW(buf,0)].len)
+ { // packet must exist for the client version
+ WFIFOHEAD(fd,len);
+ memcpy(WFIFOP(fd,0), buf, len);
+ WFIFOSET(fd,len);
}
}
}
@@ -541,6 +537,7 @@ int clif_authok(struct map_session_data *sd)
* 3 - timeout/too much lag -> MsgStringTable[241]
* 4 - server full -> MsgStringTable[264]
* 5 - underaged -> MsgStringTable[305]
+ * 8 - Server sill recognizes last connection -> MsgStringTable[441]
* 9 - too many connections from this ip -> MsgStringTable[529]
* 10 - out of available time paid for -> MsgStringTable[530]
* 15 - disconnected by a GM -> if( servicetype == taiwan ) MsgStringTable[579]
@@ -1038,7 +1035,7 @@ int clif_weather(int m)
for(i = 0; i < fd_max; i++) {
if (session[i] && session[i]->func_parse == clif_parse &&
(sd = session[i]->session_data) != NULL &&
- sd->state.auth && sd->bl.m == m) {
+ sd->state.active && sd->bl.m == m) {
clif_weather_check(sd);
}
}
@@ -1327,8 +1324,7 @@ static int clif_delayquit(int tid, unsigned int tick, int id, int data)
*------------------------------------------*/
void clif_quitsave(int fd,struct map_session_data *sd)
{
- if (sd->state.waitingdisconnect || //Was already waiting to be disconnected.
- !battle_config.prevent_logout ||
+ if (!battle_config.prevent_logout ||
DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout)
map_quit(sd);
else if (sd->fd)
@@ -1356,10 +1352,9 @@ static int clif_waitclose(int tid, unsigned int tick, int id, int data)
*------------------------------------------*/
void clif_setwaitclose(int fd)
{
- struct map_session_data *sd;
// if player is not already in the game (double connection probably)
- if ((sd = (struct map_session_data*)session[fd]->session_data) == NULL) {
+ if (session[fd]->session_data == NULL) {
// limited timer, just to send information.
add_timer(gettick() + 1000, clif_waitclose, fd, 0);
} else
@@ -3775,7 +3770,7 @@ void clif_01ac(struct block_list* bl)
sd=va_arg(ap,struct map_session_data*);
- if (sd == NULL || !sd->fd || session[sd->fd] == NULL)
+ if (sd == NULL || !sd->fd)
return 0;
switch(bl->type){
@@ -5614,7 +5609,7 @@ int clif_hpmeter(struct map_session_data *sd)
for (i = 0; i < fd_max; i++) {
if (session[i] && session[i]->func_parse == clif_parse &&
(sd2 = (struct map_session_data*)session[i]->session_data) &&
- sd != sd2 && sd2->state.auth) {
+ sd != sd2 && sd2->state.active) {
if (sd2->bl.m != sd->bl.m ||
sd2->bl.x < x0 || sd2->bl.y < y0 ||
sd2->bl.x > x1 || sd2->bl.y > y1 ||
@@ -7616,12 +7611,14 @@ static int clif_guess_PacketVer(int fd, int get_previous, int *error)
*------------------------------------------*/
void clif_parse_WantToConnection(int fd, TBL_PC* sd)
{
+ struct block_list* bl;
+ struct auth_node* node;
int cmd, account_id, char_id, login_id1, sex;
unsigned int client_tick; //The client tick is a tick, therefore it needs be unsigned. [Skotlex]
int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor])
if (sd) {
- ShowError("clif_parse_WantToConnection : invalid request (character already logged in)?\n");
+ ShowError("clif_parse_WantToConnection : invalid request (character already logged in)\n");
return;
}
@@ -7646,13 +7643,12 @@ void clif_parse_WantToConnection(int fd, TBL_PC* sd)
WFIFOSET(fd,packet_len(0x6a));
clif_setwaitclose(fd);
return;
- } else if( map_knowsaccount(account_id) )
- {// double login
- sd = map_id2sd(account_id);
- if( sd && sd->state.autotrade )
- map_quit(sd);// kick autotrading character
- else
- ShowError("clif_parse_WantToConnection: double login attempt AID/CID: %d/%d, rejecting...\n", account_id, char_id);
+ }
+
+ //Check for double login.
+ bl = map_id2bl(account_id);
+ if(bl && bl->type != BL_PC) {
+ ShowError("clif_parse_WantToConnection: a non-player object already has id %d, please increase the starting account number\n", account_id);
WFIFOHEAD(fd,packet_len(0x6a));
WFIFOW(fd,0) = 0x6a;
WFIFOB(fd,2) = 3; // Rejected by server
@@ -7660,19 +7656,22 @@ void clif_parse_WantToConnection(int fd, TBL_PC* sd)
clif_setwaitclose(fd);
return;
}
- else
- {// packet version accepted
- struct block_list* bl;
- if( (bl=map_id2bl(account_id)) != NULL && bl->type != BL_PC )
- {// non-player object already has that id
- ShowError("clif_parse_WantToConnection: a non-player object already has id %d, please increase the starting account number\n", account_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;
- }
+
+ if (bl ||
+ ((node=chrif_search(account_id)) && //An already existing node is valid only if it is for this login.
+ !(node->account_id == account_id && node->char_id == char_id && node->state == ST_LOGIN))) {
+ sd = BL_CAST(BL_PC, bl);
+ if (!sd)
+ ; //We have another char with the same account logging in/out.
+ else //Already connected player.
+ if (sd->fd)
+ clif_authfail_fd(sd->fd, 2); //someone else logged in
+ else
+ if(sd->state.autotrade)
+ map_quit(sd);// kick autotrading character
+ //Else do not kick character, it could be on its 10 sec penalty for Alt+F4
+ clif_authfail_fd(fd, 8); //Still recognizes last connection
+ return;
}
CREATE(sd, TBL_PC, 1);
@@ -7706,7 +7705,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
if(sd->bl.prev != NULL)
return;
- if (!sd->state.auth)
+ if (!sd->state.active)
{ //Character loading is not complete yet!
//Let pc_reg_received reinvoke this when ready.
sd->state.connect_new = 0;
@@ -11652,12 +11651,13 @@ int clif_parse(int fd)
sd->fd = 0;
ShowInfo("%sCharacter '"CL_WHITE"%s"CL_RESET"' logged off (using @autotrade).\n", (pc_isGM(sd))?"GM ":"", sd->status.name);
} else
- if (sd->state.auth) {
+ if (sd->state.active) {
// Player logout display [Valaris]
ShowInfo("%sCharacter '"CL_WHITE"%s"CL_RESET"' logged off.\n", (pc_isGM(sd))?"GM ":"", sd->status.name);
clif_quitsave(fd, sd);
} else {
- ShowInfo("Player AID:%d/CID:%d (not authenticated) logged off.\n", sd->bl.id, sd->status.char_id);
+ //Unusual logout (during log on/off/map-changer procedure)
+ ShowInfo("Player AID:%d/CID:%d logged off.\n", sd->status.account_id, sd->status.char_id);
map_quit(sd);
}
} else {
@@ -11723,17 +11723,14 @@ int clif_parse(int fd)
if ((int)RFIFOREST(fd) < packet_len)
return 0; // not enough data received to form the packet
- if (sd && sd->state.waitingdisconnect == 1) {
- // 切断待ちの場合パケットを処理しない
- } else
if (packet_db[packet_ver][cmd].func) {
if (sd && sd->bl.prev == NULL && packet_db[packet_ver][cmd].func != clif_parse_LoadEndAck)
; //Only valid packet when player is not on a map is the finish-loading packet.
else
- if (sd
+ if ((sd && sd->state.active)
|| packet_db[packet_ver][cmd].func == clif_parse_WantToConnection
|| packet_db[packet_ver][cmd].func == clif_parse_debug
- ) //Only execute the function when there's an sd (except for debug/wanttoconnect packets)
+ ) //Only execute the function when there's an active sd (except for debug/wanttoconnect packets)
packet_db[packet_ver][cmd].func(fd, sd);
}
#if DUMP_UNKNOWN_PACKET
@@ -11750,7 +11747,7 @@ int clif_parse(int fd)
return 1;
} else {
time(&now);
- if (sd && sd->state.auth) {
+ if (sd && sd->state.active) {
fprintf(fp, "%sPlayer with account ID %d (character ID %d, player name %s) sent wrong packet:\n",
asctime(localtime(&now)), sd->status.account_id, sd->status.char_id, sd->status.name);
} else if (sd) // not authentified! (refused by char-server or disconnect before to be authentified)
@@ -11779,7 +11776,7 @@ int clif_parse(int fd)
ShowMessage("%02X ", RFIFOB(fd,i));
}
ShowMessage("\n");
- if (sd && sd->state.auth) {
+ if (sd && sd->state.active) {
if (sd->status.name != NULL)
ShowMessage("\nAccount ID %d, character ID %d, player name %s.\n",
sd->status.account_id, sd->status.char_id, sd->status.name);